ol.js 2.7 MB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017270182701927020270212702227023270242702527026270272702827029270302703127032270332703427035270362703727038270392704027041270422704327044270452704627047270482704927050270512705227053270542705527056270572705827059270602706127062270632706427065270662706727068270692707027071270722707327074270752707627077270782707927080270812708227083270842708527086270872708827089270902709127092270932709427095270962709727098270992710027101271022710327104271052710627107271082710927110271112711227113271142711527116271172711827119271202712127122271232712427125271262712727128271292713027131271322713327134271352713627137271382713927140271412714227143271442714527146271472714827149271502715127152271532715427155271562715727158271592716027161271622716327164271652716627167271682716927170271712717227173271742717527176271772717827179271802718127182271832718427185271862718727188271892719027191271922719327194271952719627197271982719927200272012720227203272042720527206272072720827209272102721127212272132721427215272162721727218272192722027221272222722327224272252722627227272282722927230272312723227233272342723527236272372723827239272402724127242272432724427245272462724727248272492725027251272522725327254272552725627257272582725927260272612726227263272642726527266272672726827269272702727127272272732727427275272762727727278272792728027281272822728327284272852728627287272882728927290272912729227293272942729527296272972729827299273002730127302273032730427305273062730727308273092731027311273122731327314273152731627317273182731927320273212732227323273242732527326273272732827329273302733127332273332733427335273362733727338273392734027341273422734327344273452734627347273482734927350273512735227353273542735527356273572735827359273602736127362273632736427365273662736727368273692737027371273722737327374273752737627377273782737927380273812738227383273842738527386273872738827389273902739127392273932739427395273962739727398273992740027401274022740327404274052740627407274082740927410274112741227413274142741527416274172741827419274202742127422274232742427425274262742727428274292743027431274322743327434274352743627437274382743927440274412744227443274442744527446274472744827449274502745127452274532745427455274562745727458274592746027461274622746327464274652746627467274682746927470274712747227473274742747527476274772747827479274802748127482274832748427485274862748727488274892749027491274922749327494274952749627497274982749927500275012750227503275042750527506275072750827509275102751127512275132751427515275162751727518275192752027521275222752327524275252752627527275282752927530275312753227533275342753527536275372753827539275402754127542275432754427545275462754727548275492755027551275522755327554275552755627557275582755927560275612756227563275642756527566275672756827569275702757127572275732757427575275762757727578275792758027581275822758327584275852758627587275882758927590275912759227593275942759527596275972759827599276002760127602276032760427605276062760727608276092761027611276122761327614276152761627617276182761927620276212762227623276242762527626276272762827629276302763127632276332763427635276362763727638276392764027641276422764327644276452764627647276482764927650276512765227653276542765527656276572765827659276602766127662276632766427665276662766727668276692767027671276722767327674276752767627677276782767927680276812768227683276842768527686276872768827689276902769127692276932769427695276962769727698276992770027701277022770327704277052770627707277082770927710277112771227713277142771527716277172771827719277202772127722277232772427725277262772727728277292773027731277322773327734277352773627737277382773927740277412774227743277442774527746277472774827749277502775127752277532775427755277562775727758277592776027761277622776327764277652776627767277682776927770277712777227773277742777527776277772777827779277802778127782277832778427785277862778727788277892779027791277922779327794277952779627797277982779927800278012780227803278042780527806278072780827809278102781127812278132781427815278162781727818278192782027821278222782327824278252782627827278282782927830278312783227833278342783527836278372783827839278402784127842278432784427845278462784727848278492785027851278522785327854278552785627857278582785927860278612786227863278642786527866278672786827869278702787127872278732787427875278762787727878278792788027881278822788327884278852788627887278882788927890278912789227893278942789527896278972789827899279002790127902279032790427905279062790727908279092791027911279122791327914279152791627917279182791927920279212792227923279242792527926279272792827929279302793127932279332793427935279362793727938279392794027941279422794327944279452794627947279482794927950279512795227953279542795527956279572795827959279602796127962279632796427965279662796727968279692797027971279722797327974279752797627977279782797927980279812798227983279842798527986279872798827989279902799127992279932799427995279962799727998279992800028001280022800328004280052800628007280082800928010280112801228013280142801528016280172801828019280202802128022280232802428025280262802728028280292803028031280322803328034280352803628037280382803928040280412804228043280442804528046280472804828049280502805128052280532805428055280562805728058280592806028061280622806328064280652806628067280682806928070280712807228073280742807528076280772807828079280802808128082280832808428085280862808728088280892809028091280922809328094280952809628097280982809928100281012810228103281042810528106281072810828109281102811128112281132811428115281162811728118281192812028121281222812328124281252812628127281282812928130281312813228133281342813528136281372813828139281402814128142281432814428145281462814728148281492815028151281522815328154281552815628157281582815928160281612816228163281642816528166281672816828169281702817128172281732817428175281762817728178281792818028181281822818328184281852818628187281882818928190281912819228193281942819528196281972819828199282002820128202282032820428205282062820728208282092821028211282122821328214282152821628217282182821928220282212822228223282242822528226282272822828229282302823128232282332823428235282362823728238282392824028241282422824328244282452824628247282482824928250282512825228253282542825528256282572825828259282602826128262282632826428265282662826728268282692827028271282722827328274282752827628277282782827928280282812828228283282842828528286282872828828289282902829128292282932829428295282962829728298282992830028301283022830328304283052830628307283082830928310283112831228313283142831528316283172831828319283202832128322283232832428325283262832728328283292833028331283322833328334283352833628337283382833928340283412834228343283442834528346283472834828349283502835128352283532835428355283562835728358283592836028361283622836328364283652836628367283682836928370283712837228373283742837528376283772837828379283802838128382283832838428385283862838728388283892839028391283922839328394283952839628397283982839928400284012840228403284042840528406284072840828409284102841128412284132841428415284162841728418284192842028421284222842328424284252842628427284282842928430284312843228433284342843528436284372843828439284402844128442284432844428445284462844728448284492845028451284522845328454284552845628457284582845928460284612846228463284642846528466284672846828469284702847128472284732847428475284762847728478284792848028481284822848328484284852848628487284882848928490284912849228493284942849528496284972849828499285002850128502285032850428505285062850728508285092851028511285122851328514285152851628517285182851928520285212852228523285242852528526285272852828529285302853128532285332853428535285362853728538285392854028541285422854328544285452854628547285482854928550285512855228553285542855528556285572855828559285602856128562285632856428565285662856728568285692857028571285722857328574285752857628577285782857928580285812858228583285842858528586285872858828589285902859128592285932859428595285962859728598285992860028601286022860328604286052860628607286082860928610286112861228613286142861528616286172861828619286202862128622286232862428625286262862728628286292863028631286322863328634286352863628637286382863928640286412864228643286442864528646286472864828649286502865128652286532865428655286562865728658286592866028661286622866328664286652866628667286682866928670286712867228673286742867528676286772867828679286802868128682286832868428685286862868728688286892869028691286922869328694286952869628697286982869928700287012870228703287042870528706287072870828709287102871128712287132871428715287162871728718287192872028721287222872328724287252872628727287282872928730287312873228733287342873528736287372873828739287402874128742287432874428745287462874728748287492875028751287522875328754287552875628757287582875928760287612876228763287642876528766287672876828769287702877128772287732877428775287762877728778287792878028781287822878328784287852878628787287882878928790287912879228793287942879528796287972879828799288002880128802288032880428805288062880728808288092881028811288122881328814288152881628817288182881928820288212882228823288242882528826288272882828829288302883128832288332883428835288362883728838288392884028841288422884328844288452884628847288482884928850288512885228853288542885528856288572885828859288602886128862288632886428865288662886728868288692887028871288722887328874288752887628877288782887928880288812888228883288842888528886288872888828889288902889128892288932889428895288962889728898288992890028901289022890328904289052890628907289082890928910289112891228913289142891528916289172891828919289202892128922289232892428925289262892728928289292893028931289322893328934289352893628937289382893928940289412894228943289442894528946289472894828949289502895128952289532895428955289562895728958289592896028961289622896328964289652896628967289682896928970289712897228973289742897528976289772897828979289802898128982289832898428985289862898728988289892899028991289922899328994289952899628997289982899929000290012900229003290042900529006290072900829009290102901129012290132901429015290162901729018290192902029021290222902329024290252902629027290282902929030290312903229033290342903529036290372903829039290402904129042290432904429045290462904729048290492905029051290522905329054290552905629057290582905929060290612906229063290642906529066290672906829069290702907129072290732907429075290762907729078290792908029081290822908329084290852908629087290882908929090290912909229093290942909529096290972909829099291002910129102291032910429105291062910729108291092911029111291122911329114291152911629117291182911929120291212912229123291242912529126291272912829129291302913129132291332913429135291362913729138291392914029141291422914329144291452914629147291482914929150291512915229153291542915529156291572915829159291602916129162291632916429165291662916729168291692917029171291722917329174291752917629177291782917929180291812918229183291842918529186291872918829189291902919129192291932919429195291962919729198291992920029201292022920329204292052920629207292082920929210292112921229213292142921529216292172921829219292202922129222292232922429225292262922729228292292923029231292322923329234292352923629237292382923929240292412924229243292442924529246292472924829249292502925129252292532925429255292562925729258292592926029261292622926329264292652926629267292682926929270292712927229273292742927529276292772927829279292802928129282292832928429285292862928729288292892929029291292922929329294292952929629297292982929929300293012930229303293042930529306293072930829309293102931129312293132931429315293162931729318293192932029321293222932329324293252932629327293282932929330293312933229333293342933529336293372933829339293402934129342293432934429345293462934729348293492935029351293522935329354293552935629357293582935929360293612936229363293642936529366293672936829369293702937129372293732937429375293762937729378293792938029381293822938329384293852938629387293882938929390293912939229393293942939529396293972939829399294002940129402294032940429405294062940729408294092941029411294122941329414294152941629417294182941929420294212942229423294242942529426294272942829429294302943129432294332943429435294362943729438294392944029441294422944329444294452944629447294482944929450294512945229453294542945529456294572945829459294602946129462294632946429465294662946729468294692947029471294722947329474294752947629477294782947929480294812948229483294842948529486294872948829489294902949129492294932949429495294962949729498294992950029501295022950329504295052950629507295082950929510295112951229513295142951529516295172951829519295202952129522295232952429525295262952729528295292953029531295322953329534295352953629537295382953929540295412954229543295442954529546295472954829549295502955129552295532955429555295562955729558295592956029561295622956329564295652956629567295682956929570295712957229573295742957529576295772957829579295802958129582295832958429585295862958729588295892959029591295922959329594295952959629597295982959929600296012960229603296042960529606296072960829609296102961129612296132961429615296162961729618296192962029621296222962329624296252962629627296282962929630296312963229633296342963529636296372963829639296402964129642296432964429645296462964729648296492965029651296522965329654296552965629657296582965929660296612966229663296642966529666296672966829669296702967129672296732967429675296762967729678296792968029681296822968329684296852968629687296882968929690296912969229693296942969529696296972969829699297002970129702297032970429705297062970729708297092971029711297122971329714297152971629717297182971929720297212972229723297242972529726297272972829729297302973129732297332973429735297362973729738297392974029741297422974329744297452974629747297482974929750297512975229753297542975529756297572975829759297602976129762297632976429765297662976729768297692977029771297722977329774297752977629777297782977929780297812978229783297842978529786297872978829789297902979129792297932979429795297962979729798297992980029801298022980329804298052980629807298082980929810298112981229813298142981529816298172981829819298202982129822298232982429825298262982729828298292983029831298322983329834298352983629837298382983929840298412984229843298442984529846298472984829849298502985129852298532985429855298562985729858298592986029861298622986329864298652986629867298682986929870298712987229873298742987529876298772987829879298802988129882298832988429885298862988729888298892989029891298922989329894298952989629897298982989929900299012990229903299042990529906299072990829909299102991129912299132991429915299162991729918299192992029921299222992329924299252992629927299282992929930299312993229933299342993529936299372993829939299402994129942299432994429945299462994729948299492995029951299522995329954299552995629957299582995929960299612996229963299642996529966299672996829969299702997129972299732997429975299762997729978299792998029981299822998329984299852998629987299882998929990299912999229993299942999529996299972999829999300003000130002300033000430005300063000730008300093001030011300123001330014300153001630017300183001930020300213002230023300243002530026300273002830029300303003130032300333003430035300363003730038300393004030041300423004330044300453004630047300483004930050300513005230053300543005530056300573005830059300603006130062300633006430065300663006730068300693007030071300723007330074300753007630077300783007930080300813008230083300843008530086300873008830089300903009130092300933009430095300963009730098300993010030101301023010330104301053010630107301083010930110301113011230113301143011530116301173011830119301203012130122301233012430125301263012730128301293013030131301323013330134301353013630137301383013930140301413014230143301443014530146301473014830149301503015130152301533015430155301563015730158301593016030161301623016330164301653016630167301683016930170301713017230173301743017530176301773017830179301803018130182301833018430185301863018730188301893019030191301923019330194301953019630197301983019930200302013020230203302043020530206302073020830209302103021130212302133021430215302163021730218302193022030221302223022330224302253022630227302283022930230302313023230233302343023530236302373023830239302403024130242302433024430245302463024730248302493025030251302523025330254302553025630257302583025930260302613026230263302643026530266302673026830269302703027130272302733027430275302763027730278302793028030281302823028330284302853028630287302883028930290302913029230293302943029530296302973029830299303003030130302303033030430305303063030730308303093031030311303123031330314303153031630317303183031930320303213032230323303243032530326303273032830329303303033130332303333033430335303363033730338303393034030341303423034330344303453034630347303483034930350303513035230353303543035530356303573035830359303603036130362303633036430365303663036730368303693037030371303723037330374303753037630377303783037930380303813038230383303843038530386303873038830389303903039130392303933039430395303963039730398303993040030401304023040330404304053040630407304083040930410304113041230413304143041530416304173041830419304203042130422304233042430425304263042730428304293043030431304323043330434304353043630437304383043930440304413044230443304443044530446304473044830449304503045130452304533045430455304563045730458304593046030461304623046330464304653046630467304683046930470304713047230473304743047530476304773047830479304803048130482304833048430485304863048730488304893049030491304923049330494304953049630497304983049930500305013050230503305043050530506305073050830509305103051130512305133051430515305163051730518305193052030521305223052330524305253052630527305283052930530305313053230533305343053530536305373053830539305403054130542305433054430545305463054730548305493055030551305523055330554305553055630557305583055930560305613056230563305643056530566305673056830569305703057130572305733057430575305763057730578305793058030581305823058330584305853058630587305883058930590305913059230593305943059530596305973059830599306003060130602306033060430605306063060730608306093061030611306123061330614306153061630617306183061930620306213062230623306243062530626306273062830629306303063130632306333063430635306363063730638306393064030641306423064330644306453064630647306483064930650306513065230653306543065530656306573065830659306603066130662306633066430665306663066730668306693067030671306723067330674306753067630677306783067930680306813068230683306843068530686306873068830689306903069130692306933069430695306963069730698306993070030701307023070330704307053070630707307083070930710307113071230713307143071530716307173071830719307203072130722307233072430725307263072730728307293073030731307323073330734307353073630737307383073930740307413074230743307443074530746307473074830749307503075130752307533075430755307563075730758307593076030761307623076330764307653076630767307683076930770307713077230773307743077530776307773077830779307803078130782307833078430785307863078730788307893079030791307923079330794307953079630797307983079930800308013080230803308043080530806308073080830809308103081130812308133081430815308163081730818308193082030821308223082330824308253082630827308283082930830308313083230833308343083530836308373083830839308403084130842308433084430845308463084730848308493085030851308523085330854308553085630857308583085930860308613086230863308643086530866308673086830869308703087130872308733087430875308763087730878308793088030881308823088330884308853088630887308883088930890308913089230893308943089530896308973089830899309003090130902309033090430905309063090730908309093091030911309123091330914309153091630917309183091930920309213092230923309243092530926309273092830929309303093130932309333093430935309363093730938309393094030941309423094330944309453094630947309483094930950309513095230953309543095530956309573095830959309603096130962309633096430965309663096730968309693097030971309723097330974309753097630977309783097930980309813098230983309843098530986309873098830989309903099130992309933099430995309963099730998309993100031001310023100331004310053100631007310083100931010310113101231013310143101531016310173101831019310203102131022310233102431025310263102731028310293103031031310323103331034310353103631037310383103931040310413104231043310443104531046310473104831049310503105131052310533105431055310563105731058310593106031061310623106331064310653106631067310683106931070310713107231073310743107531076310773107831079310803108131082310833108431085310863108731088310893109031091310923109331094310953109631097310983109931100311013110231103311043110531106311073110831109311103111131112311133111431115311163111731118311193112031121311223112331124311253112631127311283112931130311313113231133311343113531136311373113831139311403114131142311433114431145311463114731148311493115031151311523115331154311553115631157311583115931160311613116231163311643116531166311673116831169311703117131172311733117431175311763117731178311793118031181311823118331184311853118631187311883118931190311913119231193311943119531196311973119831199312003120131202312033120431205312063120731208312093121031211312123121331214312153121631217312183121931220312213122231223312243122531226312273122831229312303123131232312333123431235312363123731238312393124031241312423124331244312453124631247312483124931250312513125231253312543125531256312573125831259312603126131262312633126431265312663126731268312693127031271312723127331274312753127631277312783127931280312813128231283312843128531286312873128831289312903129131292312933129431295312963129731298312993130031301313023130331304313053130631307313083130931310313113131231313313143131531316313173131831319313203132131322313233132431325313263132731328313293133031331313323133331334313353133631337313383133931340313413134231343313443134531346313473134831349313503135131352313533135431355313563135731358313593136031361313623136331364313653136631367313683136931370313713137231373313743137531376313773137831379313803138131382313833138431385313863138731388313893139031391313923139331394313953139631397313983139931400314013140231403314043140531406314073140831409314103141131412314133141431415314163141731418314193142031421314223142331424314253142631427314283142931430314313143231433314343143531436314373143831439314403144131442314433144431445314463144731448314493145031451314523145331454314553145631457314583145931460314613146231463314643146531466314673146831469314703147131472314733147431475314763147731478314793148031481314823148331484314853148631487314883148931490314913149231493314943149531496314973149831499315003150131502315033150431505315063150731508315093151031511315123151331514315153151631517315183151931520315213152231523315243152531526315273152831529315303153131532315333153431535315363153731538315393154031541315423154331544315453154631547315483154931550315513155231553315543155531556315573155831559315603156131562315633156431565315663156731568315693157031571315723157331574315753157631577315783157931580315813158231583315843158531586315873158831589315903159131592315933159431595315963159731598315993160031601316023160331604316053160631607316083160931610316113161231613316143161531616316173161831619316203162131622316233162431625316263162731628316293163031631316323163331634316353163631637316383163931640316413164231643316443164531646316473164831649316503165131652316533165431655316563165731658316593166031661316623166331664316653166631667316683166931670316713167231673316743167531676316773167831679316803168131682316833168431685316863168731688316893169031691316923169331694316953169631697316983169931700317013170231703317043170531706317073170831709317103171131712317133171431715317163171731718317193172031721317223172331724317253172631727317283172931730317313173231733317343173531736317373173831739317403174131742317433174431745317463174731748317493175031751317523175331754317553175631757317583175931760317613176231763317643176531766317673176831769317703177131772317733177431775317763177731778317793178031781317823178331784317853178631787317883178931790317913179231793317943179531796317973179831799318003180131802318033180431805318063180731808318093181031811318123181331814318153181631817318183181931820318213182231823318243182531826318273182831829318303183131832318333183431835318363183731838318393184031841318423184331844318453184631847318483184931850318513185231853318543185531856318573185831859318603186131862318633186431865318663186731868318693187031871318723187331874318753187631877318783187931880318813188231883318843188531886318873188831889318903189131892318933189431895318963189731898318993190031901319023190331904319053190631907319083190931910319113191231913319143191531916319173191831919319203192131922319233192431925319263192731928319293193031931319323193331934319353193631937319383193931940319413194231943319443194531946319473194831949319503195131952319533195431955319563195731958319593196031961319623196331964319653196631967319683196931970319713197231973319743197531976319773197831979319803198131982319833198431985319863198731988319893199031991319923199331994319953199631997319983199932000320013200232003320043200532006320073200832009320103201132012320133201432015320163201732018320193202032021320223202332024320253202632027320283202932030320313203232033320343203532036320373203832039320403204132042320433204432045320463204732048320493205032051320523205332054320553205632057320583205932060320613206232063320643206532066320673206832069320703207132072320733207432075320763207732078320793208032081320823208332084320853208632087320883208932090320913209232093320943209532096320973209832099321003210132102321033210432105321063210732108321093211032111321123211332114321153211632117321183211932120321213212232123321243212532126321273212832129321303213132132321333213432135321363213732138321393214032141321423214332144321453214632147321483214932150321513215232153321543215532156321573215832159321603216132162321633216432165321663216732168321693217032171321723217332174321753217632177321783217932180321813218232183321843218532186321873218832189321903219132192321933219432195321963219732198321993220032201322023220332204322053220632207322083220932210322113221232213322143221532216322173221832219322203222132222322233222432225322263222732228322293223032231322323223332234322353223632237322383223932240322413224232243322443224532246322473224832249322503225132252322533225432255322563225732258322593226032261322623226332264322653226632267322683226932270322713227232273322743227532276322773227832279322803228132282322833228432285322863228732288322893229032291322923229332294322953229632297322983229932300323013230232303323043230532306323073230832309323103231132312323133231432315323163231732318323193232032321323223232332324323253232632327323283232932330323313233232333323343233532336323373233832339323403234132342323433234432345323463234732348323493235032351323523235332354323553235632357323583235932360323613236232363323643236532366323673236832369323703237132372323733237432375323763237732378323793238032381323823238332384323853238632387323883238932390323913239232393323943239532396323973239832399324003240132402324033240432405324063240732408324093241032411324123241332414324153241632417324183241932420324213242232423324243242532426324273242832429324303243132432324333243432435324363243732438324393244032441324423244332444324453244632447324483244932450324513245232453324543245532456324573245832459324603246132462324633246432465324663246732468324693247032471324723247332474324753247632477324783247932480324813248232483324843248532486324873248832489324903249132492324933249432495324963249732498324993250032501325023250332504325053250632507325083250932510325113251232513325143251532516325173251832519325203252132522325233252432525325263252732528325293253032531325323253332534325353253632537325383253932540325413254232543325443254532546325473254832549325503255132552325533255432555325563255732558325593256032561325623256332564325653256632567325683256932570325713257232573325743257532576325773257832579325803258132582325833258432585325863258732588325893259032591325923259332594325953259632597325983259932600326013260232603326043260532606326073260832609326103261132612326133261432615326163261732618326193262032621326223262332624326253262632627326283262932630326313263232633326343263532636326373263832639326403264132642326433264432645326463264732648326493265032651326523265332654326553265632657326583265932660326613266232663326643266532666326673266832669326703267132672326733267432675326763267732678326793268032681326823268332684326853268632687326883268932690326913269232693326943269532696326973269832699327003270132702327033270432705327063270732708327093271032711327123271332714327153271632717327183271932720327213272232723327243272532726327273272832729327303273132732327333273432735327363273732738327393274032741327423274332744327453274632747327483274932750327513275232753327543275532756327573275832759327603276132762327633276432765327663276732768327693277032771327723277332774327753277632777327783277932780327813278232783327843278532786327873278832789327903279132792327933279432795327963279732798327993280032801328023280332804328053280632807328083280932810328113281232813328143281532816328173281832819328203282132822328233282432825328263282732828328293283032831328323283332834328353283632837328383283932840328413284232843328443284532846328473284832849328503285132852328533285432855328563285732858328593286032861328623286332864328653286632867328683286932870328713287232873328743287532876328773287832879328803288132882328833288432885328863288732888328893289032891328923289332894328953289632897328983289932900329013290232903329043290532906329073290832909329103291132912329133291432915329163291732918329193292032921329223292332924329253292632927329283292932930329313293232933329343293532936329373293832939329403294132942329433294432945329463294732948329493295032951329523295332954329553295632957329583295932960329613296232963329643296532966329673296832969329703297132972329733297432975329763297732978329793298032981329823298332984329853298632987329883298932990329913299232993329943299532996329973299832999330003300133002330033300433005330063300733008330093301033011330123301333014330153301633017330183301933020330213302233023330243302533026330273302833029330303303133032330333303433035330363303733038330393304033041330423304333044330453304633047330483304933050330513305233053330543305533056330573305833059330603306133062330633306433065330663306733068330693307033071330723307333074330753307633077330783307933080330813308233083330843308533086330873308833089330903309133092330933309433095330963309733098330993310033101331023310333104331053310633107331083310933110331113311233113331143311533116331173311833119331203312133122331233312433125331263312733128331293313033131331323313333134331353313633137331383313933140331413314233143331443314533146331473314833149331503315133152331533315433155331563315733158331593316033161331623316333164331653316633167331683316933170331713317233173331743317533176331773317833179331803318133182331833318433185331863318733188331893319033191331923319333194331953319633197331983319933200332013320233203332043320533206332073320833209332103321133212332133321433215332163321733218332193322033221332223322333224332253322633227332283322933230332313323233233332343323533236332373323833239332403324133242332433324433245332463324733248332493325033251332523325333254332553325633257332583325933260332613326233263332643326533266332673326833269332703327133272332733327433275332763327733278332793328033281332823328333284332853328633287332883328933290332913329233293332943329533296332973329833299333003330133302333033330433305333063330733308333093331033311333123331333314333153331633317333183331933320333213332233323333243332533326333273332833329333303333133332333333333433335333363333733338333393334033341333423334333344333453334633347333483334933350333513335233353333543335533356333573335833359333603336133362333633336433365333663336733368333693337033371333723337333374333753337633377333783337933380333813338233383333843338533386333873338833389333903339133392333933339433395333963339733398333993340033401334023340333404334053340633407334083340933410334113341233413334143341533416334173341833419334203342133422334233342433425334263342733428334293343033431334323343333434334353343633437334383343933440334413344233443334443344533446334473344833449334503345133452334533345433455334563345733458334593346033461334623346333464334653346633467334683346933470334713347233473334743347533476334773347833479334803348133482334833348433485334863348733488334893349033491334923349333494334953349633497334983349933500335013350233503335043350533506335073350833509335103351133512335133351433515335163351733518335193352033521335223352333524335253352633527335283352933530335313353233533335343353533536335373353833539335403354133542335433354433545335463354733548335493355033551335523355333554335553355633557335583355933560335613356233563335643356533566335673356833569335703357133572335733357433575335763357733578335793358033581335823358333584335853358633587335883358933590335913359233593335943359533596335973359833599336003360133602336033360433605336063360733608336093361033611336123361333614336153361633617336183361933620336213362233623336243362533626336273362833629336303363133632336333363433635336363363733638336393364033641336423364333644336453364633647336483364933650336513365233653336543365533656336573365833659336603366133662336633366433665336663366733668336693367033671336723367333674336753367633677336783367933680336813368233683336843368533686336873368833689336903369133692336933369433695336963369733698336993370033701337023370333704337053370633707337083370933710337113371233713337143371533716337173371833719337203372133722337233372433725337263372733728337293373033731337323373333734337353373633737337383373933740337413374233743337443374533746337473374833749337503375133752337533375433755337563375733758337593376033761337623376333764337653376633767337683376933770337713377233773337743377533776337773377833779337803378133782337833378433785337863378733788337893379033791337923379333794337953379633797337983379933800338013380233803338043380533806338073380833809338103381133812338133381433815338163381733818338193382033821338223382333824338253382633827338283382933830338313383233833338343383533836338373383833839338403384133842338433384433845338463384733848338493385033851338523385333854338553385633857338583385933860338613386233863338643386533866338673386833869338703387133872338733387433875338763387733878338793388033881338823388333884338853388633887338883388933890338913389233893338943389533896338973389833899339003390133902339033390433905339063390733908339093391033911339123391333914339153391633917339183391933920339213392233923339243392533926339273392833929339303393133932339333393433935339363393733938339393394033941339423394333944339453394633947339483394933950339513395233953339543395533956339573395833959339603396133962339633396433965339663396733968339693397033971339723397333974339753397633977339783397933980339813398233983339843398533986339873398833989339903399133992339933399433995339963399733998339993400034001340023400334004340053400634007340083400934010340113401234013340143401534016340173401834019340203402134022340233402434025340263402734028340293403034031340323403334034340353403634037340383403934040340413404234043340443404534046340473404834049340503405134052340533405434055340563405734058340593406034061340623406334064340653406634067340683406934070340713407234073340743407534076340773407834079340803408134082340833408434085340863408734088340893409034091340923409334094340953409634097340983409934100341013410234103341043410534106341073410834109341103411134112341133411434115341163411734118341193412034121341223412334124341253412634127341283412934130341313413234133341343413534136341373413834139341403414134142341433414434145341463414734148341493415034151341523415334154341553415634157341583415934160341613416234163341643416534166341673416834169341703417134172341733417434175341763417734178341793418034181341823418334184341853418634187341883418934190341913419234193341943419534196341973419834199342003420134202342033420434205342063420734208342093421034211342123421334214342153421634217342183421934220342213422234223342243422534226342273422834229342303423134232342333423434235342363423734238342393424034241342423424334244342453424634247342483424934250342513425234253342543425534256342573425834259342603426134262342633426434265342663426734268342693427034271342723427334274342753427634277342783427934280342813428234283342843428534286342873428834289342903429134292342933429434295342963429734298342993430034301343023430334304343053430634307343083430934310343113431234313343143431534316343173431834319343203432134322343233432434325343263432734328343293433034331343323433334334343353433634337343383433934340343413434234343343443434534346343473434834349343503435134352343533435434355343563435734358343593436034361343623436334364343653436634367343683436934370343713437234373343743437534376343773437834379343803438134382343833438434385343863438734388343893439034391343923439334394343953439634397343983439934400344013440234403344043440534406344073440834409344103441134412344133441434415344163441734418344193442034421344223442334424344253442634427344283442934430344313443234433344343443534436344373443834439344403444134442344433444434445344463444734448344493445034451344523445334454344553445634457344583445934460344613446234463344643446534466344673446834469344703447134472344733447434475344763447734478344793448034481344823448334484344853448634487344883448934490344913449234493344943449534496344973449834499345003450134502345033450434505345063450734508345093451034511345123451334514345153451634517345183451934520345213452234523345243452534526345273452834529345303453134532345333453434535345363453734538345393454034541345423454334544345453454634547345483454934550345513455234553345543455534556345573455834559345603456134562345633456434565345663456734568345693457034571345723457334574345753457634577345783457934580345813458234583345843458534586345873458834589345903459134592345933459434595345963459734598345993460034601346023460334604346053460634607346083460934610346113461234613346143461534616346173461834619346203462134622346233462434625346263462734628346293463034631346323463334634346353463634637346383463934640346413464234643346443464534646346473464834649346503465134652346533465434655346563465734658346593466034661346623466334664346653466634667346683466934670346713467234673346743467534676346773467834679346803468134682346833468434685346863468734688346893469034691346923469334694346953469634697346983469934700347013470234703347043470534706347073470834709347103471134712347133471434715347163471734718347193472034721347223472334724347253472634727347283472934730347313473234733347343473534736347373473834739347403474134742347433474434745347463474734748347493475034751347523475334754347553475634757347583475934760347613476234763347643476534766347673476834769347703477134772347733477434775347763477734778347793478034781347823478334784347853478634787347883478934790347913479234793347943479534796347973479834799348003480134802348033480434805348063480734808348093481034811348123481334814348153481634817348183481934820348213482234823348243482534826348273482834829348303483134832348333483434835348363483734838348393484034841348423484334844348453484634847348483484934850348513485234853348543485534856348573485834859348603486134862348633486434865348663486734868348693487034871348723487334874348753487634877348783487934880348813488234883348843488534886348873488834889348903489134892348933489434895348963489734898348993490034901349023490334904349053490634907349083490934910349113491234913349143491534916349173491834919349203492134922349233492434925349263492734928349293493034931349323493334934349353493634937349383493934940349413494234943349443494534946349473494834949349503495134952349533495434955349563495734958349593496034961349623496334964349653496634967349683496934970349713497234973349743497534976349773497834979349803498134982349833498434985349863498734988349893499034991349923499334994349953499634997349983499935000350013500235003350043500535006350073500835009350103501135012350133501435015350163501735018350193502035021350223502335024350253502635027350283502935030350313503235033350343503535036350373503835039350403504135042350433504435045350463504735048350493505035051350523505335054350553505635057350583505935060350613506235063350643506535066350673506835069350703507135072350733507435075350763507735078350793508035081350823508335084350853508635087350883508935090350913509235093350943509535096350973509835099351003510135102351033510435105351063510735108351093511035111351123511335114351153511635117351183511935120351213512235123351243512535126351273512835129351303513135132351333513435135351363513735138351393514035141351423514335144351453514635147351483514935150351513515235153351543515535156351573515835159351603516135162351633516435165351663516735168351693517035171351723517335174351753517635177351783517935180351813518235183351843518535186351873518835189351903519135192351933519435195351963519735198351993520035201352023520335204352053520635207352083520935210352113521235213352143521535216352173521835219352203522135222352233522435225352263522735228352293523035231352323523335234352353523635237352383523935240352413524235243352443524535246352473524835249352503525135252352533525435255352563525735258352593526035261352623526335264352653526635267352683526935270352713527235273352743527535276352773527835279352803528135282352833528435285352863528735288352893529035291352923529335294352953529635297352983529935300353013530235303353043530535306353073530835309353103531135312353133531435315353163531735318353193532035321353223532335324353253532635327353283532935330353313533235333353343533535336353373533835339353403534135342353433534435345353463534735348353493535035351353523535335354353553535635357353583535935360353613536235363353643536535366353673536835369353703537135372353733537435375353763537735378353793538035381353823538335384353853538635387353883538935390353913539235393353943539535396353973539835399354003540135402354033540435405354063540735408354093541035411354123541335414354153541635417354183541935420354213542235423354243542535426354273542835429354303543135432354333543435435354363543735438354393544035441354423544335444354453544635447354483544935450354513545235453354543545535456354573545835459354603546135462354633546435465354663546735468354693547035471354723547335474354753547635477354783547935480354813548235483354843548535486354873548835489354903549135492354933549435495354963549735498354993550035501355023550335504355053550635507355083550935510355113551235513355143551535516355173551835519355203552135522355233552435525355263552735528355293553035531355323553335534355353553635537355383553935540355413554235543355443554535546355473554835549355503555135552355533555435555355563555735558355593556035561355623556335564355653556635567355683556935570355713557235573355743557535576355773557835579355803558135582355833558435585355863558735588355893559035591355923559335594355953559635597355983559935600356013560235603356043560535606356073560835609356103561135612356133561435615356163561735618356193562035621356223562335624356253562635627356283562935630356313563235633356343563535636356373563835639356403564135642356433564435645356463564735648356493565035651356523565335654356553565635657356583565935660356613566235663356643566535666356673566835669356703567135672356733567435675356763567735678356793568035681356823568335684356853568635687356883568935690356913569235693356943569535696356973569835699357003570135702357033570435705357063570735708357093571035711357123571335714357153571635717357183571935720357213572235723357243572535726357273572835729357303573135732357333573435735357363573735738357393574035741357423574335744357453574635747357483574935750357513575235753357543575535756357573575835759357603576135762357633576435765357663576735768357693577035771357723577335774357753577635777357783577935780357813578235783357843578535786357873578835789357903579135792357933579435795357963579735798357993580035801358023580335804358053580635807358083580935810358113581235813358143581535816358173581835819358203582135822358233582435825358263582735828358293583035831358323583335834358353583635837358383583935840358413584235843358443584535846358473584835849358503585135852358533585435855358563585735858358593586035861358623586335864358653586635867358683586935870358713587235873358743587535876358773587835879358803588135882358833588435885358863588735888358893589035891358923589335894358953589635897358983589935900359013590235903359043590535906359073590835909359103591135912359133591435915359163591735918359193592035921359223592335924359253592635927359283592935930359313593235933359343593535936359373593835939359403594135942359433594435945359463594735948359493595035951359523595335954359553595635957359583595935960359613596235963359643596535966359673596835969359703597135972359733597435975359763597735978359793598035981359823598335984359853598635987359883598935990359913599235993359943599535996359973599835999360003600136002360033600436005360063600736008360093601036011360123601336014360153601636017360183601936020360213602236023360243602536026360273602836029360303603136032360333603436035360363603736038360393604036041360423604336044360453604636047360483604936050360513605236053360543605536056360573605836059360603606136062360633606436065360663606736068360693607036071360723607336074360753607636077360783607936080360813608236083360843608536086360873608836089360903609136092360933609436095360963609736098360993610036101361023610336104361053610636107361083610936110361113611236113361143611536116361173611836119361203612136122361233612436125361263612736128361293613036131361323613336134361353613636137361383613936140361413614236143361443614536146361473614836149361503615136152361533615436155361563615736158361593616036161361623616336164361653616636167361683616936170361713617236173361743617536176361773617836179361803618136182361833618436185361863618736188361893619036191361923619336194361953619636197361983619936200362013620236203362043620536206362073620836209362103621136212362133621436215362163621736218362193622036221362223622336224362253622636227362283622936230362313623236233362343623536236362373623836239362403624136242362433624436245362463624736248362493625036251362523625336254362553625636257362583625936260362613626236263362643626536266362673626836269362703627136272362733627436275362763627736278362793628036281362823628336284362853628636287362883628936290362913629236293362943629536296362973629836299363003630136302363033630436305363063630736308363093631036311363123631336314363153631636317363183631936320363213632236323363243632536326363273632836329363303633136332363333633436335363363633736338363393634036341363423634336344363453634636347363483634936350363513635236353363543635536356363573635836359363603636136362363633636436365363663636736368363693637036371363723637336374363753637636377363783637936380363813638236383363843638536386363873638836389363903639136392363933639436395363963639736398363993640036401364023640336404364053640636407364083640936410364113641236413364143641536416364173641836419364203642136422364233642436425364263642736428364293643036431364323643336434364353643636437364383643936440364413644236443364443644536446364473644836449364503645136452364533645436455364563645736458364593646036461364623646336464364653646636467364683646936470364713647236473364743647536476364773647836479364803648136482364833648436485364863648736488364893649036491364923649336494364953649636497364983649936500365013650236503365043650536506365073650836509365103651136512365133651436515365163651736518365193652036521365223652336524365253652636527365283652936530365313653236533365343653536536365373653836539365403654136542365433654436545365463654736548365493655036551365523655336554365553655636557365583655936560365613656236563365643656536566365673656836569365703657136572365733657436575365763657736578365793658036581365823658336584365853658636587365883658936590365913659236593365943659536596365973659836599366003660136602366033660436605366063660736608366093661036611366123661336614366153661636617366183661936620366213662236623366243662536626366273662836629366303663136632366333663436635366363663736638366393664036641366423664336644366453664636647366483664936650366513665236653366543665536656366573665836659366603666136662366633666436665366663666736668366693667036671366723667336674366753667636677366783667936680366813668236683366843668536686366873668836689366903669136692366933669436695366963669736698366993670036701367023670336704367053670636707367083670936710367113671236713367143671536716367173671836719367203672136722367233672436725367263672736728367293673036731367323673336734367353673636737367383673936740367413674236743367443674536746367473674836749367503675136752367533675436755367563675736758367593676036761367623676336764367653676636767367683676936770367713677236773367743677536776367773677836779367803678136782367833678436785367863678736788367893679036791367923679336794367953679636797367983679936800368013680236803368043680536806368073680836809368103681136812368133681436815368163681736818368193682036821368223682336824368253682636827368283682936830368313683236833368343683536836368373683836839368403684136842368433684436845368463684736848368493685036851368523685336854368553685636857368583685936860368613686236863368643686536866368673686836869368703687136872368733687436875368763687736878368793688036881368823688336884368853688636887368883688936890368913689236893368943689536896368973689836899369003690136902369033690436905369063690736908369093691036911369123691336914369153691636917369183691936920369213692236923369243692536926369273692836929369303693136932369333693436935369363693736938369393694036941369423694336944369453694636947369483694936950369513695236953369543695536956369573695836959369603696136962369633696436965369663696736968369693697036971369723697336974369753697636977369783697936980369813698236983369843698536986369873698836989369903699136992369933699436995369963699736998369993700037001370023700337004370053700637007370083700937010370113701237013370143701537016370173701837019370203702137022370233702437025370263702737028370293703037031370323703337034370353703637037370383703937040370413704237043370443704537046370473704837049370503705137052370533705437055370563705737058370593706037061370623706337064370653706637067370683706937070370713707237073370743707537076370773707837079370803708137082370833708437085370863708737088370893709037091370923709337094370953709637097370983709937100371013710237103371043710537106371073710837109371103711137112371133711437115371163711737118371193712037121371223712337124371253712637127371283712937130371313713237133371343713537136371373713837139371403714137142371433714437145371463714737148371493715037151371523715337154371553715637157371583715937160371613716237163371643716537166371673716837169371703717137172371733717437175371763717737178371793718037181371823718337184371853718637187371883718937190371913719237193371943719537196371973719837199372003720137202372033720437205372063720737208372093721037211372123721337214372153721637217372183721937220372213722237223372243722537226372273722837229372303723137232372333723437235372363723737238372393724037241372423724337244372453724637247372483724937250372513725237253372543725537256372573725837259372603726137262372633726437265372663726737268372693727037271372723727337274372753727637277372783727937280372813728237283372843728537286372873728837289372903729137292372933729437295372963729737298372993730037301373023730337304373053730637307373083730937310373113731237313373143731537316373173731837319373203732137322373233732437325373263732737328373293733037331373323733337334373353733637337373383733937340373413734237343373443734537346373473734837349373503735137352373533735437355373563735737358373593736037361373623736337364373653736637367373683736937370373713737237373373743737537376373773737837379373803738137382373833738437385373863738737388373893739037391373923739337394373953739637397373983739937400374013740237403374043740537406374073740837409374103741137412374133741437415374163741737418374193742037421374223742337424374253742637427374283742937430374313743237433374343743537436374373743837439374403744137442374433744437445374463744737448374493745037451374523745337454374553745637457374583745937460374613746237463374643746537466374673746837469374703747137472374733747437475374763747737478374793748037481374823748337484374853748637487374883748937490374913749237493374943749537496374973749837499375003750137502375033750437505375063750737508375093751037511375123751337514375153751637517375183751937520375213752237523375243752537526375273752837529375303753137532375333753437535375363753737538375393754037541375423754337544375453754637547375483754937550375513755237553375543755537556375573755837559375603756137562375633756437565375663756737568375693757037571375723757337574375753757637577375783757937580375813758237583375843758537586375873758837589375903759137592375933759437595375963759737598375993760037601376023760337604376053760637607376083760937610376113761237613376143761537616376173761837619376203762137622376233762437625376263762737628376293763037631376323763337634376353763637637376383763937640376413764237643376443764537646376473764837649376503765137652376533765437655376563765737658376593766037661376623766337664376653766637667376683766937670376713767237673376743767537676376773767837679376803768137682376833768437685376863768737688376893769037691376923769337694376953769637697376983769937700377013770237703377043770537706377073770837709377103771137712377133771437715377163771737718377193772037721377223772337724377253772637727377283772937730377313773237733377343773537736377373773837739377403774137742377433774437745377463774737748377493775037751377523775337754377553775637757377583775937760377613776237763377643776537766377673776837769377703777137772377733777437775377763777737778377793778037781377823778337784377853778637787377883778937790377913779237793377943779537796377973779837799378003780137802378033780437805378063780737808378093781037811378123781337814378153781637817378183781937820378213782237823378243782537826378273782837829378303783137832378333783437835378363783737838378393784037841378423784337844378453784637847378483784937850378513785237853378543785537856378573785837859378603786137862378633786437865378663786737868378693787037871378723787337874378753787637877378783787937880378813788237883378843788537886378873788837889378903789137892378933789437895378963789737898378993790037901379023790337904379053790637907379083790937910379113791237913379143791537916379173791837919379203792137922379233792437925379263792737928379293793037931379323793337934379353793637937379383793937940379413794237943379443794537946379473794837949379503795137952379533795437955379563795737958379593796037961379623796337964379653796637967379683796937970379713797237973379743797537976379773797837979379803798137982379833798437985379863798737988379893799037991379923799337994379953799637997379983799938000380013800238003380043800538006380073800838009380103801138012380133801438015380163801738018380193802038021380223802338024380253802638027380283802938030380313803238033380343803538036380373803838039380403804138042380433804438045380463804738048380493805038051380523805338054380553805638057380583805938060380613806238063380643806538066380673806838069380703807138072380733807438075380763807738078380793808038081380823808338084380853808638087380883808938090380913809238093380943809538096380973809838099381003810138102381033810438105381063810738108381093811038111381123811338114381153811638117381183811938120381213812238123381243812538126381273812838129381303813138132381333813438135381363813738138381393814038141381423814338144381453814638147381483814938150381513815238153381543815538156381573815838159381603816138162381633816438165381663816738168381693817038171381723817338174381753817638177381783817938180381813818238183381843818538186381873818838189381903819138192381933819438195381963819738198381993820038201382023820338204382053820638207382083820938210382113821238213382143821538216382173821838219382203822138222382233822438225382263822738228382293823038231382323823338234382353823638237382383823938240382413824238243382443824538246382473824838249382503825138252382533825438255382563825738258382593826038261382623826338264382653826638267382683826938270382713827238273382743827538276382773827838279382803828138282382833828438285382863828738288382893829038291382923829338294382953829638297382983829938300383013830238303383043830538306383073830838309383103831138312383133831438315383163831738318383193832038321383223832338324383253832638327383283832938330383313833238333383343833538336383373833838339383403834138342383433834438345383463834738348383493835038351383523835338354383553835638357383583835938360383613836238363383643836538366383673836838369383703837138372383733837438375383763837738378383793838038381383823838338384383853838638387383883838938390383913839238393383943839538396383973839838399384003840138402384033840438405384063840738408384093841038411384123841338414384153841638417384183841938420384213842238423384243842538426384273842838429384303843138432384333843438435384363843738438384393844038441384423844338444384453844638447384483844938450384513845238453384543845538456384573845838459384603846138462384633846438465384663846738468384693847038471384723847338474384753847638477384783847938480384813848238483384843848538486384873848838489384903849138492384933849438495384963849738498384993850038501385023850338504385053850638507385083850938510385113851238513385143851538516385173851838519385203852138522385233852438525385263852738528385293853038531385323853338534385353853638537385383853938540385413854238543385443854538546385473854838549385503855138552385533855438555385563855738558385593856038561385623856338564385653856638567385683856938570385713857238573385743857538576385773857838579385803858138582385833858438585385863858738588385893859038591385923859338594385953859638597385983859938600386013860238603386043860538606386073860838609386103861138612386133861438615386163861738618386193862038621386223862338624386253862638627386283862938630386313863238633386343863538636386373863838639386403864138642386433864438645386463864738648386493865038651386523865338654386553865638657386583865938660386613866238663386643866538666386673866838669386703867138672386733867438675386763867738678386793868038681386823868338684386853868638687386883868938690386913869238693386943869538696386973869838699387003870138702387033870438705387063870738708387093871038711387123871338714387153871638717387183871938720387213872238723387243872538726387273872838729387303873138732387333873438735387363873738738387393874038741387423874338744387453874638747387483874938750387513875238753387543875538756387573875838759387603876138762387633876438765387663876738768387693877038771387723877338774387753877638777387783877938780387813878238783387843878538786387873878838789387903879138792387933879438795387963879738798387993880038801388023880338804388053880638807388083880938810388113881238813388143881538816388173881838819388203882138822388233882438825388263882738828388293883038831388323883338834388353883638837388383883938840388413884238843388443884538846388473884838849388503885138852388533885438855388563885738858388593886038861388623886338864388653886638867388683886938870388713887238873388743887538876388773887838879388803888138882388833888438885388863888738888388893889038891388923889338894388953889638897388983889938900389013890238903389043890538906389073890838909389103891138912389133891438915389163891738918389193892038921389223892338924389253892638927389283892938930389313893238933389343893538936389373893838939389403894138942389433894438945389463894738948389493895038951389523895338954389553895638957389583895938960389613896238963389643896538966389673896838969389703897138972389733897438975389763897738978389793898038981389823898338984389853898638987389883898938990389913899238993389943899538996389973899838999390003900139002390033900439005390063900739008390093901039011390123901339014390153901639017390183901939020390213902239023390243902539026390273902839029390303903139032390333903439035390363903739038390393904039041390423904339044390453904639047390483904939050390513905239053390543905539056390573905839059390603906139062390633906439065390663906739068390693907039071390723907339074390753907639077390783907939080390813908239083390843908539086390873908839089390903909139092390933909439095390963909739098390993910039101391023910339104391053910639107391083910939110391113911239113391143911539116391173911839119391203912139122391233912439125391263912739128391293913039131391323913339134391353913639137391383913939140391413914239143391443914539146391473914839149391503915139152391533915439155391563915739158391593916039161391623916339164391653916639167391683916939170391713917239173391743917539176391773917839179391803918139182391833918439185391863918739188391893919039191391923919339194391953919639197391983919939200392013920239203392043920539206392073920839209392103921139212392133921439215392163921739218392193922039221392223922339224392253922639227392283922939230392313923239233392343923539236392373923839239392403924139242392433924439245392463924739248392493925039251392523925339254392553925639257392583925939260392613926239263392643926539266392673926839269392703927139272392733927439275392763927739278392793928039281392823928339284392853928639287392883928939290392913929239293392943929539296392973929839299393003930139302393033930439305393063930739308393093931039311393123931339314393153931639317393183931939320393213932239323393243932539326393273932839329393303933139332393333933439335393363933739338393393934039341393423934339344393453934639347393483934939350393513935239353393543935539356393573935839359393603936139362393633936439365393663936739368393693937039371393723937339374393753937639377393783937939380393813938239383393843938539386393873938839389393903939139392393933939439395393963939739398393993940039401394023940339404394053940639407394083940939410394113941239413394143941539416394173941839419394203942139422394233942439425394263942739428394293943039431394323943339434394353943639437394383943939440394413944239443394443944539446394473944839449394503945139452394533945439455394563945739458394593946039461394623946339464394653946639467394683946939470394713947239473394743947539476394773947839479394803948139482394833948439485394863948739488394893949039491394923949339494394953949639497394983949939500395013950239503395043950539506395073950839509395103951139512395133951439515395163951739518395193952039521395223952339524395253952639527395283952939530395313953239533395343953539536395373953839539395403954139542395433954439545395463954739548395493955039551395523955339554395553955639557395583955939560395613956239563395643956539566395673956839569395703957139572395733957439575395763957739578395793958039581395823958339584395853958639587395883958939590395913959239593395943959539596395973959839599396003960139602396033960439605396063960739608396093961039611396123961339614396153961639617396183961939620396213962239623396243962539626396273962839629396303963139632396333963439635396363963739638396393964039641396423964339644396453964639647396483964939650396513965239653396543965539656396573965839659396603966139662396633966439665396663966739668396693967039671396723967339674396753967639677396783967939680396813968239683396843968539686396873968839689396903969139692396933969439695396963969739698396993970039701397023970339704397053970639707397083970939710397113971239713397143971539716397173971839719397203972139722397233972439725397263972739728397293973039731397323973339734397353973639737397383973939740397413974239743397443974539746397473974839749397503975139752397533975439755397563975739758397593976039761397623976339764397653976639767397683976939770397713977239773397743977539776397773977839779397803978139782397833978439785397863978739788397893979039791397923979339794397953979639797397983979939800398013980239803398043980539806398073980839809398103981139812398133981439815398163981739818398193982039821398223982339824398253982639827398283982939830398313983239833398343983539836398373983839839398403984139842398433984439845398463984739848398493985039851398523985339854398553985639857398583985939860398613986239863398643986539866398673986839869398703987139872398733987439875398763987739878398793988039881398823988339884398853988639887398883988939890398913989239893398943989539896398973989839899399003990139902399033990439905399063990739908399093991039911399123991339914399153991639917399183991939920399213992239923399243992539926399273992839929399303993139932399333993439935399363993739938399393994039941399423994339944399453994639947399483994939950399513995239953399543995539956399573995839959399603996139962399633996439965399663996739968399693997039971399723997339974399753997639977399783997939980399813998239983399843998539986399873998839989399903999139992399933999439995399963999739998399994000040001400024000340004400054000640007400084000940010400114001240013400144001540016400174001840019400204002140022400234002440025400264002740028400294003040031400324003340034400354003640037400384003940040400414004240043400444004540046400474004840049400504005140052400534005440055400564005740058400594006040061400624006340064400654006640067400684006940070400714007240073400744007540076400774007840079400804008140082400834008440085400864008740088400894009040091400924009340094400954009640097400984009940100401014010240103401044010540106401074010840109401104011140112401134011440115401164011740118401194012040121401224012340124401254012640127401284012940130401314013240133401344013540136401374013840139401404014140142401434014440145401464014740148401494015040151401524015340154401554015640157401584015940160401614016240163401644016540166401674016840169401704017140172401734017440175401764017740178401794018040181401824018340184401854018640187401884018940190401914019240193401944019540196401974019840199402004020140202402034020440205402064020740208402094021040211402124021340214402154021640217402184021940220402214022240223402244022540226402274022840229402304023140232402334023440235402364023740238402394024040241402424024340244402454024640247402484024940250402514025240253402544025540256402574025840259402604026140262402634026440265402664026740268402694027040271402724027340274402754027640277402784027940280402814028240283402844028540286402874028840289402904029140292402934029440295402964029740298402994030040301403024030340304403054030640307403084030940310403114031240313403144031540316403174031840319403204032140322403234032440325403264032740328403294033040331403324033340334403354033640337403384033940340403414034240343403444034540346403474034840349403504035140352403534035440355403564035740358403594036040361403624036340364403654036640367403684036940370403714037240373403744037540376403774037840379403804038140382403834038440385403864038740388403894039040391403924039340394403954039640397403984039940400404014040240403404044040540406404074040840409404104041140412404134041440415404164041740418404194042040421404224042340424404254042640427404284042940430404314043240433404344043540436404374043840439404404044140442404434044440445404464044740448404494045040451404524045340454404554045640457404584045940460404614046240463404644046540466404674046840469404704047140472404734047440475404764047740478404794048040481404824048340484404854048640487404884048940490404914049240493404944049540496404974049840499405004050140502405034050440505405064050740508405094051040511405124051340514405154051640517405184051940520405214052240523405244052540526405274052840529405304053140532405334053440535405364053740538405394054040541405424054340544405454054640547405484054940550405514055240553405544055540556405574055840559405604056140562405634056440565405664056740568405694057040571405724057340574405754057640577405784057940580405814058240583405844058540586405874058840589405904059140592405934059440595405964059740598405994060040601406024060340604406054060640607406084060940610406114061240613406144061540616406174061840619406204062140622406234062440625406264062740628406294063040631406324063340634406354063640637406384063940640406414064240643406444064540646406474064840649406504065140652406534065440655406564065740658406594066040661406624066340664406654066640667406684066940670406714067240673406744067540676406774067840679406804068140682406834068440685406864068740688406894069040691406924069340694406954069640697406984069940700407014070240703407044070540706407074070840709407104071140712407134071440715407164071740718407194072040721407224072340724407254072640727407284072940730407314073240733407344073540736407374073840739407404074140742407434074440745407464074740748407494075040751407524075340754407554075640757407584075940760407614076240763407644076540766407674076840769407704077140772407734077440775407764077740778407794078040781407824078340784407854078640787407884078940790407914079240793407944079540796407974079840799408004080140802408034080440805408064080740808408094081040811408124081340814408154081640817408184081940820408214082240823408244082540826408274082840829408304083140832408334083440835408364083740838408394084040841408424084340844408454084640847408484084940850408514085240853408544085540856408574085840859408604086140862408634086440865408664086740868408694087040871408724087340874408754087640877408784087940880408814088240883408844088540886408874088840889408904089140892408934089440895408964089740898408994090040901409024090340904409054090640907409084090940910409114091240913409144091540916409174091840919409204092140922409234092440925409264092740928409294093040931409324093340934409354093640937409384093940940409414094240943409444094540946409474094840949409504095140952409534095440955409564095740958409594096040961409624096340964409654096640967409684096940970409714097240973409744097540976409774097840979409804098140982409834098440985409864098740988409894099040991409924099340994409954099640997409984099941000410014100241003410044100541006410074100841009410104101141012410134101441015410164101741018410194102041021410224102341024410254102641027410284102941030410314103241033410344103541036410374103841039410404104141042410434104441045410464104741048410494105041051410524105341054410554105641057410584105941060410614106241063410644106541066410674106841069410704107141072410734107441075410764107741078410794108041081410824108341084410854108641087410884108941090410914109241093410944109541096410974109841099411004110141102411034110441105411064110741108411094111041111411124111341114411154111641117411184111941120411214112241123411244112541126411274112841129411304113141132411334113441135411364113741138411394114041141411424114341144411454114641147411484114941150411514115241153411544115541156411574115841159411604116141162411634116441165411664116741168411694117041171411724117341174411754117641177411784117941180411814118241183411844118541186411874118841189411904119141192411934119441195411964119741198411994120041201412024120341204412054120641207412084120941210412114121241213412144121541216412174121841219412204122141222412234122441225412264122741228412294123041231412324123341234412354123641237412384123941240412414124241243412444124541246412474124841249412504125141252412534125441255412564125741258412594126041261412624126341264412654126641267412684126941270412714127241273412744127541276412774127841279412804128141282412834128441285412864128741288412894129041291412924129341294412954129641297412984129941300413014130241303413044130541306413074130841309413104131141312413134131441315413164131741318413194132041321413224132341324413254132641327413284132941330413314133241333413344133541336413374133841339413404134141342413434134441345413464134741348413494135041351413524135341354413554135641357413584135941360413614136241363413644136541366413674136841369413704137141372413734137441375413764137741378413794138041381413824138341384413854138641387413884138941390413914139241393413944139541396413974139841399414004140141402414034140441405414064140741408414094141041411414124141341414414154141641417414184141941420414214142241423414244142541426414274142841429414304143141432414334143441435414364143741438414394144041441414424144341444414454144641447414484144941450414514145241453414544145541456414574145841459414604146141462414634146441465414664146741468414694147041471414724147341474414754147641477414784147941480414814148241483414844148541486414874148841489414904149141492414934149441495414964149741498414994150041501415024150341504415054150641507415084150941510415114151241513415144151541516415174151841519415204152141522415234152441525415264152741528415294153041531415324153341534415354153641537415384153941540415414154241543415444154541546415474154841549415504155141552415534155441555415564155741558415594156041561415624156341564415654156641567415684156941570415714157241573415744157541576415774157841579415804158141582415834158441585415864158741588415894159041591415924159341594415954159641597415984159941600416014160241603416044160541606416074160841609416104161141612416134161441615416164161741618416194162041621416224162341624416254162641627416284162941630416314163241633416344163541636416374163841639416404164141642416434164441645416464164741648416494165041651416524165341654416554165641657416584165941660416614166241663416644166541666416674166841669416704167141672416734167441675416764167741678416794168041681416824168341684416854168641687416884168941690416914169241693416944169541696416974169841699417004170141702417034170441705417064170741708417094171041711417124171341714417154171641717417184171941720417214172241723417244172541726417274172841729417304173141732417334173441735417364173741738417394174041741417424174341744417454174641747417484174941750417514175241753417544175541756417574175841759417604176141762417634176441765417664176741768417694177041771417724177341774417754177641777417784177941780417814178241783417844178541786417874178841789417904179141792417934179441795417964179741798417994180041801418024180341804418054180641807418084180941810418114181241813418144181541816418174181841819418204182141822418234182441825418264182741828418294183041831418324183341834418354183641837418384183941840418414184241843418444184541846418474184841849418504185141852418534185441855418564185741858418594186041861418624186341864418654186641867418684186941870418714187241873418744187541876418774187841879418804188141882418834188441885418864188741888418894189041891418924189341894418954189641897418984189941900419014190241903419044190541906419074190841909419104191141912419134191441915419164191741918419194192041921419224192341924419254192641927419284192941930419314193241933419344193541936419374193841939419404194141942419434194441945419464194741948419494195041951419524195341954419554195641957419584195941960419614196241963419644196541966419674196841969419704197141972419734197441975419764197741978419794198041981419824198341984419854198641987419884198941990419914199241993419944199541996419974199841999420004200142002420034200442005420064200742008420094201042011420124201342014420154201642017420184201942020420214202242023420244202542026420274202842029420304203142032420334203442035420364203742038420394204042041420424204342044420454204642047420484204942050420514205242053420544205542056420574205842059420604206142062420634206442065420664206742068420694207042071420724207342074420754207642077420784207942080420814208242083420844208542086420874208842089420904209142092420934209442095420964209742098420994210042101421024210342104421054210642107421084210942110421114211242113421144211542116421174211842119421204212142122421234212442125421264212742128421294213042131421324213342134421354213642137421384213942140421414214242143421444214542146421474214842149421504215142152421534215442155421564215742158421594216042161421624216342164421654216642167421684216942170421714217242173421744217542176421774217842179421804218142182421834218442185421864218742188421894219042191421924219342194421954219642197421984219942200422014220242203422044220542206422074220842209422104221142212422134221442215422164221742218422194222042221422224222342224422254222642227422284222942230422314223242233422344223542236422374223842239422404224142242422434224442245422464224742248422494225042251422524225342254422554225642257422584225942260422614226242263422644226542266422674226842269422704227142272422734227442275422764227742278422794228042281422824228342284422854228642287422884228942290422914229242293422944229542296422974229842299423004230142302423034230442305423064230742308423094231042311423124231342314423154231642317423184231942320423214232242323423244232542326423274232842329423304233142332423334233442335423364233742338423394234042341423424234342344423454234642347423484234942350423514235242353423544235542356423574235842359423604236142362423634236442365423664236742368423694237042371423724237342374423754237642377423784237942380423814238242383423844238542386423874238842389423904239142392423934239442395423964239742398423994240042401424024240342404424054240642407424084240942410424114241242413424144241542416424174241842419424204242142422424234242442425424264242742428424294243042431424324243342434424354243642437424384243942440424414244242443424444244542446424474244842449424504245142452424534245442455424564245742458424594246042461424624246342464424654246642467424684246942470424714247242473424744247542476424774247842479424804248142482424834248442485424864248742488424894249042491424924249342494424954249642497424984249942500425014250242503425044250542506425074250842509425104251142512425134251442515425164251742518425194252042521425224252342524425254252642527425284252942530425314253242533425344253542536425374253842539425404254142542425434254442545425464254742548425494255042551425524255342554425554255642557425584255942560425614256242563425644256542566425674256842569425704257142572425734257442575425764257742578425794258042581425824258342584425854258642587425884258942590425914259242593425944259542596425974259842599426004260142602426034260442605426064260742608426094261042611426124261342614426154261642617426184261942620426214262242623426244262542626426274262842629426304263142632426334263442635426364263742638426394264042641426424264342644426454264642647426484264942650426514265242653426544265542656426574265842659426604266142662426634266442665426664266742668426694267042671426724267342674426754267642677426784267942680426814268242683426844268542686426874268842689426904269142692426934269442695426964269742698426994270042701427024270342704427054270642707427084270942710427114271242713427144271542716427174271842719427204272142722427234272442725427264272742728427294273042731427324273342734427354273642737427384273942740427414274242743427444274542746427474274842749427504275142752427534275442755427564275742758427594276042761427624276342764427654276642767427684276942770427714277242773427744277542776427774277842779427804278142782427834278442785427864278742788427894279042791427924279342794427954279642797427984279942800428014280242803428044280542806428074280842809428104281142812428134281442815428164281742818428194282042821428224282342824428254282642827428284282942830428314283242833428344283542836428374283842839428404284142842428434284442845428464284742848428494285042851428524285342854428554285642857428584285942860428614286242863428644286542866428674286842869428704287142872428734287442875428764287742878428794288042881428824288342884428854288642887428884288942890428914289242893428944289542896428974289842899429004290142902429034290442905429064290742908429094291042911429124291342914429154291642917429184291942920429214292242923429244292542926429274292842929429304293142932429334293442935429364293742938429394294042941429424294342944429454294642947429484294942950429514295242953429544295542956429574295842959429604296142962429634296442965429664296742968429694297042971429724297342974429754297642977429784297942980429814298242983429844298542986429874298842989429904299142992429934299442995429964299742998429994300043001430024300343004430054300643007430084300943010430114301243013430144301543016430174301843019430204302143022430234302443025430264302743028430294303043031430324303343034430354303643037430384303943040430414304243043430444304543046430474304843049430504305143052430534305443055430564305743058430594306043061430624306343064430654306643067430684306943070430714307243073430744307543076430774307843079430804308143082430834308443085430864308743088430894309043091430924309343094430954309643097430984309943100431014310243103431044310543106431074310843109431104311143112431134311443115431164311743118431194312043121431224312343124431254312643127431284312943130431314313243133431344313543136431374313843139431404314143142431434314443145431464314743148431494315043151431524315343154431554315643157431584315943160431614316243163431644316543166431674316843169431704317143172431734317443175431764317743178431794318043181431824318343184431854318643187431884318943190431914319243193431944319543196431974319843199432004320143202432034320443205432064320743208432094321043211432124321343214432154321643217432184321943220432214322243223432244322543226432274322843229432304323143232432334323443235432364323743238432394324043241432424324343244432454324643247432484324943250432514325243253432544325543256432574325843259432604326143262432634326443265432664326743268432694327043271432724327343274432754327643277432784327943280432814328243283432844328543286432874328843289432904329143292432934329443295432964329743298432994330043301433024330343304433054330643307433084330943310433114331243313433144331543316433174331843319433204332143322433234332443325433264332743328433294333043331433324333343334433354333643337433384333943340433414334243343433444334543346433474334843349433504335143352433534335443355433564335743358433594336043361433624336343364433654336643367433684336943370433714337243373433744337543376433774337843379433804338143382433834338443385433864338743388433894339043391433924339343394433954339643397433984339943400434014340243403434044340543406434074340843409434104341143412434134341443415434164341743418434194342043421434224342343424434254342643427434284342943430434314343243433434344343543436434374343843439434404344143442434434344443445434464344743448434494345043451434524345343454434554345643457434584345943460434614346243463434644346543466434674346843469434704347143472434734347443475434764347743478434794348043481434824348343484434854348643487434884348943490434914349243493434944349543496434974349843499435004350143502435034350443505435064350743508435094351043511435124351343514435154351643517435184351943520435214352243523435244352543526435274352843529435304353143532435334353443535435364353743538435394354043541435424354343544435454354643547435484354943550435514355243553435544355543556435574355843559435604356143562435634356443565435664356743568435694357043571435724357343574435754357643577435784357943580435814358243583435844358543586435874358843589435904359143592435934359443595435964359743598435994360043601436024360343604436054360643607436084360943610436114361243613436144361543616436174361843619436204362143622436234362443625436264362743628436294363043631436324363343634436354363643637436384363943640436414364243643436444364543646436474364843649436504365143652436534365443655436564365743658436594366043661436624366343664436654366643667436684366943670436714367243673436744367543676436774367843679436804368143682436834368443685436864368743688436894369043691436924369343694436954369643697436984369943700437014370243703437044370543706437074370843709437104371143712437134371443715437164371743718437194372043721437224372343724437254372643727437284372943730437314373243733437344373543736437374373843739437404374143742437434374443745437464374743748437494375043751437524375343754437554375643757437584375943760437614376243763437644376543766437674376843769437704377143772437734377443775437764377743778437794378043781437824378343784437854378643787437884378943790437914379243793437944379543796437974379843799438004380143802438034380443805438064380743808438094381043811438124381343814438154381643817438184381943820438214382243823438244382543826438274382843829438304383143832438334383443835438364383743838438394384043841438424384343844438454384643847438484384943850438514385243853438544385543856438574385843859438604386143862438634386443865438664386743868438694387043871438724387343874438754387643877438784387943880438814388243883438844388543886438874388843889438904389143892438934389443895438964389743898438994390043901439024390343904439054390643907439084390943910439114391243913439144391543916439174391843919439204392143922439234392443925439264392743928439294393043931439324393343934439354393643937439384393943940439414394243943439444394543946439474394843949439504395143952439534395443955439564395743958439594396043961439624396343964439654396643967439684396943970439714397243973439744397543976439774397843979439804398143982439834398443985439864398743988439894399043991439924399343994439954399643997439984399944000440014400244003440044400544006440074400844009440104401144012440134401444015440164401744018440194402044021440224402344024440254402644027440284402944030440314403244033440344403544036440374403844039440404404144042440434404444045440464404744048440494405044051440524405344054440554405644057440584405944060440614406244063440644406544066440674406844069440704407144072440734407444075440764407744078440794408044081440824408344084440854408644087440884408944090440914409244093440944409544096440974409844099441004410144102441034410444105441064410744108441094411044111441124411344114441154411644117441184411944120441214412244123441244412544126441274412844129441304413144132441334413444135441364413744138441394414044141441424414344144441454414644147441484414944150441514415244153441544415544156441574415844159441604416144162441634416444165441664416744168441694417044171441724417344174441754417644177441784417944180441814418244183441844418544186441874418844189441904419144192441934419444195441964419744198441994420044201442024420344204442054420644207442084420944210442114421244213442144421544216442174421844219442204422144222442234422444225442264422744228442294423044231442324423344234442354423644237442384423944240442414424244243442444424544246442474424844249442504425144252442534425444255442564425744258442594426044261442624426344264442654426644267442684426944270442714427244273442744427544276442774427844279442804428144282442834428444285442864428744288442894429044291442924429344294442954429644297442984429944300443014430244303443044430544306443074430844309443104431144312443134431444315443164431744318443194432044321443224432344324443254432644327443284432944330443314433244333443344433544336443374433844339443404434144342443434434444345443464434744348443494435044351443524435344354443554435644357443584435944360443614436244363443644436544366443674436844369443704437144372443734437444375443764437744378443794438044381443824438344384443854438644387443884438944390443914439244393443944439544396443974439844399444004440144402444034440444405444064440744408444094441044411444124441344414444154441644417444184441944420444214442244423444244442544426444274442844429444304443144432444334443444435444364443744438444394444044441444424444344444444454444644447444484444944450444514445244453444544445544456444574445844459444604446144462444634446444465444664446744468444694447044471444724447344474444754447644477444784447944480444814448244483444844448544486444874448844489444904449144492444934449444495444964449744498444994450044501445024450344504445054450644507445084450944510445114451244513445144451544516445174451844519445204452144522445234452444525445264452744528445294453044531445324453344534445354453644537445384453944540445414454244543445444454544546445474454844549445504455144552445534455444555445564455744558445594456044561445624456344564445654456644567445684456944570445714457244573445744457544576445774457844579445804458144582445834458444585445864458744588445894459044591445924459344594445954459644597445984459944600446014460244603446044460544606446074460844609446104461144612446134461444615446164461744618446194462044621446224462344624446254462644627446284462944630446314463244633446344463544636446374463844639446404464144642446434464444645446464464744648446494465044651446524465344654446554465644657446584465944660446614466244663446644466544666446674466844669446704467144672446734467444675446764467744678446794468044681446824468344684446854468644687446884468944690446914469244693446944469544696446974469844699447004470144702447034470444705447064470744708447094471044711447124471344714447154471644717447184471944720447214472244723447244472544726447274472844729447304473144732447334473444735447364473744738447394474044741447424474344744447454474644747447484474944750447514475244753447544475544756447574475844759447604476144762447634476444765447664476744768447694477044771447724477344774447754477644777447784477944780447814478244783447844478544786447874478844789447904479144792447934479444795447964479744798447994480044801448024480344804448054480644807448084480944810448114481244813448144481544816448174481844819448204482144822448234482444825448264482744828448294483044831448324483344834448354483644837448384483944840448414484244843448444484544846448474484844849448504485144852448534485444855448564485744858448594486044861448624486344864448654486644867448684486944870448714487244873448744487544876448774487844879448804488144882448834488444885448864488744888448894489044891448924489344894448954489644897448984489944900449014490244903449044490544906449074490844909449104491144912449134491444915449164491744918449194492044921449224492344924449254492644927449284492944930449314493244933449344493544936449374493844939449404494144942449434494444945449464494744948449494495044951449524495344954449554495644957449584495944960449614496244963449644496544966449674496844969449704497144972449734497444975449764497744978449794498044981449824498344984449854498644987449884498944990449914499244993449944499544996449974499844999450004500145002450034500445005450064500745008450094501045011450124501345014450154501645017450184501945020450214502245023450244502545026450274502845029450304503145032450334503445035450364503745038450394504045041450424504345044450454504645047450484504945050450514505245053450544505545056450574505845059450604506145062450634506445065450664506745068450694507045071450724507345074450754507645077450784507945080450814508245083450844508545086450874508845089450904509145092450934509445095450964509745098450994510045101451024510345104451054510645107451084510945110451114511245113451144511545116451174511845119451204512145122451234512445125451264512745128451294513045131451324513345134451354513645137451384513945140451414514245143451444514545146451474514845149451504515145152451534515445155451564515745158451594516045161451624516345164451654516645167451684516945170451714517245173451744517545176451774517845179451804518145182451834518445185451864518745188451894519045191451924519345194451954519645197451984519945200452014520245203452044520545206452074520845209452104521145212452134521445215452164521745218452194522045221452224522345224452254522645227452284522945230452314523245233452344523545236452374523845239452404524145242452434524445245452464524745248452494525045251452524525345254452554525645257452584525945260452614526245263452644526545266452674526845269452704527145272452734527445275452764527745278452794528045281452824528345284452854528645287452884528945290452914529245293452944529545296452974529845299453004530145302453034530445305453064530745308453094531045311453124531345314453154531645317453184531945320453214532245323453244532545326453274532845329453304533145332453334533445335453364533745338453394534045341453424534345344453454534645347453484534945350453514535245353453544535545356453574535845359453604536145362453634536445365453664536745368453694537045371453724537345374453754537645377453784537945380453814538245383453844538545386453874538845389453904539145392453934539445395453964539745398453994540045401454024540345404454054540645407454084540945410454114541245413454144541545416454174541845419454204542145422454234542445425454264542745428454294543045431454324543345434454354543645437454384543945440454414544245443454444544545446454474544845449454504545145452454534545445455454564545745458454594546045461454624546345464454654546645467454684546945470454714547245473454744547545476454774547845479454804548145482454834548445485454864548745488454894549045491454924549345494454954549645497454984549945500455014550245503455044550545506455074550845509455104551145512455134551445515455164551745518455194552045521455224552345524455254552645527455284552945530455314553245533455344553545536455374553845539455404554145542455434554445545455464554745548455494555045551455524555345554455554555645557455584555945560455614556245563455644556545566455674556845569455704557145572455734557445575455764557745578455794558045581455824558345584455854558645587455884558945590455914559245593455944559545596455974559845599456004560145602456034560445605456064560745608456094561045611456124561345614456154561645617456184561945620456214562245623456244562545626456274562845629456304563145632456334563445635456364563745638456394564045641456424564345644456454564645647456484564945650456514565245653456544565545656456574565845659456604566145662456634566445665456664566745668456694567045671456724567345674456754567645677456784567945680456814568245683456844568545686456874568845689456904569145692456934569445695456964569745698456994570045701457024570345704457054570645707457084570945710457114571245713457144571545716457174571845719457204572145722457234572445725457264572745728457294573045731457324573345734457354573645737457384573945740457414574245743457444574545746457474574845749457504575145752457534575445755457564575745758457594576045761457624576345764457654576645767457684576945770457714577245773457744577545776457774577845779457804578145782457834578445785457864578745788457894579045791457924579345794457954579645797457984579945800458014580245803458044580545806458074580845809458104581145812458134581445815458164581745818458194582045821458224582345824458254582645827458284582945830458314583245833458344583545836458374583845839458404584145842458434584445845458464584745848458494585045851458524585345854458554585645857458584585945860458614586245863458644586545866458674586845869458704587145872458734587445875458764587745878458794588045881458824588345884458854588645887458884588945890458914589245893458944589545896458974589845899459004590145902459034590445905459064590745908459094591045911459124591345914459154591645917459184591945920459214592245923459244592545926459274592845929459304593145932459334593445935459364593745938459394594045941459424594345944459454594645947459484594945950459514595245953459544595545956459574595845959459604596145962459634596445965459664596745968459694597045971459724597345974459754597645977459784597945980459814598245983459844598545986459874598845989459904599145992459934599445995459964599745998459994600046001460024600346004460054600646007460084600946010460114601246013460144601546016460174601846019460204602146022460234602446025460264602746028460294603046031460324603346034460354603646037460384603946040460414604246043460444604546046460474604846049460504605146052460534605446055460564605746058460594606046061460624606346064460654606646067460684606946070460714607246073460744607546076460774607846079460804608146082460834608446085460864608746088460894609046091460924609346094460954609646097460984609946100461014610246103461044610546106461074610846109461104611146112461134611446115461164611746118461194612046121461224612346124461254612646127461284612946130461314613246133461344613546136461374613846139461404614146142461434614446145461464614746148461494615046151461524615346154461554615646157461584615946160461614616246163461644616546166461674616846169461704617146172461734617446175461764617746178461794618046181461824618346184461854618646187461884618946190461914619246193461944619546196461974619846199462004620146202462034620446205462064620746208462094621046211462124621346214462154621646217462184621946220462214622246223462244622546226462274622846229462304623146232462334623446235462364623746238462394624046241462424624346244462454624646247462484624946250462514625246253462544625546256462574625846259462604626146262462634626446265462664626746268462694627046271462724627346274462754627646277462784627946280462814628246283462844628546286462874628846289462904629146292462934629446295462964629746298462994630046301463024630346304463054630646307463084630946310463114631246313463144631546316463174631846319463204632146322463234632446325463264632746328463294633046331463324633346334463354633646337463384633946340463414634246343463444634546346463474634846349463504635146352463534635446355463564635746358463594636046361463624636346364463654636646367463684636946370463714637246373463744637546376463774637846379463804638146382463834638446385463864638746388463894639046391463924639346394463954639646397463984639946400464014640246403464044640546406464074640846409464104641146412464134641446415464164641746418464194642046421464224642346424464254642646427464284642946430464314643246433464344643546436464374643846439464404644146442464434644446445464464644746448464494645046451464524645346454464554645646457464584645946460464614646246463464644646546466464674646846469464704647146472464734647446475464764647746478464794648046481464824648346484464854648646487464884648946490464914649246493464944649546496464974649846499465004650146502465034650446505465064650746508465094651046511465124651346514465154651646517465184651946520465214652246523465244652546526465274652846529465304653146532465334653446535465364653746538465394654046541465424654346544465454654646547465484654946550465514655246553465544655546556465574655846559465604656146562465634656446565465664656746568465694657046571465724657346574465754657646577465784657946580465814658246583465844658546586465874658846589465904659146592465934659446595465964659746598465994660046601466024660346604466054660646607466084660946610466114661246613466144661546616466174661846619466204662146622466234662446625466264662746628466294663046631466324663346634466354663646637466384663946640466414664246643466444664546646466474664846649466504665146652466534665446655466564665746658466594666046661466624666346664466654666646667466684666946670466714667246673466744667546676466774667846679466804668146682466834668446685466864668746688466894669046691466924669346694466954669646697466984669946700467014670246703467044670546706467074670846709467104671146712467134671446715467164671746718467194672046721467224672346724467254672646727467284672946730467314673246733467344673546736467374673846739467404674146742467434674446745467464674746748467494675046751467524675346754467554675646757467584675946760467614676246763467644676546766467674676846769467704677146772467734677446775467764677746778467794678046781467824678346784467854678646787467884678946790467914679246793467944679546796467974679846799468004680146802468034680446805468064680746808468094681046811468124681346814468154681646817468184681946820468214682246823468244682546826468274682846829468304683146832468334683446835468364683746838468394684046841468424684346844468454684646847468484684946850468514685246853468544685546856468574685846859468604686146862468634686446865468664686746868468694687046871468724687346874468754687646877468784687946880468814688246883468844688546886468874688846889468904689146892468934689446895468964689746898468994690046901469024690346904469054690646907469084690946910469114691246913469144691546916469174691846919469204692146922469234692446925469264692746928469294693046931469324693346934469354693646937469384693946940469414694246943469444694546946469474694846949469504695146952469534695446955469564695746958469594696046961469624696346964469654696646967469684696946970469714697246973469744697546976469774697846979469804698146982469834698446985469864698746988469894699046991469924699346994469954699646997469984699947000470014700247003470044700547006470074700847009470104701147012470134701447015470164701747018470194702047021470224702347024470254702647027470284702947030470314703247033470344703547036470374703847039470404704147042470434704447045470464704747048470494705047051470524705347054470554705647057470584705947060470614706247063470644706547066470674706847069470704707147072470734707447075470764707747078470794708047081470824708347084470854708647087470884708947090470914709247093470944709547096470974709847099471004710147102471034710447105471064710747108471094711047111471124711347114471154711647117471184711947120471214712247123471244712547126471274712847129471304713147132471334713447135471364713747138471394714047141471424714347144471454714647147471484714947150471514715247153471544715547156471574715847159471604716147162471634716447165471664716747168471694717047171471724717347174471754717647177471784717947180471814718247183471844718547186471874718847189471904719147192471934719447195471964719747198471994720047201472024720347204472054720647207472084720947210472114721247213472144721547216472174721847219472204722147222472234722447225472264722747228472294723047231472324723347234472354723647237472384723947240472414724247243472444724547246472474724847249472504725147252472534725447255472564725747258472594726047261472624726347264472654726647267472684726947270472714727247273472744727547276472774727847279472804728147282472834728447285472864728747288472894729047291472924729347294472954729647297472984729947300473014730247303473044730547306473074730847309473104731147312473134731447315473164731747318473194732047321473224732347324473254732647327473284732947330473314733247333473344733547336473374733847339473404734147342473434734447345473464734747348473494735047351473524735347354473554735647357473584735947360473614736247363473644736547366473674736847369473704737147372473734737447375473764737747378473794738047381473824738347384473854738647387473884738947390473914739247393473944739547396473974739847399474004740147402474034740447405474064740747408474094741047411474124741347414474154741647417474184741947420474214742247423474244742547426474274742847429474304743147432474334743447435474364743747438474394744047441474424744347444474454744647447474484744947450474514745247453474544745547456474574745847459474604746147462474634746447465474664746747468474694747047471474724747347474474754747647477474784747947480474814748247483474844748547486474874748847489474904749147492474934749447495474964749747498474994750047501475024750347504475054750647507475084750947510475114751247513475144751547516475174751847519475204752147522475234752447525475264752747528475294753047531475324753347534475354753647537475384753947540475414754247543475444754547546475474754847549475504755147552475534755447555475564755747558475594756047561475624756347564475654756647567475684756947570475714757247573475744757547576475774757847579475804758147582475834758447585475864758747588475894759047591475924759347594475954759647597475984759947600476014760247603476044760547606476074760847609476104761147612476134761447615476164761747618476194762047621476224762347624476254762647627476284762947630476314763247633476344763547636476374763847639476404764147642476434764447645476464764747648476494765047651476524765347654476554765647657476584765947660476614766247663476644766547666476674766847669476704767147672476734767447675476764767747678476794768047681476824768347684476854768647687476884768947690476914769247693476944769547696476974769847699477004770147702477034770447705477064770747708477094771047711477124771347714477154771647717477184771947720477214772247723477244772547726477274772847729477304773147732477334773447735477364773747738477394774047741477424774347744477454774647747477484774947750477514775247753477544775547756477574775847759477604776147762477634776447765477664776747768477694777047771477724777347774477754777647777477784777947780477814778247783477844778547786477874778847789477904779147792477934779447795477964779747798477994780047801478024780347804478054780647807478084780947810478114781247813478144781547816478174781847819478204782147822478234782447825478264782747828478294783047831478324783347834478354783647837478384783947840478414784247843478444784547846478474784847849478504785147852478534785447855478564785747858478594786047861478624786347864478654786647867478684786947870478714787247873478744787547876478774787847879478804788147882478834788447885478864788747888478894789047891478924789347894478954789647897478984789947900479014790247903479044790547906479074790847909479104791147912479134791447915479164791747918479194792047921479224792347924479254792647927479284792947930479314793247933479344793547936479374793847939479404794147942479434794447945479464794747948479494795047951479524795347954479554795647957479584795947960479614796247963479644796547966479674796847969479704797147972479734797447975479764797747978479794798047981479824798347984479854798647987479884798947990479914799247993479944799547996479974799847999480004800148002480034800448005480064800748008480094801048011480124801348014480154801648017480184801948020480214802248023480244802548026480274802848029480304803148032480334803448035480364803748038480394804048041480424804348044480454804648047480484804948050480514805248053480544805548056480574805848059480604806148062480634806448065480664806748068480694807048071480724807348074480754807648077480784807948080480814808248083480844808548086480874808848089480904809148092480934809448095480964809748098480994810048101481024810348104481054810648107481084810948110481114811248113481144811548116481174811848119481204812148122481234812448125481264812748128481294813048131481324813348134481354813648137481384813948140481414814248143481444814548146481474814848149481504815148152481534815448155481564815748158481594816048161481624816348164481654816648167481684816948170481714817248173481744817548176481774817848179481804818148182481834818448185481864818748188481894819048191481924819348194481954819648197481984819948200482014820248203482044820548206482074820848209482104821148212482134821448215482164821748218482194822048221482224822348224482254822648227482284822948230482314823248233482344823548236482374823848239482404824148242482434824448245482464824748248482494825048251482524825348254482554825648257482584825948260482614826248263482644826548266482674826848269482704827148272482734827448275482764827748278482794828048281482824828348284482854828648287482884828948290482914829248293482944829548296482974829848299483004830148302483034830448305483064830748308483094831048311483124831348314483154831648317483184831948320483214832248323483244832548326483274832848329483304833148332483334833448335483364833748338483394834048341483424834348344483454834648347483484834948350483514835248353483544835548356483574835848359483604836148362483634836448365483664836748368483694837048371483724837348374483754837648377483784837948380483814838248383483844838548386483874838848389483904839148392483934839448395483964839748398483994840048401484024840348404484054840648407484084840948410484114841248413484144841548416484174841848419484204842148422484234842448425484264842748428484294843048431484324843348434484354843648437484384843948440484414844248443484444844548446484474844848449484504845148452484534845448455484564845748458484594846048461484624846348464484654846648467484684846948470484714847248473484744847548476484774847848479484804848148482484834848448485484864848748488484894849048491484924849348494484954849648497484984849948500485014850248503485044850548506485074850848509485104851148512485134851448515485164851748518485194852048521485224852348524485254852648527485284852948530485314853248533485344853548536485374853848539485404854148542485434854448545485464854748548485494855048551485524855348554485554855648557485584855948560485614856248563485644856548566485674856848569485704857148572485734857448575485764857748578485794858048581485824858348584485854858648587485884858948590485914859248593485944859548596485974859848599486004860148602486034860448605486064860748608486094861048611486124861348614486154861648617486184861948620486214862248623486244862548626486274862848629486304863148632486334863448635486364863748638486394864048641486424864348644486454864648647486484864948650486514865248653486544865548656486574865848659486604866148662486634866448665486664866748668486694867048671486724867348674486754867648677486784867948680486814868248683486844868548686486874868848689486904869148692486934869448695486964869748698486994870048701487024870348704487054870648707487084870948710487114871248713487144871548716487174871848719487204872148722487234872448725487264872748728487294873048731487324873348734487354873648737487384873948740487414874248743487444874548746487474874848749487504875148752487534875448755487564875748758487594876048761487624876348764487654876648767487684876948770487714877248773487744877548776487774877848779487804878148782487834878448785487864878748788487894879048791487924879348794487954879648797487984879948800488014880248803488044880548806488074880848809488104881148812488134881448815488164881748818488194882048821488224882348824488254882648827488284882948830488314883248833488344883548836488374883848839488404884148842488434884448845488464884748848488494885048851488524885348854488554885648857488584885948860488614886248863488644886548866488674886848869488704887148872488734887448875488764887748878488794888048881488824888348884488854888648887488884888948890488914889248893488944889548896488974889848899489004890148902489034890448905489064890748908489094891048911489124891348914489154891648917489184891948920489214892248923489244892548926489274892848929489304893148932489334893448935489364893748938489394894048941489424894348944489454894648947489484894948950489514895248953489544895548956489574895848959489604896148962489634896448965489664896748968489694897048971489724897348974489754897648977489784897948980489814898248983489844898548986489874898848989489904899148992489934899448995489964899748998489994900049001490024900349004490054900649007490084900949010490114901249013490144901549016490174901849019490204902149022490234902449025490264902749028490294903049031490324903349034490354903649037490384903949040490414904249043490444904549046490474904849049490504905149052490534905449055490564905749058490594906049061490624906349064490654906649067490684906949070490714907249073490744907549076490774907849079490804908149082490834908449085490864908749088490894909049091490924909349094490954909649097490984909949100491014910249103491044910549106491074910849109491104911149112491134911449115491164911749118491194912049121491224912349124491254912649127491284912949130491314913249133491344913549136491374913849139491404914149142491434914449145491464914749148491494915049151491524915349154491554915649157491584915949160491614916249163491644916549166491674916849169491704917149172491734917449175491764917749178491794918049181491824918349184491854918649187491884918949190491914919249193491944919549196491974919849199492004920149202492034920449205492064920749208492094921049211492124921349214492154921649217492184921949220492214922249223492244922549226492274922849229492304923149232492334923449235492364923749238492394924049241492424924349244492454924649247492484924949250492514925249253492544925549256492574925849259492604926149262492634926449265492664926749268492694927049271492724927349274492754927649277492784927949280492814928249283492844928549286492874928849289492904929149292492934929449295492964929749298492994930049301493024930349304493054930649307493084930949310493114931249313493144931549316493174931849319493204932149322493234932449325493264932749328493294933049331493324933349334493354933649337493384933949340493414934249343493444934549346493474934849349493504935149352493534935449355493564935749358493594936049361493624936349364493654936649367493684936949370493714937249373493744937549376493774937849379493804938149382493834938449385493864938749388493894939049391493924939349394493954939649397493984939949400494014940249403494044940549406494074940849409494104941149412494134941449415494164941749418494194942049421494224942349424494254942649427494284942949430494314943249433494344943549436494374943849439494404944149442494434944449445494464944749448494494945049451494524945349454494554945649457494584945949460494614946249463494644946549466494674946849469494704947149472494734947449475494764947749478494794948049481494824948349484494854948649487494884948949490494914949249493494944949549496494974949849499495004950149502495034950449505495064950749508495094951049511495124951349514495154951649517495184951949520495214952249523495244952549526495274952849529495304953149532495334953449535495364953749538495394954049541495424954349544495454954649547495484954949550495514955249553495544955549556495574955849559495604956149562495634956449565495664956749568495694957049571495724957349574495754957649577495784957949580495814958249583495844958549586495874958849589495904959149592495934959449595495964959749598495994960049601496024960349604496054960649607496084960949610496114961249613496144961549616496174961849619496204962149622496234962449625496264962749628496294963049631496324963349634496354963649637496384963949640496414964249643496444964549646496474964849649496504965149652496534965449655496564965749658496594966049661496624966349664496654966649667496684966949670496714967249673496744967549676496774967849679496804968149682496834968449685496864968749688496894969049691496924969349694496954969649697496984969949700497014970249703497044970549706497074970849709497104971149712497134971449715497164971749718497194972049721497224972349724497254972649727497284972949730497314973249733497344973549736497374973849739497404974149742497434974449745497464974749748497494975049751497524975349754497554975649757497584975949760497614976249763497644976549766497674976849769497704977149772497734977449775497764977749778497794978049781497824978349784497854978649787497884978949790497914979249793497944979549796497974979849799498004980149802498034980449805498064980749808498094981049811498124981349814498154981649817498184981949820498214982249823498244982549826498274982849829498304983149832498334983449835498364983749838498394984049841498424984349844498454984649847498484984949850498514985249853498544985549856498574985849859498604986149862498634986449865498664986749868498694987049871498724987349874498754987649877498784987949880498814988249883498844988549886498874988849889498904989149892498934989449895498964989749898498994990049901499024990349904499054990649907499084990949910499114991249913499144991549916499174991849919499204992149922499234992449925499264992749928499294993049931499324993349934499354993649937499384993949940499414994249943499444994549946499474994849949499504995149952499534995449955499564995749958499594996049961499624996349964499654996649967499684996949970499714997249973499744997549976499774997849979499804998149982499834998449985499864998749988499894999049991499924999349994499954999649997499984999950000500015000250003500045000550006500075000850009500105001150012500135001450015500165001750018500195002050021500225002350024500255002650027500285002950030500315003250033500345003550036500375003850039500405004150042500435004450045500465004750048500495005050051500525005350054500555005650057500585005950060500615006250063500645006550066500675006850069500705007150072500735007450075500765007750078500795008050081500825008350084500855008650087500885008950090500915009250093500945009550096500975009850099501005010150102501035010450105501065010750108501095011050111501125011350114501155011650117501185011950120501215012250123501245012550126501275012850129501305013150132501335013450135501365013750138501395014050141501425014350144501455014650147501485014950150501515015250153501545015550156501575015850159501605016150162501635016450165501665016750168501695017050171501725017350174501755017650177501785017950180501815018250183501845018550186501875018850189501905019150192501935019450195501965019750198501995020050201502025020350204502055020650207502085020950210502115021250213502145021550216502175021850219502205022150222502235022450225502265022750228502295023050231502325023350234502355023650237502385023950240502415024250243502445024550246502475024850249502505025150252502535025450255502565025750258502595026050261502625026350264502655026650267502685026950270502715027250273502745027550276502775027850279502805028150282502835028450285502865028750288502895029050291502925029350294502955029650297502985029950300503015030250303503045030550306503075030850309503105031150312503135031450315503165031750318503195032050321503225032350324503255032650327503285032950330503315033250333503345033550336503375033850339503405034150342503435034450345503465034750348503495035050351503525035350354503555035650357503585035950360503615036250363503645036550366503675036850369503705037150372503735037450375503765037750378503795038050381503825038350384503855038650387503885038950390503915039250393503945039550396503975039850399504005040150402504035040450405504065040750408504095041050411504125041350414504155041650417504185041950420504215042250423504245042550426504275042850429504305043150432504335043450435504365043750438504395044050441504425044350444504455044650447504485044950450504515045250453504545045550456504575045850459504605046150462504635046450465504665046750468504695047050471504725047350474504755047650477504785047950480504815048250483504845048550486504875048850489504905049150492504935049450495504965049750498504995050050501505025050350504505055050650507505085050950510505115051250513505145051550516505175051850519505205052150522505235052450525505265052750528505295053050531505325053350534505355053650537505385053950540505415054250543505445054550546505475054850549505505055150552505535055450555505565055750558505595056050561505625056350564505655056650567505685056950570505715057250573505745057550576505775057850579505805058150582505835058450585505865058750588505895059050591505925059350594505955059650597505985059950600506015060250603506045060550606506075060850609506105061150612506135061450615506165061750618506195062050621506225062350624506255062650627506285062950630506315063250633506345063550636506375063850639506405064150642506435064450645506465064750648506495065050651506525065350654506555065650657506585065950660506615066250663506645066550666506675066850669506705067150672506735067450675506765067750678506795068050681506825068350684506855068650687506885068950690506915069250693506945069550696506975069850699507005070150702507035070450705507065070750708507095071050711507125071350714507155071650717507185071950720507215072250723507245072550726507275072850729507305073150732507335073450735507365073750738507395074050741507425074350744507455074650747507485074950750507515075250753507545075550756507575075850759507605076150762507635076450765507665076750768507695077050771507725077350774507755077650777507785077950780507815078250783507845078550786507875078850789507905079150792507935079450795507965079750798507995080050801508025080350804508055080650807508085080950810508115081250813508145081550816508175081850819508205082150822508235082450825508265082750828508295083050831508325083350834508355083650837508385083950840508415084250843508445084550846508475084850849508505085150852508535085450855508565085750858508595086050861508625086350864508655086650867508685086950870508715087250873508745087550876508775087850879508805088150882508835088450885508865088750888508895089050891508925089350894508955089650897508985089950900509015090250903509045090550906509075090850909509105091150912509135091450915509165091750918509195092050921509225092350924509255092650927509285092950930509315093250933509345093550936509375093850939509405094150942509435094450945509465094750948509495095050951509525095350954509555095650957509585095950960509615096250963509645096550966509675096850969509705097150972509735097450975509765097750978509795098050981509825098350984509855098650987509885098950990509915099250993509945099550996509975099850999510005100151002510035100451005510065100751008510095101051011510125101351014510155101651017510185101951020510215102251023510245102551026510275102851029510305103151032510335103451035510365103751038510395104051041510425104351044510455104651047510485104951050510515105251053510545105551056510575105851059510605106151062510635106451065510665106751068510695107051071510725107351074510755107651077510785107951080510815108251083510845108551086510875108851089510905109151092510935109451095510965109751098510995110051101511025110351104511055110651107511085110951110511115111251113511145111551116511175111851119511205112151122511235112451125511265112751128511295113051131511325113351134511355113651137511385113951140511415114251143511445114551146511475114851149511505115151152511535115451155511565115751158511595116051161511625116351164511655116651167511685116951170511715117251173511745117551176511775117851179511805118151182511835118451185511865118751188511895119051191511925119351194511955119651197511985119951200512015120251203512045120551206512075120851209512105121151212512135121451215512165121751218512195122051221512225122351224512255122651227512285122951230512315123251233512345123551236512375123851239512405124151242512435124451245512465124751248512495125051251512525125351254512555125651257512585125951260512615126251263512645126551266512675126851269512705127151272512735127451275512765127751278512795128051281512825128351284512855128651287512885128951290512915129251293512945129551296512975129851299513005130151302513035130451305513065130751308513095131051311513125131351314513155131651317513185131951320513215132251323513245132551326513275132851329513305133151332513335133451335513365133751338513395134051341513425134351344513455134651347513485134951350513515135251353513545135551356513575135851359513605136151362513635136451365513665136751368513695137051371513725137351374513755137651377513785137951380513815138251383513845138551386513875138851389513905139151392513935139451395513965139751398513995140051401514025140351404514055140651407514085140951410514115141251413514145141551416514175141851419514205142151422514235142451425514265142751428514295143051431514325143351434514355143651437514385143951440514415144251443514445144551446514475144851449514505145151452514535145451455514565145751458514595146051461514625146351464514655146651467514685146951470514715147251473514745147551476514775147851479514805148151482514835148451485514865148751488514895149051491514925149351494514955149651497514985149951500515015150251503515045150551506515075150851509515105151151512515135151451515515165151751518515195152051521515225152351524515255152651527515285152951530515315153251533515345153551536515375153851539515405154151542515435154451545515465154751548515495155051551515525155351554515555155651557515585155951560515615156251563515645156551566515675156851569515705157151572515735157451575515765157751578515795158051581515825158351584515855158651587515885158951590515915159251593515945159551596515975159851599516005160151602516035160451605516065160751608516095161051611516125161351614516155161651617516185161951620516215162251623516245162551626516275162851629516305163151632516335163451635516365163751638516395164051641516425164351644516455164651647516485164951650516515165251653516545165551656516575165851659516605166151662516635166451665516665166751668516695167051671516725167351674516755167651677516785167951680516815168251683516845168551686516875168851689516905169151692516935169451695516965169751698516995170051701517025170351704517055170651707517085170951710517115171251713517145171551716517175171851719517205172151722517235172451725517265172751728517295173051731517325173351734517355173651737517385173951740517415174251743517445174551746517475174851749517505175151752517535175451755517565175751758517595176051761517625176351764517655176651767517685176951770517715177251773517745177551776517775177851779517805178151782517835178451785517865178751788517895179051791517925179351794517955179651797517985179951800518015180251803518045180551806518075180851809518105181151812518135181451815518165181751818518195182051821518225182351824518255182651827518285182951830518315183251833518345183551836518375183851839518405184151842518435184451845518465184751848518495185051851518525185351854518555185651857518585185951860518615186251863518645186551866518675186851869518705187151872518735187451875518765187751878518795188051881518825188351884518855188651887518885188951890518915189251893518945189551896518975189851899519005190151902519035190451905519065190751908519095191051911519125191351914519155191651917519185191951920519215192251923519245192551926519275192851929519305193151932519335193451935519365193751938519395194051941519425194351944519455194651947519485194951950519515195251953519545195551956519575195851959519605196151962519635196451965519665196751968519695197051971519725197351974519755197651977519785197951980519815198251983519845198551986519875198851989519905199151992519935199451995519965199751998519995200052001520025200352004520055200652007520085200952010520115201252013520145201552016520175201852019520205202152022520235202452025520265202752028520295203052031520325203352034520355203652037520385203952040520415204252043520445204552046520475204852049520505205152052520535205452055520565205752058520595206052061520625206352064520655206652067520685206952070520715207252073520745207552076520775207852079520805208152082520835208452085520865208752088520895209052091520925209352094520955209652097520985209952100521015210252103521045210552106521075210852109521105211152112521135211452115521165211752118521195212052121521225212352124521255212652127521285212952130521315213252133521345213552136521375213852139521405214152142521435214452145521465214752148521495215052151521525215352154521555215652157521585215952160521615216252163521645216552166521675216852169521705217152172521735217452175521765217752178521795218052181521825218352184521855218652187521885218952190521915219252193521945219552196521975219852199522005220152202522035220452205522065220752208522095221052211522125221352214522155221652217522185221952220522215222252223522245222552226522275222852229522305223152232522335223452235522365223752238522395224052241522425224352244522455224652247522485224952250522515225252253522545225552256522575225852259522605226152262522635226452265522665226752268522695227052271522725227352274522755227652277522785227952280522815228252283522845228552286522875228852289522905229152292522935229452295522965229752298522995230052301523025230352304523055230652307523085230952310523115231252313523145231552316523175231852319523205232152322523235232452325523265232752328523295233052331523325233352334523355233652337523385233952340523415234252343523445234552346523475234852349523505235152352523535235452355523565235752358523595236052361523625236352364523655236652367523685236952370523715237252373523745237552376523775237852379523805238152382523835238452385523865238752388523895239052391523925239352394523955239652397523985239952400524015240252403524045240552406524075240852409524105241152412524135241452415524165241752418524195242052421524225242352424524255242652427524285242952430524315243252433524345243552436524375243852439524405244152442524435244452445524465244752448524495245052451524525245352454524555245652457524585245952460524615246252463524645246552466524675246852469524705247152472524735247452475524765247752478524795248052481524825248352484524855248652487524885248952490524915249252493524945249552496524975249852499525005250152502525035250452505525065250752508525095251052511525125251352514525155251652517525185251952520525215252252523525245252552526525275252852529525305253152532525335253452535525365253752538525395254052541525425254352544525455254652547525485254952550525515255252553525545255552556525575255852559525605256152562525635256452565525665256752568525695257052571525725257352574525755257652577525785257952580525815258252583525845258552586525875258852589525905259152592525935259452595525965259752598525995260052601526025260352604526055260652607526085260952610526115261252613526145261552616526175261852619526205262152622526235262452625526265262752628526295263052631526325263352634526355263652637526385263952640526415264252643526445264552646526475264852649526505265152652526535265452655526565265752658526595266052661526625266352664526655266652667526685266952670526715267252673526745267552676526775267852679526805268152682526835268452685526865268752688526895269052691526925269352694526955269652697526985269952700527015270252703527045270552706527075270852709527105271152712527135271452715527165271752718527195272052721527225272352724527255272652727527285272952730527315273252733527345273552736527375273852739527405274152742527435274452745527465274752748527495275052751527525275352754527555275652757527585275952760527615276252763527645276552766527675276852769527705277152772527735277452775527765277752778527795278052781527825278352784527855278652787527885278952790527915279252793527945279552796527975279852799528005280152802528035280452805528065280752808528095281052811528125281352814528155281652817528185281952820528215282252823528245282552826528275282852829528305283152832528335283452835528365283752838528395284052841528425284352844528455284652847528485284952850528515285252853528545285552856528575285852859528605286152862528635286452865528665286752868528695287052871528725287352874528755287652877528785287952880528815288252883528845288552886528875288852889528905289152892528935289452895528965289752898528995290052901529025290352904529055290652907529085290952910529115291252913529145291552916529175291852919529205292152922529235292452925529265292752928529295293052931529325293352934529355293652937529385293952940529415294252943529445294552946529475294852949529505295152952529535295452955529565295752958529595296052961529625296352964529655296652967529685296952970529715297252973529745297552976529775297852979529805298152982529835298452985529865298752988529895299052991529925299352994529955299652997529985299953000530015300253003530045300553006530075300853009530105301153012530135301453015530165301753018530195302053021530225302353024530255302653027530285302953030530315303253033530345303553036530375303853039530405304153042530435304453045530465304753048530495305053051530525305353054530555305653057530585305953060530615306253063530645306553066530675306853069530705307153072530735307453075530765307753078530795308053081530825308353084530855308653087530885308953090530915309253093530945309553096530975309853099531005310153102531035310453105531065310753108531095311053111531125311353114531155311653117531185311953120531215312253123531245312553126531275312853129531305313153132531335313453135531365313753138531395314053141531425314353144531455314653147531485314953150531515315253153531545315553156531575315853159531605316153162531635316453165531665316753168531695317053171531725317353174531755317653177531785317953180531815318253183531845318553186531875318853189531905319153192531935319453195531965319753198531995320053201532025320353204532055320653207532085320953210532115321253213532145321553216532175321853219532205322153222532235322453225532265322753228532295323053231532325323353234532355323653237532385323953240532415324253243532445324553246532475324853249532505325153252532535325453255532565325753258532595326053261532625326353264532655326653267532685326953270532715327253273532745327553276532775327853279532805328153282532835328453285532865328753288532895329053291532925329353294532955329653297532985329953300533015330253303533045330553306533075330853309533105331153312533135331453315533165331753318533195332053321533225332353324533255332653327533285332953330533315333253333533345333553336533375333853339533405334153342533435334453345533465334753348533495335053351533525335353354533555335653357533585335953360533615336253363533645336553366533675336853369533705337153372533735337453375533765337753378533795338053381533825338353384533855338653387533885338953390533915339253393533945339553396533975339853399534005340153402534035340453405534065340753408534095341053411534125341353414534155341653417534185341953420534215342253423534245342553426534275342853429534305343153432534335343453435534365343753438534395344053441534425344353444534455344653447534485344953450534515345253453534545345553456534575345853459534605346153462534635346453465534665346753468534695347053471534725347353474534755347653477534785347953480534815348253483534845348553486534875348853489534905349153492534935349453495534965349753498534995350053501535025350353504535055350653507535085350953510535115351253513535145351553516535175351853519535205352153522535235352453525535265352753528535295353053531535325353353534535355353653537535385353953540535415354253543535445354553546535475354853549535505355153552535535355453555535565355753558535595356053561535625356353564535655356653567535685356953570535715357253573535745357553576535775357853579535805358153582535835358453585535865358753588535895359053591535925359353594535955359653597535985359953600536015360253603536045360553606536075360853609536105361153612536135361453615536165361753618536195362053621536225362353624536255362653627536285362953630536315363253633536345363553636536375363853639536405364153642536435364453645536465364753648536495365053651536525365353654536555365653657536585365953660536615366253663536645366553666536675366853669536705367153672536735367453675536765367753678536795368053681536825368353684536855368653687536885368953690536915369253693536945369553696536975369853699537005370153702537035370453705537065370753708537095371053711537125371353714537155371653717537185371953720537215372253723537245372553726537275372853729537305373153732537335373453735537365373753738537395374053741537425374353744537455374653747537485374953750537515375253753537545375553756537575375853759537605376153762537635376453765537665376753768537695377053771537725377353774537755377653777537785377953780537815378253783537845378553786537875378853789537905379153792537935379453795537965379753798537995380053801538025380353804538055380653807538085380953810538115381253813538145381553816538175381853819538205382153822538235382453825538265382753828538295383053831538325383353834538355383653837538385383953840538415384253843538445384553846538475384853849538505385153852538535385453855538565385753858538595386053861538625386353864538655386653867538685386953870538715387253873538745387553876538775387853879538805388153882538835388453885538865388753888538895389053891538925389353894538955389653897538985389953900539015390253903539045390553906539075390853909539105391153912539135391453915539165391753918539195392053921539225392353924539255392653927539285392953930539315393253933539345393553936539375393853939539405394153942539435394453945539465394753948539495395053951539525395353954539555395653957539585395953960539615396253963539645396553966539675396853969539705397153972539735397453975539765397753978539795398053981539825398353984539855398653987539885398953990539915399253993539945399553996539975399853999540005400154002540035400454005540065400754008540095401054011540125401354014540155401654017540185401954020540215402254023540245402554026540275402854029540305403154032540335403454035540365403754038540395404054041540425404354044540455404654047540485404954050540515405254053540545405554056540575405854059540605406154062540635406454065540665406754068540695407054071540725407354074540755407654077540785407954080540815408254083540845408554086540875408854089540905409154092540935409454095540965409754098540995410054101541025410354104541055410654107541085410954110541115411254113541145411554116541175411854119541205412154122541235412454125541265412754128541295413054131541325413354134541355413654137541385413954140541415414254143541445414554146541475414854149541505415154152541535415454155541565415754158541595416054161541625416354164541655416654167541685416954170541715417254173541745417554176541775417854179541805418154182541835418454185541865418754188541895419054191541925419354194541955419654197541985419954200542015420254203542045420554206542075420854209542105421154212542135421454215542165421754218542195422054221542225422354224542255422654227542285422954230542315423254233542345423554236542375423854239542405424154242542435424454245542465424754248542495425054251542525425354254542555425654257542585425954260542615426254263542645426554266542675426854269542705427154272542735427454275542765427754278542795428054281542825428354284542855428654287542885428954290542915429254293542945429554296542975429854299543005430154302543035430454305543065430754308543095431054311543125431354314543155431654317543185431954320543215432254323543245432554326543275432854329543305433154332543335433454335543365433754338543395434054341543425434354344543455434654347543485434954350543515435254353543545435554356543575435854359543605436154362543635436454365543665436754368543695437054371543725437354374543755437654377543785437954380543815438254383543845438554386543875438854389543905439154392543935439454395543965439754398543995440054401544025440354404544055440654407544085440954410544115441254413544145441554416544175441854419544205442154422544235442454425544265442754428544295443054431544325443354434544355443654437544385443954440544415444254443544445444554446544475444854449544505445154452544535445454455544565445754458544595446054461544625446354464544655446654467544685446954470544715447254473544745447554476544775447854479544805448154482544835448454485544865448754488544895449054491544925449354494544955449654497544985449954500545015450254503545045450554506545075450854509545105451154512545135451454515545165451754518545195452054521545225452354524545255452654527545285452954530545315453254533545345453554536545375453854539545405454154542545435454454545545465454754548545495455054551545525455354554545555455654557545585455954560545615456254563545645456554566545675456854569545705457154572545735457454575545765457754578545795458054581545825458354584545855458654587545885458954590545915459254593545945459554596545975459854599546005460154602546035460454605546065460754608546095461054611546125461354614546155461654617546185461954620546215462254623546245462554626546275462854629546305463154632546335463454635546365463754638546395464054641546425464354644546455464654647546485464954650546515465254653546545465554656546575465854659546605466154662546635466454665546665466754668546695467054671546725467354674546755467654677546785467954680546815468254683546845468554686546875468854689546905469154692546935469454695546965469754698546995470054701547025470354704547055470654707547085470954710547115471254713547145471554716547175471854719547205472154722547235472454725547265472754728547295473054731547325473354734547355473654737547385473954740547415474254743547445474554746547475474854749547505475154752547535475454755547565475754758547595476054761547625476354764547655476654767547685476954770547715477254773547745477554776547775477854779547805478154782547835478454785547865478754788547895479054791547925479354794547955479654797547985479954800548015480254803548045480554806548075480854809548105481154812548135481454815548165481754818548195482054821548225482354824548255482654827548285482954830548315483254833548345483554836548375483854839548405484154842548435484454845548465484754848548495485054851548525485354854548555485654857548585485954860548615486254863548645486554866548675486854869548705487154872548735487454875548765487754878548795488054881548825488354884548855488654887548885488954890548915489254893548945489554896548975489854899549005490154902549035490454905549065490754908549095491054911549125491354914549155491654917549185491954920549215492254923549245492554926549275492854929549305493154932549335493454935549365493754938549395494054941549425494354944549455494654947549485494954950549515495254953549545495554956549575495854959549605496154962549635496454965549665496754968549695497054971549725497354974549755497654977549785497954980549815498254983549845498554986549875498854989549905499154992549935499454995549965499754998549995500055001550025500355004550055500655007550085500955010550115501255013550145501555016550175501855019550205502155022550235502455025550265502755028550295503055031550325503355034550355503655037550385503955040550415504255043550445504555046550475504855049550505505155052550535505455055550565505755058550595506055061550625506355064550655506655067550685506955070550715507255073550745507555076550775507855079550805508155082550835508455085550865508755088550895509055091550925509355094550955509655097550985509955100551015510255103551045510555106551075510855109551105511155112551135511455115551165511755118551195512055121551225512355124551255512655127551285512955130551315513255133551345513555136551375513855139551405514155142551435514455145551465514755148551495515055151551525515355154551555515655157551585515955160551615516255163551645516555166551675516855169551705517155172551735517455175551765517755178551795518055181551825518355184551855518655187551885518955190551915519255193551945519555196551975519855199552005520155202552035520455205552065520755208552095521055211552125521355214552155521655217552185521955220552215522255223552245522555226552275522855229552305523155232552335523455235552365523755238552395524055241552425524355244552455524655247552485524955250552515525255253552545525555256552575525855259552605526155262552635526455265552665526755268552695527055271552725527355274552755527655277552785527955280552815528255283552845528555286552875528855289552905529155292552935529455295552965529755298552995530055301553025530355304553055530655307553085530955310553115531255313553145531555316553175531855319553205532155322553235532455325553265532755328553295533055331553325533355334553355533655337553385533955340553415534255343553445534555346553475534855349553505535155352553535535455355553565535755358553595536055361553625536355364553655536655367553685536955370553715537255373553745537555376553775537855379553805538155382553835538455385553865538755388553895539055391553925539355394553955539655397553985539955400554015540255403554045540555406554075540855409554105541155412554135541455415554165541755418554195542055421554225542355424554255542655427554285542955430554315543255433554345543555436554375543855439554405544155442554435544455445554465544755448554495545055451554525545355454554555545655457554585545955460554615546255463554645546555466554675546855469554705547155472554735547455475554765547755478554795548055481554825548355484554855548655487554885548955490554915549255493554945549555496554975549855499555005550155502555035550455505555065550755508555095551055511555125551355514555155551655517555185551955520555215552255523555245552555526555275552855529555305553155532555335553455535555365553755538555395554055541555425554355544555455554655547555485554955550555515555255553555545555555556555575555855559555605556155562555635556455565555665556755568555695557055571555725557355574555755557655577555785557955580555815558255583555845558555586555875558855589555905559155592555935559455595555965559755598555995560055601556025560355604556055560655607556085560955610556115561255613556145561555616556175561855619556205562155622556235562455625556265562755628556295563055631556325563355634556355563655637556385563955640556415564255643556445564555646556475564855649556505565155652556535565455655556565565755658556595566055661556625566355664556655566655667556685566955670556715567255673556745567555676556775567855679556805568155682556835568455685556865568755688556895569055691556925569355694556955569655697556985569955700557015570255703557045570555706557075570855709557105571155712557135571455715557165571755718557195572055721557225572355724557255572655727557285572955730557315573255733557345573555736557375573855739557405574155742557435574455745557465574755748557495575055751557525575355754557555575655757557585575955760557615576255763557645576555766557675576855769557705577155772557735577455775557765577755778557795578055781557825578355784557855578655787557885578955790557915579255793557945579555796557975579855799558005580155802558035580455805558065580755808558095581055811558125581355814558155581655817558185581955820558215582255823558245582555826558275582855829558305583155832558335583455835558365583755838558395584055841558425584355844558455584655847558485584955850558515585255853558545585555856558575585855859558605586155862558635586455865558665586755868558695587055871558725587355874558755587655877558785587955880558815588255883558845588555886558875588855889558905589155892558935589455895558965589755898558995590055901559025590355904559055590655907559085590955910559115591255913559145591555916559175591855919559205592155922559235592455925559265592755928559295593055931559325593355934559355593655937559385593955940559415594255943559445594555946559475594855949559505595155952559535595455955559565595755958559595596055961559625596355964559655596655967559685596955970559715597255973559745597555976559775597855979559805598155982559835598455985559865598755988559895599055991559925599355994559955599655997559985599956000560015600256003560045600556006560075600856009560105601156012560135601456015560165601756018560195602056021560225602356024560255602656027560285602956030560315603256033560345603556036560375603856039560405604156042560435604456045560465604756048560495605056051560525605356054560555605656057560585605956060560615606256063560645606556066560675606856069560705607156072560735607456075560765607756078560795608056081560825608356084560855608656087560885608956090560915609256093560945609556096560975609856099561005610156102561035610456105561065610756108561095611056111561125611356114561155611656117561185611956120561215612256123561245612556126561275612856129561305613156132561335613456135561365613756138561395614056141561425614356144561455614656147561485614956150561515615256153561545615556156561575615856159561605616156162561635616456165561665616756168561695617056171561725617356174561755617656177561785617956180561815618256183561845618556186561875618856189561905619156192561935619456195561965619756198561995620056201562025620356204562055620656207562085620956210562115621256213562145621556216562175621856219562205622156222562235622456225562265622756228562295623056231562325623356234562355623656237562385623956240562415624256243562445624556246562475624856249562505625156252562535625456255562565625756258562595626056261562625626356264562655626656267562685626956270562715627256273562745627556276562775627856279562805628156282562835628456285562865628756288562895629056291562925629356294562955629656297562985629956300563015630256303563045630556306563075630856309563105631156312563135631456315563165631756318563195632056321563225632356324563255632656327563285632956330563315633256333563345633556336563375633856339563405634156342563435634456345563465634756348563495635056351563525635356354563555635656357563585635956360563615636256363563645636556366563675636856369563705637156372563735637456375563765637756378563795638056381563825638356384563855638656387563885638956390563915639256393563945639556396563975639856399564005640156402564035640456405564065640756408564095641056411564125641356414564155641656417564185641956420564215642256423564245642556426564275642856429564305643156432564335643456435564365643756438564395644056441564425644356444564455644656447564485644956450564515645256453564545645556456564575645856459564605646156462564635646456465564665646756468564695647056471564725647356474564755647656477564785647956480564815648256483564845648556486564875648856489564905649156492564935649456495564965649756498564995650056501565025650356504565055650656507565085650956510565115651256513565145651556516565175651856519565205652156522565235652456525565265652756528565295653056531565325653356534565355653656537565385653956540565415654256543565445654556546565475654856549565505655156552565535655456555565565655756558565595656056561565625656356564565655656656567565685656956570565715657256573565745657556576565775657856579565805658156582565835658456585565865658756588565895659056591565925659356594565955659656597565985659956600566015660256603566045660556606566075660856609566105661156612566135661456615566165661756618566195662056621566225662356624566255662656627566285662956630566315663256633566345663556636566375663856639566405664156642566435664456645566465664756648566495665056651566525665356654566555665656657566585665956660566615666256663566645666556666566675666856669566705667156672566735667456675566765667756678566795668056681566825668356684566855668656687566885668956690566915669256693566945669556696566975669856699567005670156702567035670456705567065670756708567095671056711567125671356714567155671656717567185671956720567215672256723567245672556726567275672856729567305673156732567335673456735567365673756738567395674056741567425674356744567455674656747567485674956750567515675256753567545675556756567575675856759567605676156762567635676456765567665676756768567695677056771567725677356774567755677656777567785677956780567815678256783567845678556786567875678856789567905679156792567935679456795567965679756798567995680056801568025680356804568055680656807568085680956810568115681256813568145681556816568175681856819568205682156822568235682456825568265682756828568295683056831568325683356834568355683656837568385683956840568415684256843568445684556846568475684856849568505685156852568535685456855568565685756858568595686056861568625686356864568655686656867568685686956870568715687256873568745687556876568775687856879568805688156882568835688456885568865688756888568895689056891568925689356894568955689656897568985689956900569015690256903569045690556906569075690856909569105691156912569135691456915569165691756918569195692056921569225692356924569255692656927569285692956930569315693256933569345693556936569375693856939569405694156942569435694456945569465694756948569495695056951569525695356954569555695656957569585695956960569615696256963569645696556966569675696856969569705697156972569735697456975569765697756978569795698056981569825698356984569855698656987569885698956990569915699256993569945699556996569975699856999570005700157002570035700457005570065700757008570095701057011570125701357014570155701657017570185701957020570215702257023570245702557026570275702857029570305703157032570335703457035570365703757038570395704057041570425704357044570455704657047570485704957050570515705257053570545705557056570575705857059570605706157062570635706457065570665706757068570695707057071570725707357074570755707657077570785707957080570815708257083570845708557086570875708857089570905709157092570935709457095570965709757098570995710057101571025710357104571055710657107571085710957110571115711257113571145711557116571175711857119571205712157122571235712457125571265712757128571295713057131571325713357134571355713657137571385713957140571415714257143571445714557146571475714857149571505715157152571535715457155571565715757158571595716057161571625716357164571655716657167571685716957170571715717257173571745717557176571775717857179571805718157182571835718457185571865718757188571895719057191571925719357194571955719657197571985719957200572015720257203572045720557206572075720857209572105721157212572135721457215572165721757218572195722057221572225722357224572255722657227572285722957230572315723257233572345723557236572375723857239572405724157242572435724457245572465724757248572495725057251572525725357254572555725657257572585725957260572615726257263572645726557266572675726857269572705727157272572735727457275572765727757278572795728057281572825728357284572855728657287572885728957290572915729257293572945729557296572975729857299573005730157302573035730457305573065730757308573095731057311573125731357314573155731657317573185731957320573215732257323573245732557326573275732857329573305733157332573335733457335573365733757338573395734057341573425734357344573455734657347573485734957350573515735257353573545735557356573575735857359573605736157362573635736457365573665736757368573695737057371573725737357374573755737657377573785737957380573815738257383573845738557386573875738857389573905739157392573935739457395573965739757398573995740057401574025740357404574055740657407574085740957410574115741257413574145741557416574175741857419574205742157422574235742457425574265742757428574295743057431574325743357434574355743657437574385743957440574415744257443574445744557446574475744857449574505745157452574535745457455574565745757458574595746057461574625746357464574655746657467574685746957470574715747257473574745747557476574775747857479574805748157482574835748457485574865748757488574895749057491574925749357494574955749657497574985749957500575015750257503575045750557506575075750857509575105751157512575135751457515575165751757518575195752057521575225752357524575255752657527575285752957530575315753257533575345753557536575375753857539575405754157542575435754457545575465754757548575495755057551575525755357554575555755657557575585755957560575615756257563575645756557566575675756857569575705757157572575735757457575575765757757578575795758057581575825758357584575855758657587575885758957590575915759257593575945759557596575975759857599576005760157602576035760457605576065760757608576095761057611576125761357614576155761657617576185761957620576215762257623576245762557626576275762857629576305763157632576335763457635576365763757638576395764057641576425764357644576455764657647576485764957650576515765257653576545765557656576575765857659576605766157662576635766457665576665766757668576695767057671576725767357674576755767657677576785767957680576815768257683576845768557686576875768857689576905769157692576935769457695576965769757698576995770057701577025770357704577055770657707577085770957710577115771257713577145771557716577175771857719577205772157722577235772457725577265772757728577295773057731577325773357734577355773657737577385773957740577415774257743577445774557746577475774857749577505775157752577535775457755577565775757758577595776057761577625776357764577655776657767577685776957770577715777257773577745777557776577775777857779577805778157782577835778457785577865778757788577895779057791577925779357794577955779657797577985779957800578015780257803578045780557806578075780857809578105781157812578135781457815578165781757818578195782057821578225782357824578255782657827578285782957830578315783257833578345783557836578375783857839578405784157842578435784457845578465784757848578495785057851578525785357854578555785657857578585785957860578615786257863578645786557866578675786857869578705787157872578735787457875578765787757878578795788057881578825788357884578855788657887578885788957890578915789257893578945789557896578975789857899579005790157902579035790457905579065790757908579095791057911579125791357914579155791657917579185791957920579215792257923579245792557926579275792857929579305793157932579335793457935579365793757938579395794057941579425794357944579455794657947579485794957950579515795257953579545795557956579575795857959579605796157962579635796457965579665796757968579695797057971579725797357974579755797657977579785797957980579815798257983579845798557986579875798857989579905799157992579935799457995579965799757998579995800058001580025800358004580055800658007580085800958010580115801258013580145801558016580175801858019580205802158022580235802458025580265802758028580295803058031580325803358034580355803658037580385803958040580415804258043580445804558046580475804858049580505805158052580535805458055580565805758058580595806058061580625806358064580655806658067580685806958070580715807258073580745807558076580775807858079580805808158082580835808458085580865808758088580895809058091580925809358094580955809658097580985809958100581015810258103581045810558106581075810858109581105811158112581135811458115581165811758118581195812058121581225812358124581255812658127581285812958130581315813258133581345813558136581375813858139581405814158142581435814458145581465814758148581495815058151581525815358154581555815658157581585815958160581615816258163581645816558166581675816858169581705817158172581735817458175581765817758178581795818058181581825818358184581855818658187581885818958190581915819258193581945819558196581975819858199582005820158202582035820458205582065820758208582095821058211582125821358214582155821658217582185821958220582215822258223582245822558226582275822858229582305823158232582335823458235582365823758238582395824058241582425824358244582455824658247582485824958250582515825258253582545825558256582575825858259582605826158262582635826458265582665826758268582695827058271582725827358274582755827658277582785827958280582815828258283582845828558286582875828858289582905829158292582935829458295582965829758298582995830058301583025830358304583055830658307583085830958310583115831258313583145831558316583175831858319583205832158322583235832458325583265832758328583295833058331583325833358334583355833658337583385833958340583415834258343583445834558346583475834858349583505835158352583535835458355583565835758358583595836058361583625836358364583655836658367583685836958370583715837258373583745837558376583775837858379583805838158382583835838458385583865838758388583895839058391583925839358394583955839658397583985839958400584015840258403584045840558406584075840858409584105841158412584135841458415584165841758418584195842058421584225842358424584255842658427584285842958430584315843258433584345843558436584375843858439584405844158442584435844458445584465844758448584495845058451584525845358454584555845658457584585845958460584615846258463584645846558466584675846858469584705847158472584735847458475584765847758478584795848058481584825848358484584855848658487584885848958490584915849258493584945849558496584975849858499585005850158502585035850458505585065850758508585095851058511585125851358514585155851658517585185851958520585215852258523585245852558526585275852858529585305853158532585335853458535585365853758538585395854058541585425854358544585455854658547585485854958550585515855258553585545855558556585575855858559585605856158562585635856458565585665856758568585695857058571585725857358574585755857658577585785857958580585815858258583585845858558586585875858858589585905859158592585935859458595585965859758598585995860058601586025860358604586055860658607586085860958610586115861258613586145861558616586175861858619586205862158622586235862458625586265862758628586295863058631586325863358634586355863658637586385863958640586415864258643586445864558646586475864858649586505865158652586535865458655586565865758658586595866058661586625866358664586655866658667586685866958670586715867258673586745867558676586775867858679586805868158682586835868458685586865868758688586895869058691586925869358694586955869658697586985869958700587015870258703587045870558706587075870858709587105871158712587135871458715587165871758718587195872058721587225872358724587255872658727587285872958730587315873258733587345873558736587375873858739587405874158742587435874458745587465874758748587495875058751587525875358754587555875658757587585875958760587615876258763587645876558766587675876858769587705877158772587735877458775587765877758778587795878058781587825878358784587855878658787587885878958790587915879258793587945879558796587975879858799588005880158802588035880458805588065880758808588095881058811588125881358814588155881658817588185881958820588215882258823588245882558826588275882858829588305883158832588335883458835588365883758838588395884058841588425884358844588455884658847588485884958850588515885258853588545885558856588575885858859588605886158862588635886458865588665886758868588695887058871588725887358874588755887658877588785887958880588815888258883588845888558886588875888858889588905889158892588935889458895588965889758898588995890058901589025890358904589055890658907589085890958910589115891258913589145891558916589175891858919589205892158922589235892458925589265892758928589295893058931589325893358934589355893658937589385893958940589415894258943589445894558946589475894858949589505895158952589535895458955589565895758958589595896058961589625896358964589655896658967589685896958970589715897258973589745897558976589775897858979589805898158982589835898458985589865898758988589895899058991589925899358994589955899658997589985899959000590015900259003590045900559006590075900859009590105901159012590135901459015590165901759018590195902059021590225902359024590255902659027590285902959030590315903259033590345903559036590375903859039590405904159042590435904459045590465904759048590495905059051590525905359054590555905659057590585905959060590615906259063590645906559066590675906859069590705907159072590735907459075590765907759078590795908059081590825908359084590855908659087590885908959090590915909259093590945909559096590975909859099591005910159102591035910459105591065910759108591095911059111591125911359114591155911659117591185911959120591215912259123591245912559126591275912859129591305913159132591335913459135591365913759138591395914059141591425914359144591455914659147591485914959150591515915259153591545915559156591575915859159591605916159162591635916459165591665916759168591695917059171591725917359174591755917659177591785917959180591815918259183591845918559186591875918859189591905919159192591935919459195591965919759198591995920059201592025920359204592055920659207592085920959210592115921259213592145921559216592175921859219592205922159222592235922459225592265922759228592295923059231592325923359234592355923659237592385923959240592415924259243592445924559246592475924859249592505925159252592535925459255592565925759258592595926059261592625926359264592655926659267592685926959270592715927259273592745927559276592775927859279592805928159282592835928459285592865928759288592895929059291592925929359294592955929659297592985929959300593015930259303593045930559306593075930859309593105931159312593135931459315593165931759318593195932059321593225932359324593255932659327593285932959330593315933259333593345933559336593375933859339593405934159342593435934459345593465934759348593495935059351593525935359354593555935659357593585935959360593615936259363593645936559366593675936859369593705937159372593735937459375593765937759378593795938059381593825938359384593855938659387593885938959390593915939259393593945939559396593975939859399594005940159402594035940459405594065940759408594095941059411594125941359414594155941659417594185941959420594215942259423594245942559426594275942859429594305943159432594335943459435594365943759438594395944059441594425944359444594455944659447594485944959450594515945259453594545945559456594575945859459594605946159462594635946459465594665946759468594695947059471594725947359474594755947659477594785947959480594815948259483594845948559486594875948859489594905949159492594935949459495594965949759498594995950059501595025950359504595055950659507595085950959510595115951259513595145951559516595175951859519595205952159522595235952459525595265952759528595295953059531595325953359534595355953659537595385953959540595415954259543595445954559546595475954859549595505955159552595535955459555595565955759558595595956059561595625956359564595655956659567595685956959570595715957259573595745957559576595775957859579595805958159582595835958459585595865958759588595895959059591595925959359594595955959659597595985959959600596015960259603596045960559606596075960859609596105961159612596135961459615596165961759618596195962059621596225962359624596255962659627596285962959630596315963259633596345963559636596375963859639596405964159642596435964459645596465964759648596495965059651596525965359654596555965659657596585965959660596615966259663596645966559666596675966859669596705967159672596735967459675596765967759678596795968059681596825968359684596855968659687596885968959690596915969259693596945969559696596975969859699597005970159702597035970459705597065970759708597095971059711597125971359714597155971659717597185971959720597215972259723597245972559726597275972859729597305973159732597335973459735597365973759738597395974059741597425974359744597455974659747597485974959750597515975259753597545975559756597575975859759597605976159762597635976459765597665976759768597695977059771597725977359774597755977659777597785977959780597815978259783597845978559786597875978859789597905979159792597935979459795597965979759798597995980059801598025980359804598055980659807598085980959810598115981259813598145981559816598175981859819598205982159822598235982459825598265982759828598295983059831598325983359834598355983659837598385983959840598415984259843598445984559846598475984859849598505985159852598535985459855598565985759858598595986059861598625986359864598655986659867598685986959870598715987259873598745987559876598775987859879598805988159882598835988459885598865988759888598895989059891598925989359894598955989659897598985989959900599015990259903599045990559906599075990859909599105991159912599135991459915599165991759918599195992059921599225992359924599255992659927599285992959930599315993259933599345993559936599375993859939599405994159942599435994459945599465994759948599495995059951599525995359954599555995659957599585995959960599615996259963599645996559966599675996859969599705997159972599735997459975599765997759978599795998059981599825998359984599855998659987599885998959990599915999259993599945999559996599975999859999600006000160002600036000460005600066000760008600096001060011600126001360014600156001660017600186001960020600216002260023600246002560026600276002860029600306003160032600336003460035600366003760038600396004060041600426004360044600456004660047600486004960050600516005260053600546005560056600576005860059600606006160062600636006460065600666006760068600696007060071600726007360074600756007660077600786007960080600816008260083600846008560086600876008860089600906009160092600936009460095600966009760098600996010060101601026010360104601056010660107601086010960110601116011260113601146011560116601176011860119601206012160122601236012460125601266012760128601296013060131601326013360134601356013660137601386013960140601416014260143601446014560146601476014860149601506015160152601536015460155601566015760158601596016060161601626016360164601656016660167601686016960170601716017260173601746017560176601776017860179601806018160182601836018460185601866018760188601896019060191601926019360194601956019660197601986019960200602016020260203602046020560206602076020860209602106021160212602136021460215602166021760218602196022060221602226022360224602256022660227602286022960230602316023260233602346023560236602376023860239602406024160242602436024460245602466024760248602496025060251602526025360254602556025660257602586025960260602616026260263602646026560266602676026860269602706027160272602736027460275602766027760278602796028060281602826028360284602856028660287602886028960290602916029260293602946029560296602976029860299603006030160302603036030460305603066030760308603096031060311603126031360314603156031660317603186031960320603216032260323603246032560326603276032860329603306033160332603336033460335603366033760338603396034060341603426034360344603456034660347603486034960350603516035260353603546035560356603576035860359603606036160362603636036460365603666036760368603696037060371603726037360374603756037660377603786037960380603816038260383603846038560386603876038860389603906039160392603936039460395603966039760398603996040060401604026040360404604056040660407604086040960410604116041260413604146041560416604176041860419604206042160422604236042460425604266042760428604296043060431604326043360434604356043660437604386043960440604416044260443604446044560446604476044860449604506045160452604536045460455604566045760458604596046060461604626046360464604656046660467604686046960470604716047260473604746047560476604776047860479604806048160482604836048460485604866048760488604896049060491604926049360494604956049660497604986049960500605016050260503605046050560506605076050860509605106051160512605136051460515605166051760518605196052060521605226052360524605256052660527605286052960530605316053260533605346053560536605376053860539605406054160542605436054460545605466054760548605496055060551605526055360554605556055660557605586055960560605616056260563605646056560566605676056860569605706057160572605736057460575605766057760578605796058060581605826058360584605856058660587605886058960590605916059260593605946059560596605976059860599606006060160602606036060460605606066060760608606096061060611606126061360614606156061660617606186061960620606216062260623606246062560626606276062860629606306063160632606336063460635606366063760638606396064060641606426064360644606456064660647606486064960650606516065260653606546065560656606576065860659606606066160662606636066460665606666066760668606696067060671606726067360674606756067660677606786067960680606816068260683606846068560686606876068860689606906069160692606936069460695606966069760698606996070060701607026070360704607056070660707607086070960710607116071260713607146071560716607176071860719607206072160722607236072460725607266072760728607296073060731607326073360734607356073660737607386073960740607416074260743607446074560746607476074860749607506075160752607536075460755607566075760758607596076060761607626076360764607656076660767607686076960770607716077260773607746077560776607776077860779607806078160782607836078460785607866078760788607896079060791607926079360794607956079660797607986079960800608016080260803608046080560806608076080860809608106081160812608136081460815608166081760818608196082060821608226082360824608256082660827608286082960830608316083260833608346083560836608376083860839608406084160842608436084460845608466084760848608496085060851608526085360854608556085660857608586085960860608616086260863608646086560866608676086860869608706087160872608736087460875608766087760878608796088060881608826088360884608856088660887608886088960890608916089260893608946089560896608976089860899609006090160902609036090460905609066090760908609096091060911609126091360914609156091660917609186091960920609216092260923609246092560926609276092860929609306093160932609336093460935609366093760938609396094060941609426094360944609456094660947609486094960950609516095260953609546095560956609576095860959609606096160962609636096460965609666096760968609696097060971609726097360974609756097660977609786097960980609816098260983609846098560986609876098860989609906099160992609936099460995609966099760998609996100061001610026100361004610056100661007610086100961010610116101261013610146101561016610176101861019610206102161022610236102461025610266102761028610296103061031610326103361034610356103661037610386103961040610416104261043610446104561046610476104861049610506105161052610536105461055610566105761058610596106061061610626106361064610656106661067610686106961070610716107261073610746107561076610776107861079610806108161082610836108461085610866108761088610896109061091610926109361094610956109661097610986109961100611016110261103611046110561106611076110861109611106111161112611136111461115611166111761118611196112061121611226112361124611256112661127611286112961130611316113261133611346113561136611376113861139611406114161142611436114461145611466114761148611496115061151611526115361154611556115661157611586115961160611616116261163611646116561166611676116861169611706117161172611736117461175611766117761178611796118061181611826118361184611856118661187611886118961190611916119261193611946119561196611976119861199612006120161202612036120461205612066120761208612096121061211612126121361214612156121661217612186121961220612216122261223612246122561226612276122861229612306123161232612336123461235612366123761238612396124061241612426124361244612456124661247612486124961250612516125261253612546125561256612576125861259612606126161262612636126461265612666126761268612696127061271612726127361274612756127661277612786127961280612816128261283612846128561286612876128861289612906129161292612936129461295612966129761298612996130061301613026130361304613056130661307613086130961310613116131261313613146131561316613176131861319613206132161322613236132461325613266132761328613296133061331613326133361334613356133661337613386133961340613416134261343613446134561346613476134861349613506135161352613536135461355613566135761358613596136061361613626136361364613656136661367613686136961370613716137261373613746137561376613776137861379613806138161382613836138461385613866138761388613896139061391613926139361394613956139661397613986139961400614016140261403614046140561406614076140861409614106141161412614136141461415614166141761418614196142061421614226142361424614256142661427614286142961430614316143261433614346143561436614376143861439614406144161442614436144461445614466144761448614496145061451614526145361454614556145661457614586145961460614616146261463614646146561466614676146861469614706147161472614736147461475614766147761478614796148061481614826148361484614856148661487614886148961490614916149261493614946149561496614976149861499615006150161502615036150461505615066150761508615096151061511615126151361514615156151661517615186151961520615216152261523615246152561526615276152861529615306153161532615336153461535615366153761538615396154061541615426154361544615456154661547615486154961550615516155261553615546155561556615576155861559615606156161562615636156461565615666156761568615696157061571615726157361574615756157661577615786157961580615816158261583615846158561586615876158861589615906159161592615936159461595615966159761598615996160061601616026160361604616056160661607616086160961610616116161261613616146161561616616176161861619616206162161622616236162461625616266162761628616296163061631616326163361634616356163661637616386163961640616416164261643616446164561646616476164861649616506165161652616536165461655616566165761658616596166061661616626166361664616656166661667616686166961670616716167261673616746167561676616776167861679616806168161682616836168461685616866168761688616896169061691616926169361694616956169661697616986169961700617016170261703617046170561706617076170861709617106171161712617136171461715617166171761718617196172061721617226172361724617256172661727617286172961730617316173261733617346173561736617376173861739617406174161742617436174461745617466174761748617496175061751617526175361754617556175661757617586175961760617616176261763617646176561766617676176861769617706177161772617736177461775617766177761778617796178061781617826178361784617856178661787617886178961790617916179261793617946179561796617976179861799618006180161802618036180461805618066180761808618096181061811618126181361814618156181661817618186181961820618216182261823618246182561826618276182861829618306183161832618336183461835618366183761838618396184061841618426184361844618456184661847618486184961850618516185261853618546185561856618576185861859618606186161862618636186461865618666186761868618696187061871618726187361874618756187661877618786187961880618816188261883618846188561886618876188861889618906189161892618936189461895618966189761898618996190061901619026190361904619056190661907619086190961910619116191261913619146191561916619176191861919619206192161922619236192461925619266192761928619296193061931619326193361934619356193661937619386193961940619416194261943619446194561946619476194861949619506195161952619536195461955619566195761958619596196061961619626196361964619656196661967619686196961970619716197261973619746197561976619776197861979619806198161982619836198461985619866198761988619896199061991619926199361994619956199661997619986199962000620016200262003620046200562006620076200862009620106201162012620136201462015620166201762018620196202062021620226202362024620256202662027620286202962030620316203262033620346203562036620376203862039620406204162042620436204462045620466204762048620496205062051620526205362054620556205662057620586205962060620616206262063620646206562066620676206862069620706207162072620736207462075620766207762078620796208062081620826208362084620856208662087620886208962090620916209262093620946209562096620976209862099621006210162102621036210462105621066210762108621096211062111621126211362114621156211662117621186211962120621216212262123621246212562126621276212862129621306213162132621336213462135621366213762138621396214062141621426214362144621456214662147621486214962150621516215262153621546215562156621576215862159621606216162162621636216462165621666216762168621696217062171621726217362174621756217662177621786217962180621816218262183621846218562186621876218862189621906219162192621936219462195621966219762198621996220062201622026220362204622056220662207622086220962210622116221262213622146221562216622176221862219622206222162222622236222462225622266222762228622296223062231622326223362234622356223662237622386223962240622416224262243622446224562246622476224862249622506225162252622536225462255622566225762258622596226062261622626226362264622656226662267622686226962270622716227262273622746227562276622776227862279622806228162282622836228462285622866228762288622896229062291622926229362294622956229662297622986229962300623016230262303623046230562306623076230862309623106231162312623136231462315623166231762318623196232062321623226232362324623256232662327623286232962330623316233262333623346233562336623376233862339623406234162342623436234462345623466234762348623496235062351623526235362354623556235662357623586235962360623616236262363623646236562366623676236862369623706237162372623736237462375623766237762378623796238062381623826238362384623856238662387623886238962390623916239262393623946239562396623976239862399624006240162402624036240462405624066240762408624096241062411624126241362414624156241662417624186241962420624216242262423624246242562426624276242862429624306243162432624336243462435624366243762438624396244062441624426244362444624456244662447624486244962450624516245262453624546245562456624576245862459624606246162462624636246462465624666246762468624696247062471624726247362474624756247662477624786247962480624816248262483624846248562486624876248862489624906249162492624936249462495624966249762498624996250062501625026250362504625056250662507625086250962510625116251262513625146251562516625176251862519625206252162522625236252462525625266252762528625296253062531625326253362534625356253662537625386253962540625416254262543625446254562546625476254862549625506255162552625536255462555625566255762558625596256062561625626256362564625656256662567625686256962570625716257262573625746257562576625776257862579625806258162582625836258462585625866258762588625896259062591625926259362594625956259662597625986259962600626016260262603626046260562606626076260862609626106261162612626136261462615626166261762618626196262062621626226262362624626256262662627626286262962630626316263262633626346263562636626376263862639626406264162642626436264462645626466264762648626496265062651626526265362654626556265662657626586265962660626616266262663626646266562666626676266862669626706267162672626736267462675626766267762678626796268062681626826268362684626856268662687626886268962690626916269262693626946269562696626976269862699627006270162702627036270462705627066270762708627096271062711627126271362714627156271662717627186271962720627216272262723627246272562726627276272862729627306273162732627336273462735627366273762738627396274062741627426274362744627456274662747627486274962750627516275262753627546275562756627576275862759627606276162762627636276462765627666276762768627696277062771627726277362774627756277662777627786277962780627816278262783627846278562786627876278862789627906279162792627936279462795627966279762798627996280062801628026280362804628056280662807628086280962810628116281262813628146281562816628176281862819628206282162822628236282462825628266282762828628296283062831628326283362834628356283662837628386283962840628416284262843628446284562846628476284862849628506285162852628536285462855628566285762858628596286062861628626286362864628656286662867628686286962870628716287262873628746287562876628776287862879628806288162882628836288462885628866288762888628896289062891628926289362894628956289662897628986289962900629016290262903629046290562906629076290862909629106291162912629136291462915629166291762918629196292062921629226292362924629256292662927629286292962930629316293262933629346293562936629376293862939629406294162942629436294462945629466294762948629496295062951629526295362954629556295662957629586295962960629616296262963629646296562966629676296862969629706297162972629736297462975629766297762978629796298062981629826298362984629856298662987629886298962990629916299262993629946299562996629976299862999630006300163002630036300463005630066300763008630096301063011630126301363014630156301663017630186301963020630216302263023630246302563026630276302863029630306303163032630336303463035630366303763038630396304063041630426304363044630456304663047630486304963050630516305263053630546305563056630576305863059630606306163062630636306463065630666306763068630696307063071630726307363074630756307663077630786307963080630816308263083630846308563086630876308863089630906309163092630936309463095630966309763098630996310063101631026310363104631056310663107631086310963110631116311263113631146311563116631176311863119631206312163122631236312463125631266312763128631296313063131631326313363134631356313663137631386313963140631416314263143631446314563146631476314863149631506315163152631536315463155631566315763158631596316063161631626316363164631656316663167631686316963170631716317263173631746317563176631776317863179631806318163182631836318463185631866318763188631896319063191631926319363194631956319663197631986319963200632016320263203632046320563206632076320863209632106321163212632136321463215632166321763218632196322063221632226322363224632256322663227632286322963230632316323263233632346323563236632376323863239632406324163242632436324463245632466324763248632496325063251632526325363254632556325663257632586325963260632616326263263632646326563266632676326863269632706327163272632736327463275632766327763278632796328063281632826328363284632856328663287632886328963290632916329263293632946329563296632976329863299633006330163302633036330463305633066330763308633096331063311633126331363314633156331663317633186331963320633216332263323633246332563326633276332863329633306333163332633336333463335633366333763338633396334063341633426334363344633456334663347633486334963350633516335263353633546335563356633576335863359633606336163362633636336463365633666336763368633696337063371633726337363374633756337663377633786337963380633816338263383633846338563386633876338863389633906339163392633936339463395633966339763398633996340063401634026340363404634056340663407634086340963410634116341263413634146341563416634176341863419634206342163422634236342463425634266342763428634296343063431634326343363434634356343663437634386343963440634416344263443634446344563446634476344863449634506345163452634536345463455634566345763458634596346063461634626346363464634656346663467634686346963470634716347263473634746347563476634776347863479634806348163482634836348463485634866348763488634896349063491634926349363494634956349663497634986349963500635016350263503635046350563506635076350863509635106351163512635136351463515635166351763518635196352063521635226352363524635256352663527635286352963530635316353263533635346353563536635376353863539635406354163542635436354463545635466354763548635496355063551635526355363554635556355663557635586355963560635616356263563635646356563566635676356863569635706357163572635736357463575635766357763578635796358063581635826358363584635856358663587635886358963590635916359263593635946359563596635976359863599636006360163602636036360463605636066360763608636096361063611636126361363614636156361663617636186361963620636216362263623636246362563626636276362863629636306363163632636336363463635636366363763638636396364063641636426364363644636456364663647636486364963650636516365263653636546365563656636576365863659636606366163662636636366463665636666366763668636696367063671636726367363674636756367663677636786367963680636816368263683636846368563686636876368863689636906369163692636936369463695636966369763698636996370063701637026370363704637056370663707637086370963710637116371263713637146371563716637176371863719637206372163722637236372463725637266372763728637296373063731637326373363734637356373663737637386373963740637416374263743637446374563746637476374863749637506375163752637536375463755637566375763758637596376063761637626376363764637656376663767637686376963770637716377263773637746377563776637776377863779637806378163782637836378463785637866378763788637896379063791637926379363794637956379663797637986379963800638016380263803638046380563806638076380863809638106381163812638136381463815638166381763818638196382063821638226382363824638256382663827638286382963830638316383263833638346383563836638376383863839638406384163842638436384463845638466384763848638496385063851638526385363854638556385663857638586385963860638616386263863638646386563866638676386863869638706387163872638736387463875638766387763878638796388063881638826388363884638856388663887638886388963890638916389263893638946389563896638976389863899639006390163902639036390463905639066390763908639096391063911639126391363914639156391663917639186391963920639216392263923639246392563926639276392863929639306393163932639336393463935639366393763938639396394063941639426394363944639456394663947639486394963950639516395263953639546395563956639576395863959639606396163962639636396463965639666396763968639696397063971639726397363974639756397663977639786397963980639816398263983639846398563986639876398863989639906399163992639936399463995639966399763998639996400064001640026400364004640056400664007640086400964010640116401264013640146401564016640176401864019640206402164022640236402464025640266402764028640296403064031640326403364034640356403664037640386403964040640416404264043640446404564046640476404864049640506405164052640536405464055640566405764058640596406064061640626406364064640656406664067640686406964070640716407264073640746407564076640776407864079640806408164082640836408464085640866408764088640896409064091640926409364094640956409664097640986409964100641016410264103641046410564106641076410864109641106411164112641136411464115641166411764118641196412064121641226412364124641256412664127641286412964130641316413264133641346413564136641376413864139641406414164142641436414464145641466414764148641496415064151641526415364154641556415664157641586415964160641616416264163641646416564166641676416864169641706417164172641736417464175641766417764178641796418064181641826418364184641856418664187641886418964190641916419264193641946419564196641976419864199642006420164202642036420464205642066420764208642096421064211642126421364214642156421664217642186421964220642216422264223642246422564226642276422864229642306423164232642336423464235642366423764238642396424064241642426424364244642456424664247642486424964250642516425264253642546425564256642576425864259642606426164262642636426464265642666426764268642696427064271642726427364274642756427664277642786427964280642816428264283642846428564286642876428864289642906429164292642936429464295642966429764298642996430064301643026430364304643056430664307643086430964310643116431264313643146431564316643176431864319643206432164322643236432464325643266432764328643296433064331643326433364334643356433664337643386433964340643416434264343643446434564346643476434864349643506435164352643536435464355643566435764358643596436064361643626436364364643656436664367643686436964370643716437264373643746437564376643776437864379643806438164382643836438464385643866438764388643896439064391643926439364394643956439664397643986439964400644016440264403644046440564406644076440864409644106441164412644136441464415644166441764418644196442064421644226442364424644256442664427644286442964430644316443264433644346443564436644376443864439644406444164442644436444464445644466444764448644496445064451644526445364454644556445664457644586445964460644616446264463644646446564466644676446864469644706447164472644736447464475644766447764478644796448064481644826448364484644856448664487644886448964490644916449264493644946449564496644976449864499645006450164502645036450464505645066450764508645096451064511645126451364514645156451664517645186451964520645216452264523645246452564526645276452864529645306453164532645336453464535645366453764538645396454064541645426454364544645456454664547645486454964550645516455264553645546455564556645576455864559645606456164562645636456464565645666456764568645696457064571645726457364574645756457664577645786457964580645816458264583645846458564586645876458864589645906459164592645936459464595645966459764598645996460064601646026460364604646056460664607646086460964610646116461264613646146461564616646176461864619646206462164622646236462464625646266462764628646296463064631646326463364634646356463664637646386463964640646416464264643646446464564646646476464864649646506465164652646536465464655646566465764658646596466064661646626466364664646656466664667646686466964670646716467264673646746467564676646776467864679646806468164682646836468464685646866468764688646896469064691646926469364694646956469664697646986469964700647016470264703647046470564706647076470864709647106471164712647136471464715647166471764718647196472064721647226472364724647256472664727647286472964730647316473264733647346473564736647376473864739647406474164742647436474464745647466474764748647496475064751647526475364754647556475664757647586475964760647616476264763647646476564766647676476864769647706477164772647736477464775647766477764778647796478064781647826478364784647856478664787647886478964790647916479264793647946479564796647976479864799648006480164802648036480464805648066480764808648096481064811648126481364814648156481664817648186481964820648216482264823648246482564826648276482864829648306483164832648336483464835648366483764838648396484064841648426484364844648456484664847648486484964850648516485264853648546485564856648576485864859648606486164862648636486464865648666486764868648696487064871648726487364874648756487664877648786487964880648816488264883648846488564886648876488864889648906489164892648936489464895648966489764898648996490064901649026490364904649056490664907649086490964910649116491264913649146491564916649176491864919649206492164922649236492464925649266492764928649296493064931649326493364934649356493664937649386493964940649416494264943649446494564946649476494864949649506495164952649536495464955649566495764958649596496064961649626496364964649656496664967649686496964970649716497264973649746497564976649776497864979649806498164982649836498464985649866498764988649896499064991649926499364994649956499664997649986499965000650016500265003650046500565006650076500865009650106501165012650136501465015650166501765018650196502065021650226502365024650256502665027650286502965030650316503265033650346503565036650376503865039650406504165042650436504465045650466504765048650496505065051650526505365054650556505665057650586505965060650616506265063650646506565066650676506865069650706507165072650736507465075650766507765078650796508065081650826508365084650856508665087650886508965090650916509265093650946509565096650976509865099651006510165102651036510465105651066510765108651096511065111651126511365114651156511665117651186511965120651216512265123651246512565126651276512865129651306513165132651336513465135651366513765138651396514065141651426514365144651456514665147651486514965150651516515265153651546515565156651576515865159651606516165162651636516465165651666516765168651696517065171651726517365174651756517665177651786517965180651816518265183651846518565186651876518865189651906519165192651936519465195651966519765198651996520065201652026520365204652056520665207652086520965210652116521265213652146521565216652176521865219652206522165222652236522465225652266522765228652296523065231652326523365234652356523665237652386523965240652416524265243652446524565246652476524865249652506525165252652536525465255652566525765258652596526065261652626526365264652656526665267652686526965270652716527265273652746527565276652776527865279652806528165282652836528465285652866528765288652896529065291652926529365294652956529665297652986529965300653016530265303653046530565306653076530865309653106531165312653136531465315653166531765318653196532065321653226532365324653256532665327653286532965330653316533265333653346533565336653376533865339653406534165342653436534465345653466534765348653496535065351653526535365354653556535665357653586535965360653616536265363653646536565366653676536865369653706537165372653736537465375653766537765378653796538065381653826538365384653856538665387653886538965390653916539265393653946539565396653976539865399654006540165402654036540465405654066540765408654096541065411654126541365414654156541665417654186541965420654216542265423654246542565426654276542865429654306543165432654336543465435654366543765438654396544065441654426544365444654456544665447654486544965450654516545265453654546545565456654576545865459654606546165462654636546465465654666546765468654696547065471654726547365474654756547665477654786547965480654816548265483654846548565486654876548865489654906549165492654936549465495654966549765498654996550065501655026550365504655056550665507655086550965510655116551265513655146551565516655176551865519655206552165522655236552465525655266552765528655296553065531655326553365534655356553665537655386553965540655416554265543655446554565546655476554865549655506555165552655536555465555655566555765558655596556065561655626556365564655656556665567655686556965570655716557265573655746557565576655776557865579655806558165582655836558465585655866558765588655896559065591655926559365594655956559665597655986559965600656016560265603656046560565606656076560865609656106561165612656136561465615656166561765618656196562065621656226562365624656256562665627656286562965630656316563265633656346563565636656376563865639656406564165642656436564465645656466564765648656496565065651656526565365654656556565665657656586565965660656616566265663656646566565666656676566865669656706567165672656736567465675656766567765678656796568065681656826568365684656856568665687656886568965690656916569265693656946569565696656976569865699657006570165702657036570465705657066570765708657096571065711657126571365714657156571665717657186571965720657216572265723657246572565726657276572865729657306573165732657336573465735657366573765738657396574065741657426574365744657456574665747657486574965750657516575265753657546575565756657576575865759657606576165762657636576465765657666576765768657696577065771657726577365774657756577665777657786577965780657816578265783657846578565786657876578865789657906579165792657936579465795657966579765798657996580065801658026580365804658056580665807658086580965810658116581265813658146581565816658176581865819658206582165822658236582465825658266582765828658296583065831658326583365834658356583665837658386583965840658416584265843658446584565846658476584865849658506585165852658536585465855658566585765858658596586065861658626586365864658656586665867658686586965870658716587265873658746587565876658776587865879658806588165882658836588465885658866588765888658896589065891658926589365894658956589665897658986589965900659016590265903659046590565906659076590865909659106591165912659136591465915659166591765918659196592065921659226592365924659256592665927659286592965930659316593265933659346593565936659376593865939659406594165942659436594465945659466594765948659496595065951659526595365954659556595665957659586595965960659616596265963659646596565966659676596865969659706597165972659736597465975659766597765978659796598065981659826598365984659856598665987659886598965990659916599265993659946599565996659976599865999660006600166002660036600466005660066600766008660096601066011660126601366014660156601666017660186601966020660216602266023660246602566026660276602866029660306603166032660336603466035660366603766038660396604066041660426604366044660456604666047660486604966050660516605266053660546605566056660576605866059660606606166062660636606466065660666606766068660696607066071660726607366074660756607666077660786607966080660816608266083660846608566086660876608866089660906609166092660936609466095660966609766098660996610066101661026610366104661056610666107661086610966110661116611266113661146611566116661176611866119661206612166122661236612466125661266612766128661296613066131661326613366134661356613666137661386613966140661416614266143661446614566146661476614866149661506615166152661536615466155661566615766158661596616066161661626616366164661656616666167661686616966170661716617266173661746617566176661776617866179661806618166182661836618466185661866618766188661896619066191661926619366194661956619666197661986619966200662016620266203662046620566206662076620866209662106621166212662136621466215662166621766218662196622066221662226622366224662256622666227662286622966230662316623266233662346623566236662376623866239662406624166242662436624466245662466624766248662496625066251662526625366254662556625666257662586625966260662616626266263662646626566266662676626866269662706627166272662736627466275662766627766278662796628066281662826628366284662856628666287662886628966290662916629266293662946629566296662976629866299663006630166302663036630466305663066630766308663096631066311663126631366314663156631666317663186631966320663216632266323663246632566326663276632866329663306633166332663336633466335663366633766338663396634066341663426634366344663456634666347663486634966350663516635266353663546635566356663576635866359663606636166362663636636466365663666636766368663696637066371663726637366374663756637666377663786637966380663816638266383663846638566386663876638866389663906639166392663936639466395663966639766398663996640066401664026640366404664056640666407664086640966410664116641266413664146641566416664176641866419664206642166422664236642466425664266642766428664296643066431664326643366434664356643666437664386643966440664416644266443664446644566446664476644866449664506645166452664536645466455664566645766458664596646066461664626646366464664656646666467664686646966470664716647266473664746647566476664776647866479664806648166482664836648466485664866648766488664896649066491664926649366494664956649666497664986649966500665016650266503665046650566506665076650866509665106651166512665136651466515665166651766518665196652066521665226652366524665256652666527665286652966530665316653266533665346653566536665376653866539665406654166542665436654466545665466654766548665496655066551665526655366554665556655666557665586655966560665616656266563665646656566566665676656866569665706657166572665736657466575665766657766578665796658066581665826658366584665856658666587665886658966590665916659266593665946659566596665976659866599666006660166602666036660466605666066660766608666096661066611666126661366614666156661666617666186661966620666216662266623666246662566626666276662866629666306663166632666336663466635666366663766638666396664066641666426664366644666456664666647666486664966650666516665266653666546665566656666576665866659666606666166662666636666466665666666666766668666696667066671666726667366674666756667666677666786667966680666816668266683666846668566686666876668866689666906669166692666936669466695666966669766698666996670066701667026670366704667056670666707667086670966710667116671266713667146671566716667176671866719667206672166722667236672466725667266672766728667296673066731667326673366734667356673666737667386673966740667416674266743667446674566746667476674866749667506675166752667536675466755667566675766758667596676066761667626676366764667656676666767667686676966770667716677266773667746677566776667776677866779667806678166782667836678466785667866678766788667896679066791667926679366794667956679666797667986679966800668016680266803668046680566806668076680866809668106681166812668136681466815668166681766818668196682066821668226682366824668256682666827668286682966830668316683266833668346683566836668376683866839668406684166842668436684466845668466684766848668496685066851668526685366854668556685666857668586685966860668616686266863668646686566866668676686866869668706687166872668736687466875668766687766878668796688066881668826688366884668856688666887668886688966890668916689266893668946689566896668976689866899669006690166902669036690466905669066690766908669096691066911669126691366914669156691666917669186691966920669216692266923669246692566926669276692866929669306693166932669336693466935669366693766938669396694066941669426694366944669456694666947669486694966950669516695266953669546695566956669576695866959669606696166962669636696466965669666696766968669696697066971669726697366974669756697666977669786697966980669816698266983669846698566986669876698866989669906699166992669936699466995669966699766998669996700067001670026700367004670056700667007670086700967010670116701267013670146701567016670176701867019670206702167022670236702467025670266702767028670296703067031670326703367034670356703667037670386703967040670416704267043670446704567046670476704867049670506705167052670536705467055670566705767058670596706067061670626706367064670656706667067670686706967070670716707267073670746707567076670776707867079670806708167082670836708467085670866708767088670896709067091670926709367094670956709667097670986709967100671016710267103671046710567106671076710867109671106711167112671136711467115671166711767118671196712067121671226712367124671256712667127671286712967130671316713267133671346713567136671376713867139671406714167142671436714467145671466714767148671496715067151671526715367154671556715667157671586715967160671616716267163671646716567166671676716867169671706717167172671736717467175671766717767178671796718067181671826718367184671856718667187671886718967190671916719267193671946719567196671976719867199672006720167202672036720467205672066720767208672096721067211672126721367214672156721667217672186721967220672216722267223672246722567226672276722867229672306723167232672336723467235672366723767238672396724067241672426724367244672456724667247672486724967250672516725267253672546725567256672576725867259672606726167262672636726467265672666726767268672696727067271672726727367274672756727667277672786727967280672816728267283672846728567286672876728867289672906729167292672936729467295672966729767298672996730067301673026730367304673056730667307673086730967310673116731267313673146731567316673176731867319673206732167322673236732467325673266732767328673296733067331673326733367334673356733667337673386733967340673416734267343673446734567346673476734867349673506735167352673536735467355673566735767358673596736067361673626736367364673656736667367673686736967370673716737267373673746737567376673776737867379673806738167382673836738467385673866738767388673896739067391673926739367394673956739667397673986739967400674016740267403674046740567406674076740867409674106741167412674136741467415674166741767418674196742067421674226742367424674256742667427674286742967430674316743267433674346743567436674376743867439674406744167442674436744467445674466744767448674496745067451674526745367454674556745667457674586745967460674616746267463674646746567466674676746867469674706747167472674736747467475674766747767478674796748067481674826748367484674856748667487674886748967490674916749267493674946749567496674976749867499675006750167502675036750467505675066750767508675096751067511675126751367514675156751667517675186751967520675216752267523675246752567526675276752867529675306753167532675336753467535675366753767538675396754067541675426754367544675456754667547675486754967550675516755267553675546755567556675576755867559675606756167562675636756467565675666756767568675696757067571675726757367574675756757667577675786757967580675816758267583675846758567586675876758867589675906759167592675936759467595675966759767598675996760067601676026760367604676056760667607676086760967610676116761267613676146761567616676176761867619676206762167622676236762467625676266762767628676296763067631676326763367634676356763667637676386763967640676416764267643676446764567646676476764867649676506765167652676536765467655676566765767658676596766067661676626766367664676656766667667676686766967670676716767267673676746767567676676776767867679676806768167682676836768467685676866768767688676896769067691676926769367694676956769667697676986769967700677016770267703677046770567706677076770867709677106771167712677136771467715677166771767718677196772067721677226772367724677256772667727677286772967730677316773267733677346773567736677376773867739677406774167742677436774467745677466774767748677496775067751677526775367754677556775667757677586775967760677616776267763677646776567766677676776867769677706777167772677736777467775677766777767778677796778067781677826778367784677856778667787677886778967790677916779267793677946779567796677976779867799678006780167802678036780467805678066780767808678096781067811678126781367814678156781667817678186781967820678216782267823678246782567826678276782867829678306783167832678336783467835678366783767838678396784067841678426784367844678456784667847678486784967850678516785267853678546785567856678576785867859678606786167862678636786467865678666786767868678696787067871678726787367874678756787667877678786787967880678816788267883678846788567886678876788867889678906789167892678936789467895678966789767898678996790067901679026790367904679056790667907679086790967910679116791267913679146791567916679176791867919679206792167922679236792467925679266792767928679296793067931679326793367934679356793667937679386793967940679416794267943679446794567946679476794867949679506795167952679536795467955679566795767958679596796067961679626796367964679656796667967679686796967970679716797267973679746797567976679776797867979679806798167982679836798467985679866798767988679896799067991679926799367994679956799667997679986799968000680016800268003680046800568006680076800868009680106801168012680136801468015680166801768018680196802068021680226802368024680256802668027680286802968030680316803268033680346803568036680376803868039680406804168042680436804468045680466804768048680496805068051680526805368054680556805668057680586805968060680616806268063680646806568066680676806868069680706807168072680736807468075680766807768078680796808068081680826808368084680856808668087680886808968090680916809268093680946809568096680976809868099681006810168102681036810468105681066810768108681096811068111681126811368114681156811668117681186811968120681216812268123681246812568126681276812868129681306813168132681336813468135681366813768138681396814068141681426814368144681456814668147681486814968150681516815268153681546815568156681576815868159681606816168162681636816468165681666816768168681696817068171681726817368174681756817668177681786817968180681816818268183681846818568186681876818868189681906819168192681936819468195681966819768198681996820068201682026820368204682056820668207682086820968210682116821268213682146821568216682176821868219682206822168222682236822468225682266822768228682296823068231682326823368234682356823668237682386823968240682416824268243682446824568246682476824868249682506825168252682536825468255682566825768258682596826068261682626826368264682656826668267682686826968270682716827268273682746827568276682776827868279682806828168282682836828468285682866828768288682896829068291682926829368294682956829668297682986829968300683016830268303683046830568306683076830868309683106831168312683136831468315683166831768318683196832068321683226832368324683256832668327683286832968330683316833268333683346833568336683376833868339683406834168342683436834468345683466834768348683496835068351683526835368354683556835668357683586835968360683616836268363683646836568366683676836868369683706837168372683736837468375683766837768378683796838068381683826838368384683856838668387683886838968390683916839268393683946839568396683976839868399684006840168402684036840468405684066840768408684096841068411684126841368414684156841668417684186841968420684216842268423684246842568426684276842868429684306843168432684336843468435684366843768438684396844068441684426844368444684456844668447684486844968450684516845268453684546845568456684576845868459684606846168462684636846468465684666846768468684696847068471684726847368474684756847668477684786847968480684816848268483684846848568486684876848868489684906849168492684936849468495684966849768498684996850068501685026850368504685056850668507685086850968510685116851268513685146851568516685176851868519685206852168522685236852468525685266852768528685296853068531685326853368534685356853668537685386853968540685416854268543685446854568546685476854868549685506855168552685536855468555685566855768558685596856068561685626856368564685656856668567685686856968570685716857268573685746857568576685776857868579685806858168582685836858468585685866858768588685896859068591685926859368594685956859668597685986859968600686016860268603686046860568606686076860868609686106861168612686136861468615686166861768618686196862068621686226862368624686256862668627686286862968630686316863268633686346863568636686376863868639686406864168642686436864468645686466864768648686496865068651686526865368654686556865668657686586865968660686616866268663686646866568666686676866868669686706867168672686736867468675686766867768678686796868068681686826868368684686856868668687686886868968690686916869268693686946869568696686976869868699687006870168702687036870468705687066870768708687096871068711687126871368714687156871668717687186871968720687216872268723687246872568726687276872868729687306873168732687336873468735687366873768738687396874068741687426874368744687456874668747687486874968750687516875268753687546875568756687576875868759687606876168762687636876468765687666876768768687696877068771687726877368774687756877668777687786877968780687816878268783687846878568786687876878868789687906879168792687936879468795687966879768798687996880068801688026880368804688056880668807688086880968810688116881268813688146881568816688176881868819688206882168822688236882468825688266882768828688296883068831688326883368834688356883668837688386883968840688416884268843688446884568846688476884868849688506885168852688536885468855688566885768858688596886068861688626886368864688656886668867688686886968870688716887268873688746887568876688776887868879688806888168882688836888468885688866888768888688896889068891688926889368894688956889668897688986889968900689016890268903689046890568906689076890868909689106891168912689136891468915689166891768918689196892068921689226892368924689256892668927689286892968930689316893268933689346893568936689376893868939689406894168942689436894468945689466894768948689496895068951689526895368954689556895668957689586895968960689616896268963689646896568966689676896868969689706897168972689736897468975689766897768978689796898068981689826898368984689856898668987689886898968990689916899268993689946899568996689976899868999690006900169002690036900469005690066900769008690096901069011690126901369014690156901669017690186901969020690216902269023690246902569026690276902869029690306903169032690336903469035690366903769038690396904069041690426904369044690456904669047690486904969050690516905269053690546905569056690576905869059690606906169062690636906469065690666906769068690696907069071690726907369074690756907669077690786907969080690816908269083690846908569086690876908869089690906909169092690936909469095690966909769098690996910069101691026910369104691056910669107691086910969110691116911269113691146911569116691176911869119691206912169122691236912469125691266912769128691296913069131691326913369134691356913669137691386913969140691416914269143691446914569146691476914869149691506915169152691536915469155691566915769158691596916069161691626916369164691656916669167691686916969170691716917269173691746917569176691776917869179691806918169182691836918469185691866918769188691896919069191691926919369194691956919669197691986919969200692016920269203692046920569206692076920869209692106921169212692136921469215692166921769218692196922069221692226922369224692256922669227692286922969230692316923269233692346923569236692376923869239692406924169242692436924469245692466924769248692496925069251692526925369254692556925669257692586925969260692616926269263692646926569266692676926869269692706927169272692736927469275692766927769278692796928069281692826928369284692856928669287692886928969290692916929269293692946929569296692976929869299693006930169302693036930469305693066930769308693096931069311693126931369314693156931669317693186931969320693216932269323693246932569326693276932869329693306933169332693336933469335693366933769338693396934069341693426934369344693456934669347693486934969350693516935269353693546935569356693576935869359693606936169362693636936469365693666936769368693696937069371693726937369374693756937669377693786937969380693816938269383693846938569386693876938869389693906939169392693936939469395693966939769398693996940069401694026940369404694056940669407694086940969410694116941269413694146941569416694176941869419694206942169422694236942469425694266942769428694296943069431694326943369434694356943669437694386943969440694416944269443694446944569446694476944869449694506945169452694536945469455694566945769458694596946069461694626946369464694656946669467694686946969470694716947269473694746947569476694776947869479694806948169482694836948469485694866948769488694896949069491694926949369494694956949669497694986949969500695016950269503695046950569506695076950869509695106951169512695136951469515695166951769518695196952069521695226952369524695256952669527695286952969530695316953269533695346953569536695376953869539695406954169542695436954469545695466954769548695496955069551695526955369554695556955669557695586955969560695616956269563695646956569566695676956869569695706957169572695736957469575695766957769578695796958069581695826958369584695856958669587695886958969590695916959269593695946959569596695976959869599696006960169602696036960469605696066960769608696096961069611696126961369614696156961669617696186961969620696216962269623696246962569626696276962869629696306963169632696336963469635696366963769638696396964069641696426964369644696456964669647696486964969650696516965269653696546965569656696576965869659696606966169662696636966469665696666966769668696696967069671696726967369674696756967669677696786967969680696816968269683696846968569686696876968869689696906969169692696936969469695696966969769698696996970069701697026970369704697056970669707697086970969710697116971269713697146971569716697176971869719697206972169722697236972469725697266972769728697296973069731697326973369734697356973669737697386973969740697416974269743697446974569746697476974869749697506975169752697536975469755697566975769758697596976069761697626976369764697656976669767697686976969770697716977269773697746977569776697776977869779697806978169782697836978469785697866978769788697896979069791697926979369794697956979669797697986979969800698016980269803698046980569806698076980869809698106981169812698136981469815698166981769818698196982069821698226982369824698256982669827698286982969830698316983269833698346983569836698376983869839698406984169842698436984469845698466984769848698496985069851698526985369854698556985669857698586985969860698616986269863698646986569866698676986869869698706987169872698736987469875698766987769878698796988069881698826988369884698856988669887698886988969890698916989269893698946989569896698976989869899699006990169902699036990469905699066990769908699096991069911699126991369914699156991669917699186991969920699216992269923699246992569926699276992869929699306993169932699336993469935699366993769938699396994069941699426994369944699456994669947699486994969950699516995269953699546995569956699576995869959699606996169962699636996469965699666996769968699696997069971699726997369974699756997669977699786997969980699816998269983699846998569986699876998869989699906999169992699936999469995699966999769998699997000070001700027000370004700057000670007700087000970010700117001270013700147001570016700177001870019700207002170022700237002470025700267002770028700297003070031700327003370034700357003670037700387003970040700417004270043700447004570046700477004870049700507005170052700537005470055700567005770058700597006070061700627006370064700657006670067700687006970070700717007270073700747007570076700777007870079700807008170082700837008470085700867008770088700897009070091700927009370094700957009670097700987009970100701017010270103701047010570106701077010870109701107011170112701137011470115701167011770118701197012070121701227012370124701257012670127701287012970130701317013270133701347013570136701377013870139701407014170142701437014470145701467014770148701497015070151701527015370154701557015670157701587015970160701617016270163701647016570166701677016870169701707017170172701737017470175701767017770178701797018070181701827018370184701857018670187701887018970190701917019270193701947019570196701977019870199702007020170202702037020470205702067020770208702097021070211702127021370214702157021670217702187021970220702217022270223702247022570226702277022870229702307023170232702337023470235702367023770238702397024070241702427024370244702457024670247702487024970250702517025270253702547025570256702577025870259702607026170262702637026470265702667026770268702697027070271702727027370274702757027670277702787027970280702817028270283702847028570286702877028870289702907029170292702937029470295702967029770298702997030070301703027030370304703057030670307703087030970310703117031270313703147031570316703177031870319703207032170322703237032470325703267032770328703297033070331703327033370334703357033670337703387033970340703417034270343703447034570346703477034870349703507035170352703537035470355703567035770358703597036070361703627036370364703657036670367703687036970370703717037270373703747037570376703777037870379703807038170382703837038470385703867038770388703897039070391703927039370394703957039670397703987039970400704017040270403704047040570406704077040870409704107041170412704137041470415704167041770418704197042070421704227042370424704257042670427704287042970430704317043270433704347043570436704377043870439704407044170442704437044470445704467044770448704497045070451704527045370454704557045670457704587045970460704617046270463704647046570466704677046870469704707047170472704737047470475704767047770478704797048070481704827048370484704857048670487704887048970490704917049270493704947049570496704977049870499705007050170502705037050470505705067050770508705097051070511705127051370514705157051670517705187051970520705217052270523705247052570526705277052870529705307053170532705337053470535705367053770538705397054070541705427054370544705457054670547705487054970550705517055270553705547055570556705577055870559705607056170562705637056470565705667056770568705697057070571705727057370574705757057670577705787057970580705817058270583705847058570586705877058870589705907059170592705937059470595705967059770598705997060070601706027060370604706057060670607706087060970610706117061270613706147061570616706177061870619706207062170622706237062470625706267062770628706297063070631706327063370634706357063670637706387063970640706417064270643706447064570646706477064870649706507065170652706537065470655706567065770658706597066070661706627066370664706657066670667706687066970670706717067270673706747067570676706777067870679706807068170682706837068470685706867068770688706897069070691706927069370694706957069670697706987069970700707017070270703707047070570706707077070870709707107071170712707137071470715707167071770718707197072070721707227072370724707257072670727707287072970730707317073270733707347073570736707377073870739707407074170742707437074470745707467074770748707497075070751707527075370754707557075670757707587075970760707617076270763707647076570766707677076870769707707077170772707737077470775707767077770778707797078070781707827078370784707857078670787707887078970790707917079270793707947079570796707977079870799708007080170802708037080470805708067080770808708097081070811708127081370814708157081670817708187081970820708217082270823708247082570826708277082870829708307083170832708337083470835708367083770838708397084070841708427084370844708457084670847708487084970850708517085270853708547085570856708577085870859708607086170862708637086470865708667086770868708697087070871708727087370874708757087670877708787087970880708817088270883708847088570886708877088870889708907089170892708937089470895708967089770898708997090070901709027090370904709057090670907709087090970910709117091270913709147091570916709177091870919709207092170922709237092470925709267092770928709297093070931709327093370934709357093670937709387093970940709417094270943709447094570946709477094870949709507095170952709537095470955709567095770958709597096070961709627096370964709657096670967709687096970970709717097270973709747097570976709777097870979709807098170982709837098470985709867098770988709897099070991709927099370994709957099670997709987099971000710017100271003710047100571006710077100871009710107101171012710137101471015710167101771018710197102071021710227102371024710257102671027710287102971030710317103271033710347103571036710377103871039710407104171042710437104471045710467104771048710497105071051710527105371054710557105671057710587105971060710617106271063710647106571066710677106871069710707107171072710737107471075710767107771078710797108071081710827108371084710857108671087710887108971090710917109271093710947109571096710977109871099711007110171102711037110471105711067110771108711097111071111711127111371114711157111671117711187111971120711217112271123711247112571126711277112871129711307113171132711337113471135711367113771138711397114071141711427114371144711457114671147711487114971150711517115271153711547115571156711577115871159711607116171162711637116471165711667116771168711697117071171711727117371174711757117671177711787117971180711817118271183711847118571186711877118871189711907119171192711937119471195711967119771198711997120071201712027120371204712057120671207712087120971210712117121271213712147121571216712177121871219712207122171222712237122471225712267122771228712297123071231712327123371234712357123671237712387123971240712417124271243712447124571246712477124871249712507125171252712537125471255712567125771258712597126071261712627126371264712657126671267712687126971270712717127271273712747127571276712777127871279712807128171282712837128471285712867128771288712897129071291712927129371294712957129671297712987129971300713017130271303713047130571306713077130871309713107131171312713137131471315713167131771318713197132071321713227132371324713257132671327713287132971330713317133271333713347133571336713377133871339713407134171342713437134471345713467134771348713497135071351713527135371354713557135671357713587135971360713617136271363713647136571366713677136871369713707137171372713737137471375713767137771378713797138071381713827138371384713857138671387713887138971390713917139271393713947139571396713977139871399714007140171402714037140471405714067140771408714097141071411714127141371414714157141671417714187141971420714217142271423714247142571426714277142871429714307143171432714337143471435714367143771438714397144071441714427144371444714457144671447714487144971450714517145271453714547145571456714577145871459714607146171462714637146471465714667146771468714697147071471714727147371474714757147671477714787147971480714817148271483714847148571486714877148871489714907149171492714937149471495714967149771498714997150071501715027150371504715057150671507715087150971510715117151271513715147151571516715177151871519715207152171522715237152471525715267152771528715297153071531715327153371534715357153671537715387153971540715417154271543715447154571546715477154871549715507155171552715537155471555715567155771558715597156071561715627156371564715657156671567715687156971570715717157271573715747157571576715777157871579715807158171582715837158471585715867158771588715897159071591715927159371594715957159671597715987159971600716017160271603716047160571606716077160871609716107161171612716137161471615716167161771618716197162071621716227162371624716257162671627716287162971630716317163271633716347163571636716377163871639716407164171642716437164471645716467164771648716497165071651716527165371654716557165671657716587165971660716617166271663716647166571666716677166871669716707167171672716737167471675716767167771678716797168071681716827168371684716857168671687716887168971690716917169271693716947169571696716977169871699717007170171702717037170471705717067170771708717097171071711717127171371714717157171671717717187171971720717217172271723717247172571726717277172871729717307173171732717337173471735717367173771738717397174071741717427174371744717457174671747717487174971750717517175271753717547175571756717577175871759717607176171762717637176471765717667176771768717697177071771717727177371774717757177671777717787177971780717817178271783717847178571786717877178871789717907179171792717937179471795717967179771798717997180071801718027180371804718057180671807718087180971810718117181271813718147181571816718177181871819718207182171822718237182471825718267182771828718297183071831718327183371834718357183671837718387183971840718417184271843718447184571846718477184871849718507185171852718537185471855718567185771858718597186071861718627186371864718657186671867718687186971870718717187271873718747187571876718777187871879718807188171882718837188471885718867188771888718897189071891718927189371894718957189671897718987189971900719017190271903719047190571906719077190871909719107191171912719137191471915719167191771918719197192071921719227192371924719257192671927719287192971930719317193271933719347193571936719377193871939719407194171942719437194471945719467194771948719497195071951719527195371954719557195671957719587195971960719617196271963719647196571966719677196871969719707197171972719737197471975719767197771978719797198071981719827198371984719857198671987719887198971990719917199271993719947199571996719977199871999720007200172002720037200472005720067200772008720097201072011720127201372014720157201672017720187201972020720217202272023720247202572026720277202872029720307203172032720337203472035720367203772038720397204072041720427204372044720457204672047720487204972050720517205272053720547205572056720577205872059720607206172062720637206472065720667206772068720697207072071720727207372074720757207672077720787207972080720817208272083720847208572086720877208872089720907209172092720937209472095720967209772098720997210072101721027210372104721057210672107721087210972110721117211272113721147211572116721177211872119721207212172122721237212472125721267212772128721297213072131721327213372134721357213672137721387213972140721417214272143721447214572146721477214872149721507215172152721537215472155721567215772158721597216072161721627216372164721657216672167721687216972170721717217272173721747217572176721777217872179721807218172182721837218472185721867218772188721897219072191721927219372194721957219672197721987219972200722017220272203722047220572206722077220872209722107221172212722137221472215722167221772218722197222072221722227222372224722257222672227722287222972230722317223272233722347223572236722377223872239722407224172242722437224472245722467224772248722497225072251722527225372254722557225672257722587225972260722617226272263722647226572266722677226872269722707227172272722737227472275722767227772278722797228072281722827228372284722857228672287722887228972290722917229272293722947229572296722977229872299723007230172302723037230472305723067230772308723097231072311723127231372314723157231672317723187231972320723217232272323723247232572326723277232872329723307233172332723337233472335723367233772338723397234072341723427234372344723457234672347723487234972350723517235272353723547235572356723577235872359723607236172362723637236472365723667236772368723697237072371723727237372374723757237672377723787237972380723817238272383723847238572386723877238872389723907239172392723937239472395723967239772398723997240072401724027240372404724057240672407724087240972410724117241272413724147241572416724177241872419724207242172422724237242472425724267242772428724297243072431724327243372434724357243672437724387243972440724417244272443724447244572446724477244872449724507245172452724537245472455724567245772458724597246072461724627246372464724657246672467724687246972470724717247272473724747247572476724777247872479724807248172482724837248472485724867248772488724897249072491724927249372494724957249672497724987249972500725017250272503725047250572506725077250872509725107251172512725137251472515725167251772518725197252072521725227252372524725257252672527725287252972530725317253272533725347253572536725377253872539725407254172542725437254472545725467254772548725497255072551725527255372554725557255672557725587255972560725617256272563725647256572566725677256872569725707257172572725737257472575725767257772578725797258072581725827258372584725857258672587725887258972590725917259272593725947259572596725977259872599726007260172602726037260472605726067260772608726097261072611726127261372614726157261672617726187261972620726217262272623726247262572626726277262872629726307263172632726337263472635726367263772638726397264072641726427264372644726457264672647726487264972650726517265272653726547265572656726577265872659726607266172662726637266472665726667266772668726697267072671726727267372674726757267672677726787267972680726817268272683726847268572686726877268872689726907269172692726937269472695726967269772698726997270072701727027270372704727057270672707727087270972710727117271272713727147271572716727177271872719727207272172722727237272472725727267272772728727297273072731727327273372734727357273672737727387273972740727417274272743727447274572746727477274872749727507275172752727537275472755727567275772758727597276072761727627276372764727657276672767727687276972770727717277272773727747277572776727777277872779727807278172782727837278472785727867278772788727897279072791727927279372794727957279672797727987279972800728017280272803728047280572806728077280872809728107281172812728137281472815728167281772818728197282072821728227282372824728257282672827728287282972830728317283272833728347283572836728377283872839728407284172842728437284472845728467284772848728497285072851728527285372854728557285672857728587285972860728617286272863728647286572866728677286872869728707287172872728737287472875728767287772878728797288072881728827288372884728857288672887728887288972890728917289272893728947289572896728977289872899729007290172902729037290472905729067290772908729097291072911729127291372914729157291672917729187291972920729217292272923729247292572926729277292872929729307293172932729337293472935729367293772938729397294072941729427294372944729457294672947729487294972950729517295272953729547295572956729577295872959729607296172962729637296472965729667296772968729697297072971729727297372974729757297672977729787297972980729817298272983729847298572986729877298872989729907299172992729937299472995729967299772998729997300073001730027300373004730057300673007730087300973010730117301273013730147301573016730177301873019730207302173022730237302473025730267302773028730297303073031730327303373034730357303673037730387303973040730417304273043730447304573046730477304873049730507305173052730537305473055730567305773058730597306073061730627306373064730657306673067730687306973070730717307273073730747307573076730777307873079730807308173082730837308473085730867308773088730897309073091730927309373094730957309673097730987309973100731017310273103731047310573106731077310873109731107311173112731137311473115731167311773118731197312073121731227312373124731257312673127731287312973130731317313273133731347313573136731377313873139731407314173142731437314473145731467314773148731497315073151731527315373154731557315673157731587315973160731617316273163731647316573166731677316873169731707317173172731737317473175731767317773178731797318073181731827318373184731857318673187731887318973190731917319273193731947319573196731977319873199732007320173202732037320473205732067320773208732097321073211732127321373214732157321673217732187321973220732217322273223732247322573226732277322873229732307323173232732337323473235732367323773238732397324073241732427324373244732457324673247732487324973250732517325273253732547325573256732577325873259732607326173262732637326473265732667326773268732697327073271732727327373274732757327673277732787327973280732817328273283732847328573286732877328873289732907329173292732937329473295732967329773298732997330073301733027330373304733057330673307733087330973310733117331273313733147331573316733177331873319733207332173322733237332473325733267332773328733297333073331733327333373334733357333673337733387333973340733417334273343733447334573346733477334873349733507335173352733537335473355733567335773358733597336073361733627336373364733657336673367733687336973370733717337273373733747337573376733777337873379733807338173382733837338473385733867338773388733897339073391733927339373394733957339673397733987339973400734017340273403734047340573406734077340873409734107341173412734137341473415734167341773418734197342073421734227342373424734257342673427734287342973430734317343273433734347343573436734377343873439734407344173442734437344473445734467344773448734497345073451734527345373454734557345673457734587345973460734617346273463734647346573466734677346873469734707347173472734737347473475734767347773478734797348073481734827348373484734857348673487734887348973490734917349273493734947349573496734977349873499735007350173502735037350473505735067350773508735097351073511735127351373514735157351673517735187351973520735217352273523735247352573526735277352873529735307353173532735337353473535735367353773538735397354073541735427354373544735457354673547735487354973550735517355273553735547355573556735577355873559735607356173562735637356473565735667356773568735697357073571735727357373574735757357673577735787357973580735817358273583735847358573586735877358873589735907359173592735937359473595735967359773598735997360073601736027360373604736057360673607736087360973610736117361273613736147361573616736177361873619736207362173622736237362473625736267362773628736297363073631736327363373634736357363673637736387363973640736417364273643736447364573646736477364873649736507365173652736537365473655736567365773658736597366073661736627366373664736657366673667736687366973670736717367273673736747367573676736777367873679736807368173682736837368473685736867368773688736897369073691736927369373694736957369673697736987369973700737017370273703737047370573706737077370873709737107371173712737137371473715737167371773718737197372073721737227372373724737257372673727737287372973730737317373273733737347373573736737377373873739737407374173742737437374473745737467374773748737497375073751737527375373754737557375673757737587375973760737617376273763737647376573766737677376873769737707377173772737737377473775737767377773778737797378073781737827378373784737857378673787737887378973790737917379273793737947379573796737977379873799738007380173802738037380473805738067380773808738097381073811738127381373814738157381673817738187381973820738217382273823738247382573826738277382873829738307383173832738337383473835738367383773838738397384073841738427384373844738457384673847738487384973850738517385273853738547385573856738577385873859738607386173862738637386473865738667386773868738697387073871738727387373874738757387673877738787387973880738817388273883738847388573886738877388873889738907389173892738937389473895738967389773898738997390073901739027390373904739057390673907739087390973910739117391273913739147391573916739177391873919739207392173922739237392473925739267392773928739297393073931739327393373934739357393673937739387393973940739417394273943739447394573946739477394873949739507395173952739537395473955739567395773958739597396073961739627396373964739657396673967739687396973970739717397273973739747397573976739777397873979739807398173982739837398473985739867398773988739897399073991739927399373994739957399673997739987399974000740017400274003740047400574006740077400874009740107401174012740137401474015740167401774018740197402074021740227402374024740257402674027740287402974030740317403274033740347403574036740377403874039740407404174042740437404474045740467404774048740497405074051740527405374054740557405674057740587405974060740617406274063740647406574066740677406874069740707407174072740737407474075740767407774078740797408074081740827408374084740857408674087740887408974090740917409274093740947409574096740977409874099741007410174102741037410474105741067410774108741097411074111741127411374114741157411674117741187411974120741217412274123741247412574126741277412874129741307413174132741337413474135741367413774138741397414074141741427414374144741457414674147741487414974150741517415274153741547415574156741577415874159741607416174162741637416474165741667416774168741697417074171741727417374174741757417674177741787417974180741817418274183741847418574186741877418874189741907419174192741937419474195741967419774198741997420074201742027420374204742057420674207742087420974210742117421274213742147421574216742177421874219742207422174222742237422474225742267422774228742297423074231742327423374234742357423674237742387423974240742417424274243742447424574246742477424874249742507425174252742537425474255742567425774258742597426074261742627426374264742657426674267742687426974270742717427274273742747427574276742777427874279742807428174282742837428474285742867428774288742897429074291742927429374294742957429674297742987429974300743017430274303743047430574306743077430874309743107431174312743137431474315743167431774318743197432074321743227432374324743257432674327743287432974330743317433274333743347433574336743377433874339743407434174342743437434474345743467434774348743497435074351743527435374354743557435674357743587435974360743617436274363743647436574366743677436874369743707437174372743737437474375743767437774378743797438074381743827438374384743857438674387743887438974390743917439274393743947439574396743977439874399744007440174402744037440474405744067440774408744097441074411744127441374414744157441674417744187441974420744217442274423744247442574426744277442874429744307443174432744337443474435744367443774438744397444074441744427444374444744457444674447744487444974450744517445274453744547445574456744577445874459744607446174462744637446474465744667446774468744697447074471744727447374474744757447674477744787447974480744817448274483744847448574486744877448874489744907449174492744937449474495744967449774498744997450074501745027450374504745057450674507745087450974510745117451274513745147451574516745177451874519745207452174522745237452474525745267452774528745297453074531745327453374534745357453674537745387453974540745417454274543745447454574546745477454874549745507455174552745537455474555745567455774558745597456074561745627456374564745657456674567745687456974570745717457274573745747457574576745777457874579745807458174582745837458474585745867458774588745897459074591745927459374594745957459674597745987459974600746017460274603746047460574606746077460874609746107461174612746137461474615746167461774618746197462074621746227462374624746257462674627746287462974630746317463274633746347463574636746377463874639746407464174642746437464474645746467464774648746497465074651746527465374654746557465674657746587465974660746617466274663746647466574666746677466874669746707467174672746737467474675746767467774678746797468074681746827468374684746857468674687746887468974690746917469274693746947469574696746977469874699747007470174702747037470474705747067470774708747097471074711747127471374714747157471674717747187471974720747217472274723747247472574726747277472874729747307473174732747337473474735747367473774738747397474074741747427474374744747457474674747747487474974750747517475274753747547475574756747577475874759747607476174762747637476474765747667476774768747697477074771747727477374774747757477674777747787477974780747817478274783747847478574786747877478874789747907479174792747937479474795747967479774798747997480074801748027480374804748057480674807748087480974810748117481274813748147481574816748177481874819748207482174822748237482474825748267482774828748297483074831748327483374834748357483674837748387483974840748417484274843748447484574846748477484874849748507485174852748537485474855748567485774858748597486074861748627486374864748657486674867748687486974870748717487274873748747487574876748777487874879748807488174882748837488474885748867488774888748897489074891748927489374894748957489674897748987489974900749017490274903749047490574906749077490874909749107491174912749137491474915749167491774918749197492074921749227492374924749257492674927749287492974930749317493274933749347493574936749377493874939749407494174942749437494474945749467494774948749497495074951749527495374954749557495674957749587495974960749617496274963749647496574966749677496874969749707497174972749737497474975749767497774978749797498074981749827498374984749857498674987749887498974990749917499274993749947499574996749977499874999750007500175002750037500475005750067500775008750097501075011750127501375014750157501675017750187501975020750217502275023750247502575026750277502875029750307503175032750337503475035750367503775038750397504075041750427504375044750457504675047750487504975050750517505275053750547505575056750577505875059750607506175062750637506475065750667506775068750697507075071750727507375074750757507675077750787507975080750817508275083750847508575086750877508875089750907509175092750937509475095750967509775098750997510075101751027510375104751057510675107751087510975110751117511275113751147511575116751177511875119751207512175122751237512475125751267512775128751297513075131751327513375134751357513675137751387513975140751417514275143751447514575146751477514875149751507515175152751537515475155751567515775158751597516075161751627516375164751657516675167751687516975170751717517275173751747517575176751777517875179751807518175182751837518475185751867518775188751897519075191751927519375194751957519675197751987519975200752017520275203752047520575206752077520875209752107521175212752137521475215752167521775218752197522075221752227522375224752257522675227752287522975230752317523275233752347523575236752377523875239752407524175242752437524475245752467524775248752497525075251752527525375254752557525675257752587525975260752617526275263752647526575266752677526875269752707527175272752737527475275752767527775278752797528075281752827528375284752857528675287752887528975290752917529275293752947529575296752977529875299753007530175302753037530475305753067530775308753097531075311753127531375314753157531675317753187531975320753217532275323753247532575326753277532875329753307533175332753337533475335753367533775338753397534075341753427534375344753457534675347753487534975350753517535275353753547535575356753577535875359753607536175362753637536475365753667536775368753697537075371753727537375374753757537675377753787537975380753817538275383753847538575386753877538875389753907539175392753937539475395753967539775398753997540075401754027540375404754057540675407754087540975410754117541275413754147541575416754177541875419754207542175422754237542475425754267542775428754297543075431754327543375434754357543675437754387543975440754417544275443754447544575446754477544875449754507545175452754537545475455754567545775458754597546075461754627546375464754657546675467754687546975470754717547275473754747547575476754777547875479754807548175482754837548475485754867548775488754897549075491754927549375494754957549675497754987549975500755017550275503755047550575506755077550875509755107551175512755137551475515755167551775518755197552075521755227552375524755257552675527755287552975530755317553275533755347553575536755377553875539755407554175542755437554475545755467554775548755497555075551755527555375554755557555675557755587555975560755617556275563755647556575566755677556875569755707557175572755737557475575755767557775578755797558075581755827558375584755857558675587755887558975590755917559275593755947559575596755977559875599756007560175602756037560475605756067560775608756097561075611756127561375614756157561675617756187561975620756217562275623756247562575626756277562875629756307563175632756337563475635756367563775638756397564075641756427564375644756457564675647756487564975650756517565275653756547565575656756577565875659756607566175662756637566475665756667566775668756697567075671756727567375674756757567675677756787567975680756817568275683756847568575686756877568875689756907569175692756937569475695756967569775698756997570075701757027570375704757057570675707757087570975710757117571275713757147571575716757177571875719757207572175722757237572475725757267572775728757297573075731757327573375734757357573675737757387573975740757417574275743757447574575746757477574875749757507575175752757537575475755757567575775758757597576075761757627576375764757657576675767757687576975770757717577275773757747577575776757777577875779757807578175782757837578475785757867578775788757897579075791757927579375794757957579675797757987579975800758017580275803758047580575806758077580875809758107581175812758137581475815758167581775818758197582075821758227582375824758257582675827758287582975830758317583275833758347583575836758377583875839758407584175842758437584475845758467584775848758497585075851758527585375854758557585675857758587585975860758617586275863758647586575866758677586875869758707587175872758737587475875758767587775878758797588075881758827588375884758857588675887758887588975890758917589275893758947589575896758977589875899759007590175902759037590475905759067590775908759097591075911759127591375914759157591675917759187591975920759217592275923759247592575926759277592875929759307593175932759337593475935759367593775938759397594075941759427594375944759457594675947759487594975950759517595275953759547595575956759577595875959759607596175962759637596475965759667596775968759697597075971759727597375974759757597675977759787597975980759817598275983759847598575986759877598875989759907599175992759937599475995759967599775998759997600076001760027600376004760057600676007760087600976010760117601276013760147601576016760177601876019760207602176022760237602476025760267602776028760297603076031760327603376034760357603676037760387603976040760417604276043760447604576046760477604876049760507605176052760537605476055760567605776058760597606076061760627606376064760657606676067760687606976070760717607276073760747607576076760777607876079760807608176082760837608476085760867608776088760897609076091760927609376094760957609676097760987609976100761017610276103761047610576106761077610876109761107611176112761137611476115761167611776118761197612076121761227612376124761257612676127761287612976130761317613276133761347613576136761377613876139761407614176142761437614476145761467614776148761497615076151761527615376154761557615676157761587615976160761617616276163761647616576166761677616876169761707617176172761737617476175761767617776178761797618076181761827618376184761857618676187761887618976190761917619276193761947619576196761977619876199762007620176202762037620476205762067620776208762097621076211762127621376214762157621676217762187621976220762217622276223762247622576226762277622876229762307623176232762337623476235762367623776238762397624076241762427624376244762457624676247762487624976250762517625276253762547625576256762577625876259762607626176262762637626476265762667626776268762697627076271762727627376274762757627676277762787627976280762817628276283762847628576286762877628876289762907629176292762937629476295762967629776298762997630076301763027630376304763057630676307763087630976310763117631276313763147631576316763177631876319763207632176322763237632476325763267632776328763297633076331763327633376334763357633676337763387633976340763417634276343763447634576346763477634876349763507635176352763537635476355763567635776358763597636076361763627636376364763657636676367763687636976370763717637276373763747637576376763777637876379763807638176382763837638476385763867638776388763897639076391763927639376394763957639676397763987639976400764017640276403764047640576406764077640876409764107641176412764137641476415764167641776418764197642076421764227642376424764257642676427764287642976430764317643276433764347643576436764377643876439764407644176442764437644476445764467644776448764497645076451764527645376454764557645676457764587645976460764617646276463764647646576466764677646876469764707647176472764737647476475764767647776478764797648076481764827648376484764857648676487764887648976490764917649276493764947649576496764977649876499765007650176502765037650476505765067650776508765097651076511765127651376514765157651676517765187651976520765217652276523765247652576526765277652876529765307653176532765337653476535765367653776538765397654076541765427654376544765457654676547765487654976550765517655276553765547655576556765577655876559765607656176562765637656476565765667656776568765697657076571765727657376574765757657676577765787657976580765817658276583765847658576586765877658876589765907659176592765937659476595765967659776598765997660076601766027660376604766057660676607766087660976610766117661276613766147661576616766177661876619766207662176622766237662476625766267662776628766297663076631766327663376634766357663676637766387663976640766417664276643766447664576646766477664876649766507665176652766537665476655766567665776658766597666076661766627666376664766657666676667766687666976670766717667276673766747667576676766777667876679766807668176682766837668476685766867668776688766897669076691766927669376694766957669676697766987669976700767017670276703767047670576706767077670876709767107671176712767137671476715767167671776718767197672076721767227672376724767257672676727767287672976730767317673276733767347673576736767377673876739767407674176742767437674476745767467674776748767497675076751767527675376754767557675676757767587675976760767617676276763767647676576766767677676876769767707677176772767737677476775767767677776778767797678076781767827678376784767857678676787767887678976790767917679276793767947679576796767977679876799768007680176802768037680476805768067680776808768097681076811768127681376814768157681676817768187681976820768217682276823768247682576826768277682876829768307683176832768337683476835768367683776838768397684076841768427684376844768457684676847768487684976850768517685276853768547685576856768577685876859768607686176862768637686476865768667686776868768697687076871768727687376874768757687676877768787687976880768817688276883768847688576886768877688876889768907689176892768937689476895768967689776898768997690076901769027690376904769057690676907769087690976910769117691276913769147691576916769177691876919769207692176922769237692476925769267692776928769297693076931769327693376934769357693676937769387693976940769417694276943769447694576946769477694876949769507695176952769537695476955769567695776958769597696076961769627696376964769657696676967769687696976970769717697276973769747697576976769777697876979769807698176982769837698476985769867698776988769897699076991769927699376994769957699676997769987699977000770017700277003770047700577006770077700877009770107701177012770137701477015770167701777018770197702077021770227702377024770257702677027770287702977030770317703277033770347703577036770377703877039770407704177042770437704477045770467704777048770497705077051770527705377054770557705677057770587705977060770617706277063770647706577066770677706877069770707707177072770737707477075770767707777078770797708077081770827708377084770857708677087770887708977090770917709277093770947709577096770977709877099771007710177102771037710477105771067710777108771097711077111771127711377114771157711677117771187711977120771217712277123771247712577126771277712877129771307713177132771337713477135771367713777138771397714077141771427714377144771457714677147771487714977150771517715277153771547715577156771577715877159771607716177162771637716477165771667716777168771697717077171771727717377174771757717677177771787717977180771817718277183771847718577186771877718877189771907719177192771937719477195771967719777198771997720077201772027720377204772057720677207772087720977210772117721277213772147721577216772177721877219772207722177222772237722477225772267722777228772297723077231772327723377234772357723677237772387723977240772417724277243772447724577246772477724877249772507725177252772537725477255772567725777258772597726077261772627726377264772657726677267772687726977270772717727277273772747727577276772777727877279772807728177282772837728477285772867728777288772897729077291772927729377294772957729677297772987729977300773017730277303773047730577306773077730877309773107731177312773137731477315773167731777318773197732077321773227732377324773257732677327773287732977330773317733277333773347733577336773377733877339773407734177342773437734477345773467734777348773497735077351773527735377354773557735677357773587735977360773617736277363773647736577366773677736877369773707737177372773737737477375773767737777378773797738077381773827738377384773857738677387773887738977390773917739277393773947739577396773977739877399774007740177402774037740477405774067740777408774097741077411774127741377414774157741677417774187741977420774217742277423774247742577426774277742877429774307743177432774337743477435774367743777438774397744077441774427744377444774457744677447774487744977450774517745277453774547745577456774577745877459774607746177462774637746477465774667746777468774697747077471774727747377474774757747677477774787747977480774817748277483774847748577486774877748877489774907749177492774937749477495774967749777498774997750077501775027750377504775057750677507775087750977510775117751277513775147751577516775177751877519775207752177522775237752477525775267752777528775297753077531775327753377534775357753677537775387753977540775417754277543775447754577546775477754877549775507755177552775537755477555775567755777558775597756077561775627756377564775657756677567775687756977570775717757277573775747757577576775777757877579775807758177582775837758477585775867758777588775897759077591775927759377594775957759677597775987759977600776017760277603776047760577606776077760877609776107761177612776137761477615776167761777618776197762077621776227762377624776257762677627776287762977630776317763277633776347763577636776377763877639776407764177642776437764477645776467764777648776497765077651776527765377654776557765677657776587765977660776617766277663776647766577666776677766877669776707767177672776737767477675776767767777678776797768077681776827768377684776857768677687776887768977690776917769277693776947769577696776977769877699777007770177702777037770477705777067770777708777097771077711777127771377714777157771677717777187771977720777217772277723777247772577726777277772877729777307773177732777337773477735777367773777738777397774077741777427774377744777457774677747777487774977750777517775277753777547775577756777577775877759777607776177762777637776477765777667776777768777697777077771777727777377774777757777677777777787777977780777817778277783777847778577786777877778877789777907779177792777937779477795777967779777798777997780077801778027780377804778057780677807778087780977810778117781277813778147781577816778177781877819778207782177822778237782477825778267782777828778297783077831778327783377834778357783677837778387783977840778417784277843778447784577846778477784877849778507785177852778537785477855778567785777858778597786077861778627786377864778657786677867778687786977870778717787277873778747787577876778777787877879778807788177882778837788477885778867788777888778897789077891778927789377894778957789677897778987789977900779017790277903779047790577906779077790877909779107791177912779137791477915779167791777918779197792077921779227792377924779257792677927779287792977930779317793277933779347793577936779377793877939779407794177942779437794477945779467794777948779497795077951779527795377954779557795677957779587795977960779617796277963779647796577966779677796877969779707797177972779737797477975779767797777978779797798077981779827798377984779857798677987779887798977990779917799277993779947799577996779977799877999780007800178002780037800478005780067800778008780097801078011780127801378014780157801678017780187801978020780217802278023780247802578026780277802878029780307803178032780337803478035780367803778038780397804078041780427804378044780457804678047780487804978050780517805278053780547805578056780577805878059780607806178062780637806478065780667806778068780697807078071780727807378074780757807678077780787807978080780817808278083780847808578086780877808878089780907809178092780937809478095780967809778098780997810078101781027810378104781057810678107781087810978110781117811278113781147811578116781177811878119781207812178122781237812478125781267812778128781297813078131781327813378134781357813678137781387813978140781417814278143781447814578146781477814878149781507815178152781537815478155781567815778158781597816078161781627816378164781657816678167781687816978170781717817278173781747817578176781777817878179781807818178182781837818478185781867818778188781897819078191781927819378194781957819678197781987819978200782017820278203782047820578206782077820878209782107821178212782137821478215782167821778218782197822078221782227822378224782257822678227782287822978230782317823278233782347823578236782377823878239782407824178242782437824478245782467824778248782497825078251782527825378254782557825678257782587825978260782617826278263782647826578266782677826878269782707827178272782737827478275782767827778278782797828078281782827828378284782857828678287782887828978290782917829278293782947829578296782977829878299783007830178302783037830478305783067830778308783097831078311783127831378314783157831678317783187831978320783217832278323783247832578326783277832878329783307833178332783337833478335783367833778338783397834078341783427834378344783457834678347783487834978350783517835278353783547835578356783577835878359783607836178362783637836478365783667836778368783697837078371783727837378374783757837678377783787837978380783817838278383783847838578386783877838878389783907839178392783937839478395783967839778398783997840078401784027840378404784057840678407784087840978410784117841278413784147841578416784177841878419784207842178422784237842478425784267842778428784297843078431784327843378434784357843678437784387843978440784417844278443784447844578446784477844878449784507845178452784537845478455784567845778458784597846078461784627846378464784657846678467784687846978470784717847278473784747847578476784777847878479784807848178482784837848478485784867848778488784897849078491784927849378494784957849678497784987849978500785017850278503785047850578506785077850878509785107851178512785137851478515785167851778518785197852078521785227852378524785257852678527785287852978530785317853278533785347853578536785377853878539785407854178542785437854478545785467854778548785497855078551785527855378554785557855678557785587855978560785617856278563785647856578566785677856878569785707857178572785737857478575785767857778578785797858078581785827858378584785857858678587785887858978590785917859278593785947859578596785977859878599786007860178602786037860478605786067860778608786097861078611786127861378614786157861678617786187861978620786217862278623786247862578626786277862878629786307863178632786337863478635786367863778638786397864078641786427864378644786457864678647786487864978650786517865278653786547865578656786577865878659786607866178662786637866478665786667866778668786697867078671786727867378674786757867678677786787867978680786817868278683786847868578686786877868878689786907869178692786937869478695786967869778698786997870078701787027870378704787057870678707787087870978710787117871278713787147871578716787177871878719787207872178722787237872478725787267872778728787297873078731787327873378734787357873678737787387873978740787417874278743787447874578746787477874878749787507875178752787537875478755787567875778758787597876078761787627876378764787657876678767787687876978770787717877278773787747877578776787777877878779787807878178782787837878478785787867878778788787897879078791787927879378794787957879678797787987879978800788017880278803788047880578806788077880878809788107881178812788137881478815788167881778818788197882078821788227882378824788257882678827788287882978830788317883278833788347883578836788377883878839788407884178842788437884478845788467884778848788497885078851788527885378854788557885678857788587885978860788617886278863788647886578866788677886878869788707887178872788737887478875788767887778878788797888078881788827888378884788857888678887788887888978890788917889278893788947889578896788977889878899789007890178902789037890478905789067890778908789097891078911789127891378914789157891678917789187891978920789217892278923789247892578926789277892878929789307893178932789337893478935789367893778938789397894078941789427894378944789457894678947789487894978950789517895278953789547895578956789577895878959789607896178962789637896478965789667896778968789697897078971789727897378974789757897678977789787897978980789817898278983789847898578986789877898878989789907899178992789937899478995789967899778998789997900079001790027900379004790057900679007790087900979010790117901279013790147901579016790177901879019790207902179022790237902479025790267902779028790297903079031790327903379034790357903679037790387903979040790417904279043790447904579046790477904879049790507905179052790537905479055790567905779058790597906079061790627906379064790657906679067790687906979070790717907279073790747907579076790777907879079790807908179082790837908479085790867908779088790897909079091790927909379094790957909679097790987909979100791017910279103791047910579106791077910879109791107911179112791137911479115791167911779118791197912079121791227912379124791257912679127791287912979130791317913279133791347913579136791377913879139791407914179142791437914479145791467914779148791497915079151791527915379154791557915679157791587915979160791617916279163791647916579166791677916879169791707917179172791737917479175791767917779178791797918079181791827918379184791857918679187791887918979190791917919279193791947919579196791977919879199792007920179202792037920479205792067920779208792097921079211792127921379214792157921679217792187921979220792217922279223792247922579226792277922879229792307923179232792337923479235792367923779238792397924079241792427924379244792457924679247792487924979250792517925279253792547925579256792577925879259792607926179262792637926479265792667926779268792697927079271792727927379274792757927679277792787927979280792817928279283792847928579286792877928879289792907929179292792937929479295792967929779298792997930079301793027930379304793057930679307793087930979310793117931279313793147931579316793177931879319793207932179322793237932479325793267932779328793297933079331793327933379334793357933679337793387933979340793417934279343793447934579346793477934879349793507935179352793537935479355793567935779358793597936079361793627936379364793657936679367793687936979370793717937279373793747937579376793777937879379793807938179382793837938479385793867938779388793897939079391793927939379394793957939679397793987939979400794017940279403794047940579406794077940879409794107941179412794137941479415794167941779418794197942079421794227942379424794257942679427794287942979430794317943279433794347943579436794377943879439794407944179442794437944479445794467944779448794497945079451794527945379454794557945679457794587945979460794617946279463794647946579466794677946879469794707947179472794737947479475794767947779478794797948079481794827948379484794857948679487794887948979490794917949279493794947949579496794977949879499795007950179502795037950479505795067950779508795097951079511795127951379514795157951679517795187951979520795217952279523795247952579526795277952879529795307953179532795337953479535795367953779538795397954079541795427954379544795457954679547795487954979550795517955279553795547955579556795577955879559795607956179562795637956479565795667956779568795697957079571795727957379574795757957679577795787957979580795817958279583795847958579586795877958879589795907959179592795937959479595795967959779598795997960079601796027960379604796057960679607796087960979610796117961279613796147961579616796177961879619796207962179622796237962479625796267962779628796297963079631796327963379634796357963679637796387963979640796417964279643796447964579646796477964879649796507965179652796537965479655796567965779658796597966079661796627966379664796657966679667796687966979670796717967279673796747967579676796777967879679796807968179682796837968479685796867968779688796897969079691796927969379694796957969679697796987969979700797017970279703797047970579706797077970879709797107971179712797137971479715797167971779718797197972079721797227972379724797257972679727797287972979730797317973279733797347973579736797377973879739797407974179742797437974479745797467974779748797497975079751797527975379754797557975679757797587975979760797617976279763797647976579766797677976879769797707977179772797737977479775797767977779778797797978079781797827978379784797857978679787797887978979790797917979279793797947979579796797977979879799798007980179802798037980479805798067980779808798097981079811798127981379814798157981679817798187981979820798217982279823798247982579826798277982879829798307983179832798337983479835798367983779838798397984079841798427984379844798457984679847798487984979850798517985279853798547985579856798577985879859798607986179862798637986479865798667986779868798697987079871798727987379874798757987679877798787987979880798817988279883798847988579886798877988879889798907989179892798937989479895798967989779898798997990079901799027990379904799057990679907799087990979910799117991279913799147991579916799177991879919799207992179922799237992479925799267992779928799297993079931799327993379934799357993679937799387993979940799417994279943799447994579946799477994879949799507995179952799537995479955799567995779958799597996079961799627996379964799657996679967799687996979970799717997279973799747997579976799777997879979799807998179982799837998479985799867998779988799897999079991799927999379994799957999679997799987999980000800018000280003800048000580006800078000880009800108001180012800138001480015800168001780018800198002080021800228002380024800258002680027800288002980030800318003280033800348003580036800378003880039800408004180042800438004480045800468004780048800498005080051800528005380054800558005680057800588005980060800618006280063800648006580066800678006880069800708007180072800738007480075800768007780078800798008080081800828008380084800858008680087800888008980090800918009280093800948009580096800978009880099801008010180102801038010480105801068010780108801098011080111801128011380114801158011680117801188011980120801218012280123801248012580126801278012880129801308013180132801338013480135801368013780138801398014080141801428014380144801458014680147801488014980150801518015280153801548015580156801578015880159801608016180162801638016480165801668016780168801698017080171801728017380174801758017680177801788017980180801818018280183801848018580186801878018880189801908019180192801938019480195801968019780198801998020080201802028020380204802058020680207802088020980210802118021280213802148021580216802178021880219802208022180222802238022480225802268022780228802298023080231802328023380234802358023680237802388023980240802418024280243802448024580246802478024880249802508025180252802538025480255802568025780258802598026080261802628026380264802658026680267802688026980270802718027280273802748027580276802778027880279802808028180282802838028480285802868028780288802898029080291802928029380294802958029680297802988029980300803018030280303803048030580306803078030880309803108031180312803138031480315803168031780318803198032080321803228032380324803258032680327803288032980330803318033280333803348033580336803378033880339803408034180342803438034480345803468034780348803498035080351803528035380354803558035680357803588035980360803618036280363803648036580366803678036880369803708037180372803738037480375803768037780378803798038080381803828038380384803858038680387803888038980390803918039280393803948039580396803978039880399804008040180402804038040480405804068040780408804098041080411804128041380414804158041680417804188041980420804218042280423804248042580426804278042880429804308043180432804338043480435804368043780438804398044080441804428044380444804458044680447804488044980450804518045280453804548045580456804578045880459804608046180462804638046480465804668046780468804698047080471804728047380474804758047680477804788047980480804818048280483804848048580486804878048880489804908049180492804938049480495804968049780498804998050080501805028050380504805058050680507805088050980510805118051280513805148051580516805178051880519805208052180522805238052480525805268052780528805298053080531805328053380534805358053680537805388053980540805418054280543805448054580546805478054880549805508055180552805538055480555805568055780558805598056080561805628056380564805658056680567805688056980570805718057280573805748057580576805778057880579805808058180582805838058480585805868058780588805898059080591805928059380594805958059680597805988059980600806018060280603806048060580606806078060880609806108061180612806138061480615806168061780618806198062080621806228062380624806258062680627806288062980630806318063280633806348063580636806378063880639806408064180642806438064480645806468064780648806498065080651806528065380654806558065680657806588065980660806618066280663806648066580666806678066880669806708067180672806738067480675806768067780678806798068080681806828068380684806858068680687806888068980690806918069280693806948069580696806978069880699807008070180702807038070480705807068070780708807098071080711807128071380714807158071680717807188071980720807218072280723807248072580726807278072880729807308073180732807338073480735807368073780738807398074080741807428074380744807458074680747807488074980750807518075280753807548075580756807578075880759807608076180762807638076480765807668076780768807698077080771807728077380774807758077680777807788077980780807818078280783807848078580786807878078880789807908079180792807938079480795807968079780798807998080080801808028080380804808058080680807808088080980810808118081280813808148081580816808178081880819808208082180822808238082480825808268082780828808298083080831808328083380834808358083680837808388083980840808418084280843808448084580846808478084880849808508085180852808538085480855808568085780858808598086080861808628086380864808658086680867808688086980870808718087280873808748087580876808778087880879808808088180882808838088480885808868088780888808898089080891808928089380894808958089680897808988089980900809018090280903809048090580906809078090880909809108091180912809138091480915809168091780918809198092080921809228092380924809258092680927809288092980930809318093280933809348093580936809378093880939809408094180942809438094480945809468094780948809498095080951809528095380954809558095680957809588095980960809618096280963809648096580966809678096880969809708097180972809738097480975809768097780978809798098080981809828098380984809858098680987809888098980990809918099280993809948099580996809978099880999810008100181002810038100481005810068100781008810098101081011810128101381014810158101681017810188101981020810218102281023810248102581026810278102881029810308103181032810338103481035810368103781038810398104081041810428104381044810458104681047810488104981050810518105281053810548105581056810578105881059810608106181062810638106481065810668106781068810698107081071810728107381074810758107681077810788107981080810818108281083810848108581086810878108881089810908109181092810938109481095810968109781098810998110081101811028110381104811058110681107811088110981110811118111281113811148111581116811178111881119811208112181122811238112481125811268112781128811298113081131811328113381134811358113681137811388113981140811418114281143811448114581146811478114881149811508115181152811538115481155811568115781158811598116081161811628116381164811658116681167811688116981170811718117281173811748117581176811778117881179811808118181182811838118481185811868118781188811898119081191811928119381194811958119681197811988119981200812018120281203812048120581206812078120881209812108121181212812138121481215812168121781218812198122081221812228122381224812258122681227812288122981230812318123281233812348123581236812378123881239812408124181242812438124481245812468124781248812498125081251812528125381254812558125681257812588125981260812618126281263812648126581266812678126881269812708127181272812738127481275812768127781278812798128081281812828128381284812858128681287812888128981290812918129281293812948129581296812978129881299813008130181302813038130481305813068130781308813098131081311813128131381314813158131681317813188131981320813218132281323813248132581326813278132881329813308133181332813338133481335813368133781338813398134081341813428134381344813458134681347813488134981350813518135281353813548135581356813578135881359813608136181362813638136481365813668136781368813698137081371813728137381374813758137681377813788137981380813818138281383813848138581386813878138881389813908139181392813938139481395813968139781398813998140081401814028140381404814058140681407814088140981410814118141281413814148141581416814178141881419814208142181422814238142481425814268142781428814298143081431814328143381434814358143681437814388143981440814418144281443814448144581446814478144881449814508145181452814538145481455814568145781458814598146081461814628146381464814658146681467814688146981470814718147281473814748147581476814778147881479814808148181482814838148481485814868148781488814898149081491814928149381494814958149681497814988149981500815018150281503815048150581506815078150881509815108151181512815138151481515815168151781518815198152081521815228152381524815258152681527815288152981530815318153281533815348153581536815378153881539815408154181542815438154481545815468154781548815498155081551815528155381554815558155681557815588155981560815618156281563815648156581566815678156881569815708157181572815738157481575815768157781578815798158081581815828158381584815858158681587815888158981590815918159281593815948159581596815978159881599816008160181602816038160481605816068160781608816098161081611816128161381614816158161681617816188161981620816218162281623816248162581626816278162881629816308163181632816338163481635816368163781638816398164081641816428164381644816458164681647816488164981650816518165281653816548165581656816578165881659816608166181662816638166481665816668166781668816698167081671816728167381674816758167681677816788167981680816818168281683816848168581686816878168881689816908169181692816938169481695816968169781698816998170081701817028170381704817058170681707817088170981710817118171281713817148171581716817178171881719817208172181722817238172481725817268172781728817298173081731817328173381734817358173681737817388173981740817418174281743817448174581746817478174881749817508175181752817538175481755817568175781758817598176081761817628176381764817658176681767817688176981770817718177281773817748177581776817778177881779817808178181782817838178481785817868178781788817898179081791817928179381794817958179681797817988179981800818018180281803818048180581806818078180881809818108181181812818138181481815818168181781818818198182081821818228182381824818258182681827818288182981830818318183281833818348183581836818378183881839818408184181842818438184481845818468184781848818498185081851818528185381854818558185681857818588185981860818618186281863818648186581866818678186881869818708187181872818738187481875818768187781878818798188081881818828188381884818858188681887818888188981890818918189281893818948189581896818978189881899819008190181902819038190481905819068190781908819098191081911819128191381914819158191681917819188191981920819218192281923819248192581926819278192881929819308193181932819338193481935819368193781938819398194081941819428194381944819458194681947819488194981950819518195281953819548195581956819578195881959819608196181962819638196481965819668196781968819698197081971819728197381974819758197681977819788197981980819818198281983819848198581986819878198881989819908199181992819938199481995819968199781998819998200082001820028200382004820058200682007820088200982010820118201282013820148201582016820178201882019820208202182022820238202482025820268202782028820298203082031820328203382034820358203682037820388203982040820418204282043820448204582046820478204882049820508205182052820538205482055820568205782058820598206082061820628206382064820658206682067820688206982070820718207282073820748207582076820778207882079820808208182082820838208482085820868208782088820898209082091820928209382094820958209682097820988209982100821018210282103821048210582106821078210882109821108211182112821138211482115821168211782118821198212082121821228212382124821258212682127821288212982130821318213282133821348213582136821378213882139821408214182142821438214482145821468214782148821498215082151821528215382154821558215682157821588215982160821618216282163821648216582166821678216882169821708217182172821738217482175821768217782178821798218082181821828218382184821858218682187821888218982190821918219282193821948219582196821978219882199822008220182202822038220482205822068220782208822098221082211822128221382214822158221682217822188221982220822218222282223822248222582226822278222882229822308223182232822338223482235822368223782238822398224082241822428224382244822458224682247822488224982250822518225282253822548225582256822578225882259822608226182262822638226482265822668226782268822698227082271822728227382274822758227682277822788227982280822818228282283822848228582286822878228882289822908229182292822938229482295822968229782298822998230082301823028230382304823058230682307823088230982310823118231282313823148231582316823178231882319823208232182322823238232482325823268232782328823298233082331823328233382334823358233682337823388233982340823418234282343823448234582346823478234882349823508235182352823538235482355823568235782358823598236082361823628236382364823658236682367823688236982370823718237282373823748237582376823778237882379823808238182382823838238482385823868238782388823898239082391823928239382394823958239682397823988239982400824018240282403824048240582406824078240882409824108241182412824138241482415824168241782418824198242082421824228242382424824258242682427824288242982430824318243282433824348243582436824378243882439824408244182442824438244482445824468244782448824498245082451824528245382454824558245682457824588245982460824618246282463824648246582466824678246882469824708247182472824738247482475824768247782478824798248082481824828248382484824858248682487824888248982490824918249282493824948249582496824978249882499825008250182502825038250482505825068250782508825098251082511825128251382514825158251682517825188251982520825218252282523825248252582526825278252882529825308253182532825338253482535825368253782538825398254082541825428254382544825458254682547825488254982550825518255282553825548255582556825578255882559825608256182562825638256482565825668256782568825698257082571825728257382574825758257682577825788257982580825818258282583825848258582586825878258882589825908259182592825938259482595825968259782598825998260082601826028260382604826058260682607826088260982610826118261282613826148261582616826178261882619826208262182622826238262482625826268262782628826298263082631826328263382634826358263682637826388263982640826418264282643826448264582646826478264882649826508265182652826538265482655826568265782658826598266082661826628266382664826658266682667826688266982670826718267282673826748267582676826778267882679826808268182682826838268482685826868268782688826898269082691826928269382694826958269682697826988269982700827018270282703827048270582706827078270882709827108271182712827138271482715827168271782718827198272082721827228272382724827258272682727827288272982730827318273282733827348273582736827378273882739827408274182742827438274482745827468274782748827498275082751827528275382754827558275682757827588275982760827618276282763827648276582766827678276882769827708277182772827738277482775827768277782778827798278082781827828278382784827858278682787827888278982790827918279282793827948279582796827978279882799828008280182802828038280482805828068280782808828098281082811828128281382814828158281682817828188281982820828218282282823828248282582826828278282882829828308283182832828338283482835828368283782838828398284082841828428284382844828458284682847828488284982850828518285282853828548285582856828578285882859828608286182862828638286482865828668286782868828698287082871828728287382874828758287682877828788287982880828818288282883828848288582886828878288882889828908289182892828938289482895828968289782898828998290082901829028290382904829058290682907829088290982910829118291282913829148291582916829178291882919829208292182922829238292482925829268292782928829298293082931829328293382934829358293682937829388293982940829418294282943829448294582946829478294882949829508295182952829538295482955829568295782958829598296082961829628296382964829658296682967829688296982970829718297282973829748297582976829778297882979829808298182982829838298482985829868298782988829898299082991829928299382994829958299682997829988299983000830018300283003830048300583006830078300883009830108301183012830138301483015830168301783018830198302083021830228302383024830258302683027830288302983030830318303283033830348303583036830378303883039830408304183042830438304483045830468304783048830498305083051830528305383054830558305683057830588305983060830618306283063830648306583066830678306883069830708307183072830738307483075830768307783078830798308083081830828308383084830858308683087830888308983090830918309283093830948309583096830978309883099831008310183102831038310483105831068310783108831098311083111831128311383114831158311683117831188311983120831218312283123831248312583126831278312883129831308313183132831338313483135831368313783138831398314083141831428314383144831458314683147831488314983150831518315283153831548315583156831578315883159831608316183162831638316483165831668316783168831698317083171831728317383174831758317683177831788317983180831818318283183831848318583186831878318883189831908319183192831938319483195831968319783198831998320083201832028320383204832058320683207832088320983210832118321283213832148321583216832178321883219832208322183222832238322483225832268322783228832298323083231832328323383234832358323683237832388323983240832418324283243832448324583246832478324883249832508325183252832538325483255832568325783258832598326083261832628326383264832658326683267832688326983270832718327283273832748327583276832778327883279832808328183282832838328483285832868328783288832898329083291832928329383294832958329683297832988329983300833018330283303833048330583306833078330883309833108331183312833138331483315833168331783318833198332083321833228332383324833258332683327833288332983330833318333283333833348333583336833378333883339833408334183342833438334483345833468334783348833498335083351833528335383354833558335683357833588335983360833618336283363833648336583366833678336883369833708337183372833738337483375833768337783378833798338083381833828338383384833858338683387833888338983390833918339283393833948339583396833978339883399834008340183402834038340483405834068340783408834098341083411834128341383414834158341683417834188341983420834218342283423834248342583426834278342883429834308343183432834338343483435834368343783438834398344083441834428344383444834458344683447834488344983450834518345283453834548345583456834578345883459834608346183462834638346483465834668346783468834698347083471834728347383474834758347683477834788347983480834818348283483834848348583486834878348883489834908349183492834938349483495834968349783498834998350083501835028350383504835058350683507835088350983510835118351283513835148351583516835178351883519835208352183522835238352483525835268352783528835298353083531835328353383534835358353683537835388353983540835418354283543835448354583546835478354883549835508355183552835538355483555835568355783558835598356083561835628356383564835658356683567835688356983570835718357283573835748357583576835778357883579835808358183582835838358483585835868358783588835898359083591835928359383594835958359683597835988359983600836018360283603836048360583606836078360883609836108361183612836138361483615836168361783618836198362083621836228362383624836258362683627836288362983630836318363283633836348363583636836378363883639836408364183642836438364483645836468364783648836498365083651836528365383654836558365683657836588365983660836618366283663836648366583666836678366883669836708367183672836738367483675836768367783678836798368083681836828368383684836858368683687836888368983690836918369283693836948369583696836978369883699837008370183702837038370483705837068370783708837098371083711837128371383714837158371683717837188371983720837218372283723837248372583726837278372883729837308373183732837338373483735837368373783738837398374083741837428374383744837458374683747837488374983750837518375283753837548375583756837578375883759837608376183762837638376483765837668376783768837698377083771837728377383774837758377683777837788377983780837818378283783837848378583786837878378883789837908379183792837938379483795837968379783798837998380083801838028380383804838058380683807838088380983810838118381283813838148381583816838178381883819838208382183822838238382483825838268382783828838298383083831838328383383834838358383683837838388383983840838418384283843838448384583846838478384883849838508385183852838538385483855838568385783858838598386083861838628386383864838658386683867838688386983870838718387283873838748387583876838778387883879838808388183882838838388483885838868388783888838898389083891838928389383894838958389683897838988389983900839018390283903839048390583906839078390883909839108391183912839138391483915839168391783918839198392083921839228392383924839258392683927839288392983930839318393283933839348393583936839378393883939839408394183942839438394483945839468394783948839498395083951839528395383954839558395683957839588395983960839618396283963839648396583966839678396883969839708397183972839738397483975839768397783978839798398083981839828398383984839858398683987839888398983990839918399283993839948399583996839978399883999840008400184002840038400484005840068400784008840098401084011840128401384014840158401684017840188401984020840218402284023840248402584026840278402884029840308403184032840338403484035840368403784038840398404084041840428404384044840458404684047840488404984050840518405284053840548405584056840578405884059840608406184062840638406484065840668406784068840698407084071840728407384074840758407684077840788407984080840818408284083840848408584086840878408884089840908409184092840938409484095840968409784098840998410084101841028410384104841058410684107841088410984110841118411284113841148411584116841178411884119841208412184122841238412484125841268412784128841298413084131841328413384134841358413684137841388413984140841418414284143841448414584146841478414884149841508415184152841538415484155841568415784158841598416084161841628416384164841658416684167841688416984170841718417284173841748417584176841778417884179841808418184182841838418484185841868418784188841898419084191841928419384194841958419684197841988419984200842018420284203842048420584206842078420884209842108421184212842138421484215842168421784218842198422084221842228422384224842258422684227842288422984230842318423284233842348423584236842378423884239842408424184242842438424484245842468424784248842498425084251842528425384254842558425684257842588425984260842618426284263842648426584266842678426884269842708427184272842738427484275842768427784278842798428084281842828428384284842858428684287842888428984290842918429284293842948429584296842978429884299843008430184302843038430484305843068430784308843098431084311843128431384314843158431684317843188431984320843218432284323843248432584326843278432884329843308433184332843338433484335843368433784338843398434084341843428434384344843458434684347843488434984350843518435284353843548435584356843578435884359843608436184362843638436484365843668436784368843698437084371843728437384374843758437684377843788437984380843818438284383843848438584386843878438884389843908439184392843938439484395843968439784398843998440084401844028440384404844058440684407844088440984410844118441284413844148441584416844178441884419844208442184422844238442484425844268442784428844298443084431844328443384434844358443684437844388443984440844418444284443844448444584446844478444884449844508445184452844538445484455844568445784458844598446084461844628446384464844658446684467844688446984470844718447284473844748447584476844778447884479844808448184482844838448484485844868448784488844898449084491844928449384494844958449684497844988449984500845018450284503845048450584506845078450884509845108451184512845138451484515845168451784518845198452084521845228452384524845258452684527845288452984530845318453284533845348453584536845378453884539845408454184542845438454484545845468454784548845498455084551845528455384554845558455684557845588455984560845618456284563845648456584566845678456884569845708457184572845738457484575845768457784578845798458084581845828458384584845858458684587845888458984590845918459284593845948459584596845978459884599846008460184602846038460484605846068460784608846098461084611846128461384614846158461684617846188461984620846218462284623846248462584626846278462884629846308463184632846338463484635846368463784638846398464084641846428464384644846458464684647846488464984650846518465284653846548465584656846578465884659846608466184662846638466484665846668466784668846698467084671846728467384674846758467684677846788467984680846818468284683846848468584686846878468884689846908469184692846938469484695846968469784698846998470084701847028470384704847058470684707847088470984710847118471284713847148471584716847178471884719847208472184722847238472484725847268472784728847298473084731847328473384734847358473684737847388473984740847418474284743847448474584746847478474884749847508475184752847538475484755847568475784758847598476084761847628476384764847658476684767847688476984770847718477284773847748477584776847778477884779847808478184782847838478484785847868478784788847898479084791847928479384794847958479684797847988479984800848018480284803848048480584806848078480884809848108481184812848138481484815848168481784818848198482084821848228482384824848258482684827848288482984830848318483284833848348483584836848378483884839848408484184842848438484484845848468484784848848498485084851848528485384854848558485684857848588485984860848618486284863848648486584866848678486884869848708487184872848738487484875848768487784878848798488084881848828488384884848858488684887848888488984890848918489284893848948489584896848978489884899849008490184902849038490484905849068490784908849098491084911849128491384914849158491684917849188491984920849218492284923849248492584926849278492884929849308493184932849338493484935849368493784938849398494084941849428494384944849458494684947849488494984950849518495284953849548495584956849578495884959849608496184962849638496484965849668496784968849698497084971849728497384974849758497684977849788497984980849818498284983849848498584986849878498884989849908499184992849938499484995849968499784998849998500085001850028500385004850058500685007850088500985010850118501285013850148501585016850178501885019850208502185022850238502485025850268502785028850298503085031850328503385034850358503685037850388503985040850418504285043850448504585046850478504885049850508505185052850538505485055850568505785058850598506085061850628506385064850658506685067850688506985070850718507285073850748507585076850778507885079850808508185082850838508485085850868508785088850898509085091850928509385094850958509685097850988509985100851018510285103851048510585106851078510885109851108511185112851138511485115851168511785118851198512085121851228512385124851258512685127851288512985130851318513285133851348513585136851378513885139851408514185142851438514485145851468514785148851498515085151851528515385154851558515685157851588515985160851618516285163851648516585166851678516885169851708517185172851738517485175851768517785178851798518085181851828518385184851858518685187851888518985190851918519285193851948519585196851978519885199852008520185202852038520485205852068520785208852098521085211852128521385214852158521685217852188521985220852218522285223852248522585226852278522885229852308523185232852338523485235852368523785238852398524085241852428524385244852458524685247852488524985250852518525285253852548525585256852578525885259852608526185262852638526485265852668526785268852698527085271852728527385274852758527685277852788527985280852818528285283852848528585286852878528885289852908529185292852938529485295852968529785298852998530085301853028530385304853058530685307853088530985310853118531285313853148531585316853178531885319853208532185322853238532485325853268532785328853298533085331853328533385334853358533685337853388533985340853418534285343853448534585346853478534885349853508535185352853538535485355853568535785358853598536085361853628536385364853658536685367853688536985370853718537285373853748537585376853778537885379853808538185382853838538485385853868538785388853898539085391853928539385394853958539685397853988539985400854018540285403854048540585406854078540885409854108541185412854138541485415854168541785418854198542085421854228542385424854258542685427854288542985430854318543285433854348543585436854378543885439854408544185442854438544485445854468544785448854498545085451854528545385454854558545685457854588545985460854618546285463854648546585466854678546885469854708547185472854738547485475854768547785478854798548085481854828548385484854858548685487854888548985490854918549285493854948549585496854978549885499855008550185502855038550485505855068550785508855098551085511855128551385514855158551685517855188551985520855218552285523855248552585526855278552885529855308553185532855338553485535855368553785538855398554085541855428554385544855458554685547855488554985550855518555285553855548555585556855578555885559855608556185562855638556485565855668556785568855698557085571855728557385574855758557685577855788557985580855818558285583855848558585586855878558885589855908559185592855938559485595855968559785598855998560085601856028560385604856058560685607856088560985610856118561285613856148561585616856178561885619856208562185622856238562485625856268562785628856298563085631856328563385634856358563685637856388563985640856418564285643856448564585646856478564885649856508565185652856538565485655856568565785658856598566085661856628566385664856658566685667856688566985670856718567285673856748567585676856778567885679856808568185682856838568485685856868568785688856898569085691856928569385694856958569685697856988569985700857018570285703857048570585706857078570885709857108571185712857138571485715857168571785718857198572085721857228572385724857258572685727857288572985730857318573285733857348573585736857378573885739857408574185742857438574485745857468574785748857498575085751857528575385754857558575685757857588575985760857618576285763857648576585766857678576885769857708577185772857738577485775857768577785778857798578085781857828578385784857858578685787857888578985790857918579285793857948579585796857978579885799858008580185802858038580485805858068580785808858098581085811858128581385814858158581685817858188581985820858218582285823858248582585826858278582885829858308583185832858338583485835858368583785838858398584085841858428584385844858458584685847858488584985850858518585285853858548585585856858578585885859858608586185862858638586485865858668586785868858698587085871858728587385874858758587685877858788587985880858818588285883858848588585886858878588885889858908589185892858938589485895858968589785898858998590085901859028590385904859058590685907859088590985910859118591285913859148591585916859178591885919859208592185922859238592485925859268592785928859298593085931859328593385934859358593685937859388593985940859418594285943859448594585946859478594885949859508595185952859538595485955859568595785958859598596085961859628596385964859658596685967859688596985970859718597285973859748597585976859778597885979859808598185982859838598485985859868598785988859898599085991859928599385994859958599685997859988599986000860018600286003860048600586006860078600886009860108601186012860138601486015860168601786018860198602086021860228602386024860258602686027860288602986030860318603286033860348603586036860378603886039860408604186042860438604486045860468604786048860498605086051860528605386054860558605686057860588605986060860618606286063860648606586066860678606886069860708607186072860738607486075860768607786078860798608086081860828608386084860858608686087860888608986090860918609286093860948609586096860978609886099861008610186102861038610486105861068610786108861098611086111861128611386114861158611686117861188611986120861218612286123861248612586126861278612886129861308613186132861338613486135861368613786138861398614086141861428614386144861458614686147861488614986150861518615286153861548615586156861578615886159861608616186162861638616486165861668616786168861698617086171861728617386174861758617686177861788617986180861818618286183861848618586186861878618886189861908619186192861938619486195861968619786198861998620086201862028620386204862058620686207862088620986210862118621286213862148621586216862178621886219862208622186222862238622486225862268622786228862298623086231862328623386234862358623686237862388623986240862418624286243862448624586246862478624886249862508625186252862538625486255862568625786258862598626086261862628626386264862658626686267862688626986270862718627286273862748627586276862778627886279862808628186282862838628486285862868628786288862898629086291862928629386294862958629686297862988629986300863018630286303863048630586306863078630886309863108631186312863138631486315863168631786318863198632086321863228632386324863258632686327863288632986330863318633286333863348633586336863378633886339863408634186342863438634486345863468634786348863498635086351863528635386354863558635686357863588635986360863618636286363863648636586366863678636886369863708637186372863738637486375863768637786378863798638086381863828638386384863858638686387863888638986390863918639286393863948639586396863978639886399864008640186402864038640486405864068640786408864098641086411864128641386414864158641686417864188641986420864218642286423864248642586426864278642886429864308643186432864338643486435864368643786438864398644086441864428644386444864458644686447864488644986450864518645286453864548645586456864578645886459864608646186462864638646486465864668646786468864698647086471864728647386474864758647686477864788647986480864818648286483864848648586486864878648886489864908649186492864938649486495864968649786498864998650086501865028650386504865058650686507865088650986510865118651286513865148651586516865178651886519865208652186522865238652486525865268652786528865298653086531865328653386534865358653686537865388653986540865418654286543865448654586546865478654886549865508655186552865538655486555865568655786558865598656086561865628656386564865658656686567865688656986570865718657286573865748657586576865778657886579865808658186582865838658486585865868658786588865898659086591865928659386594865958659686597865988659986600866018660286603866048660586606866078660886609866108661186612866138661486615866168661786618866198662086621866228662386624866258662686627866288662986630866318663286633866348663586636866378663886639866408664186642866438664486645866468664786648866498665086651866528665386654866558665686657866588665986660866618666286663866648666586666866678666886669866708667186672866738667486675866768667786678866798668086681866828668386684866858668686687866888668986690866918669286693866948669586696866978669886699867008670186702867038670486705867068670786708867098671086711867128671386714867158671686717867188671986720867218672286723867248672586726867278672886729867308673186732867338673486735867368673786738867398674086741867428674386744867458674686747867488674986750867518675286753867548675586756867578675886759867608676186762867638676486765867668676786768867698677086771867728677386774867758677686777867788677986780867818678286783867848678586786867878678886789867908679186792867938679486795867968679786798867998680086801868028680386804868058680686807868088680986810868118681286813868148681586816868178681886819868208682186822868238682486825868268682786828868298683086831868328683386834868358683686837868388683986840868418684286843868448684586846868478684886849868508685186852868538685486855868568685786858868598686086861868628686386864868658686686867868688686986870868718687286873868748687586876868778687886879868808688186882868838688486885868868688786888868898689086891868928689386894868958689686897868988689986900869018690286903869048690586906869078690886909869108691186912869138691486915869168691786918869198692086921869228692386924869258692686927869288692986930869318693286933869348693586936869378693886939869408694186942869438694486945869468694786948869498695086951869528695386954869558695686957869588695986960869618696286963869648696586966869678696886969869708697186972869738697486975869768697786978869798698086981869828698386984869858698686987869888698986990869918699286993869948699586996869978699886999870008700187002870038700487005870068700787008870098701087011870128701387014870158701687017870188701987020870218702287023870248702587026870278702887029870308703187032870338703487035870368703787038870398704087041870428704387044870458704687047870488704987050870518705287053870548705587056870578705887059870608706187062870638706487065870668706787068870698707087071870728707387074870758707687077870788707987080870818708287083870848708587086870878708887089870908709187092870938709487095870968709787098870998710087101871028710387104871058710687107871088710987110871118711287113871148711587116871178711887119871208712187122871238712487125871268712787128871298713087131871328713387134871358713687137871388713987140871418714287143871448714587146871478714887149871508715187152871538715487155871568715787158871598716087161871628716387164871658716687167871688716987170871718717287173871748717587176871778717887179871808718187182871838718487185871868718787188871898719087191871928719387194871958719687197871988719987200872018720287203872048720587206872078720887209872108721187212872138721487215872168721787218872198722087221872228722387224872258722687227872288722987230872318723287233872348723587236872378723887239872408724187242872438724487245872468724787248872498725087251872528725387254872558725687257872588725987260872618726287263872648726587266872678726887269872708727187272872738727487275872768727787278872798728087281872828728387284872858728687287872888728987290872918729287293872948729587296872978729887299873008730187302873038730487305873068730787308873098731087311873128731387314873158731687317873188731987320873218732287323873248732587326873278732887329873308733187332873338733487335873368733787338873398734087341873428734387344873458734687347873488734987350873518735287353873548735587356873578735887359873608736187362873638736487365873668736787368873698737087371873728737387374873758737687377873788737987380873818738287383873848738587386873878738887389873908739187392873938739487395873968739787398873998740087401874028740387404874058740687407874088740987410874118741287413874148741587416874178741887419874208742187422874238742487425874268742787428874298743087431874328743387434874358743687437874388743987440874418744287443874448744587446874478744887449874508745187452874538745487455874568745787458874598746087461874628746387464874658746687467874688746987470874718747287473874748747587476874778747887479874808748187482874838748487485874868748787488874898749087491874928749387494874958749687497874988749987500875018750287503875048750587506875078750887509875108751187512875138751487515875168751787518875198752087521875228752387524875258752687527875288752987530875318753287533875348753587536875378753887539875408754187542875438754487545875468754787548875498755087551875528755387554875558755687557875588755987560875618756287563875648756587566875678756887569875708757187572875738757487575875768757787578875798758087581875828758387584875858758687587875888758987590875918759287593875948759587596875978759887599876008760187602876038760487605876068760787608876098761087611876128761387614876158761687617876188761987620876218762287623876248762587626876278762887629876308763187632876338763487635876368763787638876398764087641876428764387644876458764687647876488764987650876518765287653876548765587656876578765887659876608766187662876638766487665876668766787668876698767087671876728767387674876758767687677876788767987680876818768287683876848768587686876878768887689876908769187692876938769487695876968769787698876998770087701877028770387704877058770687707877088770987710877118771287713877148771587716877178771887719877208772187722877238772487725877268772787728877298773087731877328773387734877358773687737877388773987740877418774287743877448774587746877478774887749877508775187752877538775487755877568775787758877598776087761877628776387764877658776687767877688776987770877718777287773877748777587776877778777887779877808778187782877838778487785877868778787788877898779087791877928779387794877958779687797877988779987800878018780287803878048780587806878078780887809878108781187812878138781487815878168781787818878198782087821878228782387824878258782687827878288782987830878318783287833878348783587836878378783887839878408784187842878438784487845878468784787848878498785087851878528785387854878558785687857878588785987860878618786287863878648786587866878678786887869878708787187872878738787487875878768787787878878798788087881878828788387884878858788687887878888788987890878918789287893878948789587896878978789887899879008790187902879038790487905879068790787908879098791087911879128791387914879158791687917879188791987920879218792287923879248792587926879278792887929879308793187932879338793487935879368793787938879398794087941879428794387944879458794687947879488794987950879518795287953879548795587956879578795887959879608796187962879638796487965879668796787968879698797087971879728797387974879758797687977879788797987980879818798287983879848798587986879878798887989879908799187992879938799487995879968799787998879998800088001880028800388004880058800688007880088800988010880118801288013880148801588016880178801888019880208802188022880238802488025880268802788028880298803088031880328803388034880358803688037880388803988040880418804288043880448804588046880478804888049880508805188052880538805488055880568805788058880598806088061880628806388064880658806688067880688806988070880718807288073880748807588076880778807888079880808808188082880838808488085880868808788088880898809088091880928809388094880958809688097880988809988100881018810288103881048810588106881078810888109881108811188112881138811488115881168811788118881198812088121881228812388124881258812688127881288812988130881318813288133881348813588136881378813888139881408814188142881438814488145881468814788148881498815088151881528815388154881558815688157881588815988160881618816288163881648816588166881678816888169881708817188172881738817488175881768817788178881798818088181881828818388184881858818688187881888818988190881918819288193881948819588196881978819888199882008820188202882038820488205882068820788208882098821088211882128821388214882158821688217882188821988220882218822288223882248822588226882278822888229882308823188232882338823488235882368823788238882398824088241882428824388244882458824688247882488824988250882518825288253882548825588256882578825888259882608826188262882638826488265882668826788268882698827088271882728827388274882758827688277882788827988280882818828288283882848828588286882878828888289882908829188292882938829488295882968829788298882998830088301883028830388304883058830688307883088830988310883118831288313883148831588316883178831888319883208832188322883238832488325883268832788328883298833088331883328833388334883358833688337883388833988340883418834288343883448834588346883478834888349883508835188352883538835488355883568835788358883598836088361883628836388364883658836688367883688836988370883718837288373883748837588376883778837888379883808838188382883838838488385883868838788388883898839088391883928839388394883958839688397883988839988400884018840288403884048840588406884078840888409884108841188412884138841488415884168841788418884198842088421884228842388424884258842688427884288842988430884318843288433884348843588436884378843888439884408844188442884438844488445884468844788448884498845088451884528845388454884558845688457884588845988460884618846288463884648846588466884678846888469884708847188472884738847488475884768847788478884798848088481884828848388484884858848688487884888848988490884918849288493884948849588496884978849888499885008850188502885038850488505885068850788508885098851088511885128851388514885158851688517885188851988520885218852288523885248852588526885278852888529885308853188532885338853488535885368853788538885398854088541885428854388544885458854688547885488854988550885518855288553885548855588556885578855888559885608856188562885638856488565885668856788568885698857088571885728857388574885758857688577885788857988580885818858288583885848858588586885878858888589885908859188592885938859488595885968859788598885998860088601886028860388604886058860688607886088860988610886118861288613886148861588616886178861888619886208862188622886238862488625886268862788628886298863088631886328863388634886358863688637886388863988640886418864288643886448864588646886478864888649886508865188652886538865488655886568865788658886598866088661886628866388664886658866688667886688866988670886718867288673886748867588676886778867888679886808868188682886838868488685886868868788688886898869088691886928869388694886958869688697886988869988700887018870288703887048870588706887078870888709887108871188712887138871488715887168871788718887198872088721887228872388724887258872688727887288872988730887318873288733887348873588736887378873888739887408874188742887438874488745887468874788748887498875088751887528875388754887558875688757887588875988760887618876288763887648876588766887678876888769887708877188772887738877488775887768877788778887798878088781887828878388784887858878688787887888878988790887918879288793887948879588796887978879888799888008880188802888038880488805888068880788808888098881088811888128881388814888158881688817888188881988820888218882288823888248882588826888278882888829888308883188832888338883488835888368883788838888398884088841888428884388844888458884688847888488884988850888518885288853888548885588856888578885888859888608886188862888638886488865888668886788868888698887088871888728887388874888758887688877888788887988880888818888288883888848888588886888878888888889888908889188892888938889488895888968889788898888998890088901889028890388904889058890688907889088890988910889118891288913889148891588916889178891888919889208892188922889238892488925889268892788928889298893088931889328893388934889358893688937889388893988940889418894288943889448894588946889478894888949889508895188952889538895488955889568895788958889598896088961889628896388964889658896688967889688896988970889718897288973889748897588976889778897888979889808898188982889838898488985889868898788988889898899088991889928899388994889958899688997889988899989000890018900289003890048900589006890078900889009890108901189012890138901489015890168901789018890198902089021890228902389024890258902689027890288902989030890318903289033890348903589036890378903889039890408904189042890438904489045890468904789048890498905089051890528905389054890558905689057890588905989060890618906289063890648906589066890678906889069890708907189072890738907489075890768907789078890798908089081890828908389084890858908689087890888908989090890918909289093890948909589096890978909889099891008910189102891038910489105891068910789108891098911089111891128911389114891158911689117891188911989120891218912289123891248912589126891278912889129891308913189132891338913489135891368913789138891398914089141891428914389144891458914689147891488914989150891518915289153891548915589156891578915889159891608916189162891638916489165891668916789168891698917089171891728917389174891758917689177891788917989180891818918289183891848918589186891878918889189891908919189192891938919489195891968919789198891998920089201892028920389204892058920689207892088920989210892118921289213892148921589216892178921889219892208922189222892238922489225892268922789228892298923089231892328923389234892358923689237892388923989240892418924289243892448924589246892478924889249892508925189252892538925489255892568925789258892598926089261892628926389264892658926689267892688926989270892718927289273892748927589276892778927889279892808928189282892838928489285892868928789288892898929089291892928929389294892958929689297892988929989300893018930289303893048930589306893078930889309893108931189312893138931489315893168931789318893198932089321893228932389324893258932689327893288932989330893318933289333893348933589336893378933889339893408934189342893438934489345893468934789348893498935089351893528935389354893558935689357893588935989360893618936289363893648936589366893678936889369893708937189372893738937489375893768937789378893798938089381893828938389384893858938689387893888938989390893918939289393893948939589396893978939889399894008940189402894038940489405894068940789408894098941089411894128941389414894158941689417894188941989420894218942289423894248942589426894278942889429894308943189432894338943489435894368943789438894398944089441894428944389444894458944689447894488944989450894518945289453894548945589456894578945889459894608946189462894638946489465894668946789468894698947089471894728947389474894758947689477894788947989480894818948289483894848948589486894878948889489894908949189492894938949489495894968949789498894998950089501895028950389504895058950689507895088950989510895118951289513895148951589516895178951889519895208952189522895238952489525895268952789528895298953089531895328953389534895358953689537895388953989540895418954289543895448954589546895478954889549895508955189552895538955489555895568955789558895598956089561895628956389564895658956689567895688956989570895718957289573895748957589576895778957889579895808958189582895838958489585895868958789588895898959089591895928959389594895958959689597895988959989600896018960289603896048960589606896078960889609896108961189612896138961489615896168961789618896198962089621896228962389624896258962689627896288962989630896318963289633896348963589636896378963889639896408964189642896438964489645896468964789648896498965089651896528965389654896558965689657896588965989660896618966289663896648966589666896678966889669896708967189672896738967489675896768967789678896798968089681896828968389684896858968689687896888968989690896918969289693896948969589696896978969889699897008970189702897038970489705897068970789708897098971089711897128971389714897158971689717897188971989720897218972289723897248972589726897278972889729897308973189732897338973489735897368973789738897398974089741897428974389744897458974689747897488974989750897518975289753897548975589756897578975889759897608976189762897638976489765897668976789768897698977089771897728977389774897758977689777897788977989780897818978289783897848978589786897878978889789897908979189792897938979489795897968979789798897998980089801898028980389804898058980689807898088980989810898118981289813898148981589816898178981889819898208982189822898238982489825898268982789828898298983089831898328983389834898358983689837898388983989840898418984289843898448984589846898478984889849898508985189852898538985489855898568985789858898598986089861898628986389864898658986689867898688986989870898718987289873898748987589876898778987889879898808988189882898838988489885898868988789888898898989089891898928989389894898958989689897898988989989900899018990289903899048990589906899078990889909899108991189912899138991489915899168991789918899198992089921899228992389924899258992689927899288992989930899318993289933899348993589936899378993889939899408994189942899438994489945899468994789948899498995089951899528995389954899558995689957899588995989960899618996289963899648996589966899678996889969899708997189972899738997489975899768997789978899798998089981899828998389984899858998689987899888998989990899918999289993899948999589996899978999889999900009000190002900039000490005900069000790008900099001090011900129001390014900159001690017900189001990020900219002290023900249002590026900279002890029900309003190032900339003490035900369003790038900399004090041900429004390044900459004690047900489004990050900519005290053900549005590056900579005890059900609006190062900639006490065900669006790068900699007090071900729007390074900759007690077900789007990080900819008290083900849008590086900879008890089900909009190092900939009490095900969009790098900999010090101901029010390104901059010690107901089010990110901119011290113901149011590116901179011890119901209012190122901239012490125901269012790128901299013090131901329013390134901359013690137901389013990140901419014290143901449014590146901479014890149901509015190152901539015490155901569015790158901599016090161901629016390164901659016690167901689016990170901719017290173901749017590176901779017890179901809018190182901839018490185901869018790188901899019090191901929019390194901959019690197901989019990200902019020290203902049020590206902079020890209902109021190212902139021490215902169021790218902199022090221902229022390224902259022690227902289022990230902319023290233902349023590236902379023890239902409024190242902439024490245902469024790248902499025090251902529025390254902559025690257902589025990260902619026290263902649026590266902679026890269902709027190272902739027490275902769027790278902799028090281902829028390284902859028690287902889028990290902919029290293902949029590296902979029890299903009030190302903039030490305903069030790308903099031090311903129031390314903159031690317903189031990320903219032290323903249032590326903279032890329903309033190332903339033490335903369033790338903399034090341903429034390344903459034690347903489034990350903519035290353903549035590356903579035890359903609036190362903639036490365903669036790368903699037090371903729037390374903759037690377903789037990380903819038290383903849038590386903879038890389903909039190392903939039490395903969039790398903999040090401904029040390404904059040690407904089040990410904119041290413904149041590416904179041890419904209042190422904239042490425904269042790428904299043090431904329043390434904359043690437904389043990440904419044290443904449044590446904479044890449904509045190452904539045490455904569045790458904599046090461904629046390464904659046690467904689046990470904719047290473904749047590476904779047890479904809048190482904839048490485904869048790488904899049090491904929049390494904959049690497904989049990500905019050290503905049050590506905079050890509905109051190512905139051490515905169051790518905199052090521905229052390524905259052690527905289052990530905319053290533905349053590536905379053890539905409054190542905439054490545905469054790548905499055090551905529055390554905559055690557905589055990560905619056290563905649056590566905679056890569905709057190572905739057490575905769057790578905799058090581905829058390584905859058690587905889058990590905919059290593905949059590596905979059890599906009060190602906039060490605906069060790608906099061090611906129061390614906159061690617906189061990620906219062290623906249062590626906279062890629906309063190632906339063490635906369063790638906399064090641906429064390644906459064690647906489064990650906519065290653906549065590656906579065890659906609066190662906639066490665906669066790668906699067090671906729067390674906759067690677906789067990680906819068290683906849068590686906879068890689906909069190692906939069490695906969069790698906999070090701907029070390704907059070690707907089070990710907119071290713907149071590716907179071890719907209072190722907239072490725907269072790728907299073090731907329073390734907359073690737907389073990740907419074290743907449074590746907479074890749907509075190752907539075490755907569075790758907599076090761907629076390764907659076690767907689076990770907719077290773907749077590776907779077890779907809078190782907839078490785907869078790788907899079090791907929079390794907959079690797907989079990800908019080290803908049080590806908079080890809908109081190812908139081490815908169081790818908199082090821908229082390824908259082690827908289082990830908319083290833908349083590836908379083890839908409084190842908439084490845908469084790848908499085090851908529085390854908559085690857908589085990860908619086290863908649086590866908679086890869908709087190872908739087490875908769087790878908799088090881908829088390884908859088690887908889088990890908919089290893908949089590896908979089890899909009090190902909039090490905909069090790908909099091090911909129091390914909159091690917909189091990920909219092290923909249092590926909279092890929909309093190932909339093490935909369093790938909399094090941909429094390944909459094690947909489094990950909519095290953909549095590956909579095890959909609096190962909639096490965909669096790968909699097090971909729097390974909759097690977909789097990980909819098290983909849098590986909879098890989909909099190992909939099490995909969099790998909999100091001910029100391004910059100691007910089100991010910119101291013910149101591016910179101891019910209102191022910239102491025910269102791028910299103091031910329103391034910359103691037910389103991040910419104291043910449104591046910479104891049910509105191052910539105491055910569105791058910599106091061910629106391064910659106691067910689106991070910719107291073910749107591076910779107891079910809108191082910839108491085910869108791088910899109091091910929109391094910959109691097910989109991100911019110291103911049110591106911079110891109911109111191112911139111491115911169111791118911199112091121911229112391124911259112691127911289112991130911319113291133911349113591136911379113891139911409114191142911439114491145911469114791148911499115091151911529115391154911559115691157911589115991160911619116291163911649116591166911679116891169911709117191172911739117491175911769117791178911799118091181911829118391184911859118691187911889118991190911919119291193911949119591196911979119891199912009120191202912039120491205912069120791208912099121091211912129121391214912159121691217912189121991220912219122291223912249122591226912279122891229912309123191232912339123491235912369123791238912399124091241912429124391244912459124691247912489124991250912519125291253912549125591256912579125891259912609126191262912639126491265912669126791268912699127091271912729127391274912759127691277912789127991280912819128291283912849128591286912879128891289912909129191292912939129491295912969129791298912999130091301913029130391304913059130691307913089130991310913119131291313913149131591316913179131891319913209132191322913239132491325913269132791328913299133091331913329133391334913359133691337913389133991340913419134291343913449134591346913479134891349913509135191352913539135491355913569135791358913599136091361913629136391364913659136691367913689136991370913719137291373913749137591376913779137891379913809138191382913839138491385913869138791388913899139091391913929139391394913959139691397913989139991400914019140291403914049140591406914079140891409914109141191412914139141491415914169141791418914199142091421914229142391424914259142691427914289142991430914319143291433914349143591436914379143891439914409144191442914439144491445914469144791448914499145091451914529145391454914559145691457914589145991460914619146291463914649146591466914679146891469914709147191472914739147491475914769147791478914799148091481914829148391484914859148691487914889148991490914919149291493914949149591496914979149891499915009150191502915039150491505915069150791508915099151091511915129151391514915159151691517915189151991520915219152291523915249152591526915279152891529915309153191532915339153491535915369153791538915399154091541915429154391544915459154691547915489154991550915519155291553915549155591556915579155891559915609156191562915639156491565915669156791568915699157091571915729157391574915759157691577915789157991580915819158291583915849158591586915879158891589915909159191592915939159491595915969159791598915999160091601916029160391604916059160691607916089160991610916119161291613916149161591616916179161891619916209162191622916239162491625916269162791628916299163091631916329163391634916359163691637916389163991640916419164291643916449164591646916479164891649916509165191652916539165491655916569165791658916599166091661916629166391664916659166691667916689166991670916719167291673916749167591676916779167891679916809168191682916839168491685916869168791688916899169091691916929169391694916959169691697916989169991700917019170291703917049170591706917079170891709917109171191712917139171491715917169171791718917199172091721917229172391724917259172691727917289172991730917319173291733917349173591736917379173891739917409174191742917439174491745917469174791748917499175091751917529175391754917559175691757917589175991760917619176291763917649176591766917679176891769917709177191772917739177491775917769177791778917799178091781917829178391784917859178691787917889178991790917919179291793917949179591796917979179891799918009180191802918039180491805918069180791808918099181091811918129181391814918159181691817918189181991820918219182291823918249182591826918279182891829918309183191832918339183491835918369183791838918399184091841918429184391844918459184691847918489184991850918519185291853918549185591856918579185891859918609186191862918639186491865918669186791868918699187091871918729187391874918759187691877918789187991880918819188291883918849188591886918879188891889918909189191892918939189491895918969189791898918999190091901919029190391904919059190691907919089190991910919119191291913919149191591916919179191891919919209192191922919239192491925919269192791928919299193091931919329193391934919359193691937919389193991940919419194291943919449194591946919479194891949919509195191952919539195491955919569195791958919599196091961919629196391964919659196691967919689196991970919719197291973919749197591976919779197891979919809198191982919839198491985919869198791988919899199091991919929199391994919959199691997919989199992000920019200292003920049200592006920079200892009920109201192012920139201492015920169201792018920199202092021920229202392024920259202692027920289202992030920319203292033920349203592036920379203892039920409204192042920439204492045920469204792048920499205092051920529205392054920559205692057920589205992060920619206292063920649206592066920679206892069920709207192072920739207492075920769207792078920799208092081920829208392084920859208692087920889208992090920919209292093920949209592096920979209892099921009210192102921039210492105921069210792108921099211092111921129211392114921159211692117921189211992120921219212292123921249212592126921279212892129921309213192132921339213492135921369213792138921399214092141921429214392144921459214692147921489214992150921519215292153921549215592156921579215892159921609216192162921639216492165921669216792168921699217092171921729217392174921759217692177921789217992180921819218292183921849218592186921879218892189921909219192192921939219492195921969219792198921999220092201922029220392204922059220692207922089220992210922119221292213922149221592216922179221892219922209222192222922239222492225922269222792228922299223092231922329223392234922359223692237922389223992240922419224292243922449224592246922479224892249922509225192252922539225492255922569225792258922599226092261922629226392264922659226692267922689226992270922719227292273922749227592276922779227892279922809228192282922839228492285922869228792288922899229092291922929229392294922959229692297922989229992300923019230292303923049230592306923079230892309923109231192312923139231492315923169231792318923199232092321923229232392324923259232692327923289232992330923319233292333923349233592336923379233892339923409234192342923439234492345923469234792348923499235092351923529235392354923559235692357923589235992360923619236292363923649236592366923679236892369923709237192372923739237492375923769237792378923799238092381923829238392384923859238692387923889238992390923919239292393923949239592396923979239892399924009240192402924039240492405924069240792408924099241092411924129241392414924159241692417924189241992420924219242292423924249242592426924279242892429924309243192432924339243492435924369243792438924399244092441924429244392444924459244692447924489244992450924519245292453924549245592456924579245892459924609246192462924639246492465924669246792468924699247092471924729247392474924759247692477924789247992480924819248292483924849248592486924879248892489924909249192492924939249492495924969249792498924999250092501925029250392504925059250692507925089250992510925119251292513925149251592516925179251892519925209252192522925239252492525925269252792528925299253092531925329253392534925359253692537925389253992540925419254292543925449254592546925479254892549925509255192552925539255492555925569255792558925599256092561925629256392564925659256692567925689256992570925719257292573925749257592576925779257892579925809258192582925839258492585925869258792588925899259092591925929259392594925959259692597925989259992600926019260292603926049260592606926079260892609926109261192612926139261492615926169261792618926199262092621926229262392624926259262692627926289262992630926319263292633926349263592636926379263892639926409264192642926439264492645926469264792648926499265092651926529265392654926559265692657926589265992660926619266292663926649266592666926679266892669926709267192672926739267492675926769267792678926799268092681926829268392684926859268692687926889268992690926919269292693926949269592696926979269892699927009270192702927039270492705927069270792708927099271092711927129271392714927159271692717927189271992720927219272292723927249272592726927279272892729927309273192732927339273492735927369273792738927399274092741927429274392744927459274692747927489274992750927519275292753927549275592756927579275892759927609276192762927639276492765927669276792768927699277092771927729277392774927759277692777927789277992780927819278292783927849278592786927879278892789927909279192792927939279492795927969279792798927999280092801928029280392804928059280692807928089280992810928119281292813928149281592816928179281892819928209282192822928239282492825928269282792828928299283092831928329283392834928359283692837928389283992840928419284292843928449284592846928479284892849928509285192852928539285492855928569285792858928599286092861928629286392864928659286692867928689286992870928719287292873928749287592876928779287892879928809288192882928839288492885928869288792888928899289092891928929289392894928959289692897928989289992900929019290292903929049290592906929079290892909929109291192912929139291492915929169291792918929199292092921929229292392924929259292692927929289292992930929319293292933929349293592936929379293892939929409294192942929439294492945929469294792948929499295092951929529295392954929559295692957929589295992960929619296292963929649296592966929679296892969929709297192972929739297492975929769297792978929799298092981929829298392984929859298692987929889298992990929919299292993929949299592996929979299892999930009300193002930039300493005930069300793008930099301093011930129301393014930159301693017930189301993020930219302293023930249302593026930279302893029930309303193032930339303493035930369303793038930399304093041930429304393044930459304693047930489304993050930519305293053930549305593056930579305893059930609306193062930639306493065930669306793068930699307093071930729307393074930759307693077930789307993080930819308293083930849308593086930879308893089930909309193092930939309493095930969309793098930999310093101931029310393104931059310693107931089310993110931119311293113931149311593116931179311893119931209312193122931239312493125931269312793128931299313093131931329313393134931359313693137931389313993140931419314293143931449314593146931479314893149931509315193152931539315493155931569315793158931599316093161931629316393164931659316693167931689316993170931719317293173931749317593176931779317893179931809318193182931839318493185931869318793188931899319093191931929319393194931959319693197931989319993200932019320293203932049320593206932079320893209932109321193212932139321493215932169321793218932199322093221932229322393224932259322693227932289322993230932319323293233932349323593236932379323893239932409324193242932439324493245932469324793248932499325093251932529325393254932559325693257932589325993260932619326293263932649326593266932679326893269932709327193272932739327493275932769327793278932799328093281932829328393284932859328693287932889328993290932919329293293932949329593296932979329893299933009330193302933039330493305933069330793308933099331093311933129331393314933159331693317933189331993320933219332293323933249332593326933279332893329933309333193332933339333493335933369333793338933399334093341933429334393344933459334693347933489334993350933519335293353933549335593356933579335893359933609336193362933639336493365933669336793368933699337093371933729337393374933759337693377933789337993380933819338293383933849338593386933879338893389933909339193392933939339493395933969339793398933999340093401934029340393404934059340693407934089340993410934119341293413934149341593416934179341893419934209342193422934239342493425934269342793428934299343093431934329343393434934359343693437934389343993440934419344293443934449344593446934479344893449934509345193452934539345493455934569345793458934599346093461934629346393464934659346693467934689346993470934719347293473934749347593476934779347893479934809348193482934839348493485934869348793488934899349093491934929349393494934959349693497934989349993500935019350293503935049350593506935079350893509935109351193512935139351493515935169351793518935199352093521935229352393524935259352693527935289352993530935319353293533935349353593536935379353893539935409354193542935439354493545935469354793548935499355093551935529355393554935559355693557935589355993560935619356293563935649356593566935679356893569935709357193572935739357493575935769357793578935799358093581935829358393584935859358693587935889358993590935919359293593935949359593596935979359893599936009360193602936039360493605936069360793608936099361093611936129361393614936159361693617936189361993620936219362293623936249362593626936279362893629936309363193632936339363493635936369363793638936399364093641936429364393644936459364693647936489364993650936519365293653936549365593656936579365893659936609366193662936639366493665936669366793668936699367093671936729367393674936759367693677936789367993680936819368293683936849368593686936879368893689936909369193692936939369493695936969369793698936999370093701937029370393704937059370693707937089370993710937119371293713937149371593716937179371893719937209372193722937239372493725937269372793728937299373093731937329373393734937359373693737937389373993740937419374293743937449374593746937479374893749937509375193752937539375493755937569375793758937599376093761937629376393764937659376693767937689376993770937719377293773937749377593776937779377893779937809378193782937839378493785937869378793788937899379093791937929379393794937959379693797937989379993800938019380293803938049380593806938079380893809938109381193812938139381493815938169381793818938199382093821938229382393824938259382693827938289382993830938319383293833938349383593836938379383893839938409384193842938439384493845938469384793848938499385093851938529385393854938559385693857938589385993860938619386293863938649386593866938679386893869938709387193872938739387493875938769387793878938799388093881938829388393884938859388693887938889388993890938919389293893938949389593896938979389893899939009390193902939039390493905939069390793908
  1. // OpenLayers. See https://openlayers.org/
  2. // License: https://raw.githubusercontent.com/openlayers/openlayers/master/LICENSE.md
  3. // Version: v4.3.3
  4. ;(function (root, factory) {
  5. if (typeof exports === "object") {
  6. module.exports = factory();
  7. } else if (typeof define === "function" && define.amd) {
  8. define([], factory);
  9. } else {
  10. root.ol = factory();
  11. }
  12. }(this, function () {
  13. var OPENLAYERS = {};
  14. var goog = this.goog = {};
  15. this.CLOSURE_NO_DEPS = true;
  16. // Copyright 2006 The Closure Library Authors. All Rights Reserved.
  17. //
  18. // Licensed under the Apache License, Version 2.0 (the "License");
  19. // you may not use this file except in compliance with the License.
  20. // You may obtain a copy of the License at
  21. //
  22. // http://www.apache.org/licenses/LICENSE-2.0
  23. //
  24. // Unless required by applicable law or agreed to in writing, software
  25. // distributed under the License is distributed on an "AS-IS" BASIS,
  26. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  27. // See the License for the specific language governing permissions and
  28. // limitations under the License.
  29. /**
  30. * @fileoverview Bootstrap for the Google JS Library (Closure).
  31. *
  32. * In uncompiled mode base.js will attempt to load Closure's deps file, unless
  33. * the global <code>CLOSURE_NO_DEPS</code> is set to true. This allows projects
  34. * to include their own deps file(s) from different locations.
  35. *
  36. * Avoid including base.js more than once. This is strictly discouraged and not
  37. * supported. goog.require(...) won't work properly in that case.
  38. *
  39. * @provideGoog
  40. */
  41. /**
  42. * @define {boolean} Overridden to true by the compiler.
  43. */
  44. var COMPILED = false;
  45. /**
  46. * Base namespace for the Closure library. Checks to see goog is already
  47. * defined in the current scope before assigning to prevent clobbering if
  48. * base.js is loaded more than once.
  49. *
  50. * @const
  51. */
  52. var goog = goog || {};
  53. /**
  54. * Reference to the global context. In most cases this will be 'window'.
  55. */
  56. goog.global = this;
  57. /**
  58. * A hook for overriding the define values in uncompiled mode.
  59. *
  60. * In uncompiled mode, {@code CLOSURE_UNCOMPILED_DEFINES} may be defined before
  61. * loading base.js. If a key is defined in {@code CLOSURE_UNCOMPILED_DEFINES},
  62. * {@code goog.define} will use the value instead of the default value. This
  63. * allows flags to be overwritten without compilation (this is normally
  64. * accomplished with the compiler's "define" flag).
  65. *
  66. * Example:
  67. * <pre>
  68. * var CLOSURE_UNCOMPILED_DEFINES = {'goog.DEBUG': false};
  69. * </pre>
  70. *
  71. * @type {Object<string, (string|number|boolean)>|undefined}
  72. */
  73. goog.global.CLOSURE_UNCOMPILED_DEFINES;
  74. /**
  75. * A hook for overriding the define values in uncompiled or compiled mode,
  76. * like CLOSURE_UNCOMPILED_DEFINES but effective in compiled code. In
  77. * uncompiled code CLOSURE_UNCOMPILED_DEFINES takes precedence.
  78. *
  79. * Also unlike CLOSURE_UNCOMPILED_DEFINES the values must be number, boolean or
  80. * string literals or the compiler will emit an error.
  81. *
  82. * While any @define value may be set, only those set with goog.define will be
  83. * effective for uncompiled code.
  84. *
  85. * Example:
  86. * <pre>
  87. * var CLOSURE_DEFINES = {'goog.DEBUG': false} ;
  88. * </pre>
  89. *
  90. * @type {Object<string, (string|number|boolean)>|undefined}
  91. */
  92. goog.global.CLOSURE_DEFINES;
  93. /**
  94. * Returns true if the specified value is not undefined.
  95. *
  96. * @param {?} val Variable to test.
  97. * @return {boolean} Whether variable is defined.
  98. */
  99. goog.isDef = function(val) {
  100. // void 0 always evaluates to undefined and hence we do not need to depend on
  101. // the definition of the global variable named 'undefined'.
  102. return val !== void 0;
  103. };
  104. /**
  105. * Returns true if the specified value is a string.
  106. * @param {?} val Variable to test.
  107. * @return {boolean} Whether variable is a string.
  108. */
  109. goog.isString = function(val) {
  110. return typeof val == 'string';
  111. };
  112. /**
  113. * Returns true if the specified value is a boolean.
  114. * @param {?} val Variable to test.
  115. * @return {boolean} Whether variable is boolean.
  116. */
  117. goog.isBoolean = function(val) {
  118. return typeof val == 'boolean';
  119. };
  120. /**
  121. * Returns true if the specified value is a number.
  122. * @param {?} val Variable to test.
  123. * @return {boolean} Whether variable is a number.
  124. */
  125. goog.isNumber = function(val) {
  126. return typeof val == 'number';
  127. };
  128. /**
  129. * Builds an object structure for the provided namespace path, ensuring that
  130. * names that already exist are not overwritten. For example:
  131. * "a.b.c" -> a = {};a.b={};a.b.c={};
  132. * Used by goog.provide and goog.exportSymbol.
  133. * @param {string} name name of the object that this file defines.
  134. * @param {*=} opt_object the object to expose at the end of the path.
  135. * @param {Object=} opt_objectToExportTo The object to add the path to; default
  136. * is `goog.global`.
  137. * @private
  138. */
  139. goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) {
  140. var parts = name.split('.');
  141. var cur = opt_objectToExportTo || goog.global;
  142. // Internet Explorer exhibits strange behavior when throwing errors from
  143. // methods externed in this manner. See the testExportSymbolExceptions in
  144. // base_test.html for an example.
  145. if (!(parts[0] in cur) && cur.execScript) {
  146. cur.execScript('var ' + parts[0]);
  147. }
  148. for (var part; parts.length && (part = parts.shift());) {
  149. if (!parts.length && goog.isDef(opt_object)) {
  150. // last part and we have an object; use it
  151. cur[part] = opt_object;
  152. } else if (cur[part] && cur[part] !== Object.prototype[part]) {
  153. cur = cur[part];
  154. } else {
  155. cur = cur[part] = {};
  156. }
  157. }
  158. };
  159. /**
  160. * Defines a named value. In uncompiled mode, the value is retrieved from
  161. * CLOSURE_DEFINES or CLOSURE_UNCOMPILED_DEFINES if the object is defined and
  162. * has the property specified, and otherwise used the defined defaultValue.
  163. * When compiled the default can be overridden using the compiler
  164. * options or the value set in the CLOSURE_DEFINES object.
  165. *
  166. * @param {string} name The distinguished name to provide.
  167. * @param {string|number|boolean} defaultValue
  168. */
  169. goog.define = function(name, defaultValue) {
  170. var value = defaultValue;
  171. if (!COMPILED) {
  172. if (goog.global.CLOSURE_UNCOMPILED_DEFINES &&
  173. // Anti DOM-clobbering runtime check (b/37736576).
  174. /** @type {?} */ (goog.global.CLOSURE_UNCOMPILED_DEFINES).nodeType ===
  175. undefined &&
  176. Object.prototype.hasOwnProperty.call(
  177. goog.global.CLOSURE_UNCOMPILED_DEFINES, name)) {
  178. value = goog.global.CLOSURE_UNCOMPILED_DEFINES[name];
  179. } else if (
  180. goog.global.CLOSURE_DEFINES &&
  181. // Anti DOM-clobbering runtime check (b/37736576).
  182. /** @type {?} */ (goog.global.CLOSURE_DEFINES).nodeType === undefined &&
  183. Object.prototype.hasOwnProperty.call(
  184. goog.global.CLOSURE_DEFINES, name)) {
  185. value = goog.global.CLOSURE_DEFINES[name];
  186. }
  187. }
  188. goog.exportPath_(name, value);
  189. };
  190. /**
  191. * @define {boolean} DEBUG is provided as a convenience so that debugging code
  192. * that should not be included in a production. It can be easily stripped
  193. * by specifying --define goog.DEBUG=false to the Closure Compiler aka
  194. * JSCompiler. For example, most toString() methods should be declared inside an
  195. * "if (goog.DEBUG)" conditional because they are generally used for debugging
  196. * purposes and it is difficult for the JSCompiler to statically determine
  197. * whether they are used.
  198. */
  199. goog.define('goog.DEBUG', true);
  200. /**
  201. * @define {string} LOCALE defines the locale being used for compilation. It is
  202. * used to select locale specific data to be compiled in js binary. BUILD rule
  203. * can specify this value by "--define goog.LOCALE=<locale_name>" as a compiler
  204. * option.
  205. *
  206. * Take into account that the locale code format is important. You should use
  207. * the canonical Unicode format with hyphen as a delimiter. Language must be
  208. * lowercase, Language Script - Capitalized, Region - UPPERCASE.
  209. * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN.
  210. *
  211. * See more info about locale codes here:
  212. * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers
  213. *
  214. * For language codes you should use values defined by ISO 693-1. See it here
  215. * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from
  216. * this rule: the Hebrew language. For legacy reasons the old code (iw) should
  217. * be used instead of the new code (he).
  218. *
  219. */
  220. goog.define('goog.LOCALE', 'en'); // default to en
  221. /**
  222. * @define {boolean} Whether this code is running on trusted sites.
  223. *
  224. * On untrusted sites, several native functions can be defined or overridden by
  225. * external libraries like Prototype, Datejs, and JQuery and setting this flag
  226. * to false forces closure to use its own implementations when possible.
  227. *
  228. * If your JavaScript can be loaded by a third party site and you are wary about
  229. * relying on non-standard implementations, specify
  230. * "--define goog.TRUSTED_SITE=false" to the compiler.
  231. */
  232. goog.define('goog.TRUSTED_SITE', true);
  233. /**
  234. * @define {boolean} Whether a project is expected to be running in strict mode.
  235. *
  236. * This define can be used to trigger alternate implementations compatible with
  237. * running in EcmaScript Strict mode or warn about unavailable functionality.
  238. * @see https://goo.gl/PudQ4y
  239. *
  240. */
  241. goog.define('goog.STRICT_MODE_COMPATIBLE', false);
  242. /**
  243. * @define {boolean} Whether code that calls {@link goog.setTestOnly} should
  244. * be disallowed in the compilation unit.
  245. */
  246. goog.define('goog.DISALLOW_TEST_ONLY_CODE', COMPILED && !goog.DEBUG);
  247. /**
  248. * @define {boolean} Whether to use a Chrome app CSP-compliant method for
  249. * loading scripts via goog.require. @see appendScriptSrcNode_.
  250. */
  251. goog.define('goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING', false);
  252. /**
  253. * Defines a namespace in Closure.
  254. *
  255. * A namespace may only be defined once in a codebase. It may be defined using
  256. * goog.provide() or goog.module().
  257. *
  258. * The presence of one or more goog.provide() calls in a file indicates
  259. * that the file defines the given objects/namespaces.
  260. * Provided symbols must not be null or undefined.
  261. *
  262. * In addition, goog.provide() creates the object stubs for a namespace
  263. * (for example, goog.provide("goog.foo.bar") will create the object
  264. * goog.foo.bar if it does not already exist).
  265. *
  266. * Build tools also scan for provide/require/module statements
  267. * to discern dependencies, build dependency files (see deps.js), etc.
  268. *
  269. * @see goog.require
  270. * @see goog.module
  271. * @param {string} name Namespace provided by this file in the form
  272. * "goog.package.part".
  273. */
  274. goog.provide = function(name) {
  275. if (goog.isInModuleLoader_()) {
  276. throw Error('goog.provide can not be used within a goog.module.');
  277. }
  278. if (!COMPILED) {
  279. // Ensure that the same namespace isn't provided twice.
  280. // A goog.module/goog.provide maps a goog.require to a specific file
  281. if (goog.isProvided_(name)) {
  282. throw Error('Namespace "' + name + '" already declared.');
  283. }
  284. }
  285. goog.constructNamespace_(name);
  286. };
  287. /**
  288. * @param {string} name Namespace provided by this file in the form
  289. * "goog.package.part".
  290. * @param {Object=} opt_obj The object to embed in the namespace.
  291. * @private
  292. */
  293. goog.constructNamespace_ = function(name, opt_obj) {
  294. if (!COMPILED) {
  295. delete goog.implicitNamespaces_[name];
  296. var namespace = name;
  297. while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) {
  298. if (goog.getObjectByName(namespace)) {
  299. break;
  300. }
  301. goog.implicitNamespaces_[namespace] = true;
  302. }
  303. }
  304. goog.exportPath_(name, opt_obj);
  305. };
  306. /**
  307. * Module identifier validation regexp.
  308. * Note: This is a conservative check, it is very possible to be more lenient,
  309. * the primary exclusion here is "/" and "\" and a leading ".", these
  310. * restrictions are intended to leave the door open for using goog.require
  311. * with relative file paths rather than module identifiers.
  312. * @private
  313. */
  314. goog.VALID_MODULE_RE_ = /^[a-zA-Z_$][a-zA-Z0-9._$]*$/;
  315. /**
  316. * Defines a module in Closure.
  317. *
  318. * Marks that this file must be loaded as a module and claims the namespace.
  319. *
  320. * A namespace may only be defined once in a codebase. It may be defined using
  321. * goog.provide() or goog.module().
  322. *
  323. * goog.module() has three requirements:
  324. * - goog.module may not be used in the same file as goog.provide.
  325. * - goog.module must be the first statement in the file.
  326. * - only one goog.module is allowed per file.
  327. *
  328. * When a goog.module annotated file is loaded, it is enclosed in
  329. * a strict function closure. This means that:
  330. * - any variables declared in a goog.module file are private to the file
  331. * (not global), though the compiler is expected to inline the module.
  332. * - The code must obey all the rules of "strict" JavaScript.
  333. * - the file will be marked as "use strict"
  334. *
  335. * NOTE: unlike goog.provide, goog.module does not declare any symbols by
  336. * itself. If declared symbols are desired, use
  337. * goog.module.declareLegacyNamespace().
  338. *
  339. *
  340. * See the public goog.module proposal: http://goo.gl/Va1hin
  341. *
  342. * @param {string} name Namespace provided by this file in the form
  343. * "goog.package.part", is expected but not required.
  344. * @return {void}
  345. */
  346. goog.module = function(name) {
  347. if (!goog.isString(name) || !name ||
  348. name.search(goog.VALID_MODULE_RE_) == -1) {
  349. throw Error('Invalid module identifier');
  350. }
  351. if (!goog.isInModuleLoader_()) {
  352. throw Error(
  353. 'Module ' + name + ' has been loaded incorrectly. Note, ' +
  354. 'modules cannot be loaded as normal scripts. They require some kind of ' +
  355. 'pre-processing step. You\'re likely trying to load a module via a ' +
  356. 'script tag or as a part of a concatenated bundle without rewriting the ' +
  357. 'module. For more info see: ' +
  358. 'https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide.');
  359. }
  360. if (goog.moduleLoaderState_.moduleName) {
  361. throw Error('goog.module may only be called once per module.');
  362. }
  363. // Store the module name for the loader.
  364. goog.moduleLoaderState_.moduleName = name;
  365. if (!COMPILED) {
  366. // Ensure that the same namespace isn't provided twice.
  367. // A goog.module/goog.provide maps a goog.require to a specific file
  368. if (goog.isProvided_(name)) {
  369. throw Error('Namespace "' + name + '" already declared.');
  370. }
  371. delete goog.implicitNamespaces_[name];
  372. }
  373. };
  374. /**
  375. * @param {string} name The module identifier.
  376. * @return {?} The module exports for an already loaded module or null.
  377. *
  378. * Note: This is not an alternative to goog.require, it does not
  379. * indicate a hard dependency, instead it is used to indicate
  380. * an optional dependency or to access the exports of a module
  381. * that has already been loaded.
  382. * @suppress {missingProvide}
  383. */
  384. goog.module.get = function(name) {
  385. return goog.module.getInternal_(name);
  386. };
  387. /**
  388. * @param {string} name The module identifier.
  389. * @return {?} The module exports for an already loaded module or null.
  390. * @private
  391. */
  392. goog.module.getInternal_ = function(name) {
  393. if (!COMPILED) {
  394. if (name in goog.loadedModules_) {
  395. return goog.loadedModules_[name];
  396. } else if (!goog.implicitNamespaces_[name]) {
  397. var ns = goog.getObjectByName(name);
  398. return ns != null ? ns : null;
  399. }
  400. }
  401. return null;
  402. };
  403. /**
  404. * @private {?{moduleName: (string|undefined), declareLegacyNamespace:boolean}}
  405. */
  406. goog.moduleLoaderState_ = null;
  407. /**
  408. * @private
  409. * @return {boolean} Whether a goog.module is currently being initialized.
  410. */
  411. goog.isInModuleLoader_ = function() {
  412. return goog.moduleLoaderState_ != null;
  413. };
  414. /**
  415. * Provide the module's exports as a globally accessible object under the
  416. * module's declared name. This is intended to ease migration to goog.module
  417. * for files that have existing usages.
  418. * @suppress {missingProvide}
  419. */
  420. goog.module.declareLegacyNamespace = function() {
  421. if (!COMPILED && !goog.isInModuleLoader_()) {
  422. throw new Error(
  423. 'goog.module.declareLegacyNamespace must be called from ' +
  424. 'within a goog.module');
  425. }
  426. if (!COMPILED && !goog.moduleLoaderState_.moduleName) {
  427. throw Error(
  428. 'goog.module must be called prior to ' +
  429. 'goog.module.declareLegacyNamespace.');
  430. }
  431. goog.moduleLoaderState_.declareLegacyNamespace = true;
  432. };
  433. /**
  434. * Marks that the current file should only be used for testing, and never for
  435. * live code in production.
  436. *
  437. * In the case of unit tests, the message may optionally be an exact namespace
  438. * for the test (e.g. 'goog.stringTest'). The linter will then ignore the extra
  439. * provide (if not explicitly defined in the code).
  440. *
  441. * @param {string=} opt_message Optional message to add to the error that's
  442. * raised when used in production code.
  443. */
  444. goog.setTestOnly = function(opt_message) {
  445. if (goog.DISALLOW_TEST_ONLY_CODE) {
  446. opt_message = opt_message || '';
  447. throw Error(
  448. 'Importing test-only code into non-debug environment' +
  449. (opt_message ? ': ' + opt_message : '.'));
  450. }
  451. };
  452. /**
  453. * Forward declares a symbol. This is an indication to the compiler that the
  454. * symbol may be used in the source yet is not required and may not be provided
  455. * in compilation.
  456. *
  457. * The most common usage of forward declaration is code that takes a type as a
  458. * function parameter but does not need to require it. By forward declaring
  459. * instead of requiring, no hard dependency is made, and (if not required
  460. * elsewhere) the namespace may never be required and thus, not be pulled
  461. * into the JavaScript binary. If it is required elsewhere, it will be type
  462. * checked as normal.
  463. *
  464. * Before using goog.forwardDeclare, please read the documentation at
  465. * https://github.com/google/closure-compiler/wiki/Bad-Type-Annotation to
  466. * understand the options and tradeoffs when working with forward declarations.
  467. *
  468. * @param {string} name The namespace to forward declare in the form of
  469. * "goog.package.part".
  470. */
  471. goog.forwardDeclare = function(name) {};
  472. /**
  473. * Forward declare type information. Used to assign types to goog.global
  474. * referenced object that would otherwise result in unknown type references
  475. * and thus block property disambiguation.
  476. */
  477. goog.forwardDeclare('Document');
  478. goog.forwardDeclare('HTMLScriptElement');
  479. goog.forwardDeclare('XMLHttpRequest');
  480. if (!COMPILED) {
  481. /**
  482. * Check if the given name has been goog.provided. This will return false for
  483. * names that are available only as implicit namespaces.
  484. * @param {string} name name of the object to look for.
  485. * @return {boolean} Whether the name has been provided.
  486. * @private
  487. */
  488. goog.isProvided_ = function(name) {
  489. return (name in goog.loadedModules_) ||
  490. (!goog.implicitNamespaces_[name] &&
  491. goog.isDefAndNotNull(goog.getObjectByName(name)));
  492. };
  493. /**
  494. * Namespaces implicitly defined by goog.provide. For example,
  495. * goog.provide('goog.events.Event') implicitly declares that 'goog' and
  496. * 'goog.events' must be namespaces.
  497. *
  498. * @type {!Object<string, (boolean|undefined)>}
  499. * @private
  500. */
  501. goog.implicitNamespaces_ = {'goog.module': true};
  502. // NOTE: We add goog.module as an implicit namespace as goog.module is defined
  503. // here and because the existing module package has not been moved yet out of
  504. // the goog.module namespace. This satisifies both the debug loader and
  505. // ahead-of-time dependency management.
  506. }
  507. /**
  508. * Returns an object based on its fully qualified external name. The object
  509. * is not found if null or undefined. If you are using a compilation pass that
  510. * renames property names beware that using this function will not find renamed
  511. * properties.
  512. *
  513. * @param {string} name The fully qualified name.
  514. * @param {Object=} opt_obj The object within which to look; default is
  515. * |goog.global|.
  516. * @return {?} The value (object or primitive) or, if not found, null.
  517. */
  518. goog.getObjectByName = function(name, opt_obj) {
  519. var parts = name.split('.');
  520. var cur = opt_obj || goog.global;
  521. for (var part; part = parts.shift();) {
  522. if (goog.isDefAndNotNull(cur[part])) {
  523. cur = cur[part];
  524. } else {
  525. return null;
  526. }
  527. }
  528. return cur;
  529. };
  530. /**
  531. * Globalizes a whole namespace, such as goog or goog.lang.
  532. *
  533. * @param {!Object} obj The namespace to globalize.
  534. * @param {Object=} opt_global The object to add the properties to.
  535. * @deprecated Properties may be explicitly exported to the global scope, but
  536. * this should no longer be done in bulk.
  537. */
  538. goog.globalize = function(obj, opt_global) {
  539. var global = opt_global || goog.global;
  540. for (var x in obj) {
  541. global[x] = obj[x];
  542. }
  543. };
  544. /**
  545. * Adds a dependency from a file to the files it requires.
  546. * @param {string} relPath The path to the js file.
  547. * @param {!Array<string>} provides An array of strings with
  548. * the names of the objects this file provides.
  549. * @param {!Array<string>} requires An array of strings with
  550. * the names of the objects this file requires.
  551. * @param {boolean|!Object<string>=} opt_loadFlags Parameters indicating
  552. * how the file must be loaded. The boolean 'true' is equivalent
  553. * to {'module': 'goog'} for backwards-compatibility. Valid properties
  554. * and values include {'module': 'goog'} and {'lang': 'es6'}.
  555. */
  556. goog.addDependency = function(relPath, provides, requires, opt_loadFlags) {
  557. if (goog.DEPENDENCIES_ENABLED) {
  558. var provide, require;
  559. var path = relPath.replace(/\\/g, '/');
  560. var deps = goog.dependencies_;
  561. if (!opt_loadFlags || typeof opt_loadFlags === 'boolean') {
  562. opt_loadFlags = opt_loadFlags ? {'module': 'goog'} : {};
  563. }
  564. for (var i = 0; provide = provides[i]; i++) {
  565. deps.nameToPath[provide] = path;
  566. deps.loadFlags[path] = opt_loadFlags;
  567. }
  568. for (var j = 0; require = requires[j]; j++) {
  569. if (!(path in deps.requires)) {
  570. deps.requires[path] = {};
  571. }
  572. deps.requires[path][require] = true;
  573. }
  574. }
  575. };
  576. // NOTE(nnaze): The debug DOM loader was included in base.js as an original way
  577. // to do "debug-mode" development. The dependency system can sometimes be
  578. // confusing, as can the debug DOM loader's asynchronous nature.
  579. //
  580. // With the DOM loader, a call to goog.require() is not blocking -- the script
  581. // will not load until some point after the current script. If a namespace is
  582. // needed at runtime, it needs to be defined in a previous script, or loaded via
  583. // require() with its registered dependencies.
  584. //
  585. // User-defined namespaces may need their own deps file. For a reference on
  586. // creating a deps file, see:
  587. // Externally: https://developers.google.com/closure/library/docs/depswriter
  588. //
  589. // Because of legacy clients, the DOM loader can't be easily removed from
  590. // base.js. Work is being done to make it disableable or replaceable for
  591. // different environments (DOM-less JavaScript interpreters like Rhino or V8,
  592. // for example). See bootstrap/ for more information.
  593. /**
  594. * @define {boolean} Whether to enable the debug loader.
  595. *
  596. * If enabled, a call to goog.require() will attempt to load the namespace by
  597. * appending a script tag to the DOM (if the namespace has been registered).
  598. *
  599. * If disabled, goog.require() will simply assert that the namespace has been
  600. * provided (and depend on the fact that some outside tool correctly ordered
  601. * the script).
  602. */
  603. goog.define('goog.ENABLE_DEBUG_LOADER', true);
  604. /**
  605. * @param {string} msg
  606. * @private
  607. */
  608. goog.logToConsole_ = function(msg) {
  609. if (goog.global.console) {
  610. goog.global.console['error'](msg);
  611. }
  612. };
  613. /**
  614. * Implements a system for the dynamic resolution of dependencies that works in
  615. * parallel with the BUILD system. Note that all calls to goog.require will be
  616. * stripped by the compiler.
  617. * @see goog.provide
  618. * @param {string} name Namespace to include (as was given in goog.provide()) in
  619. * the form "goog.package.part".
  620. * @return {?} If called within a goog.module file, the associated namespace or
  621. * module otherwise null.
  622. */
  623. goog.require = function(name) {
  624. // If the object already exists we do not need to do anything.
  625. if (!COMPILED) {
  626. if (goog.ENABLE_DEBUG_LOADER && goog.IS_OLD_IE_) {
  627. goog.maybeProcessDeferredDep_(name);
  628. }
  629. if (goog.isProvided_(name)) {
  630. if (goog.isInModuleLoader_()) {
  631. return goog.module.getInternal_(name);
  632. }
  633. } else if (goog.ENABLE_DEBUG_LOADER) {
  634. var path = goog.getPathFromDeps_(name);
  635. if (path) {
  636. goog.writeScripts_(path);
  637. } else {
  638. var errorMessage = 'goog.require could not find: ' + name;
  639. goog.logToConsole_(errorMessage);
  640. throw Error(errorMessage);
  641. }
  642. }
  643. return null;
  644. }
  645. };
  646. /**
  647. * Path for included scripts.
  648. * @type {string}
  649. */
  650. goog.basePath = '';
  651. /**
  652. * A hook for overriding the base path.
  653. * @type {string|undefined}
  654. */
  655. goog.global.CLOSURE_BASE_PATH;
  656. /**
  657. * Whether to attempt to load Closure's deps file. By default, when uncompiled,
  658. * deps files will attempt to be loaded.
  659. * @type {boolean|undefined}
  660. */
  661. goog.global.CLOSURE_NO_DEPS;
  662. /**
  663. * A function to import a single script. This is meant to be overridden when
  664. * Closure is being run in non-HTML contexts, such as web workers. It's defined
  665. * in the global scope so that it can be set before base.js is loaded, which
  666. * allows deps.js to be imported properly.
  667. *
  668. * The function is passed the script source, which is a relative URI. It should
  669. * return true if the script was imported, false otherwise.
  670. * @type {(function(string): boolean)|undefined}
  671. */
  672. goog.global.CLOSURE_IMPORT_SCRIPT;
  673. /**
  674. * Null function used for default values of callbacks, etc.
  675. * @return {void} Nothing.
  676. */
  677. goog.nullFunction = function() {};
  678. /**
  679. * When defining a class Foo with an abstract method bar(), you can do:
  680. * Foo.prototype.bar = goog.abstractMethod
  681. *
  682. * Now if a subclass of Foo fails to override bar(), an error will be thrown
  683. * when bar() is invoked.
  684. *
  685. * @type {!Function}
  686. * @throws {Error} when invoked to indicate the method should be overridden.
  687. */
  688. goog.abstractMethod = function() {
  689. throw Error('unimplemented abstract method');
  690. };
  691. /**
  692. * Adds a {@code getInstance} static method that always returns the same
  693. * instance object.
  694. * @param {!Function} ctor The constructor for the class to add the static
  695. * method to.
  696. */
  697. goog.addSingletonGetter = function(ctor) {
  698. // instance_ is immediately set to prevent issues with sealed constructors
  699. // such as are encountered when a constructor is returned as the export object
  700. // of a goog.module in unoptimized code.
  701. ctor.instance_ = undefined;
  702. ctor.getInstance = function() {
  703. if (ctor.instance_) {
  704. return ctor.instance_;
  705. }
  706. if (goog.DEBUG) {
  707. // NOTE: JSCompiler can't optimize away Array#push.
  708. goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor;
  709. }
  710. return ctor.instance_ = new ctor;
  711. };
  712. };
  713. /**
  714. * All singleton classes that have been instantiated, for testing. Don't read
  715. * it directly, use the {@code goog.testing.singleton} module. The compiler
  716. * removes this variable if unused.
  717. * @type {!Array<!Function>}
  718. * @private
  719. */
  720. goog.instantiatedSingletons_ = [];
  721. /**
  722. * @define {boolean} Whether to load goog.modules using {@code eval} when using
  723. * the debug loader. This provides a better debugging experience as the
  724. * source is unmodified and can be edited using Chrome Workspaces or similar.
  725. * However in some environments the use of {@code eval} is banned
  726. * so we provide an alternative.
  727. */
  728. goog.define('goog.LOAD_MODULE_USING_EVAL', true);
  729. /**
  730. * @define {boolean} Whether the exports of goog.modules should be sealed when
  731. * possible.
  732. */
  733. goog.define('goog.SEAL_MODULE_EXPORTS', goog.DEBUG);
  734. /**
  735. * The registry of initialized modules:
  736. * the module identifier to module exports map.
  737. * @private @const {!Object<string, ?>}
  738. */
  739. goog.loadedModules_ = {};
  740. /**
  741. * True if goog.dependencies_ is available.
  742. * @const {boolean}
  743. */
  744. goog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER;
  745. /**
  746. * @define {string} How to decide whether to transpile. Valid values
  747. * are 'always', 'never', and 'detect'. The default ('detect') is to
  748. * use feature detection to determine which language levels need
  749. * transpilation.
  750. */
  751. // NOTE(user): we could expand this to accept a language level to bypass
  752. // detection: e.g. goog.TRANSPILE == 'es5' would transpile ES6 files but
  753. // would leave ES3 and ES5 files alone.
  754. goog.define('goog.TRANSPILE', 'detect');
  755. /**
  756. * @define {string} Path to the transpiler. Executing the script at this
  757. * path (relative to base.js) should define a function $jscomp.transpile.
  758. */
  759. goog.define('goog.TRANSPILER', 'transpile.js');
  760. if (goog.DEPENDENCIES_ENABLED) {
  761. /**
  762. * This object is used to keep track of dependencies and other data that is
  763. * used for loading scripts.
  764. * @private
  765. * @type {{
  766. * loadFlags: !Object<string, !Object<string, string>>,
  767. * nameToPath: !Object<string, string>,
  768. * requires: !Object<string, !Object<string, boolean>>,
  769. * visited: !Object<string, boolean>,
  770. * written: !Object<string, boolean>,
  771. * deferred: !Object<string, string>
  772. * }}
  773. */
  774. goog.dependencies_ = {
  775. loadFlags: {}, // 1 to 1
  776. nameToPath: {}, // 1 to 1
  777. requires: {}, // 1 to many
  778. // Used when resolving dependencies to prevent us from visiting file twice.
  779. visited: {},
  780. written: {}, // Used to keep track of script files we have written.
  781. deferred: {} // Used to track deferred module evaluations in old IEs
  782. };
  783. /**
  784. * Tries to detect whether is in the context of an HTML document.
  785. * @return {boolean} True if it looks like HTML document.
  786. * @private
  787. */
  788. goog.inHtmlDocument_ = function() {
  789. /** @type {Document} */
  790. var doc = goog.global.document;
  791. return doc != null && 'write' in doc; // XULDocument misses write.
  792. };
  793. /**
  794. * Tries to detect the base path of base.js script that bootstraps Closure.
  795. * @private
  796. */
  797. goog.findBasePath_ = function() {
  798. if (goog.isDef(goog.global.CLOSURE_BASE_PATH) &&
  799. // Anti DOM-clobbering runtime check (b/37736576).
  800. goog.isString(goog.global.CLOSURE_BASE_PATH)) {
  801. goog.basePath = goog.global.CLOSURE_BASE_PATH;
  802. return;
  803. } else if (!goog.inHtmlDocument_()) {
  804. return;
  805. }
  806. /** @type {Document} */
  807. var doc = goog.global.document;
  808. // If we have a currentScript available, use it exclusively.
  809. var currentScript = doc.currentScript;
  810. if (currentScript) {
  811. var scripts = [currentScript];
  812. } else {
  813. var scripts = doc.getElementsByTagName('SCRIPT');
  814. }
  815. // Search backwards since the current script is in almost all cases the one
  816. // that has base.js.
  817. for (var i = scripts.length - 1; i >= 0; --i) {
  818. var script = /** @type {!HTMLScriptElement} */ (scripts[i]);
  819. var src = script.src;
  820. var qmark = src.lastIndexOf('?');
  821. var l = qmark == -1 ? src.length : qmark;
  822. if (src.substr(l - 7, 7) == 'base.js') {
  823. goog.basePath = src.substr(0, l - 7);
  824. return;
  825. }
  826. }
  827. };
  828. /**
  829. * Imports a script if, and only if, that script hasn't already been imported.
  830. * (Must be called at execution time)
  831. * @param {string} src Script source.
  832. * @param {string=} opt_sourceText The optionally source text to evaluate
  833. * @private
  834. */
  835. goog.importScript_ = function(src, opt_sourceText) {
  836. var importScript =
  837. goog.global.CLOSURE_IMPORT_SCRIPT || goog.writeScriptTag_;
  838. if (importScript(src, opt_sourceText)) {
  839. goog.dependencies_.written[src] = true;
  840. }
  841. };
  842. /**
  843. * Whether the browser is IE9 or earlier, which needs special handling
  844. * for deferred modules.
  845. * @const @private {boolean}
  846. */
  847. goog.IS_OLD_IE_ =
  848. !!(!goog.global.atob && goog.global.document && goog.global.document.all);
  849. /**
  850. * Whether IE9 or earlier is waiting on a dependency. This ensures that
  851. * deferred modules that have no non-deferred dependencies actually get
  852. * loaded, since if we defer them and then never pull in a non-deferred
  853. * script, then `goog.loadQueuedModules_` will never be called. Instead,
  854. * if not waiting on anything we simply don't defer in the first place.
  855. * @private {boolean}
  856. */
  857. goog.oldIeWaiting_ = false;
  858. /**
  859. * Given a URL initiate retrieval and execution of a script that needs
  860. * pre-processing.
  861. * @param {string} src Script source URL.
  862. * @param {boolean} isModule Whether this is a goog.module.
  863. * @param {boolean} needsTranspile Whether this source needs transpilation.
  864. * @private
  865. */
  866. goog.importProcessedScript_ = function(src, isModule, needsTranspile) {
  867. // In an attempt to keep browsers from timing out loading scripts using
  868. // synchronous XHRs, put each load in its own script block.
  869. var bootstrap = 'goog.retrieveAndExec_("' + src + '", ' + isModule + ', ' +
  870. needsTranspile + ');';
  871. goog.importScript_('', bootstrap);
  872. };
  873. /** @private {!Array<string>} */
  874. goog.queuedModules_ = [];
  875. /**
  876. * Return an appropriate module text. Suitable to insert into
  877. * a script tag (that is unescaped).
  878. * @param {string} srcUrl
  879. * @param {string} scriptText
  880. * @return {string}
  881. * @private
  882. */
  883. goog.wrapModule_ = function(srcUrl, scriptText) {
  884. if (!goog.LOAD_MODULE_USING_EVAL || !goog.isDef(goog.global.JSON)) {
  885. return '' +
  886. 'goog.loadModule(function(exports) {' +
  887. '"use strict";' + scriptText +
  888. '\n' + // terminate any trailing single line comment.
  889. ';return exports' +
  890. '});' +
  891. '\n//# sourceURL=' + srcUrl + '\n';
  892. } else {
  893. return '' +
  894. 'goog.loadModule(' +
  895. goog.global.JSON.stringify(
  896. scriptText + '\n//# sourceURL=' + srcUrl + '\n') +
  897. ');';
  898. }
  899. };
  900. // On IE9 and earlier, it is necessary to handle
  901. // deferred module loads. In later browsers, the
  902. // code to be evaluated is simply inserted as a script
  903. // block in the correct order. To eval deferred
  904. // code at the right time, we piggy back on goog.require to call
  905. // goog.maybeProcessDeferredDep_.
  906. //
  907. // The goog.requires are used both to bootstrap
  908. // the loading process (when no deps are available) and
  909. // declare that they should be available.
  910. //
  911. // Here we eval the sources, if all the deps are available
  912. // either already eval'd or goog.require'd. This will
  913. // be the case when all the dependencies have already
  914. // been loaded, and the dependent module is loaded.
  915. //
  916. // But this alone isn't sufficient because it is also
  917. // necessary to handle the case where there is no root
  918. // that is not deferred. For that there we register for an event
  919. // and trigger goog.loadQueuedModules_ handle any remaining deferred
  920. // evaluations.
  921. /**
  922. * Handle any remaining deferred goog.module evals.
  923. * @private
  924. */
  925. goog.loadQueuedModules_ = function() {
  926. var count = goog.queuedModules_.length;
  927. if (count > 0) {
  928. var queue = goog.queuedModules_;
  929. goog.queuedModules_ = [];
  930. for (var i = 0; i < count; i++) {
  931. var path = queue[i];
  932. goog.maybeProcessDeferredPath_(path);
  933. }
  934. }
  935. goog.oldIeWaiting_ = false;
  936. };
  937. /**
  938. * Eval the named module if its dependencies are
  939. * available.
  940. * @param {string} name The module to load.
  941. * @private
  942. */
  943. goog.maybeProcessDeferredDep_ = function(name) {
  944. if (goog.isDeferredModule_(name) && goog.allDepsAreAvailable_(name)) {
  945. var path = goog.getPathFromDeps_(name);
  946. goog.maybeProcessDeferredPath_(goog.basePath + path);
  947. }
  948. };
  949. /**
  950. * @param {string} name The module to check.
  951. * @return {boolean} Whether the name represents a
  952. * module whose evaluation has been deferred.
  953. * @private
  954. */
  955. goog.isDeferredModule_ = function(name) {
  956. var path = goog.getPathFromDeps_(name);
  957. var loadFlags = path && goog.dependencies_.loadFlags[path] || {};
  958. var languageLevel = loadFlags['lang'] || 'es3';
  959. if (path && (loadFlags['module'] == 'goog' ||
  960. goog.needsTranspile_(languageLevel))) {
  961. var abspath = goog.basePath + path;
  962. return (abspath) in goog.dependencies_.deferred;
  963. }
  964. return false;
  965. };
  966. /**
  967. * @param {string} name The module to check.
  968. * @return {boolean} Whether the name represents a
  969. * module whose declared dependencies have all been loaded
  970. * (eval'd or a deferred module load)
  971. * @private
  972. */
  973. goog.allDepsAreAvailable_ = function(name) {
  974. var path = goog.getPathFromDeps_(name);
  975. if (path && (path in goog.dependencies_.requires)) {
  976. for (var requireName in goog.dependencies_.requires[path]) {
  977. if (!goog.isProvided_(requireName) &&
  978. !goog.isDeferredModule_(requireName)) {
  979. return false;
  980. }
  981. }
  982. }
  983. return true;
  984. };
  985. /**
  986. * @param {string} abspath
  987. * @private
  988. */
  989. goog.maybeProcessDeferredPath_ = function(abspath) {
  990. if (abspath in goog.dependencies_.deferred) {
  991. var src = goog.dependencies_.deferred[abspath];
  992. delete goog.dependencies_.deferred[abspath];
  993. goog.globalEval(src);
  994. }
  995. };
  996. /**
  997. * Load a goog.module from the provided URL. This is not a general purpose
  998. * code loader and does not support late loading code, that is it should only
  999. * be used during page load. This method exists to support unit tests and
  1000. * "debug" loaders that would otherwise have inserted script tags. Under the
  1001. * hood this needs to use a synchronous XHR and is not recommeneded for
  1002. * production code.
  1003. *
  1004. * The module's goog.requires must have already been satisified; an exception
  1005. * will be thrown if this is not the case. This assumption is that no
  1006. * "deps.js" file exists, so there is no way to discover and locate the
  1007. * module-to-be-loaded's dependencies and no attempt is made to do so.
  1008. *
  1009. * There should only be one attempt to load a module. If
  1010. * "goog.loadModuleFromUrl" is called for an already loaded module, an
  1011. * exception will be throw.
  1012. *
  1013. * @param {string} url The URL from which to attempt to load the goog.module.
  1014. */
  1015. goog.loadModuleFromUrl = function(url) {
  1016. // Because this executes synchronously, we don't need to do any additional
  1017. // bookkeeping. When "goog.loadModule" the namespace will be marked as
  1018. // having been provided which is sufficient.
  1019. goog.retrieveAndExec_(url, true, false);
  1020. };
  1021. /**
  1022. * Writes a new script pointing to {@code src} directly into the DOM.
  1023. *
  1024. * NOTE: This method is not CSP-compliant. @see goog.appendScriptSrcNode_ for
  1025. * the fallback mechanism.
  1026. *
  1027. * @param {string} src The script URL.
  1028. * @private
  1029. */
  1030. goog.writeScriptSrcNode_ = function(src) {
  1031. goog.global.document.write(
  1032. '<script type="text/javascript" src="' + src + '"></' +
  1033. 'script>');
  1034. };
  1035. /**
  1036. * Appends a new script node to the DOM using a CSP-compliant mechanism. This
  1037. * method exists as a fallback for document.write (which is not allowed in a
  1038. * strict CSP context, e.g., Chrome apps).
  1039. *
  1040. * NOTE: This method is not analogous to using document.write to insert a
  1041. * <script> tag; specifically, the user agent will execute a script added by
  1042. * document.write immediately after the current script block finishes
  1043. * executing, whereas the DOM-appended script node will not be executed until
  1044. * the entire document is parsed and executed. That is to say, this script is
  1045. * added to the end of the script execution queue.
  1046. *
  1047. * The page must not attempt to call goog.required entities until after the
  1048. * document has loaded, e.g., in or after the window.onload callback.
  1049. *
  1050. * @param {string} src The script URL.
  1051. * @private
  1052. */
  1053. goog.appendScriptSrcNode_ = function(src) {
  1054. /** @type {Document} */
  1055. var doc = goog.global.document;
  1056. var scriptEl =
  1057. /** @type {HTMLScriptElement} */ (doc.createElement('script'));
  1058. scriptEl.type = 'text/javascript';
  1059. scriptEl.src = src;
  1060. scriptEl.defer = false;
  1061. scriptEl.async = false;
  1062. doc.head.appendChild(scriptEl);
  1063. };
  1064. /**
  1065. * The default implementation of the import function. Writes a script tag to
  1066. * import the script.
  1067. *
  1068. * @param {string} src The script url.
  1069. * @param {string=} opt_sourceText The optionally source text to evaluate
  1070. * @return {boolean} True if the script was imported, false otherwise.
  1071. * @private
  1072. */
  1073. goog.writeScriptTag_ = function(src, opt_sourceText) {
  1074. if (goog.inHtmlDocument_()) {
  1075. /** @type {!HTMLDocument} */
  1076. var doc = goog.global.document;
  1077. // If the user tries to require a new symbol after document load,
  1078. // something has gone terribly wrong. Doing a document.write would
  1079. // wipe out the page. This does not apply to the CSP-compliant method
  1080. // of writing script tags.
  1081. if (!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING &&
  1082. doc.readyState == 'complete') {
  1083. // Certain test frameworks load base.js multiple times, which tries
  1084. // to write deps.js each time. If that happens, just fail silently.
  1085. // These frameworks wipe the page between each load of base.js, so this
  1086. // is OK.
  1087. var isDeps = /\bdeps.js$/.test(src);
  1088. if (isDeps) {
  1089. return false;
  1090. } else {
  1091. throw Error('Cannot write "' + src + '" after document load');
  1092. }
  1093. }
  1094. if (opt_sourceText === undefined) {
  1095. if (!goog.IS_OLD_IE_) {
  1096. if (goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING) {
  1097. goog.appendScriptSrcNode_(src);
  1098. } else {
  1099. goog.writeScriptSrcNode_(src);
  1100. }
  1101. } else {
  1102. goog.oldIeWaiting_ = true;
  1103. var state = ' onreadystatechange=\'goog.onScriptLoad_(this, ' +
  1104. ++goog.lastNonModuleScriptIndex_ + ')\' ';
  1105. doc.write(
  1106. '<script type="text/javascript" src="' + src + '"' + state +
  1107. '></' +
  1108. 'script>');
  1109. }
  1110. } else {
  1111. doc.write(
  1112. '<script type="text/javascript">' +
  1113. goog.protectScriptTag_(opt_sourceText) + '</' +
  1114. 'script>');
  1115. }
  1116. return true;
  1117. } else {
  1118. return false;
  1119. }
  1120. };
  1121. /**
  1122. * Rewrites closing script tags in input to avoid ending an enclosing script
  1123. * tag.
  1124. *
  1125. * @param {string} str
  1126. * @return {string}
  1127. * @private
  1128. */
  1129. goog.protectScriptTag_ = function(str) {
  1130. return str.replace(/<\/(SCRIPT)/ig, '\\x3c/$1');
  1131. };
  1132. /**
  1133. * Determines whether the given language needs to be transpiled.
  1134. * @param {string} lang
  1135. * @return {boolean}
  1136. * @private
  1137. */
  1138. goog.needsTranspile_ = function(lang) {
  1139. if (goog.TRANSPILE == 'always') {
  1140. return true;
  1141. } else if (goog.TRANSPILE == 'never') {
  1142. return false;
  1143. } else if (!goog.requiresTranspilation_) {
  1144. goog.requiresTranspilation_ = goog.createRequiresTranspilation_();
  1145. }
  1146. if (lang in goog.requiresTranspilation_) {
  1147. return goog.requiresTranspilation_[lang];
  1148. } else {
  1149. throw new Error('Unknown language mode: ' + lang);
  1150. }
  1151. };
  1152. /** @private {?Object<string, boolean>} */
  1153. goog.requiresTranspilation_ = null;
  1154. /** @private {number} */
  1155. goog.lastNonModuleScriptIndex_ = 0;
  1156. /**
  1157. * A readystatechange handler for legacy IE
  1158. * @param {?} script
  1159. * @param {number} scriptIndex
  1160. * @return {boolean}
  1161. * @private
  1162. */
  1163. goog.onScriptLoad_ = function(script, scriptIndex) {
  1164. // for now load the modules when we reach the last script,
  1165. // later allow more inter-mingling.
  1166. if (script.readyState == 'complete' &&
  1167. goog.lastNonModuleScriptIndex_ == scriptIndex) {
  1168. goog.loadQueuedModules_();
  1169. }
  1170. return true;
  1171. };
  1172. /**
  1173. * Resolves dependencies based on the dependencies added using addDependency
  1174. * and calls importScript_ in the correct order.
  1175. * @param {string} pathToLoad The path from which to start discovering
  1176. * dependencies.
  1177. * @private
  1178. */
  1179. goog.writeScripts_ = function(pathToLoad) {
  1180. /** @type {!Array<string>} The scripts we need to write this time. */
  1181. var scripts = [];
  1182. var seenScript = {};
  1183. var deps = goog.dependencies_;
  1184. /** @param {string} path */
  1185. function visitNode(path) {
  1186. if (path in deps.written) {
  1187. return;
  1188. }
  1189. // We have already visited this one. We can get here if we have cyclic
  1190. // dependencies.
  1191. if (path in deps.visited) {
  1192. return;
  1193. }
  1194. deps.visited[path] = true;
  1195. if (path in deps.requires) {
  1196. for (var requireName in deps.requires[path]) {
  1197. // If the required name is defined, we assume that it was already
  1198. // bootstrapped by other means.
  1199. if (!goog.isProvided_(requireName)) {
  1200. if (requireName in deps.nameToPath) {
  1201. visitNode(deps.nameToPath[requireName]);
  1202. } else {
  1203. throw Error('Undefined nameToPath for ' + requireName);
  1204. }
  1205. }
  1206. }
  1207. }
  1208. if (!(path in seenScript)) {
  1209. seenScript[path] = true;
  1210. scripts.push(path);
  1211. }
  1212. }
  1213. visitNode(pathToLoad);
  1214. // record that we are going to load all these scripts.
  1215. for (var i = 0; i < scripts.length; i++) {
  1216. var path = scripts[i];
  1217. goog.dependencies_.written[path] = true;
  1218. }
  1219. // If a module is loaded synchronously then we need to
  1220. // clear the current inModuleLoader value, and restore it when we are
  1221. // done loading the current "requires".
  1222. var moduleState = goog.moduleLoaderState_;
  1223. goog.moduleLoaderState_ = null;
  1224. for (var i = 0; i < scripts.length; i++) {
  1225. var path = scripts[i];
  1226. if (path) {
  1227. var loadFlags = deps.loadFlags[path] || {};
  1228. var languageLevel = loadFlags['lang'] || 'es3';
  1229. var needsTranspile = goog.needsTranspile_(languageLevel);
  1230. if (loadFlags['module'] == 'goog' || needsTranspile) {
  1231. goog.importProcessedScript_(
  1232. goog.basePath + path, loadFlags['module'] == 'goog',
  1233. needsTranspile);
  1234. } else {
  1235. goog.importScript_(goog.basePath + path);
  1236. }
  1237. } else {
  1238. goog.moduleLoaderState_ = moduleState;
  1239. throw Error('Undefined script input');
  1240. }
  1241. }
  1242. // restore the current "module loading state"
  1243. goog.moduleLoaderState_ = moduleState;
  1244. };
  1245. /**
  1246. * Looks at the dependency rules and tries to determine the script file that
  1247. * fulfills a particular rule.
  1248. * @param {string} rule In the form goog.namespace.Class or project.script.
  1249. * @return {?string} Url corresponding to the rule, or null.
  1250. * @private
  1251. */
  1252. goog.getPathFromDeps_ = function(rule) {
  1253. if (rule in goog.dependencies_.nameToPath) {
  1254. return goog.dependencies_.nameToPath[rule];
  1255. } else {
  1256. return null;
  1257. }
  1258. };
  1259. goog.findBasePath_();
  1260. // Allow projects to manage the deps files themselves.
  1261. if (!goog.global.CLOSURE_NO_DEPS) {
  1262. goog.importScript_(goog.basePath + 'deps.js');
  1263. }
  1264. }
  1265. /**
  1266. * @package {?boolean}
  1267. * Visible for testing.
  1268. */
  1269. goog.hasBadLetScoping = null;
  1270. /**
  1271. * @return {boolean}
  1272. * @package Visible for testing.
  1273. */
  1274. goog.useSafari10Workaround = function() {
  1275. if (goog.hasBadLetScoping == null) {
  1276. var hasBadLetScoping;
  1277. try {
  1278. hasBadLetScoping = !eval(
  1279. '"use strict";' +
  1280. 'let x = 1; function f() { return typeof x; };' +
  1281. 'f() == "number";');
  1282. } catch (e) {
  1283. // Assume that ES6 syntax isn't supported.
  1284. hasBadLetScoping = false;
  1285. }
  1286. goog.hasBadLetScoping = hasBadLetScoping;
  1287. }
  1288. return goog.hasBadLetScoping;
  1289. };
  1290. /**
  1291. * @param {string} moduleDef
  1292. * @return {string}
  1293. * @package Visible for testing.
  1294. */
  1295. goog.workaroundSafari10EvalBug = function(moduleDef) {
  1296. return '(function(){' + moduleDef +
  1297. '\n' + // Terminate any trailing single line comment.
  1298. ';' + // Terminate any trailing expression.
  1299. '})();\n';
  1300. };
  1301. /**
  1302. * @param {function(?):?|string} moduleDef The module definition.
  1303. */
  1304. goog.loadModule = function(moduleDef) {
  1305. // NOTE: we allow function definitions to be either in the from
  1306. // of a string to eval (which keeps the original source intact) or
  1307. // in a eval forbidden environment (CSP) we allow a function definition
  1308. // which in its body must call {@code goog.module}, and return the exports
  1309. // of the module.
  1310. var previousState = goog.moduleLoaderState_;
  1311. try {
  1312. goog.moduleLoaderState_ = {
  1313. moduleName: undefined,
  1314. declareLegacyNamespace: false
  1315. };
  1316. var exports;
  1317. if (goog.isFunction(moduleDef)) {
  1318. exports = moduleDef.call(undefined, {});
  1319. } else if (goog.isString(moduleDef)) {
  1320. if (goog.useSafari10Workaround()) {
  1321. moduleDef = goog.workaroundSafari10EvalBug(moduleDef);
  1322. }
  1323. exports = goog.loadModuleFromSource_.call(undefined, moduleDef);
  1324. } else {
  1325. throw Error('Invalid module definition');
  1326. }
  1327. var moduleName = goog.moduleLoaderState_.moduleName;
  1328. if (!goog.isString(moduleName) || !moduleName) {
  1329. throw Error('Invalid module name \"' + moduleName + '\"');
  1330. }
  1331. // Don't seal legacy namespaces as they may be uses as a parent of
  1332. // another namespace
  1333. if (goog.moduleLoaderState_.declareLegacyNamespace) {
  1334. goog.constructNamespace_(moduleName, exports);
  1335. } else if (
  1336. goog.SEAL_MODULE_EXPORTS && Object.seal && typeof exports == 'object' &&
  1337. exports != null) {
  1338. Object.seal(exports);
  1339. }
  1340. goog.loadedModules_[moduleName] = exports;
  1341. } finally {
  1342. goog.moduleLoaderState_ = previousState;
  1343. }
  1344. };
  1345. /**
  1346. * @private @const
  1347. */
  1348. goog.loadModuleFromSource_ = /** @type {function(string):?} */ (function() {
  1349. // NOTE: we avoid declaring parameters or local variables here to avoid
  1350. // masking globals or leaking values into the module definition.
  1351. 'use strict';
  1352. var exports = {};
  1353. eval(arguments[0]);
  1354. return exports;
  1355. });
  1356. /**
  1357. * Normalize a file path by removing redundant ".." and extraneous "." file
  1358. * path components.
  1359. * @param {string} path
  1360. * @return {string}
  1361. * @private
  1362. */
  1363. goog.normalizePath_ = function(path) {
  1364. var components = path.split('/');
  1365. var i = 0;
  1366. while (i < components.length) {
  1367. if (components[i] == '.') {
  1368. components.splice(i, 1);
  1369. } else if (
  1370. i && components[i] == '..' && components[i - 1] &&
  1371. components[i - 1] != '..') {
  1372. components.splice(--i, 2);
  1373. } else {
  1374. i++;
  1375. }
  1376. }
  1377. return components.join('/');
  1378. };
  1379. /**
  1380. * Provides a hook for loading a file when using Closure's goog.require() API
  1381. * with goog.modules. In particular this hook is provided to support Node.js.
  1382. *
  1383. * @type {(function(string):string)|undefined}
  1384. */
  1385. goog.global.CLOSURE_LOAD_FILE_SYNC;
  1386. /**
  1387. * Loads file by synchronous XHR. Should not be used in production environments.
  1388. * @param {string} src Source URL.
  1389. * @return {?string} File contents, or null if load failed.
  1390. * @private
  1391. */
  1392. goog.loadFileSync_ = function(src) {
  1393. if (goog.global.CLOSURE_LOAD_FILE_SYNC) {
  1394. return goog.global.CLOSURE_LOAD_FILE_SYNC(src);
  1395. } else {
  1396. try {
  1397. /** @type {XMLHttpRequest} */
  1398. var xhr = new goog.global['XMLHttpRequest']();
  1399. xhr.open('get', src, false);
  1400. xhr.send();
  1401. // NOTE: Successful http: requests have a status of 200, but successful
  1402. // file: requests may have a status of zero. Any other status, or a
  1403. // thrown exception (particularly in case of file: requests) indicates
  1404. // some sort of error, which we treat as a missing or unavailable file.
  1405. return xhr.status == 0 || xhr.status == 200 ? xhr.responseText : null;
  1406. } catch (err) {
  1407. // No need to rethrow or log, since errors should show up on their own.
  1408. return null;
  1409. }
  1410. }
  1411. };
  1412. /**
  1413. * Retrieve and execute a script that needs some sort of wrapping.
  1414. * @param {string} src Script source URL.
  1415. * @param {boolean} isModule Whether to load as a module.
  1416. * @param {boolean} needsTranspile Whether to transpile down to ES3.
  1417. * @private
  1418. */
  1419. goog.retrieveAndExec_ = function(src, isModule, needsTranspile) {
  1420. if (!COMPILED) {
  1421. // The full but non-canonicalized URL for later use.
  1422. var originalPath = src;
  1423. // Canonicalize the path, removing any /./ or /../ since Chrome's debugging
  1424. // console doesn't auto-canonicalize XHR loads as it does <script> srcs.
  1425. src = goog.normalizePath_(src);
  1426. var importScript =
  1427. goog.global.CLOSURE_IMPORT_SCRIPT || goog.writeScriptTag_;
  1428. var scriptText = goog.loadFileSync_(src);
  1429. if (scriptText == null) {
  1430. throw new Error('Load of "' + src + '" failed');
  1431. }
  1432. if (needsTranspile) {
  1433. scriptText = goog.transpile_.call(goog.global, scriptText, src);
  1434. }
  1435. if (isModule) {
  1436. scriptText = goog.wrapModule_(src, scriptText);
  1437. } else {
  1438. scriptText += '\n//# sourceURL=' + src;
  1439. }
  1440. var isOldIE = goog.IS_OLD_IE_;
  1441. if (isOldIE && goog.oldIeWaiting_) {
  1442. goog.dependencies_.deferred[originalPath] = scriptText;
  1443. goog.queuedModules_.push(originalPath);
  1444. } else {
  1445. importScript(src, scriptText);
  1446. }
  1447. }
  1448. };
  1449. /**
  1450. * Lazily retrieves the transpiler and applies it to the source.
  1451. * @param {string} code JS code.
  1452. * @param {string} path Path to the code.
  1453. * @return {string} The transpiled code.
  1454. * @private
  1455. */
  1456. goog.transpile_ = function(code, path) {
  1457. var jscomp = goog.global['$jscomp'];
  1458. if (!jscomp) {
  1459. goog.global['$jscomp'] = jscomp = {};
  1460. }
  1461. var transpile = jscomp.transpile;
  1462. if (!transpile) {
  1463. var transpilerPath = goog.basePath + goog.TRANSPILER;
  1464. var transpilerCode = goog.loadFileSync_(transpilerPath);
  1465. if (transpilerCode) {
  1466. // This must be executed synchronously, since by the time we know we
  1467. // need it, we're about to load and write the ES6 code synchronously,
  1468. // so a normal script-tag load will be too slow.
  1469. eval(transpilerCode + '\n//# sourceURL=' + transpilerPath);
  1470. // Even though the transpiler is optional, if $gwtExport is found, it's
  1471. // a sign the transpiler was loaded and the $jscomp.transpile *should*
  1472. // be there.
  1473. if (goog.global['$gwtExport'] && goog.global['$gwtExport']['$jscomp'] &&
  1474. !goog.global['$gwtExport']['$jscomp']['transpile']) {
  1475. throw new Error(
  1476. 'The transpiler did not properly export the "transpile" ' +
  1477. 'method. $gwtExport: ' + JSON.stringify(goog.global['$gwtExport']));
  1478. }
  1479. // transpile.js only exports a single $jscomp function, transpile. We
  1480. // grab just that and add it to the existing definition of $jscomp which
  1481. // contains the polyfills.
  1482. goog.global['$jscomp'].transpile =
  1483. goog.global['$gwtExport']['$jscomp']['transpile'];
  1484. jscomp = goog.global['$jscomp'];
  1485. transpile = jscomp.transpile;
  1486. }
  1487. }
  1488. if (!transpile) {
  1489. // The transpiler is an optional component. If it's not available then
  1490. // replace it with a pass-through function that simply logs.
  1491. var suffix = ' requires transpilation but no transpiler was found.';
  1492. transpile = jscomp.transpile = function(code, path) {
  1493. // TODO(user): figure out some way to get this error to show up
  1494. // in test results, noting that the failure may occur in many
  1495. // different ways, including in loadModule() before the test
  1496. // runner even comes up.
  1497. goog.logToConsole_(path + suffix);
  1498. return code;
  1499. };
  1500. }
  1501. // Note: any transpilation errors/warnings will be logged to the console.
  1502. return transpile(code, path);
  1503. };
  1504. //==============================================================================
  1505. // Language Enhancements
  1506. //==============================================================================
  1507. /**
  1508. * This is a "fixed" version of the typeof operator. It differs from the typeof
  1509. * operator in such a way that null returns 'null' and arrays return 'array'.
  1510. * @param {?} value The value to get the type of.
  1511. * @return {string} The name of the type.
  1512. */
  1513. goog.typeOf = function(value) {
  1514. var s = typeof value;
  1515. if (s == 'object') {
  1516. if (value) {
  1517. // Check these first, so we can avoid calling Object.prototype.toString if
  1518. // possible.
  1519. //
  1520. // IE improperly marshals typeof across execution contexts, but a
  1521. // cross-context object will still return false for "instanceof Object".
  1522. if (value instanceof Array) {
  1523. return 'array';
  1524. } else if (value instanceof Object) {
  1525. return s;
  1526. }
  1527. // HACK: In order to use an Object prototype method on the arbitrary
  1528. // value, the compiler requires the value be cast to type Object,
  1529. // even though the ECMA spec explicitly allows it.
  1530. var className = Object.prototype.toString.call(
  1531. /** @type {!Object} */ (value));
  1532. // In Firefox 3.6, attempting to access iframe window objects' length
  1533. // property throws an NS_ERROR_FAILURE, so we need to special-case it
  1534. // here.
  1535. if (className == '[object Window]') {
  1536. return 'object';
  1537. }
  1538. // We cannot always use constructor == Array or instanceof Array because
  1539. // different frames have different Array objects. In IE6, if the iframe
  1540. // where the array was created is destroyed, the array loses its
  1541. // prototype. Then dereferencing val.splice here throws an exception, so
  1542. // we can't use goog.isFunction. Calling typeof directly returns 'unknown'
  1543. // so that will work. In this case, this function will return false and
  1544. // most array functions will still work because the array is still
  1545. // array-like (supports length and []) even though it has lost its
  1546. // prototype.
  1547. // Mark Miller noticed that Object.prototype.toString
  1548. // allows access to the unforgeable [[Class]] property.
  1549. // 15.2.4.2 Object.prototype.toString ( )
  1550. // When the toString method is called, the following steps are taken:
  1551. // 1. Get the [[Class]] property of this object.
  1552. // 2. Compute a string value by concatenating the three strings
  1553. // "[object ", Result(1), and "]".
  1554. // 3. Return Result(2).
  1555. // and this behavior survives the destruction of the execution context.
  1556. if ((className == '[object Array]' ||
  1557. // In IE all non value types are wrapped as objects across window
  1558. // boundaries (not iframe though) so we have to do object detection
  1559. // for this edge case.
  1560. typeof value.length == 'number' &&
  1561. typeof value.splice != 'undefined' &&
  1562. typeof value.propertyIsEnumerable != 'undefined' &&
  1563. !value.propertyIsEnumerable('splice')
  1564. )) {
  1565. return 'array';
  1566. }
  1567. // HACK: There is still an array case that fails.
  1568. // function ArrayImpostor() {}
  1569. // ArrayImpostor.prototype = [];
  1570. // var impostor = new ArrayImpostor;
  1571. // this can be fixed by getting rid of the fast path
  1572. // (value instanceof Array) and solely relying on
  1573. // (value && Object.prototype.toString.vall(value) === '[object Array]')
  1574. // but that would require many more function calls and is not warranted
  1575. // unless closure code is receiving objects from untrusted sources.
  1576. // IE in cross-window calls does not correctly marshal the function type
  1577. // (it appears just as an object) so we cannot use just typeof val ==
  1578. // 'function'. However, if the object has a call property, it is a
  1579. // function.
  1580. if ((className == '[object Function]' ||
  1581. typeof value.call != 'undefined' &&
  1582. typeof value.propertyIsEnumerable != 'undefined' &&
  1583. !value.propertyIsEnumerable('call'))) {
  1584. return 'function';
  1585. }
  1586. } else {
  1587. return 'null';
  1588. }
  1589. } else if (s == 'function' && typeof value.call == 'undefined') {
  1590. // In Safari typeof nodeList returns 'function', and on Firefox typeof
  1591. // behaves similarly for HTML{Applet,Embed,Object}, Elements and RegExps. We
  1592. // would like to return object for those and we can detect an invalid
  1593. // function by making sure that the function object has a call method.
  1594. return 'object';
  1595. }
  1596. return s;
  1597. };
  1598. /**
  1599. * Returns true if the specified value is null.
  1600. * @param {?} val Variable to test.
  1601. * @return {boolean} Whether variable is null.
  1602. */
  1603. goog.isNull = function(val) {
  1604. return val === null;
  1605. };
  1606. /**
  1607. * Returns true if the specified value is defined and not null.
  1608. * @param {?} val Variable to test.
  1609. * @return {boolean} Whether variable is defined and not null.
  1610. */
  1611. goog.isDefAndNotNull = function(val) {
  1612. // Note that undefined == null.
  1613. return val != null;
  1614. };
  1615. /**
  1616. * Returns true if the specified value is an array.
  1617. * @param {?} val Variable to test.
  1618. * @return {boolean} Whether variable is an array.
  1619. */
  1620. goog.isArray = function(val) {
  1621. return goog.typeOf(val) == 'array';
  1622. };
  1623. /**
  1624. * Returns true if the object looks like an array. To qualify as array like
  1625. * the value needs to be either a NodeList or an object with a Number length
  1626. * property. As a special case, a function value is not array like, because its
  1627. * length property is fixed to correspond to the number of expected arguments.
  1628. * @param {?} val Variable to test.
  1629. * @return {boolean} Whether variable is an array.
  1630. */
  1631. goog.isArrayLike = function(val) {
  1632. var type = goog.typeOf(val);
  1633. // We do not use goog.isObject here in order to exclude function values.
  1634. return type == 'array' || type == 'object' && typeof val.length == 'number';
  1635. };
  1636. /**
  1637. * Returns true if the object looks like a Date. To qualify as Date-like the
  1638. * value needs to be an object and have a getFullYear() function.
  1639. * @param {?} val Variable to test.
  1640. * @return {boolean} Whether variable is a like a Date.
  1641. */
  1642. goog.isDateLike = function(val) {
  1643. return goog.isObject(val) && typeof val.getFullYear == 'function';
  1644. };
  1645. /**
  1646. * Returns true if the specified value is a function.
  1647. * @param {?} val Variable to test.
  1648. * @return {boolean} Whether variable is a function.
  1649. */
  1650. goog.isFunction = function(val) {
  1651. return goog.typeOf(val) == 'function';
  1652. };
  1653. /**
  1654. * Returns true if the specified value is an object. This includes arrays and
  1655. * functions.
  1656. * @param {?} val Variable to test.
  1657. * @return {boolean} Whether variable is an object.
  1658. */
  1659. goog.isObject = function(val) {
  1660. var type = typeof val;
  1661. return type == 'object' && val != null || type == 'function';
  1662. // return Object(val) === val also works, but is slower, especially if val is
  1663. // not an object.
  1664. };
  1665. /**
  1666. * Gets a unique ID for an object. This mutates the object so that further calls
  1667. * with the same object as a parameter returns the same value. The unique ID is
  1668. * guaranteed to be unique across the current session amongst objects that are
  1669. * passed into {@code getUid}. There is no guarantee that the ID is unique or
  1670. * consistent across sessions. It is unsafe to generate unique ID for function
  1671. * prototypes.
  1672. *
  1673. * @param {Object} obj The object to get the unique ID for.
  1674. * @return {number} The unique ID for the object.
  1675. */
  1676. goog.getUid = function(obj) {
  1677. // TODO(arv): Make the type stricter, do not accept null.
  1678. // In Opera window.hasOwnProperty exists but always returns false so we avoid
  1679. // using it. As a consequence the unique ID generated for BaseClass.prototype
  1680. // and SubClass.prototype will be the same.
  1681. return obj[goog.UID_PROPERTY_] ||
  1682. (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_);
  1683. };
  1684. /**
  1685. * Whether the given object is already assigned a unique ID.
  1686. *
  1687. * This does not modify the object.
  1688. *
  1689. * @param {!Object} obj The object to check.
  1690. * @return {boolean} Whether there is an assigned unique id for the object.
  1691. */
  1692. goog.hasUid = function(obj) {
  1693. return !!obj[goog.UID_PROPERTY_];
  1694. };
  1695. /**
  1696. * Removes the unique ID from an object. This is useful if the object was
  1697. * previously mutated using {@code goog.getUid} in which case the mutation is
  1698. * undone.
  1699. * @param {Object} obj The object to remove the unique ID field from.
  1700. */
  1701. goog.removeUid = function(obj) {
  1702. // TODO(arv): Make the type stricter, do not accept null.
  1703. // In IE, DOM nodes are not instances of Object and throw an exception if we
  1704. // try to delete. Instead we try to use removeAttribute.
  1705. if (obj !== null && 'removeAttribute' in obj) {
  1706. obj.removeAttribute(goog.UID_PROPERTY_);
  1707. }
  1708. try {
  1709. delete obj[goog.UID_PROPERTY_];
  1710. } catch (ex) {
  1711. }
  1712. };
  1713. /**
  1714. * Name for unique ID property. Initialized in a way to help avoid collisions
  1715. * with other closure JavaScript on the same page.
  1716. * @type {string}
  1717. * @private
  1718. */
  1719. goog.UID_PROPERTY_ = 'closure_uid_' + ((Math.random() * 1e9) >>> 0);
  1720. /**
  1721. * Counter for UID.
  1722. * @type {number}
  1723. * @private
  1724. */
  1725. goog.uidCounter_ = 0;
  1726. /**
  1727. * Adds a hash code field to an object. The hash code is unique for the
  1728. * given object.
  1729. * @param {Object} obj The object to get the hash code for.
  1730. * @return {number} The hash code for the object.
  1731. * @deprecated Use goog.getUid instead.
  1732. */
  1733. goog.getHashCode = goog.getUid;
  1734. /**
  1735. * Removes the hash code field from an object.
  1736. * @param {Object} obj The object to remove the field from.
  1737. * @deprecated Use goog.removeUid instead.
  1738. */
  1739. goog.removeHashCode = goog.removeUid;
  1740. /**
  1741. * Clones a value. The input may be an Object, Array, or basic type. Objects and
  1742. * arrays will be cloned recursively.
  1743. *
  1744. * WARNINGS:
  1745. * <code>goog.cloneObject</code> does not detect reference loops. Objects that
  1746. * refer to themselves will cause infinite recursion.
  1747. *
  1748. * <code>goog.cloneObject</code> is unaware of unique identifiers, and copies
  1749. * UIDs created by <code>getUid</code> into cloned results.
  1750. *
  1751. * @param {*} obj The value to clone.
  1752. * @return {*} A clone of the input value.
  1753. * @deprecated goog.cloneObject is unsafe. Prefer the goog.object methods.
  1754. */
  1755. goog.cloneObject = function(obj) {
  1756. var type = goog.typeOf(obj);
  1757. if (type == 'object' || type == 'array') {
  1758. if (obj.clone) {
  1759. return obj.clone();
  1760. }
  1761. var clone = type == 'array' ? [] : {};
  1762. for (var key in obj) {
  1763. clone[key] = goog.cloneObject(obj[key]);
  1764. }
  1765. return clone;
  1766. }
  1767. return obj;
  1768. };
  1769. /**
  1770. * A native implementation of goog.bind.
  1771. * @param {?function(this:T, ...)} fn A function to partially apply.
  1772. * @param {T} selfObj Specifies the object which this should point to when the
  1773. * function is run.
  1774. * @param {...*} var_args Additional arguments that are partially applied to the
  1775. * function.
  1776. * @return {!Function} A partially-applied form of the function goog.bind() was
  1777. * invoked as a method of.
  1778. * @template T
  1779. * @private
  1780. */
  1781. goog.bindNative_ = function(fn, selfObj, var_args) {
  1782. return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments));
  1783. };
  1784. /**
  1785. * A pure-JS implementation of goog.bind.
  1786. * @param {?function(this:T, ...)} fn A function to partially apply.
  1787. * @param {T} selfObj Specifies the object which this should point to when the
  1788. * function is run.
  1789. * @param {...*} var_args Additional arguments that are partially applied to the
  1790. * function.
  1791. * @return {!Function} A partially-applied form of the function goog.bind() was
  1792. * invoked as a method of.
  1793. * @template T
  1794. * @private
  1795. */
  1796. goog.bindJs_ = function(fn, selfObj, var_args) {
  1797. if (!fn) {
  1798. throw new Error();
  1799. }
  1800. if (arguments.length > 2) {
  1801. var boundArgs = Array.prototype.slice.call(arguments, 2);
  1802. return function() {
  1803. // Prepend the bound arguments to the current arguments.
  1804. var newArgs = Array.prototype.slice.call(arguments);
  1805. Array.prototype.unshift.apply(newArgs, boundArgs);
  1806. return fn.apply(selfObj, newArgs);
  1807. };
  1808. } else {
  1809. return function() {
  1810. return fn.apply(selfObj, arguments);
  1811. };
  1812. }
  1813. };
  1814. /**
  1815. * Partially applies this function to a particular 'this object' and zero or
  1816. * more arguments. The result is a new function with some arguments of the first
  1817. * function pre-filled and the value of this 'pre-specified'.
  1818. *
  1819. * Remaining arguments specified at call-time are appended to the pre-specified
  1820. * ones.
  1821. *
  1822. * Also see: {@link #partial}.
  1823. *
  1824. * Usage:
  1825. * <pre>var barMethBound = goog.bind(myFunction, myObj, 'arg1', 'arg2');
  1826. * barMethBound('arg3', 'arg4');</pre>
  1827. *
  1828. * @param {?function(this:T, ...)} fn A function to partially apply.
  1829. * @param {T} selfObj Specifies the object which this should point to when the
  1830. * function is run.
  1831. * @param {...*} var_args Additional arguments that are partially applied to the
  1832. * function.
  1833. * @return {!Function} A partially-applied form of the function goog.bind() was
  1834. * invoked as a method of.
  1835. * @template T
  1836. * @suppress {deprecated} See above.
  1837. */
  1838. goog.bind = function(fn, selfObj, var_args) {
  1839. // TODO(nicksantos): narrow the type signature.
  1840. if (Function.prototype.bind &&
  1841. // NOTE(nicksantos): Somebody pulled base.js into the default Chrome
  1842. // extension environment. This means that for Chrome extensions, they get
  1843. // the implementation of Function.prototype.bind that calls goog.bind
  1844. // instead of the native one. Even worse, we don't want to introduce a
  1845. // circular dependency between goog.bind and Function.prototype.bind, so
  1846. // we have to hack this to make sure it works correctly.
  1847. Function.prototype.bind.toString().indexOf('native code') != -1) {
  1848. goog.bind = goog.bindNative_;
  1849. } else {
  1850. goog.bind = goog.bindJs_;
  1851. }
  1852. return goog.bind.apply(null, arguments);
  1853. };
  1854. /**
  1855. * Like goog.bind(), except that a 'this object' is not required. Useful when
  1856. * the target function is already bound.
  1857. *
  1858. * Usage:
  1859. * var g = goog.partial(f, arg1, arg2);
  1860. * g(arg3, arg4);
  1861. *
  1862. * @param {Function} fn A function to partially apply.
  1863. * @param {...*} var_args Additional arguments that are partially applied to fn.
  1864. * @return {!Function} A partially-applied form of the function goog.partial()
  1865. * was invoked as a method of.
  1866. */
  1867. goog.partial = function(fn, var_args) {
  1868. var args = Array.prototype.slice.call(arguments, 1);
  1869. return function() {
  1870. // Clone the array (with slice()) and append additional arguments
  1871. // to the existing arguments.
  1872. var newArgs = args.slice();
  1873. newArgs.push.apply(newArgs, arguments);
  1874. return fn.apply(this, newArgs);
  1875. };
  1876. };
  1877. /**
  1878. * Copies all the members of a source object to a target object. This method
  1879. * does not work on all browsers for all objects that contain keys such as
  1880. * toString or hasOwnProperty. Use goog.object.extend for this purpose.
  1881. * @param {Object} target Target.
  1882. * @param {Object} source Source.
  1883. */
  1884. goog.mixin = function(target, source) {
  1885. for (var x in source) {
  1886. target[x] = source[x];
  1887. }
  1888. // For IE7 or lower, the for-in-loop does not contain any properties that are
  1889. // not enumerable on the prototype object (for example, isPrototypeOf from
  1890. // Object.prototype) but also it will not include 'replace' on objects that
  1891. // extend String and change 'replace' (not that it is common for anyone to
  1892. // extend anything except Object).
  1893. };
  1894. /**
  1895. * @return {number} An integer value representing the number of milliseconds
  1896. * between midnight, January 1, 1970 and the current time.
  1897. */
  1898. goog.now = (goog.TRUSTED_SITE && Date.now) || (function() {
  1899. // Unary plus operator converts its operand to a number which in
  1900. // the case of
  1901. // a date is done by calling getTime().
  1902. return +new Date();
  1903. });
  1904. /**
  1905. * Evals JavaScript in the global scope. In IE this uses execScript, other
  1906. * browsers use goog.global.eval. If goog.global.eval does not evaluate in the
  1907. * global scope (for example, in Safari), appends a script tag instead.
  1908. * Throws an exception if neither execScript or eval is defined.
  1909. * @param {string} script JavaScript string.
  1910. */
  1911. goog.globalEval = function(script) {
  1912. if (goog.global.execScript) {
  1913. goog.global.execScript(script, 'JavaScript');
  1914. } else if (goog.global.eval) {
  1915. // Test to see if eval works
  1916. if (goog.evalWorksForGlobals_ == null) {
  1917. goog.global.eval('var _evalTest_ = 1;');
  1918. if (typeof goog.global['_evalTest_'] != 'undefined') {
  1919. try {
  1920. delete goog.global['_evalTest_'];
  1921. } catch (ignore) {
  1922. // Microsoft edge fails the deletion above in strict mode.
  1923. }
  1924. goog.evalWorksForGlobals_ = true;
  1925. } else {
  1926. goog.evalWorksForGlobals_ = false;
  1927. }
  1928. }
  1929. if (goog.evalWorksForGlobals_) {
  1930. goog.global.eval(script);
  1931. } else {
  1932. /** @type {Document} */
  1933. var doc = goog.global.document;
  1934. var scriptElt =
  1935. /** @type {!HTMLScriptElement} */ (doc.createElement('SCRIPT'));
  1936. scriptElt.type = 'text/javascript';
  1937. scriptElt.defer = false;
  1938. // Note(user): can't use .innerHTML since "t('<test>')" will fail and
  1939. // .text doesn't work in Safari 2. Therefore we append a text node.
  1940. scriptElt.appendChild(doc.createTextNode(script));
  1941. doc.body.appendChild(scriptElt);
  1942. doc.body.removeChild(scriptElt);
  1943. }
  1944. } else {
  1945. throw Error('goog.globalEval not available');
  1946. }
  1947. };
  1948. /**
  1949. * Indicates whether or not we can call 'eval' directly to eval code in the
  1950. * global scope. Set to a Boolean by the first call to goog.globalEval (which
  1951. * empirically tests whether eval works for globals). @see goog.globalEval
  1952. * @type {?boolean}
  1953. * @private
  1954. */
  1955. goog.evalWorksForGlobals_ = null;
  1956. /**
  1957. * Optional map of CSS class names to obfuscated names used with
  1958. * goog.getCssName().
  1959. * @private {!Object<string, string>|undefined}
  1960. * @see goog.setCssNameMapping
  1961. */
  1962. goog.cssNameMapping_;
  1963. /**
  1964. * Optional obfuscation style for CSS class names. Should be set to either
  1965. * 'BY_WHOLE' or 'BY_PART' if defined.
  1966. * @type {string|undefined}
  1967. * @private
  1968. * @see goog.setCssNameMapping
  1969. */
  1970. goog.cssNameMappingStyle_;
  1971. /**
  1972. * A hook for modifying the default behavior goog.getCssName. The function
  1973. * if present, will recieve the standard output of the goog.getCssName as
  1974. * its input.
  1975. *
  1976. * @type {(function(string):string)|undefined}
  1977. */
  1978. goog.global.CLOSURE_CSS_NAME_MAP_FN;
  1979. /**
  1980. * Handles strings that are intended to be used as CSS class names.
  1981. *
  1982. * This function works in tandem with @see goog.setCssNameMapping.
  1983. *
  1984. * Without any mapping set, the arguments are simple joined with a hyphen and
  1985. * passed through unaltered.
  1986. *
  1987. * When there is a mapping, there are two possible styles in which these
  1988. * mappings are used. In the BY_PART style, each part (i.e. in between hyphens)
  1989. * of the passed in css name is rewritten according to the map. In the BY_WHOLE
  1990. * style, the full css name is looked up in the map directly. If a rewrite is
  1991. * not specified by the map, the compiler will output a warning.
  1992. *
  1993. * When the mapping is passed to the compiler, it will replace calls to
  1994. * goog.getCssName with the strings from the mapping, e.g.
  1995. * var x = goog.getCssName('foo');
  1996. * var y = goog.getCssName(this.baseClass, 'active');
  1997. * becomes:
  1998. * var x = 'foo';
  1999. * var y = this.baseClass + '-active';
  2000. *
  2001. * If one argument is passed it will be processed, if two are passed only the
  2002. * modifier will be processed, as it is assumed the first argument was generated
  2003. * as a result of calling goog.getCssName.
  2004. *
  2005. * @param {string} className The class name.
  2006. * @param {string=} opt_modifier A modifier to be appended to the class name.
  2007. * @return {string} The class name or the concatenation of the class name and
  2008. * the modifier.
  2009. */
  2010. goog.getCssName = function(className, opt_modifier) {
  2011. // String() is used for compatibility with compiled soy where the passed
  2012. // className can be non-string objects.
  2013. if (String(className).charAt(0) == '.') {
  2014. throw new Error(
  2015. 'className passed in goog.getCssName must not start with ".".' +
  2016. ' You passed: ' + className);
  2017. }
  2018. var getMapping = function(cssName) {
  2019. return goog.cssNameMapping_[cssName] || cssName;
  2020. };
  2021. var renameByParts = function(cssName) {
  2022. // Remap all the parts individually.
  2023. var parts = cssName.split('-');
  2024. var mapped = [];
  2025. for (var i = 0; i < parts.length; i++) {
  2026. mapped.push(getMapping(parts[i]));
  2027. }
  2028. return mapped.join('-');
  2029. };
  2030. var rename;
  2031. if (goog.cssNameMapping_) {
  2032. rename =
  2033. goog.cssNameMappingStyle_ == 'BY_WHOLE' ? getMapping : renameByParts;
  2034. } else {
  2035. rename = function(a) {
  2036. return a;
  2037. };
  2038. }
  2039. var result =
  2040. opt_modifier ? className + '-' + rename(opt_modifier) : rename(className);
  2041. // The special CLOSURE_CSS_NAME_MAP_FN allows users to specify further
  2042. // processing of the class name.
  2043. if (goog.global.CLOSURE_CSS_NAME_MAP_FN) {
  2044. return goog.global.CLOSURE_CSS_NAME_MAP_FN(result);
  2045. }
  2046. return result;
  2047. };
  2048. /**
  2049. * Sets the map to check when returning a value from goog.getCssName(). Example:
  2050. * <pre>
  2051. * goog.setCssNameMapping({
  2052. * "goog": "a",
  2053. * "disabled": "b",
  2054. * });
  2055. *
  2056. * var x = goog.getCssName('goog');
  2057. * // The following evaluates to: "a a-b".
  2058. * goog.getCssName('goog') + ' ' + goog.getCssName(x, 'disabled')
  2059. * </pre>
  2060. * When declared as a map of string literals to string literals, the JSCompiler
  2061. * will replace all calls to goog.getCssName() using the supplied map if the
  2062. * --process_closure_primitives flag is set.
  2063. *
  2064. * @param {!Object} mapping A map of strings to strings where keys are possible
  2065. * arguments to goog.getCssName() and values are the corresponding values
  2066. * that should be returned.
  2067. * @param {string=} opt_style The style of css name mapping. There are two valid
  2068. * options: 'BY_PART', and 'BY_WHOLE'.
  2069. * @see goog.getCssName for a description.
  2070. */
  2071. goog.setCssNameMapping = function(mapping, opt_style) {
  2072. goog.cssNameMapping_ = mapping;
  2073. goog.cssNameMappingStyle_ = opt_style;
  2074. };
  2075. /**
  2076. * To use CSS renaming in compiled mode, one of the input files should have a
  2077. * call to goog.setCssNameMapping() with an object literal that the JSCompiler
  2078. * can extract and use to replace all calls to goog.getCssName(). In uncompiled
  2079. * mode, JavaScript code should be loaded before this base.js file that declares
  2080. * a global variable, CLOSURE_CSS_NAME_MAPPING, which is used below. This is
  2081. * to ensure that the mapping is loaded before any calls to goog.getCssName()
  2082. * are made in uncompiled mode.
  2083. *
  2084. * A hook for overriding the CSS name mapping.
  2085. * @type {!Object<string, string>|undefined}
  2086. */
  2087. goog.global.CLOSURE_CSS_NAME_MAPPING;
  2088. if (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) {
  2089. // This does not call goog.setCssNameMapping() because the JSCompiler
  2090. // requires that goog.setCssNameMapping() be called with an object literal.
  2091. goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING;
  2092. }
  2093. /**
  2094. * Gets a localized message.
  2095. *
  2096. * This function is a compiler primitive. If you give the compiler a localized
  2097. * message bundle, it will replace the string at compile-time with a localized
  2098. * version, and expand goog.getMsg call to a concatenated string.
  2099. *
  2100. * Messages must be initialized in the form:
  2101. * <code>
  2102. * var MSG_NAME = goog.getMsg('Hello {$placeholder}', {'placeholder': 'world'});
  2103. * </code>
  2104. *
  2105. * This function produces a string which should be treated as plain text. Use
  2106. * {@link goog.html.SafeHtmlFormatter} in conjunction with goog.getMsg to
  2107. * produce SafeHtml.
  2108. *
  2109. * @param {string} str Translatable string, places holders in the form {$foo}.
  2110. * @param {Object<string, string>=} opt_values Maps place holder name to value.
  2111. * @return {string} message with placeholders filled.
  2112. */
  2113. goog.getMsg = function(str, opt_values) {
  2114. if (opt_values) {
  2115. str = str.replace(/\{\$([^}]+)}/g, function(match, key) {
  2116. return (opt_values != null && key in opt_values) ? opt_values[key] :
  2117. match;
  2118. });
  2119. }
  2120. return str;
  2121. };
  2122. /**
  2123. * Gets a localized message. If the message does not have a translation, gives a
  2124. * fallback message.
  2125. *
  2126. * This is useful when introducing a new message that has not yet been
  2127. * translated into all languages.
  2128. *
  2129. * This function is a compiler primitive. Must be used in the form:
  2130. * <code>var x = goog.getMsgWithFallback(MSG_A, MSG_B);</code>
  2131. * where MSG_A and MSG_B were initialized with goog.getMsg.
  2132. *
  2133. * @param {string} a The preferred message.
  2134. * @param {string} b The fallback message.
  2135. * @return {string} The best translated message.
  2136. */
  2137. goog.getMsgWithFallback = function(a, b) {
  2138. return a;
  2139. };
  2140. /**
  2141. * Exposes an unobfuscated global namespace path for the given object.
  2142. * Note that fields of the exported object *will* be obfuscated, unless they are
  2143. * exported in turn via this function or goog.exportProperty.
  2144. *
  2145. * Also handy for making public items that are defined in anonymous closures.
  2146. *
  2147. * ex. goog.exportSymbol('public.path.Foo', Foo);
  2148. *
  2149. * ex. goog.exportSymbol('public.path.Foo.staticFunction', Foo.staticFunction);
  2150. * public.path.Foo.staticFunction();
  2151. *
  2152. * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod',
  2153. * Foo.prototype.myMethod);
  2154. * new public.path.Foo().myMethod();
  2155. *
  2156. * @param {string} publicPath Unobfuscated name to export.
  2157. * @param {*} object Object the name should point to.
  2158. * @param {Object=} opt_objectToExportTo The object to add the path to; default
  2159. * is goog.global.
  2160. */
  2161. goog.exportSymbol = function(publicPath, object, opt_objectToExportTo) {
  2162. goog.exportPath_(publicPath, object, opt_objectToExportTo);
  2163. };
  2164. /**
  2165. * Exports a property unobfuscated into the object's namespace.
  2166. * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction);
  2167. * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod);
  2168. * @param {Object} object Object whose static property is being exported.
  2169. * @param {string} publicName Unobfuscated name to export.
  2170. * @param {*} symbol Object the name should point to.
  2171. */
  2172. goog.exportProperty = function(object, publicName, symbol) {
  2173. object[publicName] = symbol;
  2174. };
  2175. /**
  2176. * Inherit the prototype methods from one constructor into another.
  2177. *
  2178. * Usage:
  2179. * <pre>
  2180. * function ParentClass(a, b) { }
  2181. * ParentClass.prototype.foo = function(a) { };
  2182. *
  2183. * function ChildClass(a, b, c) {
  2184. * ChildClass.base(this, 'constructor', a, b);
  2185. * }
  2186. * goog.inherits(ChildClass, ParentClass);
  2187. *
  2188. * var child = new ChildClass('a', 'b', 'see');
  2189. * child.foo(); // This works.
  2190. * </pre>
  2191. *
  2192. * @param {!Function} childCtor Child class.
  2193. * @param {!Function} parentCtor Parent class.
  2194. */
  2195. goog.inherits = function(childCtor, parentCtor) {
  2196. /** @constructor */
  2197. function tempCtor() {}
  2198. tempCtor.prototype = parentCtor.prototype;
  2199. childCtor.superClass_ = parentCtor.prototype;
  2200. childCtor.prototype = new tempCtor();
  2201. /** @override */
  2202. childCtor.prototype.constructor = childCtor;
  2203. /**
  2204. * Calls superclass constructor/method.
  2205. *
  2206. * This function is only available if you use goog.inherits to
  2207. * express inheritance relationships between classes.
  2208. *
  2209. * NOTE: This is a replacement for goog.base and for superClass_
  2210. * property defined in childCtor.
  2211. *
  2212. * @param {!Object} me Should always be "this".
  2213. * @param {string} methodName The method name to call. Calling
  2214. * superclass constructor can be done with the special string
  2215. * 'constructor'.
  2216. * @param {...*} var_args The arguments to pass to superclass
  2217. * method/constructor.
  2218. * @return {*} The return value of the superclass method/constructor.
  2219. */
  2220. childCtor.base = function(me, methodName, var_args) {
  2221. // Copying using loop to avoid deop due to passing arguments object to
  2222. // function. This is faster in many JS engines as of late 2014.
  2223. var args = new Array(arguments.length - 2);
  2224. for (var i = 2; i < arguments.length; i++) {
  2225. args[i - 2] = arguments[i];
  2226. }
  2227. return parentCtor.prototype[methodName].apply(me, args);
  2228. };
  2229. };
  2230. /**
  2231. * Call up to the superclass.
  2232. *
  2233. * If this is called from a constructor, then this calls the superclass
  2234. * constructor with arguments 1-N.
  2235. *
  2236. * If this is called from a prototype method, then you must pass the name of the
  2237. * method as the second argument to this function. If you do not, you will get a
  2238. * runtime error. This calls the superclass' method with arguments 2-N.
  2239. *
  2240. * This function only works if you use goog.inherits to express inheritance
  2241. * relationships between your classes.
  2242. *
  2243. * This function is a compiler primitive. At compile-time, the compiler will do
  2244. * macro expansion to remove a lot of the extra overhead that this function
  2245. * introduces. The compiler will also enforce a lot of the assumptions that this
  2246. * function makes, and treat it as a compiler error if you break them.
  2247. *
  2248. * @param {!Object} me Should always be "this".
  2249. * @param {*=} opt_methodName The method name if calling a super method.
  2250. * @param {...*} var_args The rest of the arguments.
  2251. * @return {*} The return value of the superclass method.
  2252. * @suppress {es5Strict} This method can not be used in strict mode, but
  2253. * all Closure Library consumers must depend on this file.
  2254. * @deprecated goog.base is not strict mode compatible. Prefer the static
  2255. * "base" method added to the constructor by goog.inherits
  2256. * or ES6 classes and the "super" keyword.
  2257. */
  2258. goog.base = function(me, opt_methodName, var_args) {
  2259. var caller = arguments.callee.caller;
  2260. if (goog.STRICT_MODE_COMPATIBLE || (goog.DEBUG && !caller)) {
  2261. throw Error(
  2262. 'arguments.caller not defined. goog.base() cannot be used ' +
  2263. 'with strict mode code. See ' +
  2264. 'http://www.ecma-international.org/ecma-262/5.1/#sec-C');
  2265. }
  2266. if (caller.superClass_) {
  2267. // Copying using loop to avoid deop due to passing arguments object to
  2268. // function. This is faster in many JS engines as of late 2014.
  2269. var ctorArgs = new Array(arguments.length - 1);
  2270. for (var i = 1; i < arguments.length; i++) {
  2271. ctorArgs[i - 1] = arguments[i];
  2272. }
  2273. // This is a constructor. Call the superclass constructor.
  2274. return caller.superClass_.constructor.apply(me, ctorArgs);
  2275. }
  2276. // Copying using loop to avoid deop due to passing arguments object to
  2277. // function. This is faster in many JS engines as of late 2014.
  2278. var args = new Array(arguments.length - 2);
  2279. for (var i = 2; i < arguments.length; i++) {
  2280. args[i - 2] = arguments[i];
  2281. }
  2282. var foundCaller = false;
  2283. for (var ctor = me.constructor; ctor;
  2284. ctor = ctor.superClass_ && ctor.superClass_.constructor) {
  2285. if (ctor.prototype[opt_methodName] === caller) {
  2286. foundCaller = true;
  2287. } else if (foundCaller) {
  2288. return ctor.prototype[opt_methodName].apply(me, args);
  2289. }
  2290. }
  2291. // If we did not find the caller in the prototype chain, then one of two
  2292. // things happened:
  2293. // 1) The caller is an instance method.
  2294. // 2) This method was not called by the right caller.
  2295. if (me[opt_methodName] === caller) {
  2296. return me.constructor.prototype[opt_methodName].apply(me, args);
  2297. } else {
  2298. throw Error(
  2299. 'goog.base called from a method of one name ' +
  2300. 'to a method of a different name');
  2301. }
  2302. };
  2303. /**
  2304. * Allow for aliasing within scope functions. This function exists for
  2305. * uncompiled code - in compiled code the calls will be inlined and the aliases
  2306. * applied. In uncompiled code the function is simply run since the aliases as
  2307. * written are valid JavaScript.
  2308. *
  2309. *
  2310. * @param {function()} fn Function to call. This function can contain aliases
  2311. * to namespaces (e.g. "var dom = goog.dom") or classes
  2312. * (e.g. "var Timer = goog.Timer").
  2313. */
  2314. goog.scope = function(fn) {
  2315. if (goog.isInModuleLoader_()) {
  2316. throw Error('goog.scope is not supported within a goog.module.');
  2317. }
  2318. fn.call(goog.global);
  2319. };
  2320. /*
  2321. * To support uncompiled, strict mode bundles that use eval to divide source
  2322. * like so:
  2323. * eval('someSource;//# sourceUrl sourcefile.js');
  2324. * We need to export the globally defined symbols "goog" and "COMPILED".
  2325. * Exporting "goog" breaks the compiler optimizations, so we required that
  2326. * be defined externally.
  2327. * NOTE: We don't use goog.exportSymbol here because we don't want to trigger
  2328. * extern generation when that compiler option is enabled.
  2329. */
  2330. if (!COMPILED) {
  2331. goog.global['COMPILED'] = COMPILED;
  2332. }
  2333. //==============================================================================
  2334. // goog.defineClass implementation
  2335. //==============================================================================
  2336. /**
  2337. * Creates a restricted form of a Closure "class":
  2338. * - from the compiler's perspective, the instance returned from the
  2339. * constructor is sealed (no new properties may be added). This enables
  2340. * better checks.
  2341. * - the compiler will rewrite this definition to a form that is optimal
  2342. * for type checking and optimization (initially this will be a more
  2343. * traditional form).
  2344. *
  2345. * @param {Function} superClass The superclass, Object or null.
  2346. * @param {goog.defineClass.ClassDescriptor} def
  2347. * An object literal describing
  2348. * the class. It may have the following properties:
  2349. * "constructor": the constructor function
  2350. * "statics": an object literal containing methods to add to the constructor
  2351. * as "static" methods or a function that will receive the constructor
  2352. * function as its only parameter to which static properties can
  2353. * be added.
  2354. * all other properties are added to the prototype.
  2355. * @return {!Function} The class constructor.
  2356. */
  2357. goog.defineClass = function(superClass, def) {
  2358. // TODO(johnlenz): consider making the superClass an optional parameter.
  2359. var constructor = def.constructor;
  2360. var statics = def.statics;
  2361. // Wrap the constructor prior to setting up the prototype and static methods.
  2362. if (!constructor || constructor == Object.prototype.constructor) {
  2363. constructor = function() {
  2364. throw Error('cannot instantiate an interface (no constructor defined).');
  2365. };
  2366. }
  2367. var cls = goog.defineClass.createSealingConstructor_(constructor, superClass);
  2368. if (superClass) {
  2369. goog.inherits(cls, superClass);
  2370. }
  2371. // Remove all the properties that should not be copied to the prototype.
  2372. delete def.constructor;
  2373. delete def.statics;
  2374. goog.defineClass.applyProperties_(cls.prototype, def);
  2375. if (statics != null) {
  2376. if (statics instanceof Function) {
  2377. statics(cls);
  2378. } else {
  2379. goog.defineClass.applyProperties_(cls, statics);
  2380. }
  2381. }
  2382. return cls;
  2383. };
  2384. /**
  2385. * @typedef {{
  2386. * constructor: (!Function|undefined),
  2387. * statics: (Object|undefined|function(Function):void)
  2388. * }}
  2389. */
  2390. goog.defineClass.ClassDescriptor;
  2391. /**
  2392. * @define {boolean} Whether the instances returned by goog.defineClass should
  2393. * be sealed when possible.
  2394. *
  2395. * When sealing is disabled the constructor function will not be wrapped by
  2396. * goog.defineClass, making it incompatible with ES6 class methods.
  2397. */
  2398. goog.define('goog.defineClass.SEAL_CLASS_INSTANCES', goog.DEBUG);
  2399. /**
  2400. * If goog.defineClass.SEAL_CLASS_INSTANCES is enabled and Object.seal is
  2401. * defined, this function will wrap the constructor in a function that seals the
  2402. * results of the provided constructor function.
  2403. *
  2404. * @param {!Function} ctr The constructor whose results maybe be sealed.
  2405. * @param {Function} superClass The superclass constructor.
  2406. * @return {!Function} The replacement constructor.
  2407. * @private
  2408. */
  2409. goog.defineClass.createSealingConstructor_ = function(ctr, superClass) {
  2410. if (!goog.defineClass.SEAL_CLASS_INSTANCES) {
  2411. // Do now wrap the constructor when sealing is disabled. Angular code
  2412. // depends on this for injection to work properly.
  2413. return ctr;
  2414. }
  2415. // Compute whether the constructor is sealable at definition time, rather
  2416. // than when the instance is being constructed.
  2417. var superclassSealable = !goog.defineClass.isUnsealable_(superClass);
  2418. /**
  2419. * @this {Object}
  2420. * @return {?}
  2421. */
  2422. var wrappedCtr = function() {
  2423. // Don't seal an instance of a subclass when it calls the constructor of
  2424. // its super class as there is most likely still setup to do.
  2425. var instance = ctr.apply(this, arguments) || this;
  2426. instance[goog.UID_PROPERTY_] = instance[goog.UID_PROPERTY_];
  2427. if (this.constructor === wrappedCtr && superclassSealable &&
  2428. Object.seal instanceof Function) {
  2429. Object.seal(instance);
  2430. }
  2431. return instance;
  2432. };
  2433. return wrappedCtr;
  2434. };
  2435. /**
  2436. * @param {Function} ctr The constructor to test.
  2437. * @return {boolean} Whether the constructor has been tagged as unsealable
  2438. * using goog.tagUnsealableClass.
  2439. * @private
  2440. */
  2441. goog.defineClass.isUnsealable_ = function(ctr) {
  2442. return ctr && ctr.prototype &&
  2443. ctr.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_];
  2444. };
  2445. // TODO(johnlenz): share these values with the goog.object
  2446. /**
  2447. * The names of the fields that are defined on Object.prototype.
  2448. * @type {!Array<string>}
  2449. * @private
  2450. * @const
  2451. */
  2452. goog.defineClass.OBJECT_PROTOTYPE_FIELDS_ = [
  2453. 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
  2454. 'toLocaleString', 'toString', 'valueOf'
  2455. ];
  2456. // TODO(johnlenz): share this function with the goog.object
  2457. /**
  2458. * @param {!Object} target The object to add properties to.
  2459. * @param {!Object} source The object to copy properties from.
  2460. * @private
  2461. */
  2462. goog.defineClass.applyProperties_ = function(target, source) {
  2463. // TODO(johnlenz): update this to support ES5 getters/setters
  2464. var key;
  2465. for (key in source) {
  2466. if (Object.prototype.hasOwnProperty.call(source, key)) {
  2467. target[key] = source[key];
  2468. }
  2469. }
  2470. // For IE the for-in-loop does not contain any properties that are not
  2471. // enumerable on the prototype object (for example isPrototypeOf from
  2472. // Object.prototype) and it will also not include 'replace' on objects that
  2473. // extend String and change 'replace' (not that it is common for anyone to
  2474. // extend anything except Object).
  2475. for (var i = 0; i < goog.defineClass.OBJECT_PROTOTYPE_FIELDS_.length; i++) {
  2476. key = goog.defineClass.OBJECT_PROTOTYPE_FIELDS_[i];
  2477. if (Object.prototype.hasOwnProperty.call(source, key)) {
  2478. target[key] = source[key];
  2479. }
  2480. }
  2481. };
  2482. /**
  2483. * Sealing classes breaks the older idiom of assigning properties on the
  2484. * prototype rather than in the constructor. As such, goog.defineClass
  2485. * must not seal subclasses of these old-style classes until they are fixed.
  2486. * Until then, this marks a class as "broken", instructing defineClass
  2487. * not to seal subclasses.
  2488. * @param {!Function} ctr The legacy constructor to tag as unsealable.
  2489. */
  2490. goog.tagUnsealableClass = function(ctr) {
  2491. if (!COMPILED && goog.defineClass.SEAL_CLASS_INSTANCES) {
  2492. ctr.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_] = true;
  2493. }
  2494. };
  2495. /**
  2496. * Name for unsealable tag property.
  2497. * @const @private {string}
  2498. */
  2499. goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_ = 'goog_defineClass_legacy_unsealable';
  2500. /**
  2501. * Returns a newly created map from language mode string to a boolean
  2502. * indicating whether transpilation should be done for that mode.
  2503. *
  2504. * Guaranteed invariant:
  2505. * For any two modes, l1 and l2 where l2 is a newer mode than l1,
  2506. * `map[l1] == true` implies that `map[l2] == true`.
  2507. * @private
  2508. * @return {!Object<string, boolean>}
  2509. */
  2510. goog.createRequiresTranspilation_ = function() {
  2511. var /** !Object<string, boolean> */ requiresTranspilation = {'es3': false};
  2512. var transpilationRequiredForAllLaterModes = false;
  2513. /**
  2514. * Adds an entry to requiresTranspliation for the given language mode.
  2515. *
  2516. * IMPORTANT: Calls must be made in order from oldest to newest language
  2517. * mode.
  2518. * @param {string} modeName
  2519. * @param {function(): boolean} isSupported Returns true if the JS engine
  2520. * supports the given mode.
  2521. */
  2522. function addNewerLanguageTranspilationCheck(modeName, isSupported) {
  2523. if (transpilationRequiredForAllLaterModes) {
  2524. requiresTranspilation[modeName] = true;
  2525. } else if (isSupported()) {
  2526. requiresTranspilation[modeName] = false;
  2527. } else {
  2528. requiresTranspilation[modeName] = true;
  2529. transpilationRequiredForAllLaterModes = true;
  2530. }
  2531. }
  2532. /**
  2533. * Does the given code evaluate without syntax errors and return a truthy
  2534. * result?
  2535. */
  2536. function /** boolean */ evalCheck(/** string */ code) {
  2537. try {
  2538. return !!eval(code);
  2539. } catch (ignored) {
  2540. return false;
  2541. }
  2542. }
  2543. var userAgent = goog.global.navigator && goog.global.navigator.userAgent ?
  2544. goog.global.navigator.userAgent :
  2545. '';
  2546. // Identify ES3-only browsers by their incorrect treatment of commas.
  2547. addNewerLanguageTranspilationCheck('es5', function() {
  2548. return evalCheck('[1,].length==1');
  2549. });
  2550. addNewerLanguageTranspilationCheck('es6', function() {
  2551. // Edge has a non-deterministic (i.e., not reproducible) bug with ES6:
  2552. // https://github.com/Microsoft/ChakraCore/issues/1496.
  2553. var re = /Edge\/(\d+)(\.\d)*/i;
  2554. var edgeUserAgent = userAgent.match(re);
  2555. if (edgeUserAgent && Number(edgeUserAgent[1]) < 15) {
  2556. return false;
  2557. }
  2558. // Test es6: [FF50 (?), Edge 14 (?), Chrome 50]
  2559. // (a) default params (specifically shadowing locals),
  2560. // (b) destructuring, (c) block-scoped functions,
  2561. // (d) for-of (const), (e) new.target/Reflect.construct
  2562. var es6fullTest =
  2563. 'class X{constructor(){if(new.target!=String)throw 1;this.x=42}}' +
  2564. 'let q=Reflect.construct(X,[],String);if(q.x!=42||!(q instanceof ' +
  2565. 'String))throw 1;for(const a of[2,3]){if(a==2)continue;function ' +
  2566. 'f(z={a}){let a=0;return z.a}{function f(){return 0;}}return f()' +
  2567. '==3}';
  2568. return evalCheck('(()=>{"use strict";' + es6fullTest + '})()');
  2569. });
  2570. // TODO(joeltine): Remove es6-impl references for b/31340605.
  2571. // Consider es6-impl (widely-implemented es6 features) to be supported
  2572. // whenever es6 is supported. Technically es6-impl is a lower level of
  2573. // support than es6, but we don't have tests specifically for it.
  2574. addNewerLanguageTranspilationCheck('es6-impl', function() {
  2575. return true;
  2576. });
  2577. // ** and **= are the only new features in 'es7'
  2578. addNewerLanguageTranspilationCheck('es7', function() {
  2579. return evalCheck('2 ** 2 == 4');
  2580. });
  2581. // async functions are the only new features in 'es8'
  2582. addNewerLanguageTranspilationCheck('es8', function() {
  2583. return evalCheck('async () => 1, true');
  2584. });
  2585. return requiresTranspilation;
  2586. };
  2587. goog.provide('ol.array');
  2588. /**
  2589. * Performs a binary search on the provided sorted list and returns the index of the item if found. If it can't be found it'll return -1.
  2590. * https://github.com/darkskyapp/binary-search
  2591. *
  2592. * @param {Array.<*>} haystack Items to search through.
  2593. * @param {*} needle The item to look for.
  2594. * @param {Function=} opt_comparator Comparator function.
  2595. * @return {number} The index of the item if found, -1 if not.
  2596. */
  2597. ol.array.binarySearch = function(haystack, needle, opt_comparator) {
  2598. var mid, cmp;
  2599. var comparator = opt_comparator || ol.array.numberSafeCompareFunction;
  2600. var low = 0;
  2601. var high = haystack.length;
  2602. var found = false;
  2603. while (low < high) {
  2604. /* Note that "(low + high) >>> 1" may overflow, and results in a typecast
  2605. * to double (which gives the wrong results). */
  2606. mid = low + (high - low >> 1);
  2607. cmp = +comparator(haystack[mid], needle);
  2608. if (cmp < 0.0) { /* Too low. */
  2609. low = mid + 1;
  2610. } else { /* Key found or too high */
  2611. high = mid;
  2612. found = !cmp;
  2613. }
  2614. }
  2615. /* Key not found. */
  2616. return found ? low : ~low;
  2617. };
  2618. /**
  2619. * Compare function for array sort that is safe for numbers.
  2620. * @param {*} a The first object to be compared.
  2621. * @param {*} b The second object to be compared.
  2622. * @return {number} A negative number, zero, or a positive number as the first
  2623. * argument is less than, equal to, or greater than the second.
  2624. */
  2625. ol.array.numberSafeCompareFunction = function(a, b) {
  2626. return a > b ? 1 : a < b ? -1 : 0;
  2627. };
  2628. /**
  2629. * Whether the array contains the given object.
  2630. * @param {Array.<*>} arr The array to test for the presence of the element.
  2631. * @param {*} obj The object for which to test.
  2632. * @return {boolean} The object is in the array.
  2633. */
  2634. ol.array.includes = function(arr, obj) {
  2635. return arr.indexOf(obj) >= 0;
  2636. };
  2637. /**
  2638. * @param {Array.<number>} arr Array.
  2639. * @param {number} target Target.
  2640. * @param {number} direction 0 means return the nearest, > 0
  2641. * means return the largest nearest, < 0 means return the
  2642. * smallest nearest.
  2643. * @return {number} Index.
  2644. */
  2645. ol.array.linearFindNearest = function(arr, target, direction) {
  2646. var n = arr.length;
  2647. if (arr[0] <= target) {
  2648. return 0;
  2649. } else if (target <= arr[n - 1]) {
  2650. return n - 1;
  2651. } else {
  2652. var i;
  2653. if (direction > 0) {
  2654. for (i = 1; i < n; ++i) {
  2655. if (arr[i] < target) {
  2656. return i - 1;
  2657. }
  2658. }
  2659. } else if (direction < 0) {
  2660. for (i = 1; i < n; ++i) {
  2661. if (arr[i] <= target) {
  2662. return i;
  2663. }
  2664. }
  2665. } else {
  2666. for (i = 1; i < n; ++i) {
  2667. if (arr[i] == target) {
  2668. return i;
  2669. } else if (arr[i] < target) {
  2670. if (arr[i - 1] - target < target - arr[i]) {
  2671. return i - 1;
  2672. } else {
  2673. return i;
  2674. }
  2675. }
  2676. }
  2677. }
  2678. return n - 1;
  2679. }
  2680. };
  2681. /**
  2682. * @param {Array.<*>} arr Array.
  2683. * @param {number} begin Begin index.
  2684. * @param {number} end End index.
  2685. */
  2686. ol.array.reverseSubArray = function(arr, begin, end) {
  2687. while (begin < end) {
  2688. var tmp = arr[begin];
  2689. arr[begin] = arr[end];
  2690. arr[end] = tmp;
  2691. ++begin;
  2692. --end;
  2693. }
  2694. };
  2695. /**
  2696. * @param {Array.<VALUE>} arr The array to modify.
  2697. * @param {Array.<VALUE>|VALUE} data The elements or arrays of elements
  2698. * to add to arr.
  2699. * @template VALUE
  2700. */
  2701. ol.array.extend = function(arr, data) {
  2702. var i;
  2703. var extension = Array.isArray(data) ? data : [data];
  2704. var length = extension.length;
  2705. for (i = 0; i < length; i++) {
  2706. arr[arr.length] = extension[i];
  2707. }
  2708. };
  2709. /**
  2710. * @param {Array.<VALUE>} arr The array to modify.
  2711. * @param {VALUE} obj The element to remove.
  2712. * @template VALUE
  2713. * @return {boolean} If the element was removed.
  2714. */
  2715. ol.array.remove = function(arr, obj) {
  2716. var i = arr.indexOf(obj);
  2717. var found = i > -1;
  2718. if (found) {
  2719. arr.splice(i, 1);
  2720. }
  2721. return found;
  2722. };
  2723. /**
  2724. * @param {Array.<VALUE>} arr The array to search in.
  2725. * @param {function(VALUE, number, ?) : boolean} func The function to compare.
  2726. * @template VALUE
  2727. * @return {VALUE} The element found.
  2728. */
  2729. ol.array.find = function(arr, func) {
  2730. var length = arr.length >>> 0;
  2731. var value;
  2732. for (var i = 0; i < length; i++) {
  2733. value = arr[i];
  2734. if (func(value, i, arr)) {
  2735. return value;
  2736. }
  2737. }
  2738. return null;
  2739. };
  2740. /**
  2741. * @param {Array|Uint8ClampedArray} arr1 The first array to compare.
  2742. * @param {Array|Uint8ClampedArray} arr2 The second array to compare.
  2743. * @return {boolean} Whether the two arrays are equal.
  2744. */
  2745. ol.array.equals = function(arr1, arr2) {
  2746. var len1 = arr1.length;
  2747. if (len1 !== arr2.length) {
  2748. return false;
  2749. }
  2750. for (var i = 0; i < len1; i++) {
  2751. if (arr1[i] !== arr2[i]) {
  2752. return false;
  2753. }
  2754. }
  2755. return true;
  2756. };
  2757. /**
  2758. * @param {Array.<*>} arr The array to sort (modifies original).
  2759. * @param {Function} compareFnc Comparison function.
  2760. */
  2761. ol.array.stableSort = function(arr, compareFnc) {
  2762. var length = arr.length;
  2763. var tmp = Array(arr.length);
  2764. var i;
  2765. for (i = 0; i < length; i++) {
  2766. tmp[i] = {index: i, value: arr[i]};
  2767. }
  2768. tmp.sort(function(a, b) {
  2769. return compareFnc(a.value, b.value) || a.index - b.index;
  2770. });
  2771. for (i = 0; i < arr.length; i++) {
  2772. arr[i] = tmp[i].value;
  2773. }
  2774. };
  2775. /**
  2776. * @param {Array.<*>} arr The array to search in.
  2777. * @param {Function} func Comparison function.
  2778. * @return {number} Return index.
  2779. */
  2780. ol.array.findIndex = function(arr, func) {
  2781. var index;
  2782. var found = !arr.every(function(el, idx) {
  2783. index = idx;
  2784. return !func(el, idx, arr);
  2785. });
  2786. return found ? index : -1;
  2787. };
  2788. /**
  2789. * @param {Array.<*>} arr The array to test.
  2790. * @param {Function=} opt_func Comparison function.
  2791. * @param {boolean=} opt_strict Strictly sorted (default false).
  2792. * @return {boolean} Return index.
  2793. */
  2794. ol.array.isSorted = function(arr, opt_func, opt_strict) {
  2795. var compare = opt_func || ol.array.numberSafeCompareFunction;
  2796. return arr.every(function(currentVal, index) {
  2797. if (index === 0) {
  2798. return true;
  2799. }
  2800. var res = compare(arr[index - 1], currentVal);
  2801. return !(res > 0 || opt_strict && res === 0);
  2802. });
  2803. };
  2804. goog.provide('ol');
  2805. /**
  2806. * Constants defined with the define tag cannot be changed in application
  2807. * code, but can be set at compile time.
  2808. * Some reduce the size of the build in advanced compile mode.
  2809. */
  2810. /**
  2811. * @define {boolean} Assume touch. Default is `false`.
  2812. */
  2813. ol.ASSUME_TOUCH = false;
  2814. /**
  2815. * TODO: rename this to something having to do with tile grids
  2816. * see https://github.com/openlayers/openlayers/issues/2076
  2817. * @define {number} Default maximum zoom for default tile grids.
  2818. */
  2819. ol.DEFAULT_MAX_ZOOM = 42;
  2820. /**
  2821. * @define {number} Default min zoom level for the map view. Default is `0`.
  2822. */
  2823. ol.DEFAULT_MIN_ZOOM = 0;
  2824. /**
  2825. * @define {number} Default maximum allowed threshold (in pixels) for
  2826. * reprojection triangulation. Default is `0.5`.
  2827. */
  2828. ol.DEFAULT_RASTER_REPROJECTION_ERROR_THRESHOLD = 0.5;
  2829. /**
  2830. * @define {number} Default tile size.
  2831. */
  2832. ol.DEFAULT_TILE_SIZE = 256;
  2833. /**
  2834. * @define {string} Default WMS version.
  2835. */
  2836. ol.DEFAULT_WMS_VERSION = '1.3.0';
  2837. /**
  2838. * @define {boolean} Enable the Canvas renderer. Default is `true`. Setting
  2839. * this to false at compile time in advanced mode removes all code
  2840. * supporting the Canvas renderer from the build.
  2841. */
  2842. ol.ENABLE_CANVAS = true;
  2843. /**
  2844. * @define {boolean} Enable integration with the Proj4js library. Default is
  2845. * `true`.
  2846. */
  2847. ol.ENABLE_PROJ4JS = true;
  2848. /**
  2849. * @define {boolean} Enable automatic reprojection of raster sources. Default is
  2850. * `true`.
  2851. */
  2852. ol.ENABLE_RASTER_REPROJECTION = true;
  2853. /**
  2854. * @define {boolean} Enable the WebGL renderer. Default is `true`. Setting
  2855. * this to false at compile time in advanced mode removes all code
  2856. * supporting the WebGL renderer from the build.
  2857. */
  2858. ol.ENABLE_WEBGL = true;
  2859. /**
  2860. * @define {boolean} Include debuggable shader sources. Default is `true`.
  2861. * This should be set to `false` for production builds (if `ol.ENABLE_WEBGL`
  2862. * is `true`).
  2863. */
  2864. ol.DEBUG_WEBGL = true;
  2865. /**
  2866. * @define {number} The size in pixels of the first atlas image. Default is
  2867. * `256`.
  2868. */
  2869. ol.INITIAL_ATLAS_SIZE = 256;
  2870. /**
  2871. * @define {number} The maximum size in pixels of atlas images. Default is
  2872. * `-1`, meaning it is not used (and `ol.WEBGL_MAX_TEXTURE_SIZE` is
  2873. * used instead).
  2874. */
  2875. ol.MAX_ATLAS_SIZE = -1;
  2876. /**
  2877. * @define {number} Maximum mouse wheel delta.
  2878. */
  2879. ol.MOUSEWHEELZOOM_MAXDELTA = 1;
  2880. /**
  2881. * @define {number} Maximum width and/or height extent ratio that determines
  2882. * when the overview map should be zoomed out.
  2883. */
  2884. ol.OVERVIEWMAP_MAX_RATIO = 0.75;
  2885. /**
  2886. * @define {number} Minimum width and/or height extent ratio that determines
  2887. * when the overview map should be zoomed in.
  2888. */
  2889. ol.OVERVIEWMAP_MIN_RATIO = 0.1;
  2890. /**
  2891. * @define {number} Maximum number of source tiles for raster reprojection of
  2892. * a single tile.
  2893. * If too many source tiles are determined to be loaded to create a single
  2894. * reprojected tile the browser can become unresponsive or even crash.
  2895. * This can happen if the developer defines projections improperly and/or
  2896. * with unlimited extents.
  2897. * If too many tiles are required, no tiles are loaded and
  2898. * `ol.TileState.ERROR` state is set. Default is `100`.
  2899. */
  2900. ol.RASTER_REPROJECTION_MAX_SOURCE_TILES = 100;
  2901. /**
  2902. * @define {number} Maximum number of subdivision steps during raster
  2903. * reprojection triangulation. Prevents high memory usage and large
  2904. * number of proj4 calls (for certain transformations and areas).
  2905. * At most `2*(2^this)` triangles are created for each triangulated
  2906. * extent (tile/image). Default is `10`.
  2907. */
  2908. ol.RASTER_REPROJECTION_MAX_SUBDIVISION = 10;
  2909. /**
  2910. * @define {number} Maximum allowed size of triangle relative to world width.
  2911. * When transforming corners of world extent between certain projections,
  2912. * the resulting triangulation seems to have zero error and no subdivision
  2913. * is performed.
  2914. * If the triangle width is more than this (relative to world width; 0-1),
  2915. * subdivison is forced (up to `ol.RASTER_REPROJECTION_MAX_SUBDIVISION`).
  2916. * Default is `0.25`.
  2917. */
  2918. ol.RASTER_REPROJECTION_MAX_TRIANGLE_WIDTH = 0.25;
  2919. /**
  2920. * @define {number} Tolerance for geometry simplification in device pixels.
  2921. */
  2922. ol.SIMPLIFY_TOLERANCE = 0.5;
  2923. /**
  2924. * @define {number} Texture cache high water mark.
  2925. */
  2926. ol.WEBGL_TEXTURE_CACHE_HIGH_WATER_MARK = 1024;
  2927. /**
  2928. * @define {string} OpenLayers version.
  2929. */
  2930. ol.VERSION = '';
  2931. /**
  2932. * The maximum supported WebGL texture size in pixels. If WebGL is not
  2933. * supported, the value is set to `undefined`.
  2934. * @const
  2935. * @type {number|undefined}
  2936. */
  2937. ol.WEBGL_MAX_TEXTURE_SIZE; // value is set in `ol.has`
  2938. /**
  2939. * List of supported WebGL extensions.
  2940. * @const
  2941. * @type {Array.<string>}
  2942. */
  2943. ol.WEBGL_EXTENSIONS; // value is set in `ol.has`
  2944. /**
  2945. * Inherit the prototype methods from one constructor into another.
  2946. *
  2947. * Usage:
  2948. *
  2949. * function ParentClass(a, b) { }
  2950. * ParentClass.prototype.foo = function(a) { }
  2951. *
  2952. * function ChildClass(a, b, c) {
  2953. * // Call parent constructor
  2954. * ParentClass.call(this, a, b);
  2955. * }
  2956. * ol.inherits(ChildClass, ParentClass);
  2957. *
  2958. * var child = new ChildClass('a', 'b', 'see');
  2959. * child.foo(); // This works.
  2960. *
  2961. * @param {!Function} childCtor Child constructor.
  2962. * @param {!Function} parentCtor Parent constructor.
  2963. * @function
  2964. * @api
  2965. */
  2966. ol.inherits = function(childCtor, parentCtor) {
  2967. childCtor.prototype = Object.create(parentCtor.prototype);
  2968. childCtor.prototype.constructor = childCtor;
  2969. };
  2970. /**
  2971. * A reusable function, used e.g. as a default for callbacks.
  2972. *
  2973. * @return {undefined} Nothing.
  2974. */
  2975. ol.nullFunction = function() {};
  2976. /**
  2977. * Gets a unique ID for an object. This mutates the object so that further calls
  2978. * with the same object as a parameter returns the same value. Unique IDs are generated
  2979. * as a strictly increasing sequence. Adapted from goog.getUid.
  2980. *
  2981. * @param {Object} obj The object to get the unique ID for.
  2982. * @return {number} The unique ID for the object.
  2983. */
  2984. ol.getUid = function(obj) {
  2985. return obj.ol_uid ||
  2986. (obj.ol_uid = ++ol.uidCounter_);
  2987. };
  2988. /**
  2989. * Counter for getUid.
  2990. * @type {number}
  2991. * @private
  2992. */
  2993. ol.uidCounter_ = 0;
  2994. goog.provide('ol.AssertionError');
  2995. goog.require('ol');
  2996. /**
  2997. * Error object thrown when an assertion failed. This is an ECMA-262 Error,
  2998. * extended with a `code` property.
  2999. * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error}
  3000. * @constructor
  3001. * @extends {Error}
  3002. * @implements {oli.AssertionError}
  3003. * @param {number} code Error code.
  3004. */
  3005. ol.AssertionError = function(code) {
  3006. var path = ol.VERSION ? ol.VERSION.split('-')[0] : 'latest';
  3007. /**
  3008. * @type {string}
  3009. */
  3010. this.message = 'Assertion failed. See https://openlayers.org/en/' + path +
  3011. '/doc/errors/#' + code + ' for details.';
  3012. /**
  3013. * Error code. The meaning of the code can be found on
  3014. * {@link https://openlayers.org/en/latest/doc/errors/} (replace `latest` with
  3015. * the version found in the OpenLayers script's header comment if a version
  3016. * other than the latest is used).
  3017. * @type {number}
  3018. * @api
  3019. */
  3020. this.code = code;
  3021. this.name = 'AssertionError';
  3022. };
  3023. ol.inherits(ol.AssertionError, Error);
  3024. goog.provide('ol.asserts');
  3025. goog.require('ol.AssertionError');
  3026. /**
  3027. * @param {*} assertion Assertion we expected to be truthy.
  3028. * @param {number} errorCode Error code.
  3029. */
  3030. ol.asserts.assert = function(assertion, errorCode) {
  3031. if (!assertion) {
  3032. throw new ol.AssertionError(errorCode);
  3033. }
  3034. };
  3035. goog.provide('ol.TileRange');
  3036. /**
  3037. * A representation of a contiguous block of tiles. A tile range is specified
  3038. * by its min/max tile coordinates and is inclusive of coordinates.
  3039. *
  3040. * @constructor
  3041. * @param {number} minX Minimum X.
  3042. * @param {number} maxX Maximum X.
  3043. * @param {number} minY Minimum Y.
  3044. * @param {number} maxY Maximum Y.
  3045. * @struct
  3046. */
  3047. ol.TileRange = function(minX, maxX, minY, maxY) {
  3048. /**
  3049. * @type {number}
  3050. */
  3051. this.minX = minX;
  3052. /**
  3053. * @type {number}
  3054. */
  3055. this.maxX = maxX;
  3056. /**
  3057. * @type {number}
  3058. */
  3059. this.minY = minY;
  3060. /**
  3061. * @type {number}
  3062. */
  3063. this.maxY = maxY;
  3064. };
  3065. /**
  3066. * @param {number} minX Minimum X.
  3067. * @param {number} maxX Maximum X.
  3068. * @param {number} minY Minimum Y.
  3069. * @param {number} maxY Maximum Y.
  3070. * @param {ol.TileRange|undefined} tileRange TileRange.
  3071. * @return {ol.TileRange} Tile range.
  3072. */
  3073. ol.TileRange.createOrUpdate = function(minX, maxX, minY, maxY, tileRange) {
  3074. if (tileRange !== undefined) {
  3075. tileRange.minX = minX;
  3076. tileRange.maxX = maxX;
  3077. tileRange.minY = minY;
  3078. tileRange.maxY = maxY;
  3079. return tileRange;
  3080. } else {
  3081. return new ol.TileRange(minX, maxX, minY, maxY);
  3082. }
  3083. };
  3084. /**
  3085. * @param {ol.TileCoord} tileCoord Tile coordinate.
  3086. * @return {boolean} Contains tile coordinate.
  3087. */
  3088. ol.TileRange.prototype.contains = function(tileCoord) {
  3089. return this.containsXY(tileCoord[1], tileCoord[2]);
  3090. };
  3091. /**
  3092. * @param {ol.TileRange} tileRange Tile range.
  3093. * @return {boolean} Contains.
  3094. */
  3095. ol.TileRange.prototype.containsTileRange = function(tileRange) {
  3096. return this.minX <= tileRange.minX && tileRange.maxX <= this.maxX &&
  3097. this.minY <= tileRange.minY && tileRange.maxY <= this.maxY;
  3098. };
  3099. /**
  3100. * @param {number} x Tile coordinate x.
  3101. * @param {number} y Tile coordinate y.
  3102. * @return {boolean} Contains coordinate.
  3103. */
  3104. ol.TileRange.prototype.containsXY = function(x, y) {
  3105. return this.minX <= x && x <= this.maxX && this.minY <= y && y <= this.maxY;
  3106. };
  3107. /**
  3108. * @param {ol.TileRange} tileRange Tile range.
  3109. * @return {boolean} Equals.
  3110. */
  3111. ol.TileRange.prototype.equals = function(tileRange) {
  3112. return this.minX == tileRange.minX && this.minY == tileRange.minY &&
  3113. this.maxX == tileRange.maxX && this.maxY == tileRange.maxY;
  3114. };
  3115. /**
  3116. * @param {ol.TileRange} tileRange Tile range.
  3117. */
  3118. ol.TileRange.prototype.extend = function(tileRange) {
  3119. if (tileRange.minX < this.minX) {
  3120. this.minX = tileRange.minX;
  3121. }
  3122. if (tileRange.maxX > this.maxX) {
  3123. this.maxX = tileRange.maxX;
  3124. }
  3125. if (tileRange.minY < this.minY) {
  3126. this.minY = tileRange.minY;
  3127. }
  3128. if (tileRange.maxY > this.maxY) {
  3129. this.maxY = tileRange.maxY;
  3130. }
  3131. };
  3132. /**
  3133. * @return {number} Height.
  3134. */
  3135. ol.TileRange.prototype.getHeight = function() {
  3136. return this.maxY - this.minY + 1;
  3137. };
  3138. /**
  3139. * @return {ol.Size} Size.
  3140. */
  3141. ol.TileRange.prototype.getSize = function() {
  3142. return [this.getWidth(), this.getHeight()];
  3143. };
  3144. /**
  3145. * @return {number} Width.
  3146. */
  3147. ol.TileRange.prototype.getWidth = function() {
  3148. return this.maxX - this.minX + 1;
  3149. };
  3150. /**
  3151. * @param {ol.TileRange} tileRange Tile range.
  3152. * @return {boolean} Intersects.
  3153. */
  3154. ol.TileRange.prototype.intersects = function(tileRange) {
  3155. return this.minX <= tileRange.maxX &&
  3156. this.maxX >= tileRange.minX &&
  3157. this.minY <= tileRange.maxY &&
  3158. this.maxY >= tileRange.minY;
  3159. };
  3160. goog.provide('ol.math');
  3161. goog.require('ol.asserts');
  3162. /**
  3163. * Takes a number and clamps it to within the provided bounds.
  3164. * @param {number} value The input number.
  3165. * @param {number} min The minimum value to return.
  3166. * @param {number} max The maximum value to return.
  3167. * @return {number} The input number if it is within bounds, or the nearest
  3168. * number within the bounds.
  3169. */
  3170. ol.math.clamp = function(value, min, max) {
  3171. return Math.min(Math.max(value, min), max);
  3172. };
  3173. /**
  3174. * Return the hyperbolic cosine of a given number. The method will use the
  3175. * native `Math.cosh` function if it is available, otherwise the hyperbolic
  3176. * cosine will be calculated via the reference implementation of the Mozilla
  3177. * developer network.
  3178. *
  3179. * @param {number} x X.
  3180. * @return {number} Hyperbolic cosine of x.
  3181. */
  3182. ol.math.cosh = (function() {
  3183. // Wrapped in a iife, to save the overhead of checking for the native
  3184. // implementation on every invocation.
  3185. var cosh;
  3186. if ('cosh' in Math) {
  3187. // The environment supports the native Math.cosh function, use it…
  3188. cosh = Math.cosh;
  3189. } else {
  3190. // … else, use the reference implementation of MDN:
  3191. cosh = function(x) {
  3192. var y = Math.exp(x);
  3193. return (y + 1 / y) / 2;
  3194. };
  3195. }
  3196. return cosh;
  3197. }());
  3198. /**
  3199. * @param {number} x X.
  3200. * @return {number} The smallest power of two greater than or equal to x.
  3201. */
  3202. ol.math.roundUpToPowerOfTwo = function(x) {
  3203. ol.asserts.assert(0 < x, 29); // `x` must be greater than `0`
  3204. return Math.pow(2, Math.ceil(Math.log(x) / Math.LN2));
  3205. };
  3206. /**
  3207. * Returns the square of the closest distance between the point (x, y) and the
  3208. * line segment (x1, y1) to (x2, y2).
  3209. * @param {number} x X.
  3210. * @param {number} y Y.
  3211. * @param {number} x1 X1.
  3212. * @param {number} y1 Y1.
  3213. * @param {number} x2 X2.
  3214. * @param {number} y2 Y2.
  3215. * @return {number} Squared distance.
  3216. */
  3217. ol.math.squaredSegmentDistance = function(x, y, x1, y1, x2, y2) {
  3218. var dx = x2 - x1;
  3219. var dy = y2 - y1;
  3220. if (dx !== 0 || dy !== 0) {
  3221. var t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy);
  3222. if (t > 1) {
  3223. x1 = x2;
  3224. y1 = y2;
  3225. } else if (t > 0) {
  3226. x1 += dx * t;
  3227. y1 += dy * t;
  3228. }
  3229. }
  3230. return ol.math.squaredDistance(x, y, x1, y1);
  3231. };
  3232. /**
  3233. * Returns the square of the distance between the points (x1, y1) and (x2, y2).
  3234. * @param {number} x1 X1.
  3235. * @param {number} y1 Y1.
  3236. * @param {number} x2 X2.
  3237. * @param {number} y2 Y2.
  3238. * @return {number} Squared distance.
  3239. */
  3240. ol.math.squaredDistance = function(x1, y1, x2, y2) {
  3241. var dx = x2 - x1;
  3242. var dy = y2 - y1;
  3243. return dx * dx + dy * dy;
  3244. };
  3245. /**
  3246. * Solves system of linear equations using Gaussian elimination method.
  3247. *
  3248. * @param {Array.<Array.<number>>} mat Augmented matrix (n x n + 1 column)
  3249. * in row-major order.
  3250. * @return {Array.<number>} The resulting vector.
  3251. */
  3252. ol.math.solveLinearSystem = function(mat) {
  3253. var n = mat.length;
  3254. for (var i = 0; i < n; i++) {
  3255. // Find max in the i-th column (ignoring i - 1 first rows)
  3256. var maxRow = i;
  3257. var maxEl = Math.abs(mat[i][i]);
  3258. for (var r = i + 1; r < n; r++) {
  3259. var absValue = Math.abs(mat[r][i]);
  3260. if (absValue > maxEl) {
  3261. maxEl = absValue;
  3262. maxRow = r;
  3263. }
  3264. }
  3265. if (maxEl === 0) {
  3266. return null; // matrix is singular
  3267. }
  3268. // Swap max row with i-th (current) row
  3269. var tmp = mat[maxRow];
  3270. mat[maxRow] = mat[i];
  3271. mat[i] = tmp;
  3272. // Subtract the i-th row to make all the remaining rows 0 in the i-th column
  3273. for (var j = i + 1; j < n; j++) {
  3274. var coef = -mat[j][i] / mat[i][i];
  3275. for (var k = i; k < n + 1; k++) {
  3276. if (i == k) {
  3277. mat[j][k] = 0;
  3278. } else {
  3279. mat[j][k] += coef * mat[i][k];
  3280. }
  3281. }
  3282. }
  3283. }
  3284. // Solve Ax=b for upper triangular matrix A (mat)
  3285. var x = new Array(n);
  3286. for (var l = n - 1; l >= 0; l--) {
  3287. x[l] = mat[l][n] / mat[l][l];
  3288. for (var m = l - 1; m >= 0; m--) {
  3289. mat[m][n] -= mat[m][l] * x[l];
  3290. }
  3291. }
  3292. return x;
  3293. };
  3294. /**
  3295. * Converts radians to to degrees.
  3296. *
  3297. * @param {number} angleInRadians Angle in radians.
  3298. * @return {number} Angle in degrees.
  3299. */
  3300. ol.math.toDegrees = function(angleInRadians) {
  3301. return angleInRadians * 180 / Math.PI;
  3302. };
  3303. /**
  3304. * Converts degrees to radians.
  3305. *
  3306. * @param {number} angleInDegrees Angle in degrees.
  3307. * @return {number} Angle in radians.
  3308. */
  3309. ol.math.toRadians = function(angleInDegrees) {
  3310. return angleInDegrees * Math.PI / 180;
  3311. };
  3312. /**
  3313. * Returns the modulo of a / b, depending on the sign of b.
  3314. *
  3315. * @param {number} a Dividend.
  3316. * @param {number} b Divisor.
  3317. * @return {number} Modulo.
  3318. */
  3319. ol.math.modulo = function(a, b) {
  3320. var r = a % b;
  3321. return r * b < 0 ? r + b : r;
  3322. };
  3323. /**
  3324. * Calculates the linearly interpolated value of x between a and b.
  3325. *
  3326. * @param {number} a Number
  3327. * @param {number} b Number
  3328. * @param {number} x Value to be interpolated.
  3329. * @return {number} Interpolated value.
  3330. */
  3331. ol.math.lerp = function(a, b, x) {
  3332. return a + x * (b - a);
  3333. };
  3334. goog.provide('ol.size');
  3335. /**
  3336. * Returns a buffered size.
  3337. * @param {ol.Size} size Size.
  3338. * @param {number} buffer Buffer.
  3339. * @param {ol.Size=} opt_size Optional reusable size array.
  3340. * @return {ol.Size} The buffered size.
  3341. */
  3342. ol.size.buffer = function(size, buffer, opt_size) {
  3343. if (opt_size === undefined) {
  3344. opt_size = [0, 0];
  3345. }
  3346. opt_size[0] = size[0] + 2 * buffer;
  3347. opt_size[1] = size[1] + 2 * buffer;
  3348. return opt_size;
  3349. };
  3350. /**
  3351. * Determines if a size has a positive area.
  3352. * @param {ol.Size} size The size to test.
  3353. * @return {boolean} The size has a positive area.
  3354. */
  3355. ol.size.hasArea = function(size) {
  3356. return size[0] > 0 && size[1] > 0;
  3357. };
  3358. /**
  3359. * Returns a size scaled by a ratio. The result will be an array of integers.
  3360. * @param {ol.Size} size Size.
  3361. * @param {number} ratio Ratio.
  3362. * @param {ol.Size=} opt_size Optional reusable size array.
  3363. * @return {ol.Size} The scaled size.
  3364. */
  3365. ol.size.scale = function(size, ratio, opt_size) {
  3366. if (opt_size === undefined) {
  3367. opt_size = [0, 0];
  3368. }
  3369. opt_size[0] = (size[0] * ratio + 0.5) | 0;
  3370. opt_size[1] = (size[1] * ratio + 0.5) | 0;
  3371. return opt_size;
  3372. };
  3373. /**
  3374. * Returns an `ol.Size` array for the passed in number (meaning: square) or
  3375. * `ol.Size` array.
  3376. * (meaning: non-square),
  3377. * @param {number|ol.Size} size Width and height.
  3378. * @param {ol.Size=} opt_size Optional reusable size array.
  3379. * @return {ol.Size} Size.
  3380. * @api
  3381. */
  3382. ol.size.toSize = function(size, opt_size) {
  3383. if (Array.isArray(size)) {
  3384. return size;
  3385. } else {
  3386. if (opt_size === undefined) {
  3387. opt_size = [size, size];
  3388. } else {
  3389. opt_size[0] = opt_size[1] = /** @type {number} */ (size);
  3390. }
  3391. return opt_size;
  3392. }
  3393. };
  3394. goog.provide('ol.extent.Corner');
  3395. /**
  3396. * Extent corner.
  3397. * @enum {string}
  3398. */
  3399. ol.extent.Corner = {
  3400. BOTTOM_LEFT: 'bottom-left',
  3401. BOTTOM_RIGHT: 'bottom-right',
  3402. TOP_LEFT: 'top-left',
  3403. TOP_RIGHT: 'top-right'
  3404. };
  3405. goog.provide('ol.extent.Relationship');
  3406. /**
  3407. * Relationship to an extent.
  3408. * @enum {number}
  3409. */
  3410. ol.extent.Relationship = {
  3411. UNKNOWN: 0,
  3412. INTERSECTING: 1,
  3413. ABOVE: 2,
  3414. RIGHT: 4,
  3415. BELOW: 8,
  3416. LEFT: 16
  3417. };
  3418. goog.provide('ol.extent');
  3419. goog.require('ol.asserts');
  3420. goog.require('ol.extent.Corner');
  3421. goog.require('ol.extent.Relationship');
  3422. /**
  3423. * Build an extent that includes all given coordinates.
  3424. *
  3425. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  3426. * @return {ol.Extent} Bounding extent.
  3427. * @api
  3428. */
  3429. ol.extent.boundingExtent = function(coordinates) {
  3430. var extent = ol.extent.createEmpty();
  3431. for (var i = 0, ii = coordinates.length; i < ii; ++i) {
  3432. ol.extent.extendCoordinate(extent, coordinates[i]);
  3433. }
  3434. return extent;
  3435. };
  3436. /**
  3437. * @param {Array.<number>} xs Xs.
  3438. * @param {Array.<number>} ys Ys.
  3439. * @param {ol.Extent=} opt_extent Destination extent.
  3440. * @private
  3441. * @return {ol.Extent} Extent.
  3442. */
  3443. ol.extent.boundingExtentXYs_ = function(xs, ys, opt_extent) {
  3444. var minX = Math.min.apply(null, xs);
  3445. var minY = Math.min.apply(null, ys);
  3446. var maxX = Math.max.apply(null, xs);
  3447. var maxY = Math.max.apply(null, ys);
  3448. return ol.extent.createOrUpdate(minX, minY, maxX, maxY, opt_extent);
  3449. };
  3450. /**
  3451. * Return extent increased by the provided value.
  3452. * @param {ol.Extent} extent Extent.
  3453. * @param {number} value The amount by which the extent should be buffered.
  3454. * @param {ol.Extent=} opt_extent Extent.
  3455. * @return {ol.Extent} Extent.
  3456. * @api
  3457. */
  3458. ol.extent.buffer = function(extent, value, opt_extent) {
  3459. if (opt_extent) {
  3460. opt_extent[0] = extent[0] - value;
  3461. opt_extent[1] = extent[1] - value;
  3462. opt_extent[2] = extent[2] + value;
  3463. opt_extent[3] = extent[3] + value;
  3464. return opt_extent;
  3465. } else {
  3466. return [
  3467. extent[0] - value,
  3468. extent[1] - value,
  3469. extent[2] + value,
  3470. extent[3] + value
  3471. ];
  3472. }
  3473. };
  3474. /**
  3475. * Creates a clone of an extent.
  3476. *
  3477. * @param {ol.Extent} extent Extent to clone.
  3478. * @param {ol.Extent=} opt_extent Extent.
  3479. * @return {ol.Extent} The clone.
  3480. */
  3481. ol.extent.clone = function(extent, opt_extent) {
  3482. if (opt_extent) {
  3483. opt_extent[0] = extent[0];
  3484. opt_extent[1] = extent[1];
  3485. opt_extent[2] = extent[2];
  3486. opt_extent[3] = extent[3];
  3487. return opt_extent;
  3488. } else {
  3489. return extent.slice();
  3490. }
  3491. };
  3492. /**
  3493. * @param {ol.Extent} extent Extent.
  3494. * @param {number} x X.
  3495. * @param {number} y Y.
  3496. * @return {number} Closest squared distance.
  3497. */
  3498. ol.extent.closestSquaredDistanceXY = function(extent, x, y) {
  3499. var dx, dy;
  3500. if (x < extent[0]) {
  3501. dx = extent[0] - x;
  3502. } else if (extent[2] < x) {
  3503. dx = x - extent[2];
  3504. } else {
  3505. dx = 0;
  3506. }
  3507. if (y < extent[1]) {
  3508. dy = extent[1] - y;
  3509. } else if (extent[3] < y) {
  3510. dy = y - extent[3];
  3511. } else {
  3512. dy = 0;
  3513. }
  3514. return dx * dx + dy * dy;
  3515. };
  3516. /**
  3517. * Check if the passed coordinate is contained or on the edge of the extent.
  3518. *
  3519. * @param {ol.Extent} extent Extent.
  3520. * @param {ol.Coordinate} coordinate Coordinate.
  3521. * @return {boolean} The coordinate is contained in the extent.
  3522. * @api
  3523. */
  3524. ol.extent.containsCoordinate = function(extent, coordinate) {
  3525. return ol.extent.containsXY(extent, coordinate[0], coordinate[1]);
  3526. };
  3527. /**
  3528. * Check if one extent contains another.
  3529. *
  3530. * An extent is deemed contained if it lies completely within the other extent,
  3531. * including if they share one or more edges.
  3532. *
  3533. * @param {ol.Extent} extent1 Extent 1.
  3534. * @param {ol.Extent} extent2 Extent 2.
  3535. * @return {boolean} The second extent is contained by or on the edge of the
  3536. * first.
  3537. * @api
  3538. */
  3539. ol.extent.containsExtent = function(extent1, extent2) {
  3540. return extent1[0] <= extent2[0] && extent2[2] <= extent1[2] &&
  3541. extent1[1] <= extent2[1] && extent2[3] <= extent1[3];
  3542. };
  3543. /**
  3544. * Check if the passed coordinate is contained or on the edge of the extent.
  3545. *
  3546. * @param {ol.Extent} extent Extent.
  3547. * @param {number} x X coordinate.
  3548. * @param {number} y Y coordinate.
  3549. * @return {boolean} The x, y values are contained in the extent.
  3550. * @api
  3551. */
  3552. ol.extent.containsXY = function(extent, x, y) {
  3553. return extent[0] <= x && x <= extent[2] && extent[1] <= y && y <= extent[3];
  3554. };
  3555. /**
  3556. * Get the relationship between a coordinate and extent.
  3557. * @param {ol.Extent} extent The extent.
  3558. * @param {ol.Coordinate} coordinate The coordinate.
  3559. * @return {number} The relationship (bitwise compare with
  3560. * ol.extent.Relationship).
  3561. */
  3562. ol.extent.coordinateRelationship = function(extent, coordinate) {
  3563. var minX = extent[0];
  3564. var minY = extent[1];
  3565. var maxX = extent[2];
  3566. var maxY = extent[3];
  3567. var x = coordinate[0];
  3568. var y = coordinate[1];
  3569. var relationship = ol.extent.Relationship.UNKNOWN;
  3570. if (x < minX) {
  3571. relationship = relationship | ol.extent.Relationship.LEFT;
  3572. } else if (x > maxX) {
  3573. relationship = relationship | ol.extent.Relationship.RIGHT;
  3574. }
  3575. if (y < minY) {
  3576. relationship = relationship | ol.extent.Relationship.BELOW;
  3577. } else if (y > maxY) {
  3578. relationship = relationship | ol.extent.Relationship.ABOVE;
  3579. }
  3580. if (relationship === ol.extent.Relationship.UNKNOWN) {
  3581. relationship = ol.extent.Relationship.INTERSECTING;
  3582. }
  3583. return relationship;
  3584. };
  3585. /**
  3586. * Create an empty extent.
  3587. * @return {ol.Extent} Empty extent.
  3588. * @api
  3589. */
  3590. ol.extent.createEmpty = function() {
  3591. return [Infinity, Infinity, -Infinity, -Infinity];
  3592. };
  3593. /**
  3594. * Create a new extent or update the provided extent.
  3595. * @param {number} minX Minimum X.
  3596. * @param {number} minY Minimum Y.
  3597. * @param {number} maxX Maximum X.
  3598. * @param {number} maxY Maximum Y.
  3599. * @param {ol.Extent=} opt_extent Destination extent.
  3600. * @return {ol.Extent} Extent.
  3601. */
  3602. ol.extent.createOrUpdate = function(minX, minY, maxX, maxY, opt_extent) {
  3603. if (opt_extent) {
  3604. opt_extent[0] = minX;
  3605. opt_extent[1] = minY;
  3606. opt_extent[2] = maxX;
  3607. opt_extent[3] = maxY;
  3608. return opt_extent;
  3609. } else {
  3610. return [minX, minY, maxX, maxY];
  3611. }
  3612. };
  3613. /**
  3614. * Create a new empty extent or make the provided one empty.
  3615. * @param {ol.Extent=} opt_extent Extent.
  3616. * @return {ol.Extent} Extent.
  3617. */
  3618. ol.extent.createOrUpdateEmpty = function(opt_extent) {
  3619. return ol.extent.createOrUpdate(
  3620. Infinity, Infinity, -Infinity, -Infinity, opt_extent);
  3621. };
  3622. /**
  3623. * @param {ol.Coordinate} coordinate Coordinate.
  3624. * @param {ol.Extent=} opt_extent Extent.
  3625. * @return {ol.Extent} Extent.
  3626. */
  3627. ol.extent.createOrUpdateFromCoordinate = function(coordinate, opt_extent) {
  3628. var x = coordinate[0];
  3629. var y = coordinate[1];
  3630. return ol.extent.createOrUpdate(x, y, x, y, opt_extent);
  3631. };
  3632. /**
  3633. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  3634. * @param {ol.Extent=} opt_extent Extent.
  3635. * @return {ol.Extent} Extent.
  3636. */
  3637. ol.extent.createOrUpdateFromCoordinates = function(coordinates, opt_extent) {
  3638. var extent = ol.extent.createOrUpdateEmpty(opt_extent);
  3639. return ol.extent.extendCoordinates(extent, coordinates);
  3640. };
  3641. /**
  3642. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3643. * @param {number} offset Offset.
  3644. * @param {number} end End.
  3645. * @param {number} stride Stride.
  3646. * @param {ol.Extent=} opt_extent Extent.
  3647. * @return {ol.Extent} Extent.
  3648. */
  3649. ol.extent.createOrUpdateFromFlatCoordinates = function(flatCoordinates, offset, end, stride, opt_extent) {
  3650. var extent = ol.extent.createOrUpdateEmpty(opt_extent);
  3651. return ol.extent.extendFlatCoordinates(
  3652. extent, flatCoordinates, offset, end, stride);
  3653. };
  3654. /**
  3655. * @param {Array.<Array.<ol.Coordinate>>} rings Rings.
  3656. * @param {ol.Extent=} opt_extent Extent.
  3657. * @return {ol.Extent} Extent.
  3658. */
  3659. ol.extent.createOrUpdateFromRings = function(rings, opt_extent) {
  3660. var extent = ol.extent.createOrUpdateEmpty(opt_extent);
  3661. return ol.extent.extendRings(extent, rings);
  3662. };
  3663. /**
  3664. * Determine if two extents are equivalent.
  3665. * @param {ol.Extent} extent1 Extent 1.
  3666. * @param {ol.Extent} extent2 Extent 2.
  3667. * @return {boolean} The two extents are equivalent.
  3668. * @api
  3669. */
  3670. ol.extent.equals = function(extent1, extent2) {
  3671. return extent1[0] == extent2[0] && extent1[2] == extent2[2] &&
  3672. extent1[1] == extent2[1] && extent1[3] == extent2[3];
  3673. };
  3674. /**
  3675. * Modify an extent to include another extent.
  3676. * @param {ol.Extent} extent1 The extent to be modified.
  3677. * @param {ol.Extent} extent2 The extent that will be included in the first.
  3678. * @return {ol.Extent} A reference to the first (extended) extent.
  3679. * @api
  3680. */
  3681. ol.extent.extend = function(extent1, extent2) {
  3682. if (extent2[0] < extent1[0]) {
  3683. extent1[0] = extent2[0];
  3684. }
  3685. if (extent2[2] > extent1[2]) {
  3686. extent1[2] = extent2[2];
  3687. }
  3688. if (extent2[1] < extent1[1]) {
  3689. extent1[1] = extent2[1];
  3690. }
  3691. if (extent2[3] > extent1[3]) {
  3692. extent1[3] = extent2[3];
  3693. }
  3694. return extent1;
  3695. };
  3696. /**
  3697. * @param {ol.Extent} extent Extent.
  3698. * @param {ol.Coordinate} coordinate Coordinate.
  3699. */
  3700. ol.extent.extendCoordinate = function(extent, coordinate) {
  3701. if (coordinate[0] < extent[0]) {
  3702. extent[0] = coordinate[0];
  3703. }
  3704. if (coordinate[0] > extent[2]) {
  3705. extent[2] = coordinate[0];
  3706. }
  3707. if (coordinate[1] < extent[1]) {
  3708. extent[1] = coordinate[1];
  3709. }
  3710. if (coordinate[1] > extent[3]) {
  3711. extent[3] = coordinate[1];
  3712. }
  3713. };
  3714. /**
  3715. * @param {ol.Extent} extent Extent.
  3716. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  3717. * @return {ol.Extent} Extent.
  3718. */
  3719. ol.extent.extendCoordinates = function(extent, coordinates) {
  3720. var i, ii;
  3721. for (i = 0, ii = coordinates.length; i < ii; ++i) {
  3722. ol.extent.extendCoordinate(extent, coordinates[i]);
  3723. }
  3724. return extent;
  3725. };
  3726. /**
  3727. * @param {ol.Extent} extent Extent.
  3728. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3729. * @param {number} offset Offset.
  3730. * @param {number} end End.
  3731. * @param {number} stride Stride.
  3732. * @return {ol.Extent} Extent.
  3733. */
  3734. ol.extent.extendFlatCoordinates = function(extent, flatCoordinates, offset, end, stride) {
  3735. for (; offset < end; offset += stride) {
  3736. ol.extent.extendXY(
  3737. extent, flatCoordinates[offset], flatCoordinates[offset + 1]);
  3738. }
  3739. return extent;
  3740. };
  3741. /**
  3742. * @param {ol.Extent} extent Extent.
  3743. * @param {Array.<Array.<ol.Coordinate>>} rings Rings.
  3744. * @return {ol.Extent} Extent.
  3745. */
  3746. ol.extent.extendRings = function(extent, rings) {
  3747. var i, ii;
  3748. for (i = 0, ii = rings.length; i < ii; ++i) {
  3749. ol.extent.extendCoordinates(extent, rings[i]);
  3750. }
  3751. return extent;
  3752. };
  3753. /**
  3754. * @param {ol.Extent} extent Extent.
  3755. * @param {number} x X.
  3756. * @param {number} y Y.
  3757. */
  3758. ol.extent.extendXY = function(extent, x, y) {
  3759. extent[0] = Math.min(extent[0], x);
  3760. extent[1] = Math.min(extent[1], y);
  3761. extent[2] = Math.max(extent[2], x);
  3762. extent[3] = Math.max(extent[3], y);
  3763. };
  3764. /**
  3765. * This function calls `callback` for each corner of the extent. If the
  3766. * callback returns a truthy value the function returns that value
  3767. * immediately. Otherwise the function returns `false`.
  3768. * @param {ol.Extent} extent Extent.
  3769. * @param {function(this:T, ol.Coordinate): S} callback Callback.
  3770. * @param {T=} opt_this Value to use as `this` when executing `callback`.
  3771. * @return {S|boolean} Value.
  3772. * @template S, T
  3773. */
  3774. ol.extent.forEachCorner = function(extent, callback, opt_this) {
  3775. var val;
  3776. val = callback.call(opt_this, ol.extent.getBottomLeft(extent));
  3777. if (val) {
  3778. return val;
  3779. }
  3780. val = callback.call(opt_this, ol.extent.getBottomRight(extent));
  3781. if (val) {
  3782. return val;
  3783. }
  3784. val = callback.call(opt_this, ol.extent.getTopRight(extent));
  3785. if (val) {
  3786. return val;
  3787. }
  3788. val = callback.call(opt_this, ol.extent.getTopLeft(extent));
  3789. if (val) {
  3790. return val;
  3791. }
  3792. return false;
  3793. };
  3794. /**
  3795. * Get the size of an extent.
  3796. * @param {ol.Extent} extent Extent.
  3797. * @return {number} Area.
  3798. * @api
  3799. */
  3800. ol.extent.getArea = function(extent) {
  3801. var area = 0;
  3802. if (!ol.extent.isEmpty(extent)) {
  3803. area = ol.extent.getWidth(extent) * ol.extent.getHeight(extent);
  3804. }
  3805. return area;
  3806. };
  3807. /**
  3808. * Get the bottom left coordinate of an extent.
  3809. * @param {ol.Extent} extent Extent.
  3810. * @return {ol.Coordinate} Bottom left coordinate.
  3811. * @api
  3812. */
  3813. ol.extent.getBottomLeft = function(extent) {
  3814. return [extent[0], extent[1]];
  3815. };
  3816. /**
  3817. * Get the bottom right coordinate of an extent.
  3818. * @param {ol.Extent} extent Extent.
  3819. * @return {ol.Coordinate} Bottom right coordinate.
  3820. * @api
  3821. */
  3822. ol.extent.getBottomRight = function(extent) {
  3823. return [extent[2], extent[1]];
  3824. };
  3825. /**
  3826. * Get the center coordinate of an extent.
  3827. * @param {ol.Extent} extent Extent.
  3828. * @return {ol.Coordinate} Center.
  3829. * @api
  3830. */
  3831. ol.extent.getCenter = function(extent) {
  3832. return [(extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2];
  3833. };
  3834. /**
  3835. * Get a corner coordinate of an extent.
  3836. * @param {ol.Extent} extent Extent.
  3837. * @param {ol.extent.Corner} corner Corner.
  3838. * @return {ol.Coordinate} Corner coordinate.
  3839. */
  3840. ol.extent.getCorner = function(extent, corner) {
  3841. var coordinate;
  3842. if (corner === ol.extent.Corner.BOTTOM_LEFT) {
  3843. coordinate = ol.extent.getBottomLeft(extent);
  3844. } else if (corner === ol.extent.Corner.BOTTOM_RIGHT) {
  3845. coordinate = ol.extent.getBottomRight(extent);
  3846. } else if (corner === ol.extent.Corner.TOP_LEFT) {
  3847. coordinate = ol.extent.getTopLeft(extent);
  3848. } else if (corner === ol.extent.Corner.TOP_RIGHT) {
  3849. coordinate = ol.extent.getTopRight(extent);
  3850. } else {
  3851. ol.asserts.assert(false, 13); // Invalid corner
  3852. }
  3853. return /** @type {!ol.Coordinate} */ (coordinate);
  3854. };
  3855. /**
  3856. * @param {ol.Extent} extent1 Extent 1.
  3857. * @param {ol.Extent} extent2 Extent 2.
  3858. * @return {number} Enlarged area.
  3859. */
  3860. ol.extent.getEnlargedArea = function(extent1, extent2) {
  3861. var minX = Math.min(extent1[0], extent2[0]);
  3862. var minY = Math.min(extent1[1], extent2[1]);
  3863. var maxX = Math.max(extent1[2], extent2[2]);
  3864. var maxY = Math.max(extent1[3], extent2[3]);
  3865. return (maxX - minX) * (maxY - minY);
  3866. };
  3867. /**
  3868. * @param {ol.Coordinate} center Center.
  3869. * @param {number} resolution Resolution.
  3870. * @param {number} rotation Rotation.
  3871. * @param {ol.Size} size Size.
  3872. * @param {ol.Extent=} opt_extent Destination extent.
  3873. * @return {ol.Extent} Extent.
  3874. */
  3875. ol.extent.getForViewAndSize = function(center, resolution, rotation, size, opt_extent) {
  3876. var dx = resolution * size[0] / 2;
  3877. var dy = resolution * size[1] / 2;
  3878. var cosRotation = Math.cos(rotation);
  3879. var sinRotation = Math.sin(rotation);
  3880. var xCos = dx * cosRotation;
  3881. var xSin = dx * sinRotation;
  3882. var yCos = dy * cosRotation;
  3883. var ySin = dy * sinRotation;
  3884. var x = center[0];
  3885. var y = center[1];
  3886. var x0 = x - xCos + ySin;
  3887. var x1 = x - xCos - ySin;
  3888. var x2 = x + xCos - ySin;
  3889. var x3 = x + xCos + ySin;
  3890. var y0 = y - xSin - yCos;
  3891. var y1 = y - xSin + yCos;
  3892. var y2 = y + xSin + yCos;
  3893. var y3 = y + xSin - yCos;
  3894. return ol.extent.createOrUpdate(
  3895. Math.min(x0, x1, x2, x3), Math.min(y0, y1, y2, y3),
  3896. Math.max(x0, x1, x2, x3), Math.max(y0, y1, y2, y3),
  3897. opt_extent);
  3898. };
  3899. /**
  3900. * Get the height of an extent.
  3901. * @param {ol.Extent} extent Extent.
  3902. * @return {number} Height.
  3903. * @api
  3904. */
  3905. ol.extent.getHeight = function(extent) {
  3906. return extent[3] - extent[1];
  3907. };
  3908. /**
  3909. * @param {ol.Extent} extent1 Extent 1.
  3910. * @param {ol.Extent} extent2 Extent 2.
  3911. * @return {number} Intersection area.
  3912. */
  3913. ol.extent.getIntersectionArea = function(extent1, extent2) {
  3914. var intersection = ol.extent.getIntersection(extent1, extent2);
  3915. return ol.extent.getArea(intersection);
  3916. };
  3917. /**
  3918. * Get the intersection of two extents.
  3919. * @param {ol.Extent} extent1 Extent 1.
  3920. * @param {ol.Extent} extent2 Extent 2.
  3921. * @param {ol.Extent=} opt_extent Optional extent to populate with intersection.
  3922. * @return {ol.Extent} Intersecting extent.
  3923. * @api
  3924. */
  3925. ol.extent.getIntersection = function(extent1, extent2, opt_extent) {
  3926. var intersection = opt_extent ? opt_extent : ol.extent.createEmpty();
  3927. if (ol.extent.intersects(extent1, extent2)) {
  3928. if (extent1[0] > extent2[0]) {
  3929. intersection[0] = extent1[0];
  3930. } else {
  3931. intersection[0] = extent2[0];
  3932. }
  3933. if (extent1[1] > extent2[1]) {
  3934. intersection[1] = extent1[1];
  3935. } else {
  3936. intersection[1] = extent2[1];
  3937. }
  3938. if (extent1[2] < extent2[2]) {
  3939. intersection[2] = extent1[2];
  3940. } else {
  3941. intersection[2] = extent2[2];
  3942. }
  3943. if (extent1[3] < extent2[3]) {
  3944. intersection[3] = extent1[3];
  3945. } else {
  3946. intersection[3] = extent2[3];
  3947. }
  3948. }
  3949. return intersection;
  3950. };
  3951. /**
  3952. * @param {ol.Extent} extent Extent.
  3953. * @return {number} Margin.
  3954. */
  3955. ol.extent.getMargin = function(extent) {
  3956. return ol.extent.getWidth(extent) + ol.extent.getHeight(extent);
  3957. };
  3958. /**
  3959. * Get the size (width, height) of an extent.
  3960. * @param {ol.Extent} extent The extent.
  3961. * @return {ol.Size} The extent size.
  3962. * @api
  3963. */
  3964. ol.extent.getSize = function(extent) {
  3965. return [extent[2] - extent[0], extent[3] - extent[1]];
  3966. };
  3967. /**
  3968. * Get the top left coordinate of an extent.
  3969. * @param {ol.Extent} extent Extent.
  3970. * @return {ol.Coordinate} Top left coordinate.
  3971. * @api
  3972. */
  3973. ol.extent.getTopLeft = function(extent) {
  3974. return [extent[0], extent[3]];
  3975. };
  3976. /**
  3977. * Get the top right coordinate of an extent.
  3978. * @param {ol.Extent} extent Extent.
  3979. * @return {ol.Coordinate} Top right coordinate.
  3980. * @api
  3981. */
  3982. ol.extent.getTopRight = function(extent) {
  3983. return [extent[2], extent[3]];
  3984. };
  3985. /**
  3986. * Get the width of an extent.
  3987. * @param {ol.Extent} extent Extent.
  3988. * @return {number} Width.
  3989. * @api
  3990. */
  3991. ol.extent.getWidth = function(extent) {
  3992. return extent[2] - extent[0];
  3993. };
  3994. /**
  3995. * Determine if one extent intersects another.
  3996. * @param {ol.Extent} extent1 Extent 1.
  3997. * @param {ol.Extent} extent2 Extent.
  3998. * @return {boolean} The two extents intersect.
  3999. * @api
  4000. */
  4001. ol.extent.intersects = function(extent1, extent2) {
  4002. return extent1[0] <= extent2[2] &&
  4003. extent1[2] >= extent2[0] &&
  4004. extent1[1] <= extent2[3] &&
  4005. extent1[3] >= extent2[1];
  4006. };
  4007. /**
  4008. * Determine if an extent is empty.
  4009. * @param {ol.Extent} extent Extent.
  4010. * @return {boolean} Is empty.
  4011. * @api
  4012. */
  4013. ol.extent.isEmpty = function(extent) {
  4014. return extent[2] < extent[0] || extent[3] < extent[1];
  4015. };
  4016. /**
  4017. * @param {ol.Extent} extent Extent.
  4018. * @param {ol.Extent=} opt_extent Extent.
  4019. * @return {ol.Extent} Extent.
  4020. */
  4021. ol.extent.returnOrUpdate = function(extent, opt_extent) {
  4022. if (opt_extent) {
  4023. opt_extent[0] = extent[0];
  4024. opt_extent[1] = extent[1];
  4025. opt_extent[2] = extent[2];
  4026. opt_extent[3] = extent[3];
  4027. return opt_extent;
  4028. } else {
  4029. return extent;
  4030. }
  4031. };
  4032. /**
  4033. * @param {ol.Extent} extent Extent.
  4034. * @param {number} value Value.
  4035. */
  4036. ol.extent.scaleFromCenter = function(extent, value) {
  4037. var deltaX = ((extent[2] - extent[0]) / 2) * (value - 1);
  4038. var deltaY = ((extent[3] - extent[1]) / 2) * (value - 1);
  4039. extent[0] -= deltaX;
  4040. extent[2] += deltaX;
  4041. extent[1] -= deltaY;
  4042. extent[3] += deltaY;
  4043. };
  4044. /**
  4045. * Determine if the segment between two coordinates intersects (crosses,
  4046. * touches, or is contained by) the provided extent.
  4047. * @param {ol.Extent} extent The extent.
  4048. * @param {ol.Coordinate} start Segment start coordinate.
  4049. * @param {ol.Coordinate} end Segment end coordinate.
  4050. * @return {boolean} The segment intersects the extent.
  4051. */
  4052. ol.extent.intersectsSegment = function(extent, start, end) {
  4053. var intersects = false;
  4054. var startRel = ol.extent.coordinateRelationship(extent, start);
  4055. var endRel = ol.extent.coordinateRelationship(extent, end);
  4056. if (startRel === ol.extent.Relationship.INTERSECTING ||
  4057. endRel === ol.extent.Relationship.INTERSECTING) {
  4058. intersects = true;
  4059. } else {
  4060. var minX = extent[0];
  4061. var minY = extent[1];
  4062. var maxX = extent[2];
  4063. var maxY = extent[3];
  4064. var startX = start[0];
  4065. var startY = start[1];
  4066. var endX = end[0];
  4067. var endY = end[1];
  4068. var slope = (endY - startY) / (endX - startX);
  4069. var x, y;
  4070. if (!!(endRel & ol.extent.Relationship.ABOVE) &&
  4071. !(startRel & ol.extent.Relationship.ABOVE)) {
  4072. // potentially intersects top
  4073. x = endX - ((endY - maxY) / slope);
  4074. intersects = x >= minX && x <= maxX;
  4075. }
  4076. if (!intersects && !!(endRel & ol.extent.Relationship.RIGHT) &&
  4077. !(startRel & ol.extent.Relationship.RIGHT)) {
  4078. // potentially intersects right
  4079. y = endY - ((endX - maxX) * slope);
  4080. intersects = y >= minY && y <= maxY;
  4081. }
  4082. if (!intersects && !!(endRel & ol.extent.Relationship.BELOW) &&
  4083. !(startRel & ol.extent.Relationship.BELOW)) {
  4084. // potentially intersects bottom
  4085. x = endX - ((endY - minY) / slope);
  4086. intersects = x >= minX && x <= maxX;
  4087. }
  4088. if (!intersects && !!(endRel & ol.extent.Relationship.LEFT) &&
  4089. !(startRel & ol.extent.Relationship.LEFT)) {
  4090. // potentially intersects left
  4091. y = endY - ((endX - minX) * slope);
  4092. intersects = y >= minY && y <= maxY;
  4093. }
  4094. }
  4095. return intersects;
  4096. };
  4097. /**
  4098. * Apply a transform function to the extent.
  4099. * @param {ol.Extent} extent Extent.
  4100. * @param {ol.TransformFunction} transformFn Transform function. Called with
  4101. * [minX, minY, maxX, maxY] extent coordinates.
  4102. * @param {ol.Extent=} opt_extent Destination extent.
  4103. * @return {ol.Extent} Extent.
  4104. * @api
  4105. */
  4106. ol.extent.applyTransform = function(extent, transformFn, opt_extent) {
  4107. var coordinates = [
  4108. extent[0], extent[1],
  4109. extent[0], extent[3],
  4110. extent[2], extent[1],
  4111. extent[2], extent[3]
  4112. ];
  4113. transformFn(coordinates, coordinates, 2);
  4114. var xs = [coordinates[0], coordinates[2], coordinates[4], coordinates[6]];
  4115. var ys = [coordinates[1], coordinates[3], coordinates[5], coordinates[7]];
  4116. return ol.extent.boundingExtentXYs_(xs, ys, opt_extent);
  4117. };
  4118. goog.provide('ol.obj');
  4119. /**
  4120. * Polyfill for Object.assign(). Assigns enumerable and own properties from
  4121. * one or more source objects to a target object.
  4122. *
  4123. * @see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
  4124. * @param {!Object} target The target object.
  4125. * @param {...Object} var_sources The source object(s).
  4126. * @return {!Object} The modified target object.
  4127. */
  4128. ol.obj.assign = (typeof Object.assign === 'function') ? Object.assign : function(target, var_sources) {
  4129. if (target === undefined || target === null) {
  4130. throw new TypeError('Cannot convert undefined or null to object');
  4131. }
  4132. var output = Object(target);
  4133. for (var i = 1, ii = arguments.length; i < ii; ++i) {
  4134. var source = arguments[i];
  4135. if (source !== undefined && source !== null) {
  4136. for (var key in source) {
  4137. if (source.hasOwnProperty(key)) {
  4138. output[key] = source[key];
  4139. }
  4140. }
  4141. }
  4142. }
  4143. return output;
  4144. };
  4145. /**
  4146. * Removes all properties from an object.
  4147. * @param {Object} object The object to clear.
  4148. */
  4149. ol.obj.clear = function(object) {
  4150. for (var property in object) {
  4151. delete object[property];
  4152. }
  4153. };
  4154. /**
  4155. * Get an array of property values from an object.
  4156. * @param {Object<K,V>} object The object from which to get the values.
  4157. * @return {!Array<V>} The property values.
  4158. * @template K,V
  4159. */
  4160. ol.obj.getValues = function(object) {
  4161. var values = [];
  4162. for (var property in object) {
  4163. values.push(object[property]);
  4164. }
  4165. return values;
  4166. };
  4167. /**
  4168. * Determine if an object has any properties.
  4169. * @param {Object} object The object to check.
  4170. * @return {boolean} The object is empty.
  4171. */
  4172. ol.obj.isEmpty = function(object) {
  4173. var property;
  4174. for (property in object) {
  4175. return false;
  4176. }
  4177. return !property;
  4178. };
  4179. goog.provide('ol.geom.GeometryType');
  4180. /**
  4181. * The geometry type. One of `'Point'`, `'LineString'`, `'LinearRing'`,
  4182. * `'Polygon'`, `'MultiPoint'`, `'MultiLineString'`, `'MultiPolygon'`,
  4183. * `'GeometryCollection'`, `'Circle'`.
  4184. * @enum {string}
  4185. */
  4186. ol.geom.GeometryType = {
  4187. POINT: 'Point',
  4188. LINE_STRING: 'LineString',
  4189. LINEAR_RING: 'LinearRing',
  4190. POLYGON: 'Polygon',
  4191. MULTI_POINT: 'MultiPoint',
  4192. MULTI_LINE_STRING: 'MultiLineString',
  4193. MULTI_POLYGON: 'MultiPolygon',
  4194. GEOMETRY_COLLECTION: 'GeometryCollection',
  4195. CIRCLE: 'Circle'
  4196. };
  4197. /**
  4198. * @license
  4199. * Latitude/longitude spherical geodesy formulae taken from
  4200. * http://www.movable-type.co.uk/scripts/latlong.html
  4201. * Licensed under CC-BY-3.0.
  4202. */
  4203. goog.provide('ol.Sphere');
  4204. goog.require('ol.math');
  4205. goog.require('ol.geom.GeometryType');
  4206. /**
  4207. * @classdesc
  4208. * Class to create objects that can be used with {@link
  4209. * ol.geom.Polygon.circular}.
  4210. *
  4211. * For example to create a sphere whose radius is equal to the semi-major
  4212. * axis of the WGS84 ellipsoid:
  4213. *
  4214. * ```js
  4215. * var wgs84Sphere= new ol.Sphere(6378137);
  4216. * ```
  4217. *
  4218. * @constructor
  4219. * @param {number} radius Radius.
  4220. * @api
  4221. */
  4222. ol.Sphere = function(radius) {
  4223. /**
  4224. * @type {number}
  4225. */
  4226. this.radius = radius;
  4227. };
  4228. /**
  4229. * Returns the geodesic area for a list of coordinates.
  4230. *
  4231. * [Reference](https://trs-new.jpl.nasa.gov/handle/2014/40409)
  4232. * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
  4233. * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
  4234. * Laboratory, Pasadena, CA, June 2007
  4235. *
  4236. * @param {Array.<ol.Coordinate>} coordinates List of coordinates of a linear
  4237. * ring. If the ring is oriented clockwise, the area will be positive,
  4238. * otherwise it will be negative.
  4239. * @return {number} Area.
  4240. * @api
  4241. */
  4242. ol.Sphere.prototype.geodesicArea = function(coordinates) {
  4243. return ol.Sphere.getArea_(coordinates, this.radius);
  4244. };
  4245. /**
  4246. * Returns the distance from c1 to c2 using the haversine formula.
  4247. *
  4248. * @param {ol.Coordinate} c1 Coordinate 1.
  4249. * @param {ol.Coordinate} c2 Coordinate 2.
  4250. * @return {number} Haversine distance.
  4251. * @api
  4252. */
  4253. ol.Sphere.prototype.haversineDistance = function(c1, c2) {
  4254. return ol.Sphere.getDistance_(c1, c2, this.radius);
  4255. };
  4256. /**
  4257. * Returns the coordinate at the given distance and bearing from `c1`.
  4258. *
  4259. * @param {ol.Coordinate} c1 The origin point (`[lon, lat]` in degrees).
  4260. * @param {number} distance The great-circle distance between the origin
  4261. * point and the target point.
  4262. * @param {number} bearing The bearing (in radians).
  4263. * @return {ol.Coordinate} The target point.
  4264. */
  4265. ol.Sphere.prototype.offset = function(c1, distance, bearing) {
  4266. var lat1 = ol.math.toRadians(c1[1]);
  4267. var lon1 = ol.math.toRadians(c1[0]);
  4268. var dByR = distance / this.radius;
  4269. var lat = Math.asin(
  4270. Math.sin(lat1) * Math.cos(dByR) +
  4271. Math.cos(lat1) * Math.sin(dByR) * Math.cos(bearing));
  4272. var lon = lon1 + Math.atan2(
  4273. Math.sin(bearing) * Math.sin(dByR) * Math.cos(lat1),
  4274. Math.cos(dByR) - Math.sin(lat1) * Math.sin(lat));
  4275. return [ol.math.toDegrees(lon), ol.math.toDegrees(lat)];
  4276. };
  4277. /**
  4278. * The mean Earth radius (1/3 * (2a + b)) for the WGS84 ellipsoid.
  4279. * https://en.wikipedia.org/wiki/Earth_radius#Mean_radius
  4280. * @type {number}
  4281. */
  4282. ol.Sphere.DEFAULT_RADIUS = 6371008.8;
  4283. /**
  4284. * Get the spherical length of a geometry. This length is the sum of the
  4285. * great circle distances between coordinates. For polygons, the length is
  4286. * the sum of all rings. For points, the length is zero. For multi-part
  4287. * geometries, the length is the sum of the length of each part.
  4288. * @param {ol.geom.Geometry} geometry A geometry.
  4289. * @param {olx.SphereMetricOptions=} opt_options Options for the length
  4290. * calculation. By default, geometries are assumed to be in 'EPSG:3857'.
  4291. * You can change this by providing a `projection` option.
  4292. * @return {number} The spherical length (in meters).
  4293. * @api
  4294. */
  4295. ol.Sphere.getLength = function(geometry, opt_options) {
  4296. var options = opt_options || {};
  4297. var radius = options.radius || ol.Sphere.DEFAULT_RADIUS;
  4298. var projection = options.projection || 'EPSG:3857';
  4299. geometry = geometry.clone().transform(projection, 'EPSG:4326');
  4300. var type = geometry.getType();
  4301. var length = 0;
  4302. var coordinates, coords, i, ii, j, jj;
  4303. switch (type) {
  4304. case ol.geom.GeometryType.POINT:
  4305. case ol.geom.GeometryType.MULTI_POINT: {
  4306. break;
  4307. }
  4308. case ol.geom.GeometryType.LINE_STRING:
  4309. case ol.geom.GeometryType.LINEAR_RING: {
  4310. coordinates = /** @type {ol.geom.SimpleGeometry} */ (geometry).getCoordinates();
  4311. length = ol.Sphere.getLength_(coordinates, radius);
  4312. break;
  4313. }
  4314. case ol.geom.GeometryType.MULTI_LINE_STRING:
  4315. case ol.geom.GeometryType.POLYGON: {
  4316. coordinates = /** @type {ol.geom.SimpleGeometry} */ (geometry).getCoordinates();
  4317. for (i = 0, ii = coordinates.length; i < ii; ++i) {
  4318. length += ol.Sphere.getLength_(coordinates[i], radius);
  4319. }
  4320. break;
  4321. }
  4322. case ol.geom.GeometryType.MULTI_POLYGON: {
  4323. coordinates = /** @type {ol.geom.SimpleGeometry} */ (geometry).getCoordinates();
  4324. for (i = 0, ii = coordinates.length; i < ii; ++i) {
  4325. coords = coordinates[i];
  4326. for (j = 0, jj = coords.length; j < jj; ++j) {
  4327. length += ol.Sphere.getLength_(coords[j], radius);
  4328. }
  4329. }
  4330. break;
  4331. }
  4332. case ol.geom.GeometryType.GEOMETRY_COLLECTION: {
  4333. var geometries = /** @type {ol.geom.GeometryCollection} */ (geometry).getGeometries();
  4334. for (i = 0, ii = geometries.length; i < ii; ++i) {
  4335. length += ol.Sphere.getLength(geometries[i], opt_options);
  4336. }
  4337. break;
  4338. }
  4339. default: {
  4340. throw new Error('Unsupported geometry type: ' + type);
  4341. }
  4342. }
  4343. return length;
  4344. };
  4345. /**
  4346. * Get the cumulative great circle length of linestring coordinates (geographic).
  4347. * @param {Array} coordinates Linestring coordinates.
  4348. * @param {number} radius The sphere radius to use.
  4349. * @return {number} The length (in meters).
  4350. */
  4351. ol.Sphere.getLength_ = function(coordinates, radius) {
  4352. var length = 0;
  4353. for (var i = 0, ii = coordinates.length; i < ii - 1; ++i) {
  4354. length += ol.Sphere.getDistance_(coordinates[i], coordinates[i + 1], radius);
  4355. }
  4356. return length;
  4357. };
  4358. /**
  4359. * Get the great circle distance between two geographic coordinates.
  4360. * @param {Array} c1 Starting coordinate.
  4361. * @param {Array} c2 Ending coordinate.
  4362. * @param {number} radius The sphere radius to use.
  4363. * @return {number} The great circle distance between the points (in meters).
  4364. */
  4365. ol.Sphere.getDistance_ = function(c1, c2, radius) {
  4366. var lat1 = ol.math.toRadians(c1[1]);
  4367. var lat2 = ol.math.toRadians(c2[1]);
  4368. var deltaLatBy2 = (lat2 - lat1) / 2;
  4369. var deltaLonBy2 = ol.math.toRadians(c2[0] - c1[0]) / 2;
  4370. var a = Math.sin(deltaLatBy2) * Math.sin(deltaLatBy2) +
  4371. Math.sin(deltaLonBy2) * Math.sin(deltaLonBy2) *
  4372. Math.cos(lat1) * Math.cos(lat2);
  4373. return 2 * radius * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  4374. };
  4375. /**
  4376. * Get the spherical area of a geometry. This is the area (in meters) assuming
  4377. * that polygon edges are segments of great circles on a sphere.
  4378. * @param {ol.geom.Geometry} geometry A geometry.
  4379. * @param {olx.SphereMetricOptions=} opt_options Options for the area
  4380. * calculation. By default, geometries are assumed to be in 'EPSG:3857'.
  4381. * You can change this by providing a `projection` option.
  4382. * @return {number} The spherical area (in square meters).
  4383. * @api
  4384. */
  4385. ol.Sphere.getArea = function(geometry, opt_options) {
  4386. var options = opt_options || {};
  4387. var radius = options.radius || ol.Sphere.DEFAULT_RADIUS;
  4388. var projection = options.projection || 'EPSG:3857';
  4389. geometry = geometry.clone().transform(projection, 'EPSG:4326');
  4390. var type = geometry.getType();
  4391. var area = 0;
  4392. var coordinates, coords, i, ii, j, jj;
  4393. switch (type) {
  4394. case ol.geom.GeometryType.POINT:
  4395. case ol.geom.GeometryType.MULTI_POINT:
  4396. case ol.geom.GeometryType.LINE_STRING:
  4397. case ol.geom.GeometryType.MULTI_LINE_STRING:
  4398. case ol.geom.GeometryType.LINEAR_RING: {
  4399. break;
  4400. }
  4401. case ol.geom.GeometryType.POLYGON: {
  4402. coordinates = /** @type {ol.geom.Polygon} */ (geometry).getCoordinates();
  4403. area = Math.abs(ol.Sphere.getArea_(coordinates[0], radius));
  4404. for (i = 1, ii = coordinates.length; i < ii; ++i) {
  4405. area -= Math.abs(ol.Sphere.getArea_(coordinates[i], radius));
  4406. }
  4407. break;
  4408. }
  4409. case ol.geom.GeometryType.MULTI_POLYGON: {
  4410. coordinates = /** @type {ol.geom.SimpleGeometry} */ (geometry).getCoordinates();
  4411. for (i = 0, ii = coordinates.length; i < ii; ++i) {
  4412. coords = coordinates[i];
  4413. area += Math.abs(ol.Sphere.getArea_(coords[0], radius));
  4414. for (j = 1, jj = coords.length; j < jj; ++j) {
  4415. area -= Math.abs(ol.Sphere.getArea_(coords[j], radius));
  4416. }
  4417. }
  4418. break;
  4419. }
  4420. case ol.geom.GeometryType.GEOMETRY_COLLECTION: {
  4421. var geometries = /** @type {ol.geom.GeometryCollection} */ (geometry).getGeometries();
  4422. for (i = 0, ii = geometries.length; i < ii; ++i) {
  4423. area += ol.Sphere.getArea(geometries[i], opt_options);
  4424. }
  4425. break;
  4426. }
  4427. default: {
  4428. throw new Error('Unsupported geometry type: ' + type);
  4429. }
  4430. }
  4431. return area;
  4432. };
  4433. /**
  4434. * Returns the spherical area for a list of coordinates.
  4435. *
  4436. * [Reference](https://trs-new.jpl.nasa.gov/handle/2014/40409)
  4437. * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
  4438. * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
  4439. * Laboratory, Pasadena, CA, June 2007
  4440. *
  4441. * @param {Array.<ol.Coordinate>} coordinates List of coordinates of a linear
  4442. * ring. If the ring is oriented clockwise, the area will be positive,
  4443. * otherwise it will be negative.
  4444. * @param {number} radius The sphere radius.
  4445. * @return {number} Area (in square meters).
  4446. */
  4447. ol.Sphere.getArea_ = function(coordinates, radius) {
  4448. var area = 0, len = coordinates.length;
  4449. var x1 = coordinates[len - 1][0];
  4450. var y1 = coordinates[len - 1][1];
  4451. for (var i = 0; i < len; i++) {
  4452. var x2 = coordinates[i][0], y2 = coordinates[i][1];
  4453. area += ol.math.toRadians(x2 - x1) *
  4454. (2 + Math.sin(ol.math.toRadians(y1)) +
  4455. Math.sin(ol.math.toRadians(y2)));
  4456. x1 = x2;
  4457. y1 = y2;
  4458. }
  4459. return area * radius * radius / 2.0;
  4460. };
  4461. goog.provide('ol.proj.Units');
  4462. /**
  4463. * Projection units: `'degrees'`, `'ft'`, `'m'`, `'pixels'`, `'tile-pixels'` or
  4464. * `'us-ft'`.
  4465. * @enum {string}
  4466. */
  4467. ol.proj.Units = {
  4468. DEGREES: 'degrees',
  4469. FEET: 'ft',
  4470. METERS: 'm',
  4471. PIXELS: 'pixels',
  4472. TILE_PIXELS: 'tile-pixels',
  4473. USFEET: 'us-ft'
  4474. };
  4475. /**
  4476. * Meters per unit lookup table.
  4477. * @const
  4478. * @type {Object.<ol.proj.Units, number>}
  4479. * @api
  4480. */
  4481. ol.proj.Units.METERS_PER_UNIT = {};
  4482. // use the radius of the Normal sphere
  4483. ol.proj.Units.METERS_PER_UNIT[ol.proj.Units.DEGREES] =
  4484. 2 * Math.PI * 6370997 / 360;
  4485. ol.proj.Units.METERS_PER_UNIT[ol.proj.Units.FEET] = 0.3048;
  4486. ol.proj.Units.METERS_PER_UNIT[ol.proj.Units.METERS] = 1;
  4487. ol.proj.Units.METERS_PER_UNIT[ol.proj.Units.USFEET] = 1200 / 3937;
  4488. goog.provide('ol.proj.proj4');
  4489. /**
  4490. * @private
  4491. * @type {Proj4}
  4492. */
  4493. ol.proj.proj4.cache_ = null;
  4494. /**
  4495. * Store the proj4 function.
  4496. * @param {Proj4} proj4 The proj4 function.
  4497. */
  4498. ol.proj.proj4.set = function(proj4) {
  4499. ol.proj.proj4.cache_ = proj4;
  4500. };
  4501. /**
  4502. * Get proj4.
  4503. * @return {Proj4} The proj4 function set above or available globally.
  4504. */
  4505. ol.proj.proj4.get = function() {
  4506. return ol.proj.proj4.cache_ || window['proj4'];
  4507. };
  4508. goog.provide('ol.proj.Projection');
  4509. goog.require('ol');
  4510. goog.require('ol.proj.Units');
  4511. goog.require('ol.proj.proj4');
  4512. /**
  4513. * @classdesc
  4514. * Projection definition class. One of these is created for each projection
  4515. * supported in the application and stored in the {@link ol.proj} namespace.
  4516. * You can use these in applications, but this is not required, as API params
  4517. * and options use {@link ol.ProjectionLike} which means the simple string
  4518. * code will suffice.
  4519. *
  4520. * You can use {@link ol.proj.get} to retrieve the object for a particular
  4521. * projection.
  4522. *
  4523. * The library includes definitions for `EPSG:4326` and `EPSG:3857`, together
  4524. * with the following aliases:
  4525. * * `EPSG:4326`: CRS:84, urn:ogc:def:crs:EPSG:6.6:4326,
  4526. * urn:ogc:def:crs:OGC:1.3:CRS84, urn:ogc:def:crs:OGC:2:84,
  4527. * http://www.opengis.net/gml/srs/epsg.xml#4326,
  4528. * urn:x-ogc:def:crs:EPSG:4326
  4529. * * `EPSG:3857`: EPSG:102100, EPSG:102113, EPSG:900913,
  4530. * urn:ogc:def:crs:EPSG:6.18:3:3857,
  4531. * http://www.opengis.net/gml/srs/epsg.xml#3857
  4532. *
  4533. * If you use proj4js, aliases can be added using `proj4.defs()`; see
  4534. * [documentation](https://github.com/proj4js/proj4js). To set an alternative
  4535. * namespace for proj4, use {@link ol.proj.setProj4}.
  4536. *
  4537. * @constructor
  4538. * @param {olx.ProjectionOptions} options Projection options.
  4539. * @struct
  4540. * @api
  4541. */
  4542. ol.proj.Projection = function(options) {
  4543. /**
  4544. * @private
  4545. * @type {string}
  4546. */
  4547. this.code_ = options.code;
  4548. /**
  4549. * @private
  4550. * @type {ol.proj.Units}
  4551. */
  4552. this.units_ = /** @type {ol.proj.Units} */ (options.units);
  4553. /**
  4554. * @private
  4555. * @type {ol.Extent}
  4556. */
  4557. this.extent_ = options.extent !== undefined ? options.extent : null;
  4558. /**
  4559. * @private
  4560. * @type {ol.Extent}
  4561. */
  4562. this.worldExtent_ = options.worldExtent !== undefined ?
  4563. options.worldExtent : null;
  4564. /**
  4565. * @private
  4566. * @type {string}
  4567. */
  4568. this.axisOrientation_ = options.axisOrientation !== undefined ?
  4569. options.axisOrientation : 'enu';
  4570. /**
  4571. * @private
  4572. * @type {boolean}
  4573. */
  4574. this.global_ = options.global !== undefined ? options.global : false;
  4575. /**
  4576. * @private
  4577. * @type {boolean}
  4578. */
  4579. this.canWrapX_ = !!(this.global_ && this.extent_);
  4580. /**
  4581. * @private
  4582. * @type {function(number, ol.Coordinate):number|undefined}
  4583. */
  4584. this.getPointResolutionFunc_ = options.getPointResolution;
  4585. /**
  4586. * @private
  4587. * @type {ol.tilegrid.TileGrid}
  4588. */
  4589. this.defaultTileGrid_ = null;
  4590. /**
  4591. * @private
  4592. * @type {number|undefined}
  4593. */
  4594. this.metersPerUnit_ = options.metersPerUnit;
  4595. var code = options.code;
  4596. if (ol.ENABLE_PROJ4JS) {
  4597. var proj4js = ol.proj.proj4.get();
  4598. if (typeof proj4js == 'function') {
  4599. var def = proj4js.defs(code);
  4600. if (def !== undefined) {
  4601. if (def.axis !== undefined && options.axisOrientation === undefined) {
  4602. this.axisOrientation_ = def.axis;
  4603. }
  4604. if (options.metersPerUnit === undefined) {
  4605. this.metersPerUnit_ = def.to_meter;
  4606. }
  4607. if (options.units === undefined) {
  4608. this.units_ = def.units;
  4609. }
  4610. }
  4611. }
  4612. }
  4613. };
  4614. /**
  4615. * @return {boolean} The projection is suitable for wrapping the x-axis
  4616. */
  4617. ol.proj.Projection.prototype.canWrapX = function() {
  4618. return this.canWrapX_;
  4619. };
  4620. /**
  4621. * Get the code for this projection, e.g. 'EPSG:4326'.
  4622. * @return {string} Code.
  4623. * @api
  4624. */
  4625. ol.proj.Projection.prototype.getCode = function() {
  4626. return this.code_;
  4627. };
  4628. /**
  4629. * Get the validity extent for this projection.
  4630. * @return {ol.Extent} Extent.
  4631. * @api
  4632. */
  4633. ol.proj.Projection.prototype.getExtent = function() {
  4634. return this.extent_;
  4635. };
  4636. /**
  4637. * Get the units of this projection.
  4638. * @return {ol.proj.Units} Units.
  4639. * @api
  4640. */
  4641. ol.proj.Projection.prototype.getUnits = function() {
  4642. return this.units_;
  4643. };
  4644. /**
  4645. * Get the amount of meters per unit of this projection. If the projection is
  4646. * not configured with `metersPerUnit` or a units identifier, the return is
  4647. * `undefined`.
  4648. * @return {number|undefined} Meters.
  4649. * @api
  4650. */
  4651. ol.proj.Projection.prototype.getMetersPerUnit = function() {
  4652. return this.metersPerUnit_ || ol.proj.Units.METERS_PER_UNIT[this.units_];
  4653. };
  4654. /**
  4655. * Get the world extent for this projection.
  4656. * @return {ol.Extent} Extent.
  4657. * @api
  4658. */
  4659. ol.proj.Projection.prototype.getWorldExtent = function() {
  4660. return this.worldExtent_;
  4661. };
  4662. /**
  4663. * Get the axis orientation of this projection.
  4664. * Example values are:
  4665. * enu - the default easting, northing, elevation.
  4666. * neu - northing, easting, up - useful for "lat/long" geographic coordinates,
  4667. * or south orientated transverse mercator.
  4668. * wnu - westing, northing, up - some planetary coordinate systems have
  4669. * "west positive" coordinate systems
  4670. * @return {string} Axis orientation.
  4671. */
  4672. ol.proj.Projection.prototype.getAxisOrientation = function() {
  4673. return this.axisOrientation_;
  4674. };
  4675. /**
  4676. * Is this projection a global projection which spans the whole world?
  4677. * @return {boolean} Whether the projection is global.
  4678. * @api
  4679. */
  4680. ol.proj.Projection.prototype.isGlobal = function() {
  4681. return this.global_;
  4682. };
  4683. /**
  4684. * Set if the projection is a global projection which spans the whole world
  4685. * @param {boolean} global Whether the projection is global.
  4686. * @api
  4687. */
  4688. ol.proj.Projection.prototype.setGlobal = function(global) {
  4689. this.global_ = global;
  4690. this.canWrapX_ = !!(global && this.extent_);
  4691. };
  4692. /**
  4693. * @return {ol.tilegrid.TileGrid} The default tile grid.
  4694. */
  4695. ol.proj.Projection.prototype.getDefaultTileGrid = function() {
  4696. return this.defaultTileGrid_;
  4697. };
  4698. /**
  4699. * @param {ol.tilegrid.TileGrid} tileGrid The default tile grid.
  4700. */
  4701. ol.proj.Projection.prototype.setDefaultTileGrid = function(tileGrid) {
  4702. this.defaultTileGrid_ = tileGrid;
  4703. };
  4704. /**
  4705. * Set the validity extent for this projection.
  4706. * @param {ol.Extent} extent Extent.
  4707. * @api
  4708. */
  4709. ol.proj.Projection.prototype.setExtent = function(extent) {
  4710. this.extent_ = extent;
  4711. this.canWrapX_ = !!(this.global_ && extent);
  4712. };
  4713. /**
  4714. * Set the world extent for this projection.
  4715. * @param {ol.Extent} worldExtent World extent
  4716. * [minlon, minlat, maxlon, maxlat].
  4717. * @api
  4718. */
  4719. ol.proj.Projection.prototype.setWorldExtent = function(worldExtent) {
  4720. this.worldExtent_ = worldExtent;
  4721. };
  4722. /**
  4723. * Set the getPointResolution function (see {@link ol.proj#getPointResolution}
  4724. * for this projection.
  4725. * @param {function(number, ol.Coordinate):number} func Function
  4726. * @api
  4727. */
  4728. ol.proj.Projection.prototype.setGetPointResolution = function(func) {
  4729. this.getPointResolutionFunc_ = func;
  4730. };
  4731. /**
  4732. * Get the custom point resolution function for this projection (if set).
  4733. * @return {function(number, ol.Coordinate):number|undefined} The custom point
  4734. * resolution function (if set).
  4735. */
  4736. ol.proj.Projection.prototype.getPointResolutionFunc = function() {
  4737. return this.getPointResolutionFunc_;
  4738. };
  4739. goog.provide('ol.proj.EPSG3857');
  4740. goog.require('ol');
  4741. goog.require('ol.math');
  4742. goog.require('ol.proj.Projection');
  4743. goog.require('ol.proj.Units');
  4744. /**
  4745. * @classdesc
  4746. * Projection object for web/spherical Mercator (EPSG:3857).
  4747. *
  4748. * @constructor
  4749. * @extends {ol.proj.Projection}
  4750. * @param {string} code Code.
  4751. * @private
  4752. */
  4753. ol.proj.EPSG3857.Projection_ = function(code) {
  4754. ol.proj.Projection.call(this, {
  4755. code: code,
  4756. units: ol.proj.Units.METERS,
  4757. extent: ol.proj.EPSG3857.EXTENT,
  4758. global: true,
  4759. worldExtent: ol.proj.EPSG3857.WORLD_EXTENT,
  4760. getPointResolution: function(resolution, point) {
  4761. return resolution / ol.math.cosh(point[1] / ol.proj.EPSG3857.RADIUS);
  4762. }
  4763. });
  4764. };
  4765. ol.inherits(ol.proj.EPSG3857.Projection_, ol.proj.Projection);
  4766. /**
  4767. * Radius of WGS84 sphere
  4768. *
  4769. * @const
  4770. * @type {number}
  4771. */
  4772. ol.proj.EPSG3857.RADIUS = 6378137;
  4773. /**
  4774. * @const
  4775. * @type {number}
  4776. */
  4777. ol.proj.EPSG3857.HALF_SIZE = Math.PI * ol.proj.EPSG3857.RADIUS;
  4778. /**
  4779. * @const
  4780. * @type {ol.Extent}
  4781. */
  4782. ol.proj.EPSG3857.EXTENT = [
  4783. -ol.proj.EPSG3857.HALF_SIZE, -ol.proj.EPSG3857.HALF_SIZE,
  4784. ol.proj.EPSG3857.HALF_SIZE, ol.proj.EPSG3857.HALF_SIZE
  4785. ];
  4786. /**
  4787. * @const
  4788. * @type {ol.Extent}
  4789. */
  4790. ol.proj.EPSG3857.WORLD_EXTENT = [-180, -85, 180, 85];
  4791. /**
  4792. * Projections equal to EPSG:3857.
  4793. *
  4794. * @const
  4795. * @type {Array.<ol.proj.Projection>}
  4796. */
  4797. ol.proj.EPSG3857.PROJECTIONS = [
  4798. new ol.proj.EPSG3857.Projection_('EPSG:3857'),
  4799. new ol.proj.EPSG3857.Projection_('EPSG:102100'),
  4800. new ol.proj.EPSG3857.Projection_('EPSG:102113'),
  4801. new ol.proj.EPSG3857.Projection_('EPSG:900913'),
  4802. new ol.proj.EPSG3857.Projection_('urn:ogc:def:crs:EPSG:6.18:3:3857'),
  4803. new ol.proj.EPSG3857.Projection_('urn:ogc:def:crs:EPSG::3857'),
  4804. new ol.proj.EPSG3857.Projection_('http://www.opengis.net/gml/srs/epsg.xml#3857')
  4805. ];
  4806. /**
  4807. * Transformation from EPSG:4326 to EPSG:3857.
  4808. *
  4809. * @param {Array.<number>} input Input array of coordinate values.
  4810. * @param {Array.<number>=} opt_output Output array of coordinate values.
  4811. * @param {number=} opt_dimension Dimension (default is `2`).
  4812. * @return {Array.<number>} Output array of coordinate values.
  4813. */
  4814. ol.proj.EPSG3857.fromEPSG4326 = function(input, opt_output, opt_dimension) {
  4815. var length = input.length,
  4816. dimension = opt_dimension > 1 ? opt_dimension : 2,
  4817. output = opt_output;
  4818. if (output === undefined) {
  4819. if (dimension > 2) {
  4820. // preserve values beyond second dimension
  4821. output = input.slice();
  4822. } else {
  4823. output = new Array(length);
  4824. }
  4825. }
  4826. var halfSize = ol.proj.EPSG3857.HALF_SIZE;
  4827. for (var i = 0; i < length; i += dimension) {
  4828. output[i] = halfSize * input[i] / 180;
  4829. var y = ol.proj.EPSG3857.RADIUS *
  4830. Math.log(Math.tan(Math.PI * (input[i + 1] + 90) / 360));
  4831. if (y > halfSize) {
  4832. y = halfSize;
  4833. } else if (y < -halfSize) {
  4834. y = -halfSize;
  4835. }
  4836. output[i + 1] = y;
  4837. }
  4838. return output;
  4839. };
  4840. /**
  4841. * Transformation from EPSG:3857 to EPSG:4326.
  4842. *
  4843. * @param {Array.<number>} input Input array of coordinate values.
  4844. * @param {Array.<number>=} opt_output Output array of coordinate values.
  4845. * @param {number=} opt_dimension Dimension (default is `2`).
  4846. * @return {Array.<number>} Output array of coordinate values.
  4847. */
  4848. ol.proj.EPSG3857.toEPSG4326 = function(input, opt_output, opt_dimension) {
  4849. var length = input.length,
  4850. dimension = opt_dimension > 1 ? opt_dimension : 2,
  4851. output = opt_output;
  4852. if (output === undefined) {
  4853. if (dimension > 2) {
  4854. // preserve values beyond second dimension
  4855. output = input.slice();
  4856. } else {
  4857. output = new Array(length);
  4858. }
  4859. }
  4860. for (var i = 0; i < length; i += dimension) {
  4861. output[i] = 180 * input[i] / ol.proj.EPSG3857.HALF_SIZE;
  4862. output[i + 1] = 360 * Math.atan(
  4863. Math.exp(input[i + 1] / ol.proj.EPSG3857.RADIUS)) / Math.PI - 90;
  4864. }
  4865. return output;
  4866. };
  4867. goog.provide('ol.proj.EPSG4326');
  4868. goog.require('ol');
  4869. goog.require('ol.proj.Projection');
  4870. goog.require('ol.proj.Units');
  4871. /**
  4872. * @classdesc
  4873. * Projection object for WGS84 geographic coordinates (EPSG:4326).
  4874. *
  4875. * Note that OpenLayers does not strictly comply with the EPSG definition.
  4876. * The EPSG registry defines 4326 as a CRS for Latitude,Longitude (y,x).
  4877. * OpenLayers treats EPSG:4326 as a pseudo-projection, with x,y coordinates.
  4878. *
  4879. * @constructor
  4880. * @extends {ol.proj.Projection}
  4881. * @param {string} code Code.
  4882. * @param {string=} opt_axisOrientation Axis orientation.
  4883. * @private
  4884. */
  4885. ol.proj.EPSG4326.Projection_ = function(code, opt_axisOrientation) {
  4886. ol.proj.Projection.call(this, {
  4887. code: code,
  4888. units: ol.proj.Units.DEGREES,
  4889. extent: ol.proj.EPSG4326.EXTENT,
  4890. axisOrientation: opt_axisOrientation,
  4891. global: true,
  4892. metersPerUnit: ol.proj.EPSG4326.METERS_PER_UNIT,
  4893. worldExtent: ol.proj.EPSG4326.EXTENT
  4894. });
  4895. };
  4896. ol.inherits(ol.proj.EPSG4326.Projection_, ol.proj.Projection);
  4897. /**
  4898. * Radius of WGS84 sphere
  4899. *
  4900. * @const
  4901. * @type {number}
  4902. */
  4903. ol.proj.EPSG4326.RADIUS = 6378137;
  4904. /**
  4905. * Extent of the EPSG:4326 projection which is the whole world.
  4906. *
  4907. * @const
  4908. * @type {ol.Extent}
  4909. */
  4910. ol.proj.EPSG4326.EXTENT = [-180, -90, 180, 90];
  4911. /**
  4912. * @const
  4913. * @type {number}
  4914. */
  4915. ol.proj.EPSG4326.METERS_PER_UNIT = Math.PI * ol.proj.EPSG4326.RADIUS / 180;
  4916. /**
  4917. * Projections equal to EPSG:4326.
  4918. *
  4919. * @const
  4920. * @type {Array.<ol.proj.Projection>}
  4921. */
  4922. ol.proj.EPSG4326.PROJECTIONS = [
  4923. new ol.proj.EPSG4326.Projection_('CRS:84'),
  4924. new ol.proj.EPSG4326.Projection_('EPSG:4326', 'neu'),
  4925. new ol.proj.EPSG4326.Projection_('urn:ogc:def:crs:EPSG::4326', 'neu'),
  4926. new ol.proj.EPSG4326.Projection_('urn:ogc:def:crs:EPSG:6.6:4326', 'neu'),
  4927. new ol.proj.EPSG4326.Projection_('urn:ogc:def:crs:OGC:1.3:CRS84'),
  4928. new ol.proj.EPSG4326.Projection_('urn:ogc:def:crs:OGC:2:84'),
  4929. new ol.proj.EPSG4326.Projection_('http://www.opengis.net/gml/srs/epsg.xml#4326', 'neu'),
  4930. new ol.proj.EPSG4326.Projection_('urn:x-ogc:def:crs:EPSG:4326', 'neu')
  4931. ];
  4932. goog.provide('ol.proj.projections');
  4933. /**
  4934. * @private
  4935. * @type {Object.<string, ol.proj.Projection>}
  4936. */
  4937. ol.proj.projections.cache_ = {};
  4938. /**
  4939. * Clear the projections cache.
  4940. */
  4941. ol.proj.projections.clear = function() {
  4942. ol.proj.projections.cache_ = {};
  4943. };
  4944. /**
  4945. * Get a cached projection by code.
  4946. * @param {string} code The code for the projection.
  4947. * @return {ol.proj.Projection} The projection (if cached).
  4948. */
  4949. ol.proj.projections.get = function(code) {
  4950. var projections = ol.proj.projections.cache_;
  4951. return projections[code] || null;
  4952. };
  4953. /**
  4954. * Add a projection to the cache.
  4955. * @param {string} code The projection code.
  4956. * @param {ol.proj.Projection} projection The projection to cache.
  4957. */
  4958. ol.proj.projections.add = function(code, projection) {
  4959. var projections = ol.proj.projections.cache_;
  4960. projections[code] = projection;
  4961. };
  4962. goog.provide('ol.proj.transforms');
  4963. goog.require('ol.obj');
  4964. /**
  4965. * @private
  4966. * @type {Object.<string, Object.<string, ol.TransformFunction>>}
  4967. */
  4968. ol.proj.transforms.cache_ = {};
  4969. /**
  4970. * Clear the transform cache.
  4971. */
  4972. ol.proj.transforms.clear = function() {
  4973. ol.proj.transforms.cache_ = {};
  4974. };
  4975. /**
  4976. * Registers a conversion function to convert coordinates from the source
  4977. * projection to the destination projection.
  4978. *
  4979. * @param {ol.proj.Projection} source Source.
  4980. * @param {ol.proj.Projection} destination Destination.
  4981. * @param {ol.TransformFunction} transformFn Transform.
  4982. */
  4983. ol.proj.transforms.add = function(source, destination, transformFn) {
  4984. var sourceCode = source.getCode();
  4985. var destinationCode = destination.getCode();
  4986. var transforms = ol.proj.transforms.cache_;
  4987. if (!(sourceCode in transforms)) {
  4988. transforms[sourceCode] = {};
  4989. }
  4990. transforms[sourceCode][destinationCode] = transformFn;
  4991. };
  4992. /**
  4993. * Unregisters the conversion function to convert coordinates from the source
  4994. * projection to the destination projection. This method is used to clean up
  4995. * cached transforms during testing.
  4996. *
  4997. * @param {ol.proj.Projection} source Source projection.
  4998. * @param {ol.proj.Projection} destination Destination projection.
  4999. * @return {ol.TransformFunction} transformFn The unregistered transform.
  5000. */
  5001. ol.proj.transforms.remove = function(source, destination) {
  5002. var sourceCode = source.getCode();
  5003. var destinationCode = destination.getCode();
  5004. var transforms = ol.proj.transforms.cache_;
  5005. var transform = transforms[sourceCode][destinationCode];
  5006. delete transforms[sourceCode][destinationCode];
  5007. if (ol.obj.isEmpty(transforms[sourceCode])) {
  5008. delete transforms[sourceCode];
  5009. }
  5010. return transform;
  5011. };
  5012. /**
  5013. * Get a transform given a source code and a destination code.
  5014. * @param {string} sourceCode The code for the source projection.
  5015. * @param {string} destinationCode The code for the destination projection.
  5016. * @return {ol.TransformFunction|undefined} The transform function (if found).
  5017. */
  5018. ol.proj.transforms.get = function(sourceCode, destinationCode) {
  5019. var transform;
  5020. var transforms = ol.proj.transforms.cache_;
  5021. if (sourceCode in transforms && destinationCode in transforms[sourceCode]) {
  5022. transform = transforms[sourceCode][destinationCode];
  5023. }
  5024. return transform;
  5025. };
  5026. goog.provide('ol.proj');
  5027. goog.require('ol');
  5028. goog.require('ol.Sphere');
  5029. goog.require('ol.extent');
  5030. goog.require('ol.proj.EPSG3857');
  5031. goog.require('ol.proj.EPSG4326');
  5032. goog.require('ol.proj.Projection');
  5033. goog.require('ol.proj.Units');
  5034. goog.require('ol.proj.proj4');
  5035. goog.require('ol.proj.projections');
  5036. goog.require('ol.proj.transforms');
  5037. /**
  5038. * Meters per unit lookup table.
  5039. * @const
  5040. * @type {Object.<ol.proj.Units, number>}
  5041. * @api
  5042. */
  5043. ol.proj.METERS_PER_UNIT = ol.proj.Units.METERS_PER_UNIT;
  5044. /**
  5045. * A place to store the mean radius of the Earth.
  5046. * @private
  5047. * @type {ol.Sphere}
  5048. */
  5049. ol.proj.SPHERE_ = new ol.Sphere(ol.Sphere.DEFAULT_RADIUS);
  5050. if (ol.ENABLE_PROJ4JS) {
  5051. /**
  5052. * Register proj4. If not explicitly registered, it will be assumed that
  5053. * proj4js will be loaded in the global namespace. For example in a
  5054. * browserify ES6 environment you could use:
  5055. *
  5056. * import ol from 'openlayers';
  5057. * import proj4 from 'proj4';
  5058. * ol.proj.setProj4(proj4);
  5059. *
  5060. * @param {Proj4} proj4 Proj4.
  5061. * @api
  5062. */
  5063. ol.proj.setProj4 = function(proj4) {
  5064. ol.proj.proj4.set(proj4);
  5065. };
  5066. }
  5067. /**
  5068. * Get the resolution of the point in degrees or distance units.
  5069. * For projections with degrees as the unit this will simply return the
  5070. * provided resolution. For other projections the point resolution is
  5071. * by default estimated by transforming the 'point' pixel to EPSG:4326,
  5072. * measuring its width and height on the normal sphere,
  5073. * and taking the average of the width and height.
  5074. * A custom function can be provided for a specific projection, either
  5075. * by setting the `getPointResolution` option in the
  5076. * {@link ol.proj.Projection} constructor or by using
  5077. * {@link ol.proj.Projection#setGetPointResolution} to change an existing
  5078. * projection object.
  5079. * @param {ol.ProjectionLike} projection The projection.
  5080. * @param {number} resolution Nominal resolution in projection units.
  5081. * @param {ol.Coordinate} point Point to find adjusted resolution at.
  5082. * @param {ol.proj.Units=} opt_units Units to get the point resolution in.
  5083. * Default is the projection's units.
  5084. * @return {number} Point resolution.
  5085. * @api
  5086. */
  5087. ol.proj.getPointResolution = function(projection, resolution, point, opt_units) {
  5088. projection = ol.proj.get(projection);
  5089. var pointResolution;
  5090. var getter = projection.getPointResolutionFunc();
  5091. if (getter) {
  5092. pointResolution = getter(resolution, point);
  5093. } else {
  5094. var units = projection.getUnits();
  5095. if (units == ol.proj.Units.DEGREES && !opt_units || opt_units == ol.proj.Units.DEGREES) {
  5096. pointResolution = resolution;
  5097. } else {
  5098. // Estimate point resolution by transforming the center pixel to EPSG:4326,
  5099. // measuring its width and height on the normal sphere, and taking the
  5100. // average of the width and height.
  5101. var toEPSG4326 = ol.proj.getTransformFromProjections(projection, ol.proj.get('EPSG:4326'));
  5102. var vertices = [
  5103. point[0] - resolution / 2, point[1],
  5104. point[0] + resolution / 2, point[1],
  5105. point[0], point[1] - resolution / 2,
  5106. point[0], point[1] + resolution / 2
  5107. ];
  5108. vertices = toEPSG4326(vertices, vertices, 2);
  5109. var width = ol.proj.SPHERE_.haversineDistance(
  5110. vertices.slice(0, 2), vertices.slice(2, 4));
  5111. var height = ol.proj.SPHERE_.haversineDistance(
  5112. vertices.slice(4, 6), vertices.slice(6, 8));
  5113. pointResolution = (width + height) / 2;
  5114. var metersPerUnit = opt_units ?
  5115. ol.proj.Units.METERS_PER_UNIT[opt_units] :
  5116. projection.getMetersPerUnit();
  5117. if (metersPerUnit !== undefined) {
  5118. pointResolution /= metersPerUnit;
  5119. }
  5120. }
  5121. }
  5122. return pointResolution;
  5123. };
  5124. /**
  5125. * Registers transformation functions that don't alter coordinates. Those allow
  5126. * to transform between projections with equal meaning.
  5127. *
  5128. * @param {Array.<ol.proj.Projection>} projections Projections.
  5129. * @api
  5130. */
  5131. ol.proj.addEquivalentProjections = function(projections) {
  5132. ol.proj.addProjections(projections);
  5133. projections.forEach(function(source) {
  5134. projections.forEach(function(destination) {
  5135. if (source !== destination) {
  5136. ol.proj.transforms.add(source, destination, ol.proj.cloneTransform);
  5137. }
  5138. });
  5139. });
  5140. };
  5141. /**
  5142. * Registers transformation functions to convert coordinates in any projection
  5143. * in projection1 to any projection in projection2.
  5144. *
  5145. * @param {Array.<ol.proj.Projection>} projections1 Projections with equal
  5146. * meaning.
  5147. * @param {Array.<ol.proj.Projection>} projections2 Projections with equal
  5148. * meaning.
  5149. * @param {ol.TransformFunction} forwardTransform Transformation from any
  5150. * projection in projection1 to any projection in projection2.
  5151. * @param {ol.TransformFunction} inverseTransform Transform from any projection
  5152. * in projection2 to any projection in projection1..
  5153. */
  5154. ol.proj.addEquivalentTransforms = function(projections1, projections2, forwardTransform, inverseTransform) {
  5155. projections1.forEach(function(projection1) {
  5156. projections2.forEach(function(projection2) {
  5157. ol.proj.transforms.add(projection1, projection2, forwardTransform);
  5158. ol.proj.transforms.add(projection2, projection1, inverseTransform);
  5159. });
  5160. });
  5161. };
  5162. /**
  5163. * Add a Projection object to the list of supported projections that can be
  5164. * looked up by their code.
  5165. *
  5166. * @param {ol.proj.Projection} projection Projection instance.
  5167. * @api
  5168. */
  5169. ol.proj.addProjection = function(projection) {
  5170. ol.proj.projections.add(projection.getCode(), projection);
  5171. ol.proj.transforms.add(projection, projection, ol.proj.cloneTransform);
  5172. };
  5173. /**
  5174. * @param {Array.<ol.proj.Projection>} projections Projections.
  5175. */
  5176. ol.proj.addProjections = function(projections) {
  5177. projections.forEach(ol.proj.addProjection);
  5178. };
  5179. /**
  5180. * Clear all cached projections and transforms.
  5181. */
  5182. ol.proj.clearAllProjections = function() {
  5183. ol.proj.projections.clear();
  5184. ol.proj.transforms.clear();
  5185. };
  5186. /**
  5187. * @param {ol.proj.Projection|string|undefined} projection Projection.
  5188. * @param {string} defaultCode Default code.
  5189. * @return {ol.proj.Projection} Projection.
  5190. */
  5191. ol.proj.createProjection = function(projection, defaultCode) {
  5192. if (!projection) {
  5193. return ol.proj.get(defaultCode);
  5194. } else if (typeof projection === 'string') {
  5195. return ol.proj.get(projection);
  5196. } else {
  5197. return /** @type {ol.proj.Projection} */ (projection);
  5198. }
  5199. };
  5200. /**
  5201. * Registers coordinate transform functions to convert coordinates between the
  5202. * source projection and the destination projection.
  5203. * The forward and inverse functions convert coordinate pairs; this function
  5204. * converts these into the functions used internally which also handle
  5205. * extents and coordinate arrays.
  5206. *
  5207. * @param {ol.ProjectionLike} source Source projection.
  5208. * @param {ol.ProjectionLike} destination Destination projection.
  5209. * @param {function(ol.Coordinate): ol.Coordinate} forward The forward transform
  5210. * function (that is, from the source projection to the destination
  5211. * projection) that takes a {@link ol.Coordinate} as argument and returns
  5212. * the transformed {@link ol.Coordinate}.
  5213. * @param {function(ol.Coordinate): ol.Coordinate} inverse The inverse transform
  5214. * function (that is, from the destination projection to the source
  5215. * projection) that takes a {@link ol.Coordinate} as argument and returns
  5216. * the transformed {@link ol.Coordinate}.
  5217. * @api
  5218. */
  5219. ol.proj.addCoordinateTransforms = function(source, destination, forward, inverse) {
  5220. var sourceProj = ol.proj.get(source);
  5221. var destProj = ol.proj.get(destination);
  5222. ol.proj.transforms.add(sourceProj, destProj,
  5223. ol.proj.createTransformFromCoordinateTransform(forward));
  5224. ol.proj.transforms.add(destProj, sourceProj,
  5225. ol.proj.createTransformFromCoordinateTransform(inverse));
  5226. };
  5227. /**
  5228. * Creates a {@link ol.TransformFunction} from a simple 2D coordinate transform
  5229. * function.
  5230. * @param {function(ol.Coordinate): ol.Coordinate} transform Coordinate
  5231. * transform.
  5232. * @return {ol.TransformFunction} Transform function.
  5233. */
  5234. ol.proj.createTransformFromCoordinateTransform = function(transform) {
  5235. return (
  5236. /**
  5237. * @param {Array.<number>} input Input.
  5238. * @param {Array.<number>=} opt_output Output.
  5239. * @param {number=} opt_dimension Dimension.
  5240. * @return {Array.<number>} Output.
  5241. */
  5242. function(input, opt_output, opt_dimension) {
  5243. var length = input.length;
  5244. var dimension = opt_dimension !== undefined ? opt_dimension : 2;
  5245. var output = opt_output !== undefined ? opt_output : new Array(length);
  5246. var point, i, j;
  5247. for (i = 0; i < length; i += dimension) {
  5248. point = transform([input[i], input[i + 1]]);
  5249. output[i] = point[0];
  5250. output[i + 1] = point[1];
  5251. for (j = dimension - 1; j >= 2; --j) {
  5252. output[i + j] = input[i + j];
  5253. }
  5254. }
  5255. return output;
  5256. });
  5257. };
  5258. /**
  5259. * Transforms a coordinate from longitude/latitude to a different projection.
  5260. * @param {ol.Coordinate} coordinate Coordinate as longitude and latitude, i.e.
  5261. * an array with longitude as 1st and latitude as 2nd element.
  5262. * @param {ol.ProjectionLike=} opt_projection Target projection. The
  5263. * default is Web Mercator, i.e. 'EPSG:3857'.
  5264. * @return {ol.Coordinate} Coordinate projected to the target projection.
  5265. * @api
  5266. */
  5267. ol.proj.fromLonLat = function(coordinate, opt_projection) {
  5268. return ol.proj.transform(coordinate, 'EPSG:4326',
  5269. opt_projection !== undefined ? opt_projection : 'EPSG:3857');
  5270. };
  5271. /**
  5272. * Transforms a coordinate to longitude/latitude.
  5273. * @param {ol.Coordinate} coordinate Projected coordinate.
  5274. * @param {ol.ProjectionLike=} opt_projection Projection of the coordinate.
  5275. * The default is Web Mercator, i.e. 'EPSG:3857'.
  5276. * @return {ol.Coordinate} Coordinate as longitude and latitude, i.e. an array
  5277. * with longitude as 1st and latitude as 2nd element.
  5278. * @api
  5279. */
  5280. ol.proj.toLonLat = function(coordinate, opt_projection) {
  5281. return ol.proj.transform(coordinate,
  5282. opt_projection !== undefined ? opt_projection : 'EPSG:3857', 'EPSG:4326');
  5283. };
  5284. /**
  5285. * Fetches a Projection object for the code specified.
  5286. *
  5287. * @param {ol.ProjectionLike} projectionLike Either a code string which is
  5288. * a combination of authority and identifier such as "EPSG:4326", or an
  5289. * existing projection object, or undefined.
  5290. * @return {ol.proj.Projection} Projection object, or null if not in list.
  5291. * @api
  5292. */
  5293. ol.proj.get = function(projectionLike) {
  5294. var projection = null;
  5295. if (projectionLike instanceof ol.proj.Projection) {
  5296. projection = projectionLike;
  5297. } else if (typeof projectionLike === 'string') {
  5298. var code = projectionLike;
  5299. projection = ol.proj.projections.get(code);
  5300. if (ol.ENABLE_PROJ4JS && !projection) {
  5301. var proj4js = ol.proj.proj4.get();
  5302. if (typeof proj4js == 'function' &&
  5303. proj4js.defs(code) !== undefined) {
  5304. projection = new ol.proj.Projection({code: code});
  5305. ol.proj.addProjection(projection);
  5306. }
  5307. }
  5308. }
  5309. return projection;
  5310. };
  5311. /**
  5312. * Checks if two projections are the same, that is every coordinate in one
  5313. * projection does represent the same geographic point as the same coordinate in
  5314. * the other projection.
  5315. *
  5316. * @param {ol.proj.Projection} projection1 Projection 1.
  5317. * @param {ol.proj.Projection} projection2 Projection 2.
  5318. * @return {boolean} Equivalent.
  5319. * @api
  5320. */
  5321. ol.proj.equivalent = function(projection1, projection2) {
  5322. if (projection1 === projection2) {
  5323. return true;
  5324. }
  5325. var equalUnits = projection1.getUnits() === projection2.getUnits();
  5326. if (projection1.getCode() === projection2.getCode()) {
  5327. return equalUnits;
  5328. } else {
  5329. var transformFn = ol.proj.getTransformFromProjections(
  5330. projection1, projection2);
  5331. return transformFn === ol.proj.cloneTransform && equalUnits;
  5332. }
  5333. };
  5334. /**
  5335. * Given the projection-like objects, searches for a transformation
  5336. * function to convert a coordinates array from the source projection to the
  5337. * destination projection.
  5338. *
  5339. * @param {ol.ProjectionLike} source Source.
  5340. * @param {ol.ProjectionLike} destination Destination.
  5341. * @return {ol.TransformFunction} Transform function.
  5342. * @api
  5343. */
  5344. ol.proj.getTransform = function(source, destination) {
  5345. var sourceProjection = ol.proj.get(source);
  5346. var destinationProjection = ol.proj.get(destination);
  5347. return ol.proj.getTransformFromProjections(
  5348. sourceProjection, destinationProjection);
  5349. };
  5350. /**
  5351. * Searches in the list of transform functions for the function for converting
  5352. * coordinates from the source projection to the destination projection.
  5353. *
  5354. * @param {ol.proj.Projection} sourceProjection Source Projection object.
  5355. * @param {ol.proj.Projection} destinationProjection Destination Projection
  5356. * object.
  5357. * @return {ol.TransformFunction} Transform function.
  5358. */
  5359. ol.proj.getTransformFromProjections = function(sourceProjection, destinationProjection) {
  5360. var sourceCode = sourceProjection.getCode();
  5361. var destinationCode = destinationProjection.getCode();
  5362. var transform = ol.proj.transforms.get(sourceCode, destinationCode);
  5363. if (ol.ENABLE_PROJ4JS && !transform) {
  5364. var proj4js = ol.proj.proj4.get();
  5365. if (typeof proj4js == 'function') {
  5366. var sourceDef = proj4js.defs(sourceCode);
  5367. var destinationDef = proj4js.defs(destinationCode);
  5368. if (sourceDef !== undefined && destinationDef !== undefined) {
  5369. if (sourceDef === destinationDef) {
  5370. ol.proj.addEquivalentProjections([destinationProjection, sourceProjection]);
  5371. } else {
  5372. var proj4Transform = proj4js(destinationCode, sourceCode);
  5373. ol.proj.addCoordinateTransforms(destinationProjection, sourceProjection,
  5374. proj4Transform.forward, proj4Transform.inverse);
  5375. }
  5376. transform = ol.proj.transforms.get(sourceCode, destinationCode);
  5377. }
  5378. }
  5379. }
  5380. if (!transform) {
  5381. transform = ol.proj.identityTransform;
  5382. }
  5383. return transform;
  5384. };
  5385. /**
  5386. * @param {Array.<number>} input Input coordinate array.
  5387. * @param {Array.<number>=} opt_output Output array of coordinate values.
  5388. * @param {number=} opt_dimension Dimension.
  5389. * @return {Array.<number>} Input coordinate array (same array as input).
  5390. */
  5391. ol.proj.identityTransform = function(input, opt_output, opt_dimension) {
  5392. if (opt_output !== undefined && input !== opt_output) {
  5393. for (var i = 0, ii = input.length; i < ii; ++i) {
  5394. opt_output[i] = input[i];
  5395. }
  5396. input = opt_output;
  5397. }
  5398. return input;
  5399. };
  5400. /**
  5401. * @param {Array.<number>} input Input coordinate array.
  5402. * @param {Array.<number>=} opt_output Output array of coordinate values.
  5403. * @param {number=} opt_dimension Dimension.
  5404. * @return {Array.<number>} Output coordinate array (new array, same coordinate
  5405. * values).
  5406. */
  5407. ol.proj.cloneTransform = function(input, opt_output, opt_dimension) {
  5408. var output;
  5409. if (opt_output !== undefined) {
  5410. for (var i = 0, ii = input.length; i < ii; ++i) {
  5411. opt_output[i] = input[i];
  5412. }
  5413. output = opt_output;
  5414. } else {
  5415. output = input.slice();
  5416. }
  5417. return output;
  5418. };
  5419. /**
  5420. * Transforms a coordinate from source projection to destination projection.
  5421. * This returns a new coordinate (and does not modify the original).
  5422. *
  5423. * See {@link ol.proj.transformExtent} for extent transformation.
  5424. * See the transform method of {@link ol.geom.Geometry} and its subclasses for
  5425. * geometry transforms.
  5426. *
  5427. * @param {ol.Coordinate} coordinate Coordinate.
  5428. * @param {ol.ProjectionLike} source Source projection-like.
  5429. * @param {ol.ProjectionLike} destination Destination projection-like.
  5430. * @return {ol.Coordinate} Coordinate.
  5431. * @api
  5432. */
  5433. ol.proj.transform = function(coordinate, source, destination) {
  5434. var transformFn = ol.proj.getTransform(source, destination);
  5435. return transformFn(coordinate, undefined, coordinate.length);
  5436. };
  5437. /**
  5438. * Transforms an extent from source projection to destination projection. This
  5439. * returns a new extent (and does not modify the original).
  5440. *
  5441. * @param {ol.Extent} extent The extent to transform.
  5442. * @param {ol.ProjectionLike} source Source projection-like.
  5443. * @param {ol.ProjectionLike} destination Destination projection-like.
  5444. * @return {ol.Extent} The transformed extent.
  5445. * @api
  5446. */
  5447. ol.proj.transformExtent = function(extent, source, destination) {
  5448. var transformFn = ol.proj.getTransform(source, destination);
  5449. return ol.extent.applyTransform(extent, transformFn);
  5450. };
  5451. /**
  5452. * Transforms the given point to the destination projection.
  5453. *
  5454. * @param {ol.Coordinate} point Point.
  5455. * @param {ol.proj.Projection} sourceProjection Source projection.
  5456. * @param {ol.proj.Projection} destinationProjection Destination projection.
  5457. * @return {ol.Coordinate} Point.
  5458. */
  5459. ol.proj.transformWithProjections = function(point, sourceProjection, destinationProjection) {
  5460. var transformFn = ol.proj.getTransformFromProjections(
  5461. sourceProjection, destinationProjection);
  5462. return transformFn(point);
  5463. };
  5464. /**
  5465. * Add transforms to and from EPSG:4326 and EPSG:3857. This function is called
  5466. * by when this module is executed and should only need to be called again after
  5467. * `ol.proj.clearAllProjections()` is called (e.g. in tests).
  5468. */
  5469. ol.proj.addCommon = function() {
  5470. // Add transformations that don't alter coordinates to convert within set of
  5471. // projections with equal meaning.
  5472. ol.proj.addEquivalentProjections(ol.proj.EPSG3857.PROJECTIONS);
  5473. ol.proj.addEquivalentProjections(ol.proj.EPSG4326.PROJECTIONS);
  5474. // Add transformations to convert EPSG:4326 like coordinates to EPSG:3857 like
  5475. // coordinates and back.
  5476. ol.proj.addEquivalentTransforms(
  5477. ol.proj.EPSG4326.PROJECTIONS,
  5478. ol.proj.EPSG3857.PROJECTIONS,
  5479. ol.proj.EPSG3857.fromEPSG4326,
  5480. ol.proj.EPSG3857.toEPSG4326);
  5481. };
  5482. ol.proj.addCommon();
  5483. goog.provide('ol.tilecoord');
  5484. /**
  5485. * @param {number} z Z.
  5486. * @param {number} x X.
  5487. * @param {number} y Y.
  5488. * @param {ol.TileCoord=} opt_tileCoord Tile coordinate.
  5489. * @return {ol.TileCoord} Tile coordinate.
  5490. */
  5491. ol.tilecoord.createOrUpdate = function(z, x, y, opt_tileCoord) {
  5492. if (opt_tileCoord !== undefined) {
  5493. opt_tileCoord[0] = z;
  5494. opt_tileCoord[1] = x;
  5495. opt_tileCoord[2] = y;
  5496. return opt_tileCoord;
  5497. } else {
  5498. return [z, x, y];
  5499. }
  5500. };
  5501. /**
  5502. * @param {number} z Z.
  5503. * @param {number} x X.
  5504. * @param {number} y Y.
  5505. * @return {string} Key.
  5506. */
  5507. ol.tilecoord.getKeyZXY = function(z, x, y) {
  5508. return z + '/' + x + '/' + y;
  5509. };
  5510. /**
  5511. * @param {ol.TileCoord} tileCoord Tile coord.
  5512. * @return {number} Hash.
  5513. */
  5514. ol.tilecoord.hash = function(tileCoord) {
  5515. return (tileCoord[1] << tileCoord[0]) + tileCoord[2];
  5516. };
  5517. /**
  5518. * @param {ol.TileCoord} tileCoord Tile coord.
  5519. * @return {string} Quad key.
  5520. */
  5521. ol.tilecoord.quadKey = function(tileCoord) {
  5522. var z = tileCoord[0];
  5523. var digits = new Array(z);
  5524. var mask = 1 << (z - 1);
  5525. var i, charCode;
  5526. for (i = 0; i < z; ++i) {
  5527. // 48 is charCode for 0 - '0'.charCodeAt(0)
  5528. charCode = 48;
  5529. if (tileCoord[1] & mask) {
  5530. charCode += 1;
  5531. }
  5532. if (tileCoord[2] & mask) {
  5533. charCode += 2;
  5534. }
  5535. digits[i] = String.fromCharCode(charCode);
  5536. mask >>= 1;
  5537. }
  5538. return digits.join('');
  5539. };
  5540. /**
  5541. * @param {ol.TileCoord} tileCoord Tile coordinate.
  5542. * @param {!ol.tilegrid.TileGrid} tileGrid Tile grid.
  5543. * @return {boolean} Tile coordinate is within extent and zoom level range.
  5544. */
  5545. ol.tilecoord.withinExtentAndZ = function(tileCoord, tileGrid) {
  5546. var z = tileCoord[0];
  5547. var x = tileCoord[1];
  5548. var y = tileCoord[2];
  5549. if (tileGrid.getMinZoom() > z || z > tileGrid.getMaxZoom()) {
  5550. return false;
  5551. }
  5552. var extent = tileGrid.getExtent();
  5553. var tileRange;
  5554. if (!extent) {
  5555. tileRange = tileGrid.getFullTileRange(z);
  5556. } else {
  5557. tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z);
  5558. }
  5559. if (!tileRange) {
  5560. return true;
  5561. } else {
  5562. return tileRange.containsXY(x, y);
  5563. }
  5564. };
  5565. goog.provide('ol.tilegrid.TileGrid');
  5566. goog.require('ol');
  5567. goog.require('ol.asserts');
  5568. goog.require('ol.TileRange');
  5569. goog.require('ol.array');
  5570. goog.require('ol.extent');
  5571. goog.require('ol.math');
  5572. goog.require('ol.size');
  5573. goog.require('ol.tilecoord');
  5574. /**
  5575. * @classdesc
  5576. * Base class for setting the grid pattern for sources accessing tiled-image
  5577. * servers.
  5578. *
  5579. * @constructor
  5580. * @param {olx.tilegrid.TileGridOptions} options Tile grid options.
  5581. * @struct
  5582. * @api
  5583. */
  5584. ol.tilegrid.TileGrid = function(options) {
  5585. /**
  5586. * @protected
  5587. * @type {number}
  5588. */
  5589. this.minZoom = options.minZoom !== undefined ? options.minZoom : 0;
  5590. /**
  5591. * @private
  5592. * @type {!Array.<number>}
  5593. */
  5594. this.resolutions_ = options.resolutions;
  5595. ol.asserts.assert(ol.array.isSorted(this.resolutions_, function(a, b) {
  5596. return b - a;
  5597. }, true), 17); // `resolutions` must be sorted in descending order
  5598. /**
  5599. * @protected
  5600. * @type {number}
  5601. */
  5602. this.maxZoom = this.resolutions_.length - 1;
  5603. /**
  5604. * @private
  5605. * @type {ol.Coordinate}
  5606. */
  5607. this.origin_ = options.origin !== undefined ? options.origin : null;
  5608. /**
  5609. * @private
  5610. * @type {Array.<ol.Coordinate>}
  5611. */
  5612. this.origins_ = null;
  5613. if (options.origins !== undefined) {
  5614. this.origins_ = options.origins;
  5615. ol.asserts.assert(this.origins_.length == this.resolutions_.length,
  5616. 20); // Number of `origins` and `resolutions` must be equal
  5617. }
  5618. var extent = options.extent;
  5619. if (extent !== undefined &&
  5620. !this.origin_ && !this.origins_) {
  5621. this.origin_ = ol.extent.getTopLeft(extent);
  5622. }
  5623. ol.asserts.assert(
  5624. (!this.origin_ && this.origins_) || (this.origin_ && !this.origins_),
  5625. 18); // Either `origin` or `origins` must be configured, never both
  5626. /**
  5627. * @private
  5628. * @type {Array.<number|ol.Size>}
  5629. */
  5630. this.tileSizes_ = null;
  5631. if (options.tileSizes !== undefined) {
  5632. this.tileSizes_ = options.tileSizes;
  5633. ol.asserts.assert(this.tileSizes_.length == this.resolutions_.length,
  5634. 19); // Number of `tileSizes` and `resolutions` must be equal
  5635. }
  5636. /**
  5637. * @private
  5638. * @type {number|ol.Size}
  5639. */
  5640. this.tileSize_ = options.tileSize !== undefined ?
  5641. options.tileSize :
  5642. !this.tileSizes_ ? ol.DEFAULT_TILE_SIZE : null;
  5643. ol.asserts.assert(
  5644. (!this.tileSize_ && this.tileSizes_) ||
  5645. (this.tileSize_ && !this.tileSizes_),
  5646. 22); // Either `tileSize` or `tileSizes` must be configured, never both
  5647. /**
  5648. * @private
  5649. * @type {ol.Extent}
  5650. */
  5651. this.extent_ = extent !== undefined ? extent : null;
  5652. /**
  5653. * @private
  5654. * @type {Array.<ol.TileRange>}
  5655. */
  5656. this.fullTileRanges_ = null;
  5657. /**
  5658. * @private
  5659. * @type {ol.Size}
  5660. */
  5661. this.tmpSize_ = [0, 0];
  5662. if (options.sizes !== undefined) {
  5663. this.fullTileRanges_ = options.sizes.map(function(size, z) {
  5664. var tileRange = new ol.TileRange(
  5665. Math.min(0, size[0]), Math.max(size[0] - 1, -1),
  5666. Math.min(0, size[1]), Math.max(size[1] - 1, -1));
  5667. return tileRange;
  5668. }, this);
  5669. } else if (extent) {
  5670. this.calculateTileRanges_(extent);
  5671. }
  5672. };
  5673. /**
  5674. * @private
  5675. * @type {ol.TileCoord}
  5676. */
  5677. ol.tilegrid.TileGrid.tmpTileCoord_ = [0, 0, 0];
  5678. /**
  5679. * Call a function with each tile coordinate for a given extent and zoom level.
  5680. *
  5681. * @param {ol.Extent} extent Extent.
  5682. * @param {number} zoom Zoom level.
  5683. * @param {function(ol.TileCoord)} callback Function called with each tile coordinate.
  5684. * @api
  5685. */
  5686. ol.tilegrid.TileGrid.prototype.forEachTileCoord = function(extent, zoom, callback) {
  5687. var tileRange = this.getTileRangeForExtentAndZ(extent, zoom);
  5688. for (var i = tileRange.minX, ii = tileRange.maxX; i <= ii; ++i) {
  5689. for (var j = tileRange.minY, jj = tileRange.maxY; j <= jj; ++j) {
  5690. callback([zoom, i, j]);
  5691. }
  5692. }
  5693. };
  5694. /**
  5695. * @param {ol.TileCoord} tileCoord Tile coordinate.
  5696. * @param {function(this: T, number, ol.TileRange): boolean} callback Callback.
  5697. * @param {T=} opt_this The object to use as `this` in `callback`.
  5698. * @param {ol.TileRange=} opt_tileRange Temporary ol.TileRange object.
  5699. * @param {ol.Extent=} opt_extent Temporary ol.Extent object.
  5700. * @return {boolean} Callback succeeded.
  5701. * @template T
  5702. */
  5703. ol.tilegrid.TileGrid.prototype.forEachTileCoordParentTileRange = function(tileCoord, callback, opt_this, opt_tileRange, opt_extent) {
  5704. var tileCoordExtent = this.getTileCoordExtent(tileCoord, opt_extent);
  5705. var z = tileCoord[0] - 1;
  5706. while (z >= this.minZoom) {
  5707. if (callback.call(opt_this, z,
  5708. this.getTileRangeForExtentAndZ(tileCoordExtent, z, opt_tileRange))) {
  5709. return true;
  5710. }
  5711. --z;
  5712. }
  5713. return false;
  5714. };
  5715. /**
  5716. * Get the extent for this tile grid, if it was configured.
  5717. * @return {ol.Extent} Extent.
  5718. */
  5719. ol.tilegrid.TileGrid.prototype.getExtent = function() {
  5720. return this.extent_;
  5721. };
  5722. /**
  5723. * Get the maximum zoom level for the grid.
  5724. * @return {number} Max zoom.
  5725. * @api
  5726. */
  5727. ol.tilegrid.TileGrid.prototype.getMaxZoom = function() {
  5728. return this.maxZoom;
  5729. };
  5730. /**
  5731. * Get the minimum zoom level for the grid.
  5732. * @return {number} Min zoom.
  5733. * @api
  5734. */
  5735. ol.tilegrid.TileGrid.prototype.getMinZoom = function() {
  5736. return this.minZoom;
  5737. };
  5738. /**
  5739. * Get the origin for the grid at the given zoom level.
  5740. * @param {number} z Z.
  5741. * @return {ol.Coordinate} Origin.
  5742. * @api
  5743. */
  5744. ol.tilegrid.TileGrid.prototype.getOrigin = function(z) {
  5745. if (this.origin_) {
  5746. return this.origin_;
  5747. } else {
  5748. return this.origins_[z];
  5749. }
  5750. };
  5751. /**
  5752. * Get the resolution for the given zoom level.
  5753. * @param {number} z Z.
  5754. * @return {number} Resolution.
  5755. * @api
  5756. */
  5757. ol.tilegrid.TileGrid.prototype.getResolution = function(z) {
  5758. return this.resolutions_[z];
  5759. };
  5760. /**
  5761. * Get the list of resolutions for the tile grid.
  5762. * @return {Array.<number>} Resolutions.
  5763. * @api
  5764. */
  5765. ol.tilegrid.TileGrid.prototype.getResolutions = function() {
  5766. return this.resolutions_;
  5767. };
  5768. /**
  5769. * @param {ol.TileCoord} tileCoord Tile coordinate.
  5770. * @param {ol.TileRange=} opt_tileRange Temporary ol.TileRange object.
  5771. * @param {ol.Extent=} opt_extent Temporary ol.Extent object.
  5772. * @return {ol.TileRange} Tile range.
  5773. */
  5774. ol.tilegrid.TileGrid.prototype.getTileCoordChildTileRange = function(tileCoord, opt_tileRange, opt_extent) {
  5775. if (tileCoord[0] < this.maxZoom) {
  5776. var tileCoordExtent = this.getTileCoordExtent(tileCoord, opt_extent);
  5777. return this.getTileRangeForExtentAndZ(
  5778. tileCoordExtent, tileCoord[0] + 1, opt_tileRange);
  5779. } else {
  5780. return null;
  5781. }
  5782. };
  5783. /**
  5784. * @param {number} z Z.
  5785. * @param {ol.TileRange} tileRange Tile range.
  5786. * @param {ol.Extent=} opt_extent Temporary ol.Extent object.
  5787. * @return {ol.Extent} Extent.
  5788. */
  5789. ol.tilegrid.TileGrid.prototype.getTileRangeExtent = function(z, tileRange, opt_extent) {
  5790. var origin = this.getOrigin(z);
  5791. var resolution = this.getResolution(z);
  5792. var tileSize = ol.size.toSize(this.getTileSize(z), this.tmpSize_);
  5793. var minX = origin[0] + tileRange.minX * tileSize[0] * resolution;
  5794. var maxX = origin[0] + (tileRange.maxX + 1) * tileSize[0] * resolution;
  5795. var minY = origin[1] + tileRange.minY * tileSize[1] * resolution;
  5796. var maxY = origin[1] + (tileRange.maxY + 1) * tileSize[1] * resolution;
  5797. return ol.extent.createOrUpdate(minX, minY, maxX, maxY, opt_extent);
  5798. };
  5799. /**
  5800. * @param {ol.Extent} extent Extent.
  5801. * @param {number} resolution Resolution.
  5802. * @param {ol.TileRange=} opt_tileRange Temporary tile range object.
  5803. * @return {ol.TileRange} Tile range.
  5804. */
  5805. ol.tilegrid.TileGrid.prototype.getTileRangeForExtentAndResolution = function(extent, resolution, opt_tileRange) {
  5806. var tileCoord = ol.tilegrid.TileGrid.tmpTileCoord_;
  5807. this.getTileCoordForXYAndResolution_(
  5808. extent[0], extent[1], resolution, false, tileCoord);
  5809. var minX = tileCoord[1];
  5810. var minY = tileCoord[2];
  5811. this.getTileCoordForXYAndResolution_(
  5812. extent[2], extent[3], resolution, true, tileCoord);
  5813. return ol.TileRange.createOrUpdate(
  5814. minX, tileCoord[1], minY, tileCoord[2], opt_tileRange);
  5815. };
  5816. /**
  5817. * @param {ol.Extent} extent Extent.
  5818. * @param {number} z Z.
  5819. * @param {ol.TileRange=} opt_tileRange Temporary tile range object.
  5820. * @return {ol.TileRange} Tile range.
  5821. */
  5822. ol.tilegrid.TileGrid.prototype.getTileRangeForExtentAndZ = function(extent, z, opt_tileRange) {
  5823. var resolution = this.getResolution(z);
  5824. return this.getTileRangeForExtentAndResolution(
  5825. extent, resolution, opt_tileRange);
  5826. };
  5827. /**
  5828. * @param {ol.TileCoord} tileCoord Tile coordinate.
  5829. * @return {ol.Coordinate} Tile center.
  5830. */
  5831. ol.tilegrid.TileGrid.prototype.getTileCoordCenter = function(tileCoord) {
  5832. var origin = this.getOrigin(tileCoord[0]);
  5833. var resolution = this.getResolution(tileCoord[0]);
  5834. var tileSize = ol.size.toSize(this.getTileSize(tileCoord[0]), this.tmpSize_);
  5835. return [
  5836. origin[0] + (tileCoord[1] + 0.5) * tileSize[0] * resolution,
  5837. origin[1] + (tileCoord[2] + 0.5) * tileSize[1] * resolution
  5838. ];
  5839. };
  5840. /**
  5841. * Get the extent of a tile coordinate.
  5842. *
  5843. * @param {ol.TileCoord} tileCoord Tile coordinate.
  5844. * @param {ol.Extent=} opt_extent Temporary extent object.
  5845. * @return {ol.Extent} Extent.
  5846. * @api
  5847. */
  5848. ol.tilegrid.TileGrid.prototype.getTileCoordExtent = function(tileCoord, opt_extent) {
  5849. var origin = this.getOrigin(tileCoord[0]);
  5850. var resolution = this.getResolution(tileCoord[0]);
  5851. var tileSize = ol.size.toSize(this.getTileSize(tileCoord[0]), this.tmpSize_);
  5852. var minX = origin[0] + tileCoord[1] * tileSize[0] * resolution;
  5853. var minY = origin[1] + tileCoord[2] * tileSize[1] * resolution;
  5854. var maxX = minX + tileSize[0] * resolution;
  5855. var maxY = minY + tileSize[1] * resolution;
  5856. return ol.extent.createOrUpdate(minX, minY, maxX, maxY, opt_extent);
  5857. };
  5858. /**
  5859. * Get the tile coordinate for the given map coordinate and resolution. This
  5860. * method considers that coordinates that intersect tile boundaries should be
  5861. * assigned the higher tile coordinate.
  5862. *
  5863. * @param {ol.Coordinate} coordinate Coordinate.
  5864. * @param {number} resolution Resolution.
  5865. * @param {ol.TileCoord=} opt_tileCoord Destination ol.TileCoord object.
  5866. * @return {ol.TileCoord} Tile coordinate.
  5867. * @api
  5868. */
  5869. ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndResolution = function(coordinate, resolution, opt_tileCoord) {
  5870. return this.getTileCoordForXYAndResolution_(
  5871. coordinate[0], coordinate[1], resolution, false, opt_tileCoord);
  5872. };
  5873. /**
  5874. * @param {number} x X.
  5875. * @param {number} y Y.
  5876. * @param {number} resolution Resolution.
  5877. * @param {boolean} reverseIntersectionPolicy Instead of letting edge
  5878. * intersections go to the higher tile coordinate, let edge intersections
  5879. * go to the lower tile coordinate.
  5880. * @param {ol.TileCoord=} opt_tileCoord Temporary ol.TileCoord object.
  5881. * @return {ol.TileCoord} Tile coordinate.
  5882. * @private
  5883. */
  5884. ol.tilegrid.TileGrid.prototype.getTileCoordForXYAndResolution_ = function(
  5885. x, y, resolution, reverseIntersectionPolicy, opt_tileCoord) {
  5886. var z = this.getZForResolution(resolution);
  5887. var scale = resolution / this.getResolution(z);
  5888. var origin = this.getOrigin(z);
  5889. var tileSize = ol.size.toSize(this.getTileSize(z), this.tmpSize_);
  5890. var adjustX = reverseIntersectionPolicy ? 0.5 : 0;
  5891. var adjustY = reverseIntersectionPolicy ? 0 : 0.5;
  5892. var xFromOrigin = Math.floor((x - origin[0]) / resolution + adjustX);
  5893. var yFromOrigin = Math.floor((y - origin[1]) / resolution + adjustY);
  5894. var tileCoordX = scale * xFromOrigin / tileSize[0];
  5895. var tileCoordY = scale * yFromOrigin / tileSize[1];
  5896. if (reverseIntersectionPolicy) {
  5897. tileCoordX = Math.ceil(tileCoordX) - 1;
  5898. tileCoordY = Math.ceil(tileCoordY) - 1;
  5899. } else {
  5900. tileCoordX = Math.floor(tileCoordX);
  5901. tileCoordY = Math.floor(tileCoordY);
  5902. }
  5903. return ol.tilecoord.createOrUpdate(z, tileCoordX, tileCoordY, opt_tileCoord);
  5904. };
  5905. /**
  5906. * Get a tile coordinate given a map coordinate and zoom level.
  5907. * @param {ol.Coordinate} coordinate Coordinate.
  5908. * @param {number} z Zoom level.
  5909. * @param {ol.TileCoord=} opt_tileCoord Destination ol.TileCoord object.
  5910. * @return {ol.TileCoord} Tile coordinate.
  5911. * @api
  5912. */
  5913. ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndZ = function(coordinate, z, opt_tileCoord) {
  5914. var resolution = this.getResolution(z);
  5915. return this.getTileCoordForXYAndResolution_(
  5916. coordinate[0], coordinate[1], resolution, false, opt_tileCoord);
  5917. };
  5918. /**
  5919. * @param {ol.TileCoord} tileCoord Tile coordinate.
  5920. * @return {number} Tile resolution.
  5921. */
  5922. ol.tilegrid.TileGrid.prototype.getTileCoordResolution = function(tileCoord) {
  5923. return this.resolutions_[tileCoord[0]];
  5924. };
  5925. /**
  5926. * Get the tile size for a zoom level. The type of the return value matches the
  5927. * `tileSize` or `tileSizes` that the tile grid was configured with. To always
  5928. * get an `ol.Size`, run the result through `ol.size.toSize()`.
  5929. * @param {number} z Z.
  5930. * @return {number|ol.Size} Tile size.
  5931. * @api
  5932. */
  5933. ol.tilegrid.TileGrid.prototype.getTileSize = function(z) {
  5934. if (this.tileSize_) {
  5935. return this.tileSize_;
  5936. } else {
  5937. return this.tileSizes_[z];
  5938. }
  5939. };
  5940. /**
  5941. * @param {number} z Zoom level.
  5942. * @return {ol.TileRange} Extent tile range for the specified zoom level.
  5943. */
  5944. ol.tilegrid.TileGrid.prototype.getFullTileRange = function(z) {
  5945. if (!this.fullTileRanges_) {
  5946. return null;
  5947. } else {
  5948. return this.fullTileRanges_[z];
  5949. }
  5950. };
  5951. /**
  5952. * @param {number} resolution Resolution.
  5953. * @param {number=} opt_direction If 0, the nearest resolution will be used.
  5954. * If 1, the nearest lower resolution will be used. If -1, the nearest
  5955. * higher resolution will be used. Default is 0.
  5956. * @return {number} Z.
  5957. * @api
  5958. */
  5959. ol.tilegrid.TileGrid.prototype.getZForResolution = function(
  5960. resolution, opt_direction) {
  5961. var z = ol.array.linearFindNearest(this.resolutions_, resolution,
  5962. opt_direction || 0);
  5963. return ol.math.clamp(z, this.minZoom, this.maxZoom);
  5964. };
  5965. /**
  5966. * @param {!ol.Extent} extent Extent for this tile grid.
  5967. * @private
  5968. */
  5969. ol.tilegrid.TileGrid.prototype.calculateTileRanges_ = function(extent) {
  5970. var length = this.resolutions_.length;
  5971. var fullTileRanges = new Array(length);
  5972. for (var z = this.minZoom; z < length; ++z) {
  5973. fullTileRanges[z] = this.getTileRangeForExtentAndZ(extent, z);
  5974. }
  5975. this.fullTileRanges_ = fullTileRanges;
  5976. };
  5977. goog.provide('ol.tilegrid');
  5978. goog.require('ol');
  5979. goog.require('ol.size');
  5980. goog.require('ol.extent');
  5981. goog.require('ol.extent.Corner');
  5982. goog.require('ol.obj');
  5983. goog.require('ol.proj');
  5984. goog.require('ol.proj.Units');
  5985. goog.require('ol.tilegrid.TileGrid');
  5986. /**
  5987. * @param {ol.proj.Projection} projection Projection.
  5988. * @return {!ol.tilegrid.TileGrid} Default tile grid for the passed projection.
  5989. */
  5990. ol.tilegrid.getForProjection = function(projection) {
  5991. var tileGrid = projection.getDefaultTileGrid();
  5992. if (!tileGrid) {
  5993. tileGrid = ol.tilegrid.createForProjection(projection);
  5994. projection.setDefaultTileGrid(tileGrid);
  5995. }
  5996. return tileGrid;
  5997. };
  5998. /**
  5999. * @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
  6000. * @param {ol.TileCoord} tileCoord Tile coordinate.
  6001. * @param {ol.proj.Projection} projection Projection.
  6002. * @return {ol.TileCoord} Tile coordinate.
  6003. */
  6004. ol.tilegrid.wrapX = function(tileGrid, tileCoord, projection) {
  6005. var z = tileCoord[0];
  6006. var center = tileGrid.getTileCoordCenter(tileCoord);
  6007. var projectionExtent = ol.tilegrid.extentFromProjection(projection);
  6008. if (!ol.extent.containsCoordinate(projectionExtent, center)) {
  6009. var worldWidth = ol.extent.getWidth(projectionExtent);
  6010. var worldsAway = Math.ceil((projectionExtent[0] - center[0]) / worldWidth);
  6011. center[0] += worldWidth * worldsAway;
  6012. return tileGrid.getTileCoordForCoordAndZ(center, z);
  6013. } else {
  6014. return tileCoord;
  6015. }
  6016. };
  6017. /**
  6018. * @param {ol.Extent} extent Extent.
  6019. * @param {number=} opt_maxZoom Maximum zoom level (default is
  6020. * ol.DEFAULT_MAX_ZOOM).
  6021. * @param {number|ol.Size=} opt_tileSize Tile size (default uses
  6022. * ol.DEFAULT_TILE_SIZE).
  6023. * @param {ol.extent.Corner=} opt_corner Extent corner (default is
  6024. * ol.extent.Corner.TOP_LEFT).
  6025. * @return {!ol.tilegrid.TileGrid} TileGrid instance.
  6026. */
  6027. ol.tilegrid.createForExtent = function(extent, opt_maxZoom, opt_tileSize, opt_corner) {
  6028. var corner = opt_corner !== undefined ?
  6029. opt_corner : ol.extent.Corner.TOP_LEFT;
  6030. var resolutions = ol.tilegrid.resolutionsFromExtent(
  6031. extent, opt_maxZoom, opt_tileSize);
  6032. return new ol.tilegrid.TileGrid({
  6033. extent: extent,
  6034. origin: ol.extent.getCorner(extent, corner),
  6035. resolutions: resolutions,
  6036. tileSize: opt_tileSize
  6037. });
  6038. };
  6039. /**
  6040. * Creates a tile grid with a standard XYZ tiling scheme.
  6041. * @param {olx.tilegrid.XYZOptions=} opt_options Tile grid options.
  6042. * @return {!ol.tilegrid.TileGrid} Tile grid instance.
  6043. * @api
  6044. */
  6045. ol.tilegrid.createXYZ = function(opt_options) {
  6046. var options = /** @type {olx.tilegrid.TileGridOptions} */ ({});
  6047. ol.obj.assign(options, opt_options !== undefined ?
  6048. opt_options : /** @type {olx.tilegrid.XYZOptions} */ ({}));
  6049. if (options.extent === undefined) {
  6050. options.extent = ol.proj.get('EPSG:3857').getExtent();
  6051. }
  6052. options.resolutions = ol.tilegrid.resolutionsFromExtent(
  6053. options.extent, options.maxZoom, options.tileSize);
  6054. delete options.maxZoom;
  6055. return new ol.tilegrid.TileGrid(options);
  6056. };
  6057. /**
  6058. * Create a resolutions array from an extent. A zoom factor of 2 is assumed.
  6059. * @param {ol.Extent} extent Extent.
  6060. * @param {number=} opt_maxZoom Maximum zoom level (default is
  6061. * ol.DEFAULT_MAX_ZOOM).
  6062. * @param {number|ol.Size=} opt_tileSize Tile size (default uses
  6063. * ol.DEFAULT_TILE_SIZE).
  6064. * @return {!Array.<number>} Resolutions array.
  6065. */
  6066. ol.tilegrid.resolutionsFromExtent = function(extent, opt_maxZoom, opt_tileSize) {
  6067. var maxZoom = opt_maxZoom !== undefined ?
  6068. opt_maxZoom : ol.DEFAULT_MAX_ZOOM;
  6069. var height = ol.extent.getHeight(extent);
  6070. var width = ol.extent.getWidth(extent);
  6071. var tileSize = ol.size.toSize(opt_tileSize !== undefined ?
  6072. opt_tileSize : ol.DEFAULT_TILE_SIZE);
  6073. var maxResolution = Math.max(
  6074. width / tileSize[0], height / tileSize[1]);
  6075. var length = maxZoom + 1;
  6076. var resolutions = new Array(length);
  6077. for (var z = 0; z < length; ++z) {
  6078. resolutions[z] = maxResolution / Math.pow(2, z);
  6079. }
  6080. return resolutions;
  6081. };
  6082. /**
  6083. * @param {ol.ProjectionLike} projection Projection.
  6084. * @param {number=} opt_maxZoom Maximum zoom level (default is
  6085. * ol.DEFAULT_MAX_ZOOM).
  6086. * @param {number|ol.Size=} opt_tileSize Tile size (default uses
  6087. * ol.DEFAULT_TILE_SIZE).
  6088. * @param {ol.extent.Corner=} opt_corner Extent corner (default is
  6089. * ol.extent.Corner.BOTTOM_LEFT).
  6090. * @return {!ol.tilegrid.TileGrid} TileGrid instance.
  6091. */
  6092. ol.tilegrid.createForProjection = function(projection, opt_maxZoom, opt_tileSize, opt_corner) {
  6093. var extent = ol.tilegrid.extentFromProjection(projection);
  6094. return ol.tilegrid.createForExtent(
  6095. extent, opt_maxZoom, opt_tileSize, opt_corner);
  6096. };
  6097. /**
  6098. * Generate a tile grid extent from a projection. If the projection has an
  6099. * extent, it is used. If not, a global extent is assumed.
  6100. * @param {ol.ProjectionLike} projection Projection.
  6101. * @return {ol.Extent} Extent.
  6102. */
  6103. ol.tilegrid.extentFromProjection = function(projection) {
  6104. projection = ol.proj.get(projection);
  6105. var extent = projection.getExtent();
  6106. if (!extent) {
  6107. var half = 180 * ol.proj.METERS_PER_UNIT[ol.proj.Units.DEGREES] /
  6108. projection.getMetersPerUnit();
  6109. extent = ol.extent.createOrUpdate(-half, -half, half, half);
  6110. }
  6111. return extent;
  6112. };
  6113. goog.provide('ol.Attribution');
  6114. goog.require('ol.TileRange');
  6115. goog.require('ol.math');
  6116. goog.require('ol.tilegrid');
  6117. /**
  6118. * @classdesc
  6119. * An attribution for a layer source.
  6120. *
  6121. * Example:
  6122. *
  6123. * source: new ol.source.OSM({
  6124. * attributions: [
  6125. * new ol.Attribution({
  6126. * html: 'All maps &copy; ' +
  6127. * '<a href="https://www.opencyclemap.org/">OpenCycleMap</a>'
  6128. * }),
  6129. * ol.source.OSM.ATTRIBUTION
  6130. * ],
  6131. * ..
  6132. *
  6133. * @constructor
  6134. * @param {olx.AttributionOptions} options Attribution options.
  6135. * @struct
  6136. * @api
  6137. */
  6138. ol.Attribution = function(options) {
  6139. /**
  6140. * @private
  6141. * @type {string}
  6142. */
  6143. this.html_ = options.html;
  6144. /**
  6145. * @private
  6146. * @type {Object.<string, Array.<ol.TileRange>>}
  6147. */
  6148. this.tileRanges_ = options.tileRanges ? options.tileRanges : null;
  6149. };
  6150. /**
  6151. * Get the attribution markup.
  6152. * @return {string} The attribution HTML.
  6153. * @api
  6154. */
  6155. ol.Attribution.prototype.getHTML = function() {
  6156. return this.html_;
  6157. };
  6158. /**
  6159. * @param {Object.<string, ol.TileRange>} tileRanges Tile ranges.
  6160. * @param {!ol.tilegrid.TileGrid} tileGrid Tile grid.
  6161. * @param {!ol.proj.Projection} projection Projection.
  6162. * @return {boolean} Intersects any tile range.
  6163. */
  6164. ol.Attribution.prototype.intersectsAnyTileRange = function(tileRanges, tileGrid, projection) {
  6165. if (!this.tileRanges_) {
  6166. return true;
  6167. }
  6168. var i, ii, tileRange, zKey;
  6169. for (zKey in tileRanges) {
  6170. if (!(zKey in this.tileRanges_)) {
  6171. continue;
  6172. }
  6173. tileRange = tileRanges[zKey];
  6174. var testTileRange;
  6175. for (i = 0, ii = this.tileRanges_[zKey].length; i < ii; ++i) {
  6176. testTileRange = this.tileRanges_[zKey][i];
  6177. if (testTileRange.intersects(tileRange)) {
  6178. return true;
  6179. }
  6180. var extentTileRange = tileGrid.getTileRangeForExtentAndZ(
  6181. ol.tilegrid.extentFromProjection(projection), parseInt(zKey, 10));
  6182. var width = extentTileRange.getWidth();
  6183. if (tileRange.minX < extentTileRange.minX ||
  6184. tileRange.maxX > extentTileRange.maxX) {
  6185. if (testTileRange.intersects(new ol.TileRange(
  6186. ol.math.modulo(tileRange.minX, width),
  6187. ol.math.modulo(tileRange.maxX, width),
  6188. tileRange.minY, tileRange.maxY))) {
  6189. return true;
  6190. }
  6191. if (tileRange.getWidth() > width &&
  6192. testTileRange.intersects(extentTileRange)) {
  6193. return true;
  6194. }
  6195. }
  6196. }
  6197. }
  6198. return false;
  6199. };
  6200. goog.provide('ol.CenterConstraint');
  6201. goog.require('ol.math');
  6202. /**
  6203. * @param {ol.Extent} extent Extent.
  6204. * @return {ol.CenterConstraintType} The constraint.
  6205. */
  6206. ol.CenterConstraint.createExtent = function(extent) {
  6207. return (
  6208. /**
  6209. * @param {ol.Coordinate|undefined} center Center.
  6210. * @return {ol.Coordinate|undefined} Center.
  6211. */
  6212. function(center) {
  6213. if (center) {
  6214. return [
  6215. ol.math.clamp(center[0], extent[0], extent[2]),
  6216. ol.math.clamp(center[1], extent[1], extent[3])
  6217. ];
  6218. } else {
  6219. return undefined;
  6220. }
  6221. });
  6222. };
  6223. /**
  6224. * @param {ol.Coordinate|undefined} center Center.
  6225. * @return {ol.Coordinate|undefined} Center.
  6226. */
  6227. ol.CenterConstraint.none = function(center) {
  6228. return center;
  6229. };
  6230. goog.provide('ol.CollectionEventType');
  6231. /**
  6232. * @enum {string}
  6233. */
  6234. ol.CollectionEventType = {
  6235. /**
  6236. * Triggered when an item is added to the collection.
  6237. * @event ol.Collection.Event#add
  6238. * @api
  6239. */
  6240. ADD: 'add',
  6241. /**
  6242. * Triggered when an item is removed from the collection.
  6243. * @event ol.Collection.Event#remove
  6244. * @api
  6245. */
  6246. REMOVE: 'remove'
  6247. };
  6248. goog.provide('ol.ObjectEventType');
  6249. /**
  6250. * @enum {string}
  6251. */
  6252. ol.ObjectEventType = {
  6253. /**
  6254. * Triggered when a property is changed.
  6255. * @event ol.Object.Event#propertychange
  6256. * @api
  6257. */
  6258. PROPERTYCHANGE: 'propertychange'
  6259. };
  6260. goog.provide('ol.events');
  6261. goog.require('ol.obj');
  6262. /**
  6263. * @param {ol.EventsKey} listenerObj Listener object.
  6264. * @return {ol.EventsListenerFunctionType} Bound listener.
  6265. */
  6266. ol.events.bindListener_ = function(listenerObj) {
  6267. var boundListener = function(evt) {
  6268. var listener = listenerObj.listener;
  6269. var bindTo = listenerObj.bindTo || listenerObj.target;
  6270. if (listenerObj.callOnce) {
  6271. ol.events.unlistenByKey(listenerObj);
  6272. }
  6273. return listener.call(bindTo, evt);
  6274. };
  6275. listenerObj.boundListener = boundListener;
  6276. return boundListener;
  6277. };
  6278. /**
  6279. * Finds the matching {@link ol.EventsKey} in the given listener
  6280. * array.
  6281. *
  6282. * @param {!Array<!ol.EventsKey>} listeners Array of listeners.
  6283. * @param {!Function} listener The listener function.
  6284. * @param {Object=} opt_this The `this` value inside the listener.
  6285. * @param {boolean=} opt_setDeleteIndex Set the deleteIndex on the matching
  6286. * listener, for {@link ol.events.unlistenByKey}.
  6287. * @return {ol.EventsKey|undefined} The matching listener object.
  6288. * @private
  6289. */
  6290. ol.events.findListener_ = function(listeners, listener, opt_this,
  6291. opt_setDeleteIndex) {
  6292. var listenerObj;
  6293. for (var i = 0, ii = listeners.length; i < ii; ++i) {
  6294. listenerObj = listeners[i];
  6295. if (listenerObj.listener === listener &&
  6296. listenerObj.bindTo === opt_this) {
  6297. if (opt_setDeleteIndex) {
  6298. listenerObj.deleteIndex = i;
  6299. }
  6300. return listenerObj;
  6301. }
  6302. }
  6303. return undefined;
  6304. };
  6305. /**
  6306. * @param {ol.EventTargetLike} target Target.
  6307. * @param {string} type Type.
  6308. * @return {Array.<ol.EventsKey>|undefined} Listeners.
  6309. */
  6310. ol.events.getListeners = function(target, type) {
  6311. var listenerMap = target.ol_lm;
  6312. return listenerMap ? listenerMap[type] : undefined;
  6313. };
  6314. /**
  6315. * Get the lookup of listeners. If one does not exist on the target, it is
  6316. * created.
  6317. * @param {ol.EventTargetLike} target Target.
  6318. * @return {!Object.<string, Array.<ol.EventsKey>>} Map of
  6319. * listeners by event type.
  6320. * @private
  6321. */
  6322. ol.events.getListenerMap_ = function(target) {
  6323. var listenerMap = target.ol_lm;
  6324. if (!listenerMap) {
  6325. listenerMap = target.ol_lm = {};
  6326. }
  6327. return listenerMap;
  6328. };
  6329. /**
  6330. * Clean up all listener objects of the given type. All properties on the
  6331. * listener objects will be removed, and if no listeners remain in the listener
  6332. * map, it will be removed from the target.
  6333. * @param {ol.EventTargetLike} target Target.
  6334. * @param {string} type Type.
  6335. * @private
  6336. */
  6337. ol.events.removeListeners_ = function(target, type) {
  6338. var listeners = ol.events.getListeners(target, type);
  6339. if (listeners) {
  6340. for (var i = 0, ii = listeners.length; i < ii; ++i) {
  6341. target.removeEventListener(type, listeners[i].boundListener);
  6342. ol.obj.clear(listeners[i]);
  6343. }
  6344. listeners.length = 0;
  6345. var listenerMap = target.ol_lm;
  6346. if (listenerMap) {
  6347. delete listenerMap[type];
  6348. if (Object.keys(listenerMap).length === 0) {
  6349. delete target.ol_lm;
  6350. }
  6351. }
  6352. }
  6353. };
  6354. /**
  6355. * Registers an event listener on an event target. Inspired by
  6356. * {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
  6357. *
  6358. * This function efficiently binds a `listener` to a `this` object, and returns
  6359. * a key for use with {@link ol.events.unlistenByKey}.
  6360. *
  6361. * @param {ol.EventTargetLike} target Event target.
  6362. * @param {string} type Event type.
  6363. * @param {ol.EventsListenerFunctionType} listener Listener.
  6364. * @param {Object=} opt_this Object referenced by the `this` keyword in the
  6365. * listener. Default is the `target`.
  6366. * @param {boolean=} opt_once If true, add the listener as one-off listener.
  6367. * @return {ol.EventsKey} Unique key for the listener.
  6368. */
  6369. ol.events.listen = function(target, type, listener, opt_this, opt_once) {
  6370. var listenerMap = ol.events.getListenerMap_(target);
  6371. var listeners = listenerMap[type];
  6372. if (!listeners) {
  6373. listeners = listenerMap[type] = [];
  6374. }
  6375. var listenerObj = ol.events.findListener_(listeners, listener, opt_this,
  6376. false);
  6377. if (listenerObj) {
  6378. if (!opt_once) {
  6379. // Turn one-off listener into a permanent one.
  6380. listenerObj.callOnce = false;
  6381. }
  6382. } else {
  6383. listenerObj = /** @type {ol.EventsKey} */ ({
  6384. bindTo: opt_this,
  6385. callOnce: !!opt_once,
  6386. listener: listener,
  6387. target: target,
  6388. type: type
  6389. });
  6390. target.addEventListener(type, ol.events.bindListener_(listenerObj));
  6391. listeners.push(listenerObj);
  6392. }
  6393. return listenerObj;
  6394. };
  6395. /**
  6396. * Registers a one-off event listener on an event target. Inspired by
  6397. * {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
  6398. *
  6399. * This function efficiently binds a `listener` as self-unregistering listener
  6400. * to a `this` object, and returns a key for use with
  6401. * {@link ol.events.unlistenByKey} in case the listener needs to be unregistered
  6402. * before it is called.
  6403. *
  6404. * When {@link ol.events.listen} is called with the same arguments after this
  6405. * function, the self-unregistering listener will be turned into a permanent
  6406. * listener.
  6407. *
  6408. * @param {ol.EventTargetLike} target Event target.
  6409. * @param {string} type Event type.
  6410. * @param {ol.EventsListenerFunctionType} listener Listener.
  6411. * @param {Object=} opt_this Object referenced by the `this` keyword in the
  6412. * listener. Default is the `target`.
  6413. * @return {ol.EventsKey} Key for unlistenByKey.
  6414. */
  6415. ol.events.listenOnce = function(target, type, listener, opt_this) {
  6416. return ol.events.listen(target, type, listener, opt_this, true);
  6417. };
  6418. /**
  6419. * Unregisters an event listener on an event target. Inspired by
  6420. * {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
  6421. *
  6422. * To return a listener, this function needs to be called with the exact same
  6423. * arguments that were used for a previous {@link ol.events.listen} call.
  6424. *
  6425. * @param {ol.EventTargetLike} target Event target.
  6426. * @param {string} type Event type.
  6427. * @param {ol.EventsListenerFunctionType} listener Listener.
  6428. * @param {Object=} opt_this Object referenced by the `this` keyword in the
  6429. * listener. Default is the `target`.
  6430. */
  6431. ol.events.unlisten = function(target, type, listener, opt_this) {
  6432. var listeners = ol.events.getListeners(target, type);
  6433. if (listeners) {
  6434. var listenerObj = ol.events.findListener_(listeners, listener, opt_this,
  6435. true);
  6436. if (listenerObj) {
  6437. ol.events.unlistenByKey(listenerObj);
  6438. }
  6439. }
  6440. };
  6441. /**
  6442. * Unregisters event listeners on an event target. Inspired by
  6443. * {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
  6444. *
  6445. * The argument passed to this function is the key returned from
  6446. * {@link ol.events.listen} or {@link ol.events.listenOnce}.
  6447. *
  6448. * @param {ol.EventsKey} key The key.
  6449. */
  6450. ol.events.unlistenByKey = function(key) {
  6451. if (key && key.target) {
  6452. key.target.removeEventListener(key.type, key.boundListener);
  6453. var listeners = ol.events.getListeners(key.target, key.type);
  6454. if (listeners) {
  6455. var i = 'deleteIndex' in key ? key.deleteIndex : listeners.indexOf(key);
  6456. if (i !== -1) {
  6457. listeners.splice(i, 1);
  6458. }
  6459. if (listeners.length === 0) {
  6460. ol.events.removeListeners_(key.target, key.type);
  6461. }
  6462. }
  6463. ol.obj.clear(key);
  6464. }
  6465. };
  6466. /**
  6467. * Unregisters all event listeners on an event target. Inspired by
  6468. * {@link https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html}
  6469. *
  6470. * @param {ol.EventTargetLike} target Target.
  6471. */
  6472. ol.events.unlistenAll = function(target) {
  6473. var listenerMap = ol.events.getListenerMap_(target);
  6474. for (var type in listenerMap) {
  6475. ol.events.removeListeners_(target, type);
  6476. }
  6477. };
  6478. goog.provide('ol.Disposable');
  6479. goog.require('ol');
  6480. /**
  6481. * Objects that need to clean up after themselves.
  6482. * @constructor
  6483. */
  6484. ol.Disposable = function() {};
  6485. /**
  6486. * The object has already been disposed.
  6487. * @type {boolean}
  6488. * @private
  6489. */
  6490. ol.Disposable.prototype.disposed_ = false;
  6491. /**
  6492. * Clean up.
  6493. */
  6494. ol.Disposable.prototype.dispose = function() {
  6495. if (!this.disposed_) {
  6496. this.disposed_ = true;
  6497. this.disposeInternal();
  6498. }
  6499. };
  6500. /**
  6501. * Extension point for disposable objects.
  6502. * @protected
  6503. */
  6504. ol.Disposable.prototype.disposeInternal = ol.nullFunction;
  6505. goog.provide('ol.events.Event');
  6506. /**
  6507. * @classdesc
  6508. * Stripped down implementation of the W3C DOM Level 2 Event interface.
  6509. * @see {@link https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-interface}
  6510. *
  6511. * This implementation only provides `type` and `target` properties, and
  6512. * `stopPropagation` and `preventDefault` methods. It is meant as base class
  6513. * for higher level events defined in the library, and works with
  6514. * {@link ol.events.EventTarget}.
  6515. *
  6516. * @constructor
  6517. * @implements {oli.events.Event}
  6518. * @param {string} type Type.
  6519. */
  6520. ol.events.Event = function(type) {
  6521. /**
  6522. * @type {boolean}
  6523. */
  6524. this.propagationStopped;
  6525. /**
  6526. * The event type.
  6527. * @type {string}
  6528. * @api
  6529. */
  6530. this.type = type;
  6531. /**
  6532. * The event target.
  6533. * @type {Object}
  6534. * @api
  6535. */
  6536. this.target = null;
  6537. };
  6538. /**
  6539. * Stop event propagation.
  6540. * @function
  6541. * @override
  6542. * @api
  6543. */
  6544. ol.events.Event.prototype.preventDefault =
  6545. /**
  6546. * Stop event propagation.
  6547. * @function
  6548. * @override
  6549. * @api
  6550. */
  6551. ol.events.Event.prototype.stopPropagation = function() {
  6552. this.propagationStopped = true;
  6553. };
  6554. /**
  6555. * @param {Event|ol.events.Event} evt Event
  6556. */
  6557. ol.events.Event.stopPropagation = function(evt) {
  6558. evt.stopPropagation();
  6559. };
  6560. /**
  6561. * @param {Event|ol.events.Event} evt Event
  6562. */
  6563. ol.events.Event.preventDefault = function(evt) {
  6564. evt.preventDefault();
  6565. };
  6566. goog.provide('ol.events.EventTarget');
  6567. goog.require('ol');
  6568. goog.require('ol.Disposable');
  6569. goog.require('ol.events');
  6570. goog.require('ol.events.Event');
  6571. /**
  6572. * @classdesc
  6573. * A simplified implementation of the W3C DOM Level 2 EventTarget interface.
  6574. * @see {@link https://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-EventTarget}
  6575. *
  6576. * There are two important simplifications compared to the specification:
  6577. *
  6578. * 1. The handling of `useCapture` in `addEventListener` and
  6579. * `removeEventListener`. There is no real capture model.
  6580. * 2. The handling of `stopPropagation` and `preventDefault` on `dispatchEvent`.
  6581. * There is no event target hierarchy. When a listener calls
  6582. * `stopPropagation` or `preventDefault` on an event object, it means that no
  6583. * more listeners after this one will be called. Same as when the listener
  6584. * returns false.
  6585. *
  6586. * @constructor
  6587. * @extends {ol.Disposable}
  6588. */
  6589. ol.events.EventTarget = function() {
  6590. ol.Disposable.call(this);
  6591. /**
  6592. * @private
  6593. * @type {!Object.<string, number>}
  6594. */
  6595. this.pendingRemovals_ = {};
  6596. /**
  6597. * @private
  6598. * @type {!Object.<string, number>}
  6599. */
  6600. this.dispatching_ = {};
  6601. /**
  6602. * @private
  6603. * @type {!Object.<string, Array.<ol.EventsListenerFunctionType>>}
  6604. */
  6605. this.listeners_ = {};
  6606. };
  6607. ol.inherits(ol.events.EventTarget, ol.Disposable);
  6608. /**
  6609. * @param {string} type Type.
  6610. * @param {ol.EventsListenerFunctionType} listener Listener.
  6611. */
  6612. ol.events.EventTarget.prototype.addEventListener = function(type, listener) {
  6613. var listeners = this.listeners_[type];
  6614. if (!listeners) {
  6615. listeners = this.listeners_[type] = [];
  6616. }
  6617. if (listeners.indexOf(listener) === -1) {
  6618. listeners.push(listener);
  6619. }
  6620. };
  6621. /**
  6622. * @param {{type: string,
  6623. * target: (EventTarget|ol.events.EventTarget|undefined)}|ol.events.Event|
  6624. * string} event Event or event type.
  6625. * @return {boolean|undefined} `false` if anyone called preventDefault on the
  6626. * event object or if any of the listeners returned false.
  6627. */
  6628. ol.events.EventTarget.prototype.dispatchEvent = function(event) {
  6629. var evt = typeof event === 'string' ? new ol.events.Event(event) : event;
  6630. var type = evt.type;
  6631. evt.target = this;
  6632. var listeners = this.listeners_[type];
  6633. var propagate;
  6634. if (listeners) {
  6635. if (!(type in this.dispatching_)) {
  6636. this.dispatching_[type] = 0;
  6637. this.pendingRemovals_[type] = 0;
  6638. }
  6639. ++this.dispatching_[type];
  6640. for (var i = 0, ii = listeners.length; i < ii; ++i) {
  6641. if (listeners[i].call(this, evt) === false || evt.propagationStopped) {
  6642. propagate = false;
  6643. break;
  6644. }
  6645. }
  6646. --this.dispatching_[type];
  6647. if (this.dispatching_[type] === 0) {
  6648. var pendingRemovals = this.pendingRemovals_[type];
  6649. delete this.pendingRemovals_[type];
  6650. while (pendingRemovals--) {
  6651. this.removeEventListener(type, ol.nullFunction);
  6652. }
  6653. delete this.dispatching_[type];
  6654. }
  6655. return propagate;
  6656. }
  6657. };
  6658. /**
  6659. * @inheritDoc
  6660. */
  6661. ol.events.EventTarget.prototype.disposeInternal = function() {
  6662. ol.events.unlistenAll(this);
  6663. };
  6664. /**
  6665. * Get the listeners for a specified event type. Listeners are returned in the
  6666. * order that they will be called in.
  6667. *
  6668. * @param {string} type Type.
  6669. * @return {Array.<ol.EventsListenerFunctionType>} Listeners.
  6670. */
  6671. ol.events.EventTarget.prototype.getListeners = function(type) {
  6672. return this.listeners_[type];
  6673. };
  6674. /**
  6675. * @param {string=} opt_type Type. If not provided,
  6676. * `true` will be returned if this EventTarget has any listeners.
  6677. * @return {boolean} Has listeners.
  6678. */
  6679. ol.events.EventTarget.prototype.hasListener = function(opt_type) {
  6680. return opt_type ?
  6681. opt_type in this.listeners_ :
  6682. Object.keys(this.listeners_).length > 0;
  6683. };
  6684. /**
  6685. * @param {string} type Type.
  6686. * @param {ol.EventsListenerFunctionType} listener Listener.
  6687. */
  6688. ol.events.EventTarget.prototype.removeEventListener = function(type, listener) {
  6689. var listeners = this.listeners_[type];
  6690. if (listeners) {
  6691. var index = listeners.indexOf(listener);
  6692. if (type in this.pendingRemovals_) {
  6693. // make listener a no-op, and remove later in #dispatchEvent()
  6694. listeners[index] = ol.nullFunction;
  6695. ++this.pendingRemovals_[type];
  6696. } else {
  6697. listeners.splice(index, 1);
  6698. if (listeners.length === 0) {
  6699. delete this.listeners_[type];
  6700. }
  6701. }
  6702. }
  6703. };
  6704. goog.provide('ol.events.EventType');
  6705. /**
  6706. * @enum {string}
  6707. * @const
  6708. */
  6709. ol.events.EventType = {
  6710. /**
  6711. * Generic change event. Triggered when the revision counter is increased.
  6712. * @event ol.events.Event#change
  6713. * @api
  6714. */
  6715. CHANGE: 'change',
  6716. CLICK: 'click',
  6717. DBLCLICK: 'dblclick',
  6718. DRAGENTER: 'dragenter',
  6719. DRAGOVER: 'dragover',
  6720. DROP: 'drop',
  6721. ERROR: 'error',
  6722. KEYDOWN: 'keydown',
  6723. KEYPRESS: 'keypress',
  6724. LOAD: 'load',
  6725. MOUSEDOWN: 'mousedown',
  6726. MOUSEMOVE: 'mousemove',
  6727. MOUSEOUT: 'mouseout',
  6728. MOUSEUP: 'mouseup',
  6729. MOUSEWHEEL: 'mousewheel',
  6730. MSPOINTERDOWN: 'MSPointerDown',
  6731. RESIZE: 'resize',
  6732. TOUCHSTART: 'touchstart',
  6733. TOUCHMOVE: 'touchmove',
  6734. TOUCHEND: 'touchend',
  6735. WHEEL: 'wheel'
  6736. };
  6737. goog.provide('ol.Observable');
  6738. goog.require('ol');
  6739. goog.require('ol.events');
  6740. goog.require('ol.events.EventTarget');
  6741. goog.require('ol.events.EventType');
  6742. /**
  6743. * @classdesc
  6744. * Abstract base class; normally only used for creating subclasses and not
  6745. * instantiated in apps.
  6746. * An event target providing convenient methods for listener registration
  6747. * and unregistration. A generic `change` event is always available through
  6748. * {@link ol.Observable#changed}.
  6749. *
  6750. * @constructor
  6751. * @extends {ol.events.EventTarget}
  6752. * @fires ol.events.Event
  6753. * @struct
  6754. * @api
  6755. */
  6756. ol.Observable = function() {
  6757. ol.events.EventTarget.call(this);
  6758. /**
  6759. * @private
  6760. * @type {number}
  6761. */
  6762. this.revision_ = 0;
  6763. };
  6764. ol.inherits(ol.Observable, ol.events.EventTarget);
  6765. /**
  6766. * Removes an event listener using the key returned by `on()` or `once()`.
  6767. * @param {ol.EventsKey|Array.<ol.EventsKey>} key The key returned by `on()`
  6768. * or `once()` (or an array of keys).
  6769. * @api
  6770. */
  6771. ol.Observable.unByKey = function(key) {
  6772. if (Array.isArray(key)) {
  6773. for (var i = 0, ii = key.length; i < ii; ++i) {
  6774. ol.events.unlistenByKey(key[i]);
  6775. }
  6776. } else {
  6777. ol.events.unlistenByKey(/** @type {ol.EventsKey} */ (key));
  6778. }
  6779. };
  6780. /**
  6781. * Increases the revision counter and dispatches a 'change' event.
  6782. * @api
  6783. */
  6784. ol.Observable.prototype.changed = function() {
  6785. ++this.revision_;
  6786. this.dispatchEvent(ol.events.EventType.CHANGE);
  6787. };
  6788. /**
  6789. * Dispatches an event and calls all listeners listening for events
  6790. * of this type. The event parameter can either be a string or an
  6791. * Object with a `type` property.
  6792. *
  6793. * @param {{type: string,
  6794. * target: (EventTarget|ol.events.EventTarget|undefined)}|ol.events.Event|
  6795. * string} event Event object.
  6796. * @function
  6797. * @api
  6798. */
  6799. ol.Observable.prototype.dispatchEvent;
  6800. /**
  6801. * Get the version number for this object. Each time the object is modified,
  6802. * its version number will be incremented.
  6803. * @return {number} Revision.
  6804. * @api
  6805. */
  6806. ol.Observable.prototype.getRevision = function() {
  6807. return this.revision_;
  6808. };
  6809. /**
  6810. * Listen for a certain type of event.
  6811. * @param {string|Array.<string>} type The event type or array of event types.
  6812. * @param {function(?): ?} listener The listener function.
  6813. * @param {Object=} opt_this The object to use as `this` in `listener`.
  6814. * @return {ol.EventsKey|Array.<ol.EventsKey>} Unique key for the listener. If
  6815. * called with an array of event types as the first argument, the return
  6816. * will be an array of keys.
  6817. * @api
  6818. */
  6819. ol.Observable.prototype.on = function(type, listener, opt_this) {
  6820. if (Array.isArray(type)) {
  6821. var len = type.length;
  6822. var keys = new Array(len);
  6823. for (var i = 0; i < len; ++i) {
  6824. keys[i] = ol.events.listen(this, type[i], listener, opt_this);
  6825. }
  6826. return keys;
  6827. } else {
  6828. return ol.events.listen(
  6829. this, /** @type {string} */ (type), listener, opt_this);
  6830. }
  6831. };
  6832. /**
  6833. * Listen once for a certain type of event.
  6834. * @param {string|Array.<string>} type The event type or array of event types.
  6835. * @param {function(?): ?} listener The listener function.
  6836. * @param {Object=} opt_this The object to use as `this` in `listener`.
  6837. * @return {ol.EventsKey|Array.<ol.EventsKey>} Unique key for the listener. If
  6838. * called with an array of event types as the first argument, the return
  6839. * will be an array of keys.
  6840. * @api
  6841. */
  6842. ol.Observable.prototype.once = function(type, listener, opt_this) {
  6843. if (Array.isArray(type)) {
  6844. var len = type.length;
  6845. var keys = new Array(len);
  6846. for (var i = 0; i < len; ++i) {
  6847. keys[i] = ol.events.listenOnce(this, type[i], listener, opt_this);
  6848. }
  6849. return keys;
  6850. } else {
  6851. return ol.events.listenOnce(
  6852. this, /** @type {string} */ (type), listener, opt_this);
  6853. }
  6854. };
  6855. /**
  6856. * Unlisten for a certain type of event.
  6857. * @param {string|Array.<string>} type The event type or array of event types.
  6858. * @param {function(?): ?} listener The listener function.
  6859. * @param {Object=} opt_this The object which was used as `this` by the
  6860. * `listener`.
  6861. * @api
  6862. */
  6863. ol.Observable.prototype.un = function(type, listener, opt_this) {
  6864. if (Array.isArray(type)) {
  6865. for (var i = 0, ii = type.length; i < ii; ++i) {
  6866. ol.events.unlisten(this, type[i], listener, opt_this);
  6867. }
  6868. return;
  6869. } else {
  6870. ol.events.unlisten(this, /** @type {string} */ (type), listener, opt_this);
  6871. }
  6872. };
  6873. goog.provide('ol.Object');
  6874. goog.require('ol');
  6875. goog.require('ol.ObjectEventType');
  6876. goog.require('ol.Observable');
  6877. goog.require('ol.events.Event');
  6878. goog.require('ol.obj');
  6879. /**
  6880. * @classdesc
  6881. * Abstract base class; normally only used for creating subclasses and not
  6882. * instantiated in apps.
  6883. * Most non-trivial classes inherit from this.
  6884. *
  6885. * This extends {@link ol.Observable} with observable properties, where each
  6886. * property is observable as well as the object as a whole.
  6887. *
  6888. * Classes that inherit from this have pre-defined properties, to which you can
  6889. * add your owns. The pre-defined properties are listed in this documentation as
  6890. * 'Observable Properties', and have their own accessors; for example,
  6891. * {@link ol.Map} has a `target` property, accessed with `getTarget()` and
  6892. * changed with `setTarget()`. Not all properties are however settable. There
  6893. * are also general-purpose accessors `get()` and `set()`. For example,
  6894. * `get('target')` is equivalent to `getTarget()`.
  6895. *
  6896. * The `set` accessors trigger a change event, and you can monitor this by
  6897. * registering a listener. For example, {@link ol.View} has a `center`
  6898. * property, so `view.on('change:center', function(evt) {...});` would call the
  6899. * function whenever the value of the center property changes. Within the
  6900. * function, `evt.target` would be the view, so `evt.target.getCenter()` would
  6901. * return the new center.
  6902. *
  6903. * You can add your own observable properties with
  6904. * `object.set('prop', 'value')`, and retrieve that with `object.get('prop')`.
  6905. * You can listen for changes on that property value with
  6906. * `object.on('change:prop', listener)`. You can get a list of all
  6907. * properties with {@link ol.Object#getProperties object.getProperties()}.
  6908. *
  6909. * Note that the observable properties are separate from standard JS properties.
  6910. * You can, for example, give your map object a title with
  6911. * `map.title='New title'` and with `map.set('title', 'Another title')`. The
  6912. * first will be a `hasOwnProperty`; the second will appear in
  6913. * `getProperties()`. Only the second is observable.
  6914. *
  6915. * Properties can be deleted by using the unset method. E.g.
  6916. * object.unset('foo').
  6917. *
  6918. * @constructor
  6919. * @extends {ol.Observable}
  6920. * @param {Object.<string, *>=} opt_values An object with key-value pairs.
  6921. * @fires ol.Object.Event
  6922. * @api
  6923. */
  6924. ol.Object = function(opt_values) {
  6925. ol.Observable.call(this);
  6926. // Call ol.getUid to ensure that the order of objects' ids is the same as
  6927. // the order in which they were created. This also helps to ensure that
  6928. // object properties are always added in the same order, which helps many
  6929. // JavaScript engines generate faster code.
  6930. ol.getUid(this);
  6931. /**
  6932. * @private
  6933. * @type {!Object.<string, *>}
  6934. */
  6935. this.values_ = {};
  6936. if (opt_values !== undefined) {
  6937. this.setProperties(opt_values);
  6938. }
  6939. };
  6940. ol.inherits(ol.Object, ol.Observable);
  6941. /**
  6942. * @private
  6943. * @type {Object.<string, string>}
  6944. */
  6945. ol.Object.changeEventTypeCache_ = {};
  6946. /**
  6947. * @param {string} key Key name.
  6948. * @return {string} Change name.
  6949. */
  6950. ol.Object.getChangeEventType = function(key) {
  6951. return ol.Object.changeEventTypeCache_.hasOwnProperty(key) ?
  6952. ol.Object.changeEventTypeCache_[key] :
  6953. (ol.Object.changeEventTypeCache_[key] = 'change:' + key);
  6954. };
  6955. /**
  6956. * Gets a value.
  6957. * @param {string} key Key name.
  6958. * @return {*} Value.
  6959. * @api
  6960. */
  6961. ol.Object.prototype.get = function(key) {
  6962. var value;
  6963. if (this.values_.hasOwnProperty(key)) {
  6964. value = this.values_[key];
  6965. }
  6966. return value;
  6967. };
  6968. /**
  6969. * Get a list of object property names.
  6970. * @return {Array.<string>} List of property names.
  6971. * @api
  6972. */
  6973. ol.Object.prototype.getKeys = function() {
  6974. return Object.keys(this.values_);
  6975. };
  6976. /**
  6977. * Get an object of all property names and values.
  6978. * @return {Object.<string, *>} Object.
  6979. * @api
  6980. */
  6981. ol.Object.prototype.getProperties = function() {
  6982. return ol.obj.assign({}, this.values_);
  6983. };
  6984. /**
  6985. * @param {string} key Key name.
  6986. * @param {*} oldValue Old value.
  6987. */
  6988. ol.Object.prototype.notify = function(key, oldValue) {
  6989. var eventType;
  6990. eventType = ol.Object.getChangeEventType(key);
  6991. this.dispatchEvent(new ol.Object.Event(eventType, key, oldValue));
  6992. eventType = ol.ObjectEventType.PROPERTYCHANGE;
  6993. this.dispatchEvent(new ol.Object.Event(eventType, key, oldValue));
  6994. };
  6995. /**
  6996. * Sets a value.
  6997. * @param {string} key Key name.
  6998. * @param {*} value Value.
  6999. * @param {boolean=} opt_silent Update without triggering an event.
  7000. * @api
  7001. */
  7002. ol.Object.prototype.set = function(key, value, opt_silent) {
  7003. if (opt_silent) {
  7004. this.values_[key] = value;
  7005. } else {
  7006. var oldValue = this.values_[key];
  7007. this.values_[key] = value;
  7008. if (oldValue !== value) {
  7009. this.notify(key, oldValue);
  7010. }
  7011. }
  7012. };
  7013. /**
  7014. * Sets a collection of key-value pairs. Note that this changes any existing
  7015. * properties and adds new ones (it does not remove any existing properties).
  7016. * @param {Object.<string, *>} values Values.
  7017. * @param {boolean=} opt_silent Update without triggering an event.
  7018. * @api
  7019. */
  7020. ol.Object.prototype.setProperties = function(values, opt_silent) {
  7021. var key;
  7022. for (key in values) {
  7023. this.set(key, values[key], opt_silent);
  7024. }
  7025. };
  7026. /**
  7027. * Unsets a property.
  7028. * @param {string} key Key name.
  7029. * @param {boolean=} opt_silent Unset without triggering an event.
  7030. * @api
  7031. */
  7032. ol.Object.prototype.unset = function(key, opt_silent) {
  7033. if (key in this.values_) {
  7034. var oldValue = this.values_[key];
  7035. delete this.values_[key];
  7036. if (!opt_silent) {
  7037. this.notify(key, oldValue);
  7038. }
  7039. }
  7040. };
  7041. /**
  7042. * @classdesc
  7043. * Events emitted by {@link ol.Object} instances are instances of this type.
  7044. *
  7045. * @param {string} type The event type.
  7046. * @param {string} key The property name.
  7047. * @param {*} oldValue The old value for `key`.
  7048. * @extends {ol.events.Event}
  7049. * @implements {oli.Object.Event}
  7050. * @constructor
  7051. */
  7052. ol.Object.Event = function(type, key, oldValue) {
  7053. ol.events.Event.call(this, type);
  7054. /**
  7055. * The name of the property whose value is changing.
  7056. * @type {string}
  7057. * @api
  7058. */
  7059. this.key = key;
  7060. /**
  7061. * The old value. To get the new value use `e.target.get(e.key)` where
  7062. * `e` is the event object.
  7063. * @type {*}
  7064. * @api
  7065. */
  7066. this.oldValue = oldValue;
  7067. };
  7068. ol.inherits(ol.Object.Event, ol.events.Event);
  7069. /**
  7070. * An implementation of Google Maps' MVCArray.
  7071. * @see https://developers.google.com/maps/documentation/javascript/reference
  7072. */
  7073. goog.provide('ol.Collection');
  7074. goog.require('ol');
  7075. goog.require('ol.AssertionError');
  7076. goog.require('ol.CollectionEventType');
  7077. goog.require('ol.Object');
  7078. goog.require('ol.events.Event');
  7079. /**
  7080. * @classdesc
  7081. * An expanded version of standard JS Array, adding convenience methods for
  7082. * manipulation. Add and remove changes to the Collection trigger a Collection
  7083. * event. Note that this does not cover changes to the objects _within_ the
  7084. * Collection; they trigger events on the appropriate object, not on the
  7085. * Collection as a whole.
  7086. *
  7087. * @constructor
  7088. * @extends {ol.Object}
  7089. * @fires ol.Collection.Event
  7090. * @param {Array.<T>=} opt_array Array.
  7091. * @param {olx.CollectionOptions=} opt_options Collection options.
  7092. * @template T
  7093. * @api
  7094. */
  7095. ol.Collection = function(opt_array, opt_options) {
  7096. ol.Object.call(this);
  7097. var options = opt_options || {};
  7098. /**
  7099. * @private
  7100. * @type {boolean}
  7101. */
  7102. this.unique_ = !!options.unique;
  7103. /**
  7104. * @private
  7105. * @type {!Array.<T>}
  7106. */
  7107. this.array_ = opt_array ? opt_array : [];
  7108. if (this.unique_) {
  7109. for (var i = 0, ii = this.array_.length; i < ii; ++i) {
  7110. this.assertUnique_(this.array_[i], i);
  7111. }
  7112. }
  7113. this.updateLength_();
  7114. };
  7115. ol.inherits(ol.Collection, ol.Object);
  7116. /**
  7117. * Remove all elements from the collection.
  7118. * @api
  7119. */
  7120. ol.Collection.prototype.clear = function() {
  7121. while (this.getLength() > 0) {
  7122. this.pop();
  7123. }
  7124. };
  7125. /**
  7126. * Add elements to the collection. This pushes each item in the provided array
  7127. * to the end of the collection.
  7128. * @param {!Array.<T>} arr Array.
  7129. * @return {ol.Collection.<T>} This collection.
  7130. * @api
  7131. */
  7132. ol.Collection.prototype.extend = function(arr) {
  7133. var i, ii;
  7134. for (i = 0, ii = arr.length; i < ii; ++i) {
  7135. this.push(arr[i]);
  7136. }
  7137. return this;
  7138. };
  7139. /**
  7140. * Iterate over each element, calling the provided callback.
  7141. * @param {function(this: S, T, number, Array.<T>): *} f The function to call
  7142. * for every element. This function takes 3 arguments (the element, the
  7143. * index and the array). The return value is ignored.
  7144. * @param {S=} opt_this The object to use as `this` in `f`.
  7145. * @template S
  7146. * @api
  7147. */
  7148. ol.Collection.prototype.forEach = function(f, opt_this) {
  7149. var fn = (opt_this) ? f.bind(opt_this) : f;
  7150. var array = this.array_;
  7151. for (var i = 0, ii = array.length; i < ii; ++i) {
  7152. fn(array[i], i, array);
  7153. }
  7154. };
  7155. /**
  7156. * Get a reference to the underlying Array object. Warning: if the array
  7157. * is mutated, no events will be dispatched by the collection, and the
  7158. * collection's "length" property won't be in sync with the actual length
  7159. * of the array.
  7160. * @return {!Array.<T>} Array.
  7161. * @api
  7162. */
  7163. ol.Collection.prototype.getArray = function() {
  7164. return this.array_;
  7165. };
  7166. /**
  7167. * Get the element at the provided index.
  7168. * @param {number} index Index.
  7169. * @return {T} Element.
  7170. * @api
  7171. */
  7172. ol.Collection.prototype.item = function(index) {
  7173. return this.array_[index];
  7174. };
  7175. /**
  7176. * Get the length of this collection.
  7177. * @return {number} The length of the array.
  7178. * @observable
  7179. * @api
  7180. */
  7181. ol.Collection.prototype.getLength = function() {
  7182. return /** @type {number} */ (this.get(ol.Collection.Property_.LENGTH));
  7183. };
  7184. /**
  7185. * Insert an element at the provided index.
  7186. * @param {number} index Index.
  7187. * @param {T} elem Element.
  7188. * @api
  7189. */
  7190. ol.Collection.prototype.insertAt = function(index, elem) {
  7191. if (this.unique_) {
  7192. this.assertUnique_(elem);
  7193. }
  7194. this.array_.splice(index, 0, elem);
  7195. this.updateLength_();
  7196. this.dispatchEvent(
  7197. new ol.Collection.Event(ol.CollectionEventType.ADD, elem));
  7198. };
  7199. /**
  7200. * Remove the last element of the collection and return it.
  7201. * Return `undefined` if the collection is empty.
  7202. * @return {T|undefined} Element.
  7203. * @api
  7204. */
  7205. ol.Collection.prototype.pop = function() {
  7206. return this.removeAt(this.getLength() - 1);
  7207. };
  7208. /**
  7209. * Insert the provided element at the end of the collection.
  7210. * @param {T} elem Element.
  7211. * @return {number} New length of the collection.
  7212. * @api
  7213. */
  7214. ol.Collection.prototype.push = function(elem) {
  7215. if (this.unique_) {
  7216. this.assertUnique_(elem);
  7217. }
  7218. var n = this.getLength();
  7219. this.insertAt(n, elem);
  7220. return this.getLength();
  7221. };
  7222. /**
  7223. * Remove the first occurrence of an element from the collection.
  7224. * @param {T} elem Element.
  7225. * @return {T|undefined} The removed element or undefined if none found.
  7226. * @api
  7227. */
  7228. ol.Collection.prototype.remove = function(elem) {
  7229. var arr = this.array_;
  7230. var i, ii;
  7231. for (i = 0, ii = arr.length; i < ii; ++i) {
  7232. if (arr[i] === elem) {
  7233. return this.removeAt(i);
  7234. }
  7235. }
  7236. return undefined;
  7237. };
  7238. /**
  7239. * Remove the element at the provided index and return it.
  7240. * Return `undefined` if the collection does not contain this index.
  7241. * @param {number} index Index.
  7242. * @return {T|undefined} Value.
  7243. * @api
  7244. */
  7245. ol.Collection.prototype.removeAt = function(index) {
  7246. var prev = this.array_[index];
  7247. this.array_.splice(index, 1);
  7248. this.updateLength_();
  7249. this.dispatchEvent(
  7250. new ol.Collection.Event(ol.CollectionEventType.REMOVE, prev));
  7251. return prev;
  7252. };
  7253. /**
  7254. * Set the element at the provided index.
  7255. * @param {number} index Index.
  7256. * @param {T} elem Element.
  7257. * @api
  7258. */
  7259. ol.Collection.prototype.setAt = function(index, elem) {
  7260. var n = this.getLength();
  7261. if (index < n) {
  7262. if (this.unique_) {
  7263. this.assertUnique_(elem, index);
  7264. }
  7265. var prev = this.array_[index];
  7266. this.array_[index] = elem;
  7267. this.dispatchEvent(
  7268. new ol.Collection.Event(ol.CollectionEventType.REMOVE, prev));
  7269. this.dispatchEvent(
  7270. new ol.Collection.Event(ol.CollectionEventType.ADD, elem));
  7271. } else {
  7272. var j;
  7273. for (j = n; j < index; ++j) {
  7274. this.insertAt(j, undefined);
  7275. }
  7276. this.insertAt(index, elem);
  7277. }
  7278. };
  7279. /**
  7280. * @private
  7281. */
  7282. ol.Collection.prototype.updateLength_ = function() {
  7283. this.set(ol.Collection.Property_.LENGTH, this.array_.length);
  7284. };
  7285. /**
  7286. * @private
  7287. * @param {T} elem Element.
  7288. * @param {number=} opt_except Optional index to ignore.
  7289. */
  7290. ol.Collection.prototype.assertUnique_ = function(elem, opt_except) {
  7291. for (var i = 0, ii = this.array_.length; i < ii; ++i) {
  7292. if (this.array_[i] === elem && i !== opt_except) {
  7293. throw new ol.AssertionError(58);
  7294. }
  7295. }
  7296. };
  7297. /**
  7298. * @enum {string}
  7299. * @private
  7300. */
  7301. ol.Collection.Property_ = {
  7302. LENGTH: 'length'
  7303. };
  7304. /**
  7305. * @classdesc
  7306. * Events emitted by {@link ol.Collection} instances are instances of this
  7307. * type.
  7308. *
  7309. * @constructor
  7310. * @extends {ol.events.Event}
  7311. * @implements {oli.Collection.Event}
  7312. * @param {ol.CollectionEventType} type Type.
  7313. * @param {*=} opt_element Element.
  7314. */
  7315. ol.Collection.Event = function(type, opt_element) {
  7316. ol.events.Event.call(this, type);
  7317. /**
  7318. * The element that is added to or removed from the collection.
  7319. * @type {*}
  7320. * @api
  7321. */
  7322. this.element = opt_element;
  7323. };
  7324. ol.inherits(ol.Collection.Event, ol.events.Event);
  7325. goog.provide('ol.color');
  7326. goog.require('ol.asserts');
  7327. goog.require('ol.math');
  7328. /**
  7329. * This RegExp matches # followed by 3 or 6 hex digits.
  7330. * @const
  7331. * @type {RegExp}
  7332. * @private
  7333. */
  7334. ol.color.HEX_COLOR_RE_ = /^#(?:[0-9a-f]{3}){1,2}$/i;
  7335. /**
  7336. * Regular expression for matching potential named color style strings.
  7337. * @const
  7338. * @type {RegExp}
  7339. * @private
  7340. */
  7341. ol.color.NAMED_COLOR_RE_ = /^([a-z]*)$/i;
  7342. /**
  7343. * Return the color as an array. This function maintains a cache of calculated
  7344. * arrays which means the result should not be modified.
  7345. * @param {ol.Color|string} color Color.
  7346. * @return {ol.Color} Color.
  7347. * @api
  7348. */
  7349. ol.color.asArray = function(color) {
  7350. if (Array.isArray(color)) {
  7351. return color;
  7352. } else {
  7353. return ol.color.fromString(/** @type {string} */ (color));
  7354. }
  7355. };
  7356. /**
  7357. * Return the color as an rgba string.
  7358. * @param {ol.Color|string} color Color.
  7359. * @return {string} Rgba string.
  7360. * @api
  7361. */
  7362. ol.color.asString = function(color) {
  7363. if (typeof color === 'string') {
  7364. return color;
  7365. } else {
  7366. return ol.color.toString(color);
  7367. }
  7368. };
  7369. /**
  7370. * Return named color as an rgba string.
  7371. * @param {string} color Named color.
  7372. * @return {string} Rgb string.
  7373. */
  7374. ol.color.fromNamed = function(color) {
  7375. var el = document.createElement('div');
  7376. el.style.color = color;
  7377. document.body.appendChild(el);
  7378. var rgb = getComputedStyle(el).color;
  7379. document.body.removeChild(el);
  7380. return rgb;
  7381. };
  7382. /**
  7383. * @param {string} s String.
  7384. * @return {ol.Color} Color.
  7385. */
  7386. ol.color.fromString = (
  7387. function() {
  7388. // We maintain a small cache of parsed strings. To provide cheap LRU-like
  7389. // semantics, whenever the cache grows too large we simply delete an
  7390. // arbitrary 25% of the entries.
  7391. /**
  7392. * @const
  7393. * @type {number}
  7394. */
  7395. var MAX_CACHE_SIZE = 1024;
  7396. /**
  7397. * @type {Object.<string, ol.Color>}
  7398. */
  7399. var cache = {};
  7400. /**
  7401. * @type {number}
  7402. */
  7403. var cacheSize = 0;
  7404. return (
  7405. /**
  7406. * @param {string} s String.
  7407. * @return {ol.Color} Color.
  7408. */
  7409. function(s) {
  7410. var color;
  7411. if (cache.hasOwnProperty(s)) {
  7412. color = cache[s];
  7413. } else {
  7414. if (cacheSize >= MAX_CACHE_SIZE) {
  7415. var i = 0;
  7416. var key;
  7417. for (key in cache) {
  7418. if ((i++ & 3) === 0) {
  7419. delete cache[key];
  7420. --cacheSize;
  7421. }
  7422. }
  7423. }
  7424. color = ol.color.fromStringInternal_(s);
  7425. cache[s] = color;
  7426. ++cacheSize;
  7427. }
  7428. return color;
  7429. });
  7430. })();
  7431. /**
  7432. * @param {string} s String.
  7433. * @private
  7434. * @return {ol.Color} Color.
  7435. */
  7436. ol.color.fromStringInternal_ = function(s) {
  7437. var r, g, b, a, color, parts;
  7438. if (ol.color.NAMED_COLOR_RE_.exec(s)) {
  7439. s = ol.color.fromNamed(s);
  7440. }
  7441. if (ol.color.HEX_COLOR_RE_.exec(s)) { // hex
  7442. var n = s.length - 1; // number of hex digits
  7443. ol.asserts.assert(n == 3 || n == 6, 54); // Hex color should have 3 or 6 digits
  7444. var d = n == 3 ? 1 : 2; // number of digits per channel
  7445. r = parseInt(s.substr(1 + 0 * d, d), 16);
  7446. g = parseInt(s.substr(1 + 1 * d, d), 16);
  7447. b = parseInt(s.substr(1 + 2 * d, d), 16);
  7448. if (d == 1) {
  7449. r = (r << 4) + r;
  7450. g = (g << 4) + g;
  7451. b = (b << 4) + b;
  7452. }
  7453. a = 1;
  7454. color = [r, g, b, a];
  7455. } else if (s.indexOf('rgba(') == 0) { // rgba()
  7456. parts = s.slice(5, -1).split(',').map(Number);
  7457. color = ol.color.normalize(parts);
  7458. } else if (s.indexOf('rgb(') == 0) { // rgb()
  7459. parts = s.slice(4, -1).split(',').map(Number);
  7460. parts.push(1);
  7461. color = ol.color.normalize(parts);
  7462. } else {
  7463. ol.asserts.assert(false, 14); // Invalid color
  7464. }
  7465. return /** @type {ol.Color} */ (color);
  7466. };
  7467. /**
  7468. * @param {ol.Color} color Color.
  7469. * @param {ol.Color=} opt_color Color.
  7470. * @return {ol.Color} Clamped color.
  7471. */
  7472. ol.color.normalize = function(color, opt_color) {
  7473. var result = opt_color || [];
  7474. result[0] = ol.math.clamp((color[0] + 0.5) | 0, 0, 255);
  7475. result[1] = ol.math.clamp((color[1] + 0.5) | 0, 0, 255);
  7476. result[2] = ol.math.clamp((color[2] + 0.5) | 0, 0, 255);
  7477. result[3] = ol.math.clamp(color[3], 0, 1);
  7478. return result;
  7479. };
  7480. /**
  7481. * @param {ol.Color} color Color.
  7482. * @return {string} String.
  7483. */
  7484. ol.color.toString = function(color) {
  7485. var r = color[0];
  7486. if (r != (r | 0)) {
  7487. r = (r + 0.5) | 0;
  7488. }
  7489. var g = color[1];
  7490. if (g != (g | 0)) {
  7491. g = (g + 0.5) | 0;
  7492. }
  7493. var b = color[2];
  7494. if (b != (b | 0)) {
  7495. b = (b + 0.5) | 0;
  7496. }
  7497. var a = color[3] === undefined ? 1 : color[3];
  7498. return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
  7499. };
  7500. goog.provide('ol.colorlike');
  7501. goog.require('ol.color');
  7502. /**
  7503. * @param {ol.Color|ol.ColorLike} color Color.
  7504. * @return {ol.ColorLike} The color as an ol.ColorLike
  7505. * @api
  7506. */
  7507. ol.colorlike.asColorLike = function(color) {
  7508. if (ol.colorlike.isColorLike(color)) {
  7509. return /** @type {string|CanvasPattern|CanvasGradient} */ (color);
  7510. } else {
  7511. return ol.color.asString(/** @type {ol.Color} */ (color));
  7512. }
  7513. };
  7514. /**
  7515. * @param {?} color The value that is potentially an ol.ColorLike
  7516. * @return {boolean} Whether the color is an ol.ColorLike
  7517. */
  7518. ol.colorlike.isColorLike = function(color) {
  7519. return (
  7520. typeof color === 'string' ||
  7521. color instanceof CanvasPattern ||
  7522. color instanceof CanvasGradient
  7523. );
  7524. };
  7525. goog.provide('ol.dom');
  7526. /**
  7527. * Create an html canvas element and returns its 2d context.
  7528. * @param {number=} opt_width Canvas width.
  7529. * @param {number=} opt_height Canvas height.
  7530. * @return {CanvasRenderingContext2D} The context.
  7531. */
  7532. ol.dom.createCanvasContext2D = function(opt_width, opt_height) {
  7533. var canvas = document.createElement('CANVAS');
  7534. if (opt_width) {
  7535. canvas.width = opt_width;
  7536. }
  7537. if (opt_height) {
  7538. canvas.height = opt_height;
  7539. }
  7540. return canvas.getContext('2d');
  7541. };
  7542. /**
  7543. * Get the current computed width for the given element including margin,
  7544. * padding and border.
  7545. * Equivalent to jQuery's `$(el).outerWidth(true)`.
  7546. * @param {!Element} element Element.
  7547. * @return {number} The width.
  7548. */
  7549. ol.dom.outerWidth = function(element) {
  7550. var width = element.offsetWidth;
  7551. var style = getComputedStyle(element);
  7552. width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10);
  7553. return width;
  7554. };
  7555. /**
  7556. * Get the current computed height for the given element including margin,
  7557. * padding and border.
  7558. * Equivalent to jQuery's `$(el).outerHeight(true)`.
  7559. * @param {!Element} element Element.
  7560. * @return {number} The height.
  7561. */
  7562. ol.dom.outerHeight = function(element) {
  7563. var height = element.offsetHeight;
  7564. var style = getComputedStyle(element);
  7565. height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10);
  7566. return height;
  7567. };
  7568. /**
  7569. * @param {Node} newNode Node to replace old node
  7570. * @param {Node} oldNode The node to be replaced
  7571. */
  7572. ol.dom.replaceNode = function(newNode, oldNode) {
  7573. var parent = oldNode.parentNode;
  7574. if (parent) {
  7575. parent.replaceChild(newNode, oldNode);
  7576. }
  7577. };
  7578. /**
  7579. * @param {Node} node The node to remove.
  7580. * @returns {Node} The node that was removed or null.
  7581. */
  7582. ol.dom.removeNode = function(node) {
  7583. return node && node.parentNode ? node.parentNode.removeChild(node) : null;
  7584. };
  7585. /**
  7586. * @param {Node} node The node to remove the children from.
  7587. */
  7588. ol.dom.removeChildren = function(node) {
  7589. while (node.lastChild) {
  7590. node.removeChild(node.lastChild);
  7591. }
  7592. };
  7593. goog.provide('ol.MapEventType');
  7594. /**
  7595. * @enum {string}
  7596. */
  7597. ol.MapEventType = {
  7598. /**
  7599. * Triggered after a map frame is rendered.
  7600. * @event ol.MapEvent#postrender
  7601. * @api
  7602. */
  7603. POSTRENDER: 'postrender',
  7604. /**
  7605. * Triggered when the map starts moving.
  7606. * @event ol.MapEvent#movestart
  7607. * @api
  7608. */
  7609. MOVESTART: 'movestart',
  7610. /**
  7611. * Triggered after the map is moved.
  7612. * @event ol.MapEvent#moveend
  7613. * @api
  7614. */
  7615. MOVEEND: 'moveend'
  7616. };
  7617. goog.provide('ol.control.Control');
  7618. goog.require('ol');
  7619. goog.require('ol.MapEventType');
  7620. goog.require('ol.Object');
  7621. goog.require('ol.dom');
  7622. goog.require('ol.events');
  7623. /**
  7624. * @classdesc
  7625. * A control is a visible widget with a DOM element in a fixed position on the
  7626. * screen. They can involve user input (buttons), or be informational only;
  7627. * the position is determined using CSS. By default these are placed in the
  7628. * container with CSS class name `ol-overlaycontainer-stopevent`, but can use
  7629. * any outside DOM element.
  7630. *
  7631. * This is the base class for controls. You can use it for simple custom
  7632. * controls by creating the element with listeners, creating an instance:
  7633. * ```js
  7634. * var myControl = new ol.control.Control({element: myElement});
  7635. * ```
  7636. * and then adding this to the map.
  7637. *
  7638. * The main advantage of having this as a control rather than a simple separate
  7639. * DOM element is that preventing propagation is handled for you. Controls
  7640. * will also be `ol.Object`s in a `ol.Collection`, so you can use their
  7641. * methods.
  7642. *
  7643. * You can also extend this base for your own control class. See
  7644. * examples/custom-controls for an example of how to do this.
  7645. *
  7646. * @constructor
  7647. * @extends {ol.Object}
  7648. * @implements {oli.control.Control}
  7649. * @param {olx.control.ControlOptions} options Control options.
  7650. * @api
  7651. */
  7652. ol.control.Control = function(options) {
  7653. ol.Object.call(this);
  7654. /**
  7655. * @protected
  7656. * @type {Element}
  7657. */
  7658. this.element = options.element ? options.element : null;
  7659. /**
  7660. * @private
  7661. * @type {Element}
  7662. */
  7663. this.target_ = null;
  7664. /**
  7665. * @private
  7666. * @type {ol.Map}
  7667. */
  7668. this.map_ = null;
  7669. /**
  7670. * @protected
  7671. * @type {!Array.<ol.EventsKey>}
  7672. */
  7673. this.listenerKeys = [];
  7674. /**
  7675. * @type {function(ol.MapEvent)}
  7676. */
  7677. this.render = options.render ? options.render : ol.nullFunction;
  7678. if (options.target) {
  7679. this.setTarget(options.target);
  7680. }
  7681. };
  7682. ol.inherits(ol.control.Control, ol.Object);
  7683. /**
  7684. * @inheritDoc
  7685. */
  7686. ol.control.Control.prototype.disposeInternal = function() {
  7687. ol.dom.removeNode(this.element);
  7688. ol.Object.prototype.disposeInternal.call(this);
  7689. };
  7690. /**
  7691. * Get the map associated with this control.
  7692. * @return {ol.Map} Map.
  7693. * @api
  7694. */
  7695. ol.control.Control.prototype.getMap = function() {
  7696. return this.map_;
  7697. };
  7698. /**
  7699. * Remove the control from its current map and attach it to the new map.
  7700. * Subclasses may set up event handlers to get notified about changes to
  7701. * the map here.
  7702. * @param {ol.Map} map Map.
  7703. * @override
  7704. * @api
  7705. */
  7706. ol.control.Control.prototype.setMap = function(map) {
  7707. if (this.map_) {
  7708. ol.dom.removeNode(this.element);
  7709. }
  7710. for (var i = 0, ii = this.listenerKeys.length; i < ii; ++i) {
  7711. ol.events.unlistenByKey(this.listenerKeys[i]);
  7712. }
  7713. this.listenerKeys.length = 0;
  7714. this.map_ = map;
  7715. if (this.map_) {
  7716. var target = this.target_ ?
  7717. this.target_ : map.getOverlayContainerStopEvent();
  7718. target.appendChild(this.element);
  7719. if (this.render !== ol.nullFunction) {
  7720. this.listenerKeys.push(ol.events.listen(map,
  7721. ol.MapEventType.POSTRENDER, this.render, this));
  7722. }
  7723. map.render();
  7724. }
  7725. };
  7726. /**
  7727. * This function is used to set a target element for the control. It has no
  7728. * effect if it is called after the control has been added to the map (i.e.
  7729. * after `setMap` is called on the control). If no `target` is set in the
  7730. * options passed to the control constructor and if `setTarget` is not called
  7731. * then the control is added to the map's overlay container.
  7732. * @param {Element|string} target Target.
  7733. * @api
  7734. */
  7735. ol.control.Control.prototype.setTarget = function(target) {
  7736. this.target_ = typeof target === 'string' ?
  7737. document.getElementById(target) :
  7738. target;
  7739. };
  7740. goog.provide('ol.css');
  7741. /**
  7742. * The CSS class for hidden feature.
  7743. *
  7744. * @const
  7745. * @type {string}
  7746. */
  7747. ol.css.CLASS_HIDDEN = 'ol-hidden';
  7748. /**
  7749. * The CSS class that we'll give the DOM elements to have them selectable.
  7750. *
  7751. * @const
  7752. * @type {string}
  7753. */
  7754. ol.css.CLASS_SELECTABLE = 'ol-selectable';
  7755. /**
  7756. * The CSS class that we'll give the DOM elements to have them unselectable.
  7757. *
  7758. * @const
  7759. * @type {string}
  7760. */
  7761. ol.css.CLASS_UNSELECTABLE = 'ol-unselectable';
  7762. /**
  7763. * The CSS class for unsupported feature.
  7764. *
  7765. * @const
  7766. * @type {string}
  7767. */
  7768. ol.css.CLASS_UNSUPPORTED = 'ol-unsupported';
  7769. /**
  7770. * The CSS class for controls.
  7771. *
  7772. * @const
  7773. * @type {string}
  7774. */
  7775. ol.css.CLASS_CONTROL = 'ol-control';
  7776. // FIXME handle date line wrap
  7777. goog.provide('ol.control.Attribution');
  7778. goog.require('ol');
  7779. goog.require('ol.dom');
  7780. goog.require('ol.control.Control');
  7781. goog.require('ol.css');
  7782. goog.require('ol.events');
  7783. goog.require('ol.events.EventType');
  7784. goog.require('ol.obj');
  7785. /**
  7786. * @classdesc
  7787. * Control to show all the attributions associated with the layer sources
  7788. * in the map. This control is one of the default controls included in maps.
  7789. * By default it will show in the bottom right portion of the map, but this can
  7790. * be changed by using a css selector for `.ol-attribution`.
  7791. *
  7792. * @constructor
  7793. * @extends {ol.control.Control}
  7794. * @param {olx.control.AttributionOptions=} opt_options Attribution options.
  7795. * @api
  7796. */
  7797. ol.control.Attribution = function(opt_options) {
  7798. var options = opt_options ? opt_options : {};
  7799. /**
  7800. * @private
  7801. * @type {Element}
  7802. */
  7803. this.ulElement_ = document.createElement('UL');
  7804. /**
  7805. * @private
  7806. * @type {Element}
  7807. */
  7808. this.logoLi_ = document.createElement('LI');
  7809. this.ulElement_.appendChild(this.logoLi_);
  7810. this.logoLi_.style.display = 'none';
  7811. /**
  7812. * @private
  7813. * @type {boolean}
  7814. */
  7815. this.collapsed_ = options.collapsed !== undefined ? options.collapsed : true;
  7816. /**
  7817. * @private
  7818. * @type {boolean}
  7819. */
  7820. this.collapsible_ = options.collapsible !== undefined ?
  7821. options.collapsible : true;
  7822. if (!this.collapsible_) {
  7823. this.collapsed_ = false;
  7824. }
  7825. var className = options.className !== undefined ? options.className : 'ol-attribution';
  7826. var tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Attributions';
  7827. var collapseLabel = options.collapseLabel !== undefined ? options.collapseLabel : '\u00BB';
  7828. if (typeof collapseLabel === 'string') {
  7829. /**
  7830. * @private
  7831. * @type {Node}
  7832. */
  7833. this.collapseLabel_ = document.createElement('span');
  7834. this.collapseLabel_.textContent = collapseLabel;
  7835. } else {
  7836. this.collapseLabel_ = collapseLabel;
  7837. }
  7838. var label = options.label !== undefined ? options.label : 'i';
  7839. if (typeof label === 'string') {
  7840. /**
  7841. * @private
  7842. * @type {Node}
  7843. */
  7844. this.label_ = document.createElement('span');
  7845. this.label_.textContent = label;
  7846. } else {
  7847. this.label_ = label;
  7848. }
  7849. var activeLabel = (this.collapsible_ && !this.collapsed_) ?
  7850. this.collapseLabel_ : this.label_;
  7851. var button = document.createElement('button');
  7852. button.setAttribute('type', 'button');
  7853. button.title = tipLabel;
  7854. button.appendChild(activeLabel);
  7855. ol.events.listen(button, ol.events.EventType.CLICK, this.handleClick_, this);
  7856. var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
  7857. ol.css.CLASS_CONTROL +
  7858. (this.collapsed_ && this.collapsible_ ? ' ol-collapsed' : '') +
  7859. (this.collapsible_ ? '' : ' ol-uncollapsible');
  7860. var element = document.createElement('div');
  7861. element.className = cssClasses;
  7862. element.appendChild(this.ulElement_);
  7863. element.appendChild(button);
  7864. var render = options.render ? options.render : ol.control.Attribution.render;
  7865. ol.control.Control.call(this, {
  7866. element: element,
  7867. render: render,
  7868. target: options.target
  7869. });
  7870. /**
  7871. * @private
  7872. * @type {boolean}
  7873. */
  7874. this.renderedVisible_ = true;
  7875. /**
  7876. * @private
  7877. * @type {Object.<string, Element>}
  7878. */
  7879. this.attributionElements_ = {};
  7880. /**
  7881. * @private
  7882. * @type {Object.<string, boolean>}
  7883. */
  7884. this.attributionElementRenderedVisible_ = {};
  7885. /**
  7886. * @private
  7887. * @type {Object.<string, Element>}
  7888. */
  7889. this.logoElements_ = {};
  7890. };
  7891. ol.inherits(ol.control.Attribution, ol.control.Control);
  7892. /**
  7893. * @param {?olx.FrameState} frameState Frame state.
  7894. * @return {Array.<Object.<string, ol.Attribution>>} Attributions.
  7895. */
  7896. ol.control.Attribution.prototype.getSourceAttributions = function(frameState) {
  7897. var i, ii, j, jj, tileRanges, source, sourceAttribution,
  7898. sourceAttributionKey, sourceAttributions, sourceKey;
  7899. var intersectsTileRange;
  7900. var layerStatesArray = frameState.layerStatesArray;
  7901. /** @type {Object.<string, ol.Attribution>} */
  7902. var attributions = ol.obj.assign({}, frameState.attributions);
  7903. /** @type {Object.<string, ol.Attribution>} */
  7904. var hiddenAttributions = {};
  7905. var uniqueAttributions = {};
  7906. var projection = /** @type {!ol.proj.Projection} */ (frameState.viewState.projection);
  7907. for (i = 0, ii = layerStatesArray.length; i < ii; i++) {
  7908. source = layerStatesArray[i].layer.getSource();
  7909. if (!source) {
  7910. continue;
  7911. }
  7912. sourceKey = ol.getUid(source).toString();
  7913. sourceAttributions = source.getAttributions();
  7914. if (!sourceAttributions) {
  7915. continue;
  7916. }
  7917. for (j = 0, jj = sourceAttributions.length; j < jj; j++) {
  7918. sourceAttribution = sourceAttributions[j];
  7919. sourceAttributionKey = ol.getUid(sourceAttribution).toString();
  7920. if (sourceAttributionKey in attributions) {
  7921. continue;
  7922. }
  7923. tileRanges = frameState.usedTiles[sourceKey];
  7924. if (tileRanges) {
  7925. var tileGrid = /** @type {ol.source.Tile} */ (source).getTileGridForProjection(projection);
  7926. intersectsTileRange = sourceAttribution.intersectsAnyTileRange(
  7927. tileRanges, tileGrid, projection);
  7928. } else {
  7929. intersectsTileRange = false;
  7930. }
  7931. if (intersectsTileRange) {
  7932. if (sourceAttributionKey in hiddenAttributions) {
  7933. delete hiddenAttributions[sourceAttributionKey];
  7934. }
  7935. var html = sourceAttribution.getHTML();
  7936. if (!(html in uniqueAttributions)) {
  7937. uniqueAttributions[html] = true;
  7938. attributions[sourceAttributionKey] = sourceAttribution;
  7939. }
  7940. } else {
  7941. hiddenAttributions[sourceAttributionKey] = sourceAttribution;
  7942. }
  7943. }
  7944. }
  7945. return [attributions, hiddenAttributions];
  7946. };
  7947. /**
  7948. * Update the attribution element.
  7949. * @param {ol.MapEvent} mapEvent Map event.
  7950. * @this {ol.control.Attribution}
  7951. * @api
  7952. */
  7953. ol.control.Attribution.render = function(mapEvent) {
  7954. this.updateElement_(mapEvent.frameState);
  7955. };
  7956. /**
  7957. * @private
  7958. * @param {?olx.FrameState} frameState Frame state.
  7959. */
  7960. ol.control.Attribution.prototype.updateElement_ = function(frameState) {
  7961. if (!frameState) {
  7962. if (this.renderedVisible_) {
  7963. this.element.style.display = 'none';
  7964. this.renderedVisible_ = false;
  7965. }
  7966. return;
  7967. }
  7968. var attributions = this.getSourceAttributions(frameState);
  7969. /** @type {Object.<string, ol.Attribution>} */
  7970. var visibleAttributions = attributions[0];
  7971. /** @type {Object.<string, ol.Attribution>} */
  7972. var hiddenAttributions = attributions[1];
  7973. var attributionElement, attributionKey;
  7974. for (attributionKey in this.attributionElements_) {
  7975. if (attributionKey in visibleAttributions) {
  7976. if (!this.attributionElementRenderedVisible_[attributionKey]) {
  7977. this.attributionElements_[attributionKey].style.display = '';
  7978. this.attributionElementRenderedVisible_[attributionKey] = true;
  7979. }
  7980. delete visibleAttributions[attributionKey];
  7981. } else if (attributionKey in hiddenAttributions) {
  7982. if (this.attributionElementRenderedVisible_[attributionKey]) {
  7983. this.attributionElements_[attributionKey].style.display = 'none';
  7984. delete this.attributionElementRenderedVisible_[attributionKey];
  7985. }
  7986. delete hiddenAttributions[attributionKey];
  7987. } else {
  7988. ol.dom.removeNode(this.attributionElements_[attributionKey]);
  7989. delete this.attributionElements_[attributionKey];
  7990. delete this.attributionElementRenderedVisible_[attributionKey];
  7991. }
  7992. }
  7993. for (attributionKey in visibleAttributions) {
  7994. attributionElement = document.createElement('LI');
  7995. attributionElement.innerHTML =
  7996. visibleAttributions[attributionKey].getHTML();
  7997. this.ulElement_.appendChild(attributionElement);
  7998. this.attributionElements_[attributionKey] = attributionElement;
  7999. this.attributionElementRenderedVisible_[attributionKey] = true;
  8000. }
  8001. for (attributionKey in hiddenAttributions) {
  8002. attributionElement = document.createElement('LI');
  8003. attributionElement.innerHTML =
  8004. hiddenAttributions[attributionKey].getHTML();
  8005. attributionElement.style.display = 'none';
  8006. this.ulElement_.appendChild(attributionElement);
  8007. this.attributionElements_[attributionKey] = attributionElement;
  8008. }
  8009. var renderVisible =
  8010. !ol.obj.isEmpty(this.attributionElementRenderedVisible_) ||
  8011. !ol.obj.isEmpty(frameState.logos);
  8012. if (this.renderedVisible_ != renderVisible) {
  8013. this.element.style.display = renderVisible ? '' : 'none';
  8014. this.renderedVisible_ = renderVisible;
  8015. }
  8016. if (renderVisible &&
  8017. ol.obj.isEmpty(this.attributionElementRenderedVisible_)) {
  8018. this.element.classList.add('ol-logo-only');
  8019. } else {
  8020. this.element.classList.remove('ol-logo-only');
  8021. }
  8022. this.insertLogos_(frameState);
  8023. };
  8024. /**
  8025. * @param {?olx.FrameState} frameState Frame state.
  8026. * @private
  8027. */
  8028. ol.control.Attribution.prototype.insertLogos_ = function(frameState) {
  8029. var logo;
  8030. var logos = frameState.logos;
  8031. var logoElements = this.logoElements_;
  8032. for (logo in logoElements) {
  8033. if (!(logo in logos)) {
  8034. ol.dom.removeNode(logoElements[logo]);
  8035. delete logoElements[logo];
  8036. }
  8037. }
  8038. var image, logoElement, logoKey;
  8039. for (logoKey in logos) {
  8040. var logoValue = logos[logoKey];
  8041. if (logoValue instanceof HTMLElement) {
  8042. this.logoLi_.appendChild(logoValue);
  8043. logoElements[logoKey] = logoValue;
  8044. }
  8045. if (!(logoKey in logoElements)) {
  8046. image = new Image();
  8047. image.src = logoKey;
  8048. if (logoValue === '') {
  8049. logoElement = image;
  8050. } else {
  8051. logoElement = document.createElement('a');
  8052. logoElement.href = logoValue;
  8053. logoElement.appendChild(image);
  8054. }
  8055. this.logoLi_.appendChild(logoElement);
  8056. logoElements[logoKey] = logoElement;
  8057. }
  8058. }
  8059. this.logoLi_.style.display = !ol.obj.isEmpty(logos) ? '' : 'none';
  8060. };
  8061. /**
  8062. * @param {Event} event The event to handle
  8063. * @private
  8064. */
  8065. ol.control.Attribution.prototype.handleClick_ = function(event) {
  8066. event.preventDefault();
  8067. this.handleToggle_();
  8068. };
  8069. /**
  8070. * @private
  8071. */
  8072. ol.control.Attribution.prototype.handleToggle_ = function() {
  8073. this.element.classList.toggle('ol-collapsed');
  8074. if (this.collapsed_) {
  8075. ol.dom.replaceNode(this.collapseLabel_, this.label_);
  8076. } else {
  8077. ol.dom.replaceNode(this.label_, this.collapseLabel_);
  8078. }
  8079. this.collapsed_ = !this.collapsed_;
  8080. };
  8081. /**
  8082. * Return `true` if the attribution is collapsible, `false` otherwise.
  8083. * @return {boolean} True if the widget is collapsible.
  8084. * @api
  8085. */
  8086. ol.control.Attribution.prototype.getCollapsible = function() {
  8087. return this.collapsible_;
  8088. };
  8089. /**
  8090. * Set whether the attribution should be collapsible.
  8091. * @param {boolean} collapsible True if the widget is collapsible.
  8092. * @api
  8093. */
  8094. ol.control.Attribution.prototype.setCollapsible = function(collapsible) {
  8095. if (this.collapsible_ === collapsible) {
  8096. return;
  8097. }
  8098. this.collapsible_ = collapsible;
  8099. this.element.classList.toggle('ol-uncollapsible');
  8100. if (!collapsible && this.collapsed_) {
  8101. this.handleToggle_();
  8102. }
  8103. };
  8104. /**
  8105. * Collapse or expand the attribution according to the passed parameter. Will
  8106. * not do anything if the attribution isn't collapsible or if the current
  8107. * collapsed state is already the one requested.
  8108. * @param {boolean} collapsed True if the widget is collapsed.
  8109. * @api
  8110. */
  8111. ol.control.Attribution.prototype.setCollapsed = function(collapsed) {
  8112. if (!this.collapsible_ || this.collapsed_ === collapsed) {
  8113. return;
  8114. }
  8115. this.handleToggle_();
  8116. };
  8117. /**
  8118. * Return `true` when the attribution is currently collapsed or `false`
  8119. * otherwise.
  8120. * @return {boolean} True if the widget is collapsed.
  8121. * @api
  8122. */
  8123. ol.control.Attribution.prototype.getCollapsed = function() {
  8124. return this.collapsed_;
  8125. };
  8126. goog.provide('ol.easing');
  8127. /**
  8128. * Start slow and speed up.
  8129. * @param {number} t Input between 0 and 1.
  8130. * @return {number} Output between 0 and 1.
  8131. * @api
  8132. */
  8133. ol.easing.easeIn = function(t) {
  8134. return Math.pow(t, 3);
  8135. };
  8136. /**
  8137. * Start fast and slow down.
  8138. * @param {number} t Input between 0 and 1.
  8139. * @return {number} Output between 0 and 1.
  8140. * @api
  8141. */
  8142. ol.easing.easeOut = function(t) {
  8143. return 1 - ol.easing.easeIn(1 - t);
  8144. };
  8145. /**
  8146. * Start slow, speed up, and then slow down again.
  8147. * @param {number} t Input between 0 and 1.
  8148. * @return {number} Output between 0 and 1.
  8149. * @api
  8150. */
  8151. ol.easing.inAndOut = function(t) {
  8152. return 3 * t * t - 2 * t * t * t;
  8153. };
  8154. /**
  8155. * Maintain a constant speed over time.
  8156. * @param {number} t Input between 0 and 1.
  8157. * @return {number} Output between 0 and 1.
  8158. * @api
  8159. */
  8160. ol.easing.linear = function(t) {
  8161. return t;
  8162. };
  8163. /**
  8164. * Start slow, speed up, and at the very end slow down again. This has the
  8165. * same general behavior as {@link ol.easing.inAndOut}, but the final slowdown
  8166. * is delayed.
  8167. * @param {number} t Input between 0 and 1.
  8168. * @return {number} Output between 0 and 1.
  8169. * @api
  8170. */
  8171. ol.easing.upAndDown = function(t) {
  8172. if (t < 0.5) {
  8173. return ol.easing.inAndOut(2 * t);
  8174. } else {
  8175. return 1 - ol.easing.inAndOut(2 * (t - 0.5));
  8176. }
  8177. };
  8178. goog.provide('ol.control.Rotate');
  8179. goog.require('ol.events');
  8180. goog.require('ol.events.EventType');
  8181. goog.require('ol');
  8182. goog.require('ol.control.Control');
  8183. goog.require('ol.css');
  8184. goog.require('ol.easing');
  8185. /**
  8186. * @classdesc
  8187. * A button control to reset rotation to 0.
  8188. * To style this control use css selector `.ol-rotate`. A `.ol-hidden` css
  8189. * selector is added to the button when the rotation is 0.
  8190. *
  8191. * @constructor
  8192. * @extends {ol.control.Control}
  8193. * @param {olx.control.RotateOptions=} opt_options Rotate options.
  8194. * @api
  8195. */
  8196. ol.control.Rotate = function(opt_options) {
  8197. var options = opt_options ? opt_options : {};
  8198. var className = options.className !== undefined ? options.className : 'ol-rotate';
  8199. var label = options.label !== undefined ? options.label : '\u21E7';
  8200. /**
  8201. * @type {Element}
  8202. * @private
  8203. */
  8204. this.label_ = null;
  8205. if (typeof label === 'string') {
  8206. this.label_ = document.createElement('span');
  8207. this.label_.className = 'ol-compass';
  8208. this.label_.textContent = label;
  8209. } else {
  8210. this.label_ = label;
  8211. this.label_.classList.add('ol-compass');
  8212. }
  8213. var tipLabel = options.tipLabel ? options.tipLabel : 'Reset rotation';
  8214. var button = document.createElement('button');
  8215. button.className = className + '-reset';
  8216. button.setAttribute('type', 'button');
  8217. button.title = tipLabel;
  8218. button.appendChild(this.label_);
  8219. ol.events.listen(button, ol.events.EventType.CLICK,
  8220. ol.control.Rotate.prototype.handleClick_, this);
  8221. var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
  8222. ol.css.CLASS_CONTROL;
  8223. var element = document.createElement('div');
  8224. element.className = cssClasses;
  8225. element.appendChild(button);
  8226. var render = options.render ? options.render : ol.control.Rotate.render;
  8227. this.callResetNorth_ = options.resetNorth ? options.resetNorth : undefined;
  8228. ol.control.Control.call(this, {
  8229. element: element,
  8230. render: render,
  8231. target: options.target
  8232. });
  8233. /**
  8234. * @type {number}
  8235. * @private
  8236. */
  8237. this.duration_ = options.duration !== undefined ? options.duration : 250;
  8238. /**
  8239. * @type {boolean}
  8240. * @private
  8241. */
  8242. this.autoHide_ = options.autoHide !== undefined ? options.autoHide : true;
  8243. /**
  8244. * @private
  8245. * @type {number|undefined}
  8246. */
  8247. this.rotation_ = undefined;
  8248. if (this.autoHide_) {
  8249. this.element.classList.add(ol.css.CLASS_HIDDEN);
  8250. }
  8251. };
  8252. ol.inherits(ol.control.Rotate, ol.control.Control);
  8253. /**
  8254. * @param {Event} event The event to handle
  8255. * @private
  8256. */
  8257. ol.control.Rotate.prototype.handleClick_ = function(event) {
  8258. event.preventDefault();
  8259. if (this.callResetNorth_ !== undefined) {
  8260. this.callResetNorth_();
  8261. } else {
  8262. this.resetNorth_();
  8263. }
  8264. };
  8265. /**
  8266. * @private
  8267. */
  8268. ol.control.Rotate.prototype.resetNorth_ = function() {
  8269. var map = this.getMap();
  8270. var view = map.getView();
  8271. if (!view) {
  8272. // the map does not have a view, so we can't act
  8273. // upon it
  8274. return;
  8275. }
  8276. if (view.getRotation() !== undefined) {
  8277. if (this.duration_ > 0) {
  8278. view.animate({
  8279. rotation: 0,
  8280. duration: this.duration_,
  8281. easing: ol.easing.easeOut
  8282. });
  8283. } else {
  8284. view.setRotation(0);
  8285. }
  8286. }
  8287. };
  8288. /**
  8289. * Update the rotate control element.
  8290. * @param {ol.MapEvent} mapEvent Map event.
  8291. * @this {ol.control.Rotate}
  8292. * @api
  8293. */
  8294. ol.control.Rotate.render = function(mapEvent) {
  8295. var frameState = mapEvent.frameState;
  8296. if (!frameState) {
  8297. return;
  8298. }
  8299. var rotation = frameState.viewState.rotation;
  8300. if (rotation != this.rotation_) {
  8301. var transform = 'rotate(' + rotation + 'rad)';
  8302. if (this.autoHide_) {
  8303. var contains = this.element.classList.contains(ol.css.CLASS_HIDDEN);
  8304. if (!contains && rotation === 0) {
  8305. this.element.classList.add(ol.css.CLASS_HIDDEN);
  8306. } else if (contains && rotation !== 0) {
  8307. this.element.classList.remove(ol.css.CLASS_HIDDEN);
  8308. }
  8309. }
  8310. this.label_.style.msTransform = transform;
  8311. this.label_.style.webkitTransform = transform;
  8312. this.label_.style.transform = transform;
  8313. }
  8314. this.rotation_ = rotation;
  8315. };
  8316. goog.provide('ol.control.Zoom');
  8317. goog.require('ol');
  8318. goog.require('ol.events');
  8319. goog.require('ol.events.EventType');
  8320. goog.require('ol.control.Control');
  8321. goog.require('ol.css');
  8322. goog.require('ol.easing');
  8323. /**
  8324. * @classdesc
  8325. * A control with 2 buttons, one for zoom in and one for zoom out.
  8326. * This control is one of the default controls of a map. To style this control
  8327. * use css selectors `.ol-zoom-in` and `.ol-zoom-out`.
  8328. *
  8329. * @constructor
  8330. * @extends {ol.control.Control}
  8331. * @param {olx.control.ZoomOptions=} opt_options Zoom options.
  8332. * @api
  8333. */
  8334. ol.control.Zoom = function(opt_options) {
  8335. var options = opt_options ? opt_options : {};
  8336. var className = options.className !== undefined ? options.className : 'ol-zoom';
  8337. var delta = options.delta !== undefined ? options.delta : 1;
  8338. var zoomInLabel = options.zoomInLabel !== undefined ? options.zoomInLabel : '+';
  8339. var zoomOutLabel = options.zoomOutLabel !== undefined ? options.zoomOutLabel : '\u2212';
  8340. var zoomInTipLabel = options.zoomInTipLabel !== undefined ?
  8341. options.zoomInTipLabel : 'Zoom in';
  8342. var zoomOutTipLabel = options.zoomOutTipLabel !== undefined ?
  8343. options.zoomOutTipLabel : 'Zoom out';
  8344. var inElement = document.createElement('button');
  8345. inElement.className = className + '-in';
  8346. inElement.setAttribute('type', 'button');
  8347. inElement.title = zoomInTipLabel;
  8348. inElement.appendChild(
  8349. typeof zoomInLabel === 'string' ? document.createTextNode(zoomInLabel) : zoomInLabel
  8350. );
  8351. ol.events.listen(inElement, ol.events.EventType.CLICK,
  8352. ol.control.Zoom.prototype.handleClick_.bind(this, delta));
  8353. var outElement = document.createElement('button');
  8354. outElement.className = className + '-out';
  8355. outElement.setAttribute('type', 'button');
  8356. outElement.title = zoomOutTipLabel;
  8357. outElement.appendChild(
  8358. typeof zoomOutLabel === 'string' ? document.createTextNode(zoomOutLabel) : zoomOutLabel
  8359. );
  8360. ol.events.listen(outElement, ol.events.EventType.CLICK,
  8361. ol.control.Zoom.prototype.handleClick_.bind(this, -delta));
  8362. var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
  8363. ol.css.CLASS_CONTROL;
  8364. var element = document.createElement('div');
  8365. element.className = cssClasses;
  8366. element.appendChild(inElement);
  8367. element.appendChild(outElement);
  8368. ol.control.Control.call(this, {
  8369. element: element,
  8370. target: options.target
  8371. });
  8372. /**
  8373. * @type {number}
  8374. * @private
  8375. */
  8376. this.duration_ = options.duration !== undefined ? options.duration : 250;
  8377. };
  8378. ol.inherits(ol.control.Zoom, ol.control.Control);
  8379. /**
  8380. * @param {number} delta Zoom delta.
  8381. * @param {Event} event The event to handle
  8382. * @private
  8383. */
  8384. ol.control.Zoom.prototype.handleClick_ = function(delta, event) {
  8385. event.preventDefault();
  8386. this.zoomByDelta_(delta);
  8387. };
  8388. /**
  8389. * @param {number} delta Zoom delta.
  8390. * @private
  8391. */
  8392. ol.control.Zoom.prototype.zoomByDelta_ = function(delta) {
  8393. var map = this.getMap();
  8394. var view = map.getView();
  8395. if (!view) {
  8396. // the map does not have a view, so we can't act
  8397. // upon it
  8398. return;
  8399. }
  8400. var currentResolution = view.getResolution();
  8401. if (currentResolution) {
  8402. var newResolution = view.constrainResolution(currentResolution, delta);
  8403. if (this.duration_ > 0) {
  8404. if (view.getAnimating()) {
  8405. view.cancelAnimations();
  8406. }
  8407. view.animate({
  8408. resolution: newResolution,
  8409. duration: this.duration_,
  8410. easing: ol.easing.easeOut
  8411. });
  8412. } else {
  8413. view.setResolution(newResolution);
  8414. }
  8415. }
  8416. };
  8417. goog.provide('ol.control');
  8418. goog.require('ol.Collection');
  8419. goog.require('ol.control.Attribution');
  8420. goog.require('ol.control.Rotate');
  8421. goog.require('ol.control.Zoom');
  8422. /**
  8423. * Set of controls included in maps by default. Unless configured otherwise,
  8424. * this returns a collection containing an instance of each of the following
  8425. * controls:
  8426. * * {@link ol.control.Zoom}
  8427. * * {@link ol.control.Rotate}
  8428. * * {@link ol.control.Attribution}
  8429. *
  8430. * @param {olx.control.DefaultsOptions=} opt_options Defaults options.
  8431. * @return {ol.Collection.<ol.control.Control>} Controls.
  8432. * @api
  8433. */
  8434. ol.control.defaults = function(opt_options) {
  8435. var options = opt_options ? opt_options : {};
  8436. var controls = new ol.Collection();
  8437. var zoomControl = options.zoom !== undefined ? options.zoom : true;
  8438. if (zoomControl) {
  8439. controls.push(new ol.control.Zoom(options.zoomOptions));
  8440. }
  8441. var rotateControl = options.rotate !== undefined ? options.rotate : true;
  8442. if (rotateControl) {
  8443. controls.push(new ol.control.Rotate(options.rotateOptions));
  8444. }
  8445. var attributionControl = options.attribution !== undefined ?
  8446. options.attribution : true;
  8447. if (attributionControl) {
  8448. controls.push(new ol.control.Attribution(options.attributionOptions));
  8449. }
  8450. return controls;
  8451. };
  8452. goog.provide('ol.control.FullScreen');
  8453. goog.require('ol');
  8454. goog.require('ol.control.Control');
  8455. goog.require('ol.css');
  8456. goog.require('ol.dom');
  8457. goog.require('ol.events');
  8458. goog.require('ol.events.EventType');
  8459. /**
  8460. * @classdesc
  8461. * Provides a button that when clicked fills up the full screen with the map.
  8462. * The full screen source element is by default the element containing the map viewport unless
  8463. * overridden by providing the `source` option. In which case, the dom
  8464. * element introduced using this parameter will be displayed in full screen.
  8465. *
  8466. * When in full screen mode, a close button is shown to exit full screen mode.
  8467. * The [Fullscreen API](http://www.w3.org/TR/fullscreen/) is used to
  8468. * toggle the map in full screen mode.
  8469. *
  8470. *
  8471. * @constructor
  8472. * @extends {ol.control.Control}
  8473. * @param {olx.control.FullScreenOptions=} opt_options Options.
  8474. * @api
  8475. */
  8476. ol.control.FullScreen = function(opt_options) {
  8477. var options = opt_options ? opt_options : {};
  8478. /**
  8479. * @private
  8480. * @type {string}
  8481. */
  8482. this.cssClassName_ = options.className !== undefined ? options.className :
  8483. 'ol-full-screen';
  8484. var label = options.label !== undefined ? options.label : '\u2922';
  8485. /**
  8486. * @private
  8487. * @type {Node}
  8488. */
  8489. this.labelNode_ = typeof label === 'string' ?
  8490. document.createTextNode(label) : label;
  8491. var labelActive = options.labelActive !== undefined ? options.labelActive : '\u00d7';
  8492. /**
  8493. * @private
  8494. * @type {Node}
  8495. */
  8496. this.labelActiveNode_ = typeof labelActive === 'string' ?
  8497. document.createTextNode(labelActive) : labelActive;
  8498. var tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
  8499. var button = document.createElement('button');
  8500. button.className = this.cssClassName_ + '-' + ol.control.FullScreen.isFullScreen();
  8501. button.setAttribute('type', 'button');
  8502. button.title = tipLabel;
  8503. button.appendChild(this.labelNode_);
  8504. ol.events.listen(button, ol.events.EventType.CLICK,
  8505. this.handleClick_, this);
  8506. var cssClasses = this.cssClassName_ + ' ' + ol.css.CLASS_UNSELECTABLE +
  8507. ' ' + ol.css.CLASS_CONTROL + ' ' +
  8508. (!ol.control.FullScreen.isFullScreenSupported() ? ol.css.CLASS_UNSUPPORTED : '');
  8509. var element = document.createElement('div');
  8510. element.className = cssClasses;
  8511. element.appendChild(button);
  8512. ol.control.Control.call(this, {
  8513. element: element,
  8514. target: options.target
  8515. });
  8516. /**
  8517. * @private
  8518. * @type {boolean}
  8519. */
  8520. this.keys_ = options.keys !== undefined ? options.keys : false;
  8521. /**
  8522. * @private
  8523. * @type {Element|string|undefined}
  8524. */
  8525. this.source_ = options.source;
  8526. };
  8527. ol.inherits(ol.control.FullScreen, ol.control.Control);
  8528. /**
  8529. * @param {Event} event The event to handle
  8530. * @private
  8531. */
  8532. ol.control.FullScreen.prototype.handleClick_ = function(event) {
  8533. event.preventDefault();
  8534. this.handleFullScreen_();
  8535. };
  8536. /**
  8537. * @private
  8538. */
  8539. ol.control.FullScreen.prototype.handleFullScreen_ = function() {
  8540. if (!ol.control.FullScreen.isFullScreenSupported()) {
  8541. return;
  8542. }
  8543. var map = this.getMap();
  8544. if (!map) {
  8545. return;
  8546. }
  8547. if (ol.control.FullScreen.isFullScreen()) {
  8548. ol.control.FullScreen.exitFullScreen();
  8549. } else {
  8550. var element;
  8551. if (this.source_) {
  8552. element = typeof this.source_ === 'string' ?
  8553. document.getElementById(this.source_) :
  8554. this.source_;
  8555. } else {
  8556. element = map.getTargetElement();
  8557. }
  8558. if (this.keys_) {
  8559. ol.control.FullScreen.requestFullScreenWithKeys(element);
  8560. } else {
  8561. ol.control.FullScreen.requestFullScreen(element);
  8562. }
  8563. }
  8564. };
  8565. /**
  8566. * @private
  8567. */
  8568. ol.control.FullScreen.prototype.handleFullScreenChange_ = function() {
  8569. var button = this.element.firstElementChild;
  8570. var map = this.getMap();
  8571. if (ol.control.FullScreen.isFullScreen()) {
  8572. button.className = this.cssClassName_ + '-true';
  8573. ol.dom.replaceNode(this.labelActiveNode_, this.labelNode_);
  8574. } else {
  8575. button.className = this.cssClassName_ + '-false';
  8576. ol.dom.replaceNode(this.labelNode_, this.labelActiveNode_);
  8577. }
  8578. if (map) {
  8579. map.updateSize();
  8580. }
  8581. };
  8582. /**
  8583. * @inheritDoc
  8584. * @api
  8585. */
  8586. ol.control.FullScreen.prototype.setMap = function(map) {
  8587. ol.control.Control.prototype.setMap.call(this, map);
  8588. if (map) {
  8589. this.listenerKeys.push(ol.events.listen(document,
  8590. ol.control.FullScreen.getChangeType_(),
  8591. this.handleFullScreenChange_, this)
  8592. );
  8593. }
  8594. };
  8595. /**
  8596. * @return {boolean} Fullscreen is supported by the current platform.
  8597. */
  8598. ol.control.FullScreen.isFullScreenSupported = function() {
  8599. var body = document.body;
  8600. return !!(
  8601. body.webkitRequestFullscreen ||
  8602. (body.mozRequestFullScreen && document.mozFullScreenEnabled) ||
  8603. (body.msRequestFullscreen && document.msFullscreenEnabled) ||
  8604. (body.requestFullscreen && document.fullscreenEnabled)
  8605. );
  8606. };
  8607. /**
  8608. * @return {boolean} Element is currently in fullscreen.
  8609. */
  8610. ol.control.FullScreen.isFullScreen = function() {
  8611. return !!(
  8612. document.webkitIsFullScreen || document.mozFullScreen ||
  8613. document.msFullscreenElement || document.fullscreenElement
  8614. );
  8615. };
  8616. /**
  8617. * Request to fullscreen an element.
  8618. * @param {Node} element Element to request fullscreen
  8619. */
  8620. ol.control.FullScreen.requestFullScreen = function(element) {
  8621. if (element.requestFullscreen) {
  8622. element.requestFullscreen();
  8623. } else if (element.msRequestFullscreen) {
  8624. element.msRequestFullscreen();
  8625. } else if (element.mozRequestFullScreen) {
  8626. element.mozRequestFullScreen();
  8627. } else if (element.webkitRequestFullscreen) {
  8628. element.webkitRequestFullscreen();
  8629. }
  8630. };
  8631. /**
  8632. * Request to fullscreen an element with keyboard input.
  8633. * @param {Node} element Element to request fullscreen
  8634. */
  8635. ol.control.FullScreen.requestFullScreenWithKeys = function(element) {
  8636. if (element.mozRequestFullScreenWithKeys) {
  8637. element.mozRequestFullScreenWithKeys();
  8638. } else if (element.webkitRequestFullscreen) {
  8639. element.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
  8640. } else {
  8641. ol.control.FullScreen.requestFullScreen(element);
  8642. }
  8643. };
  8644. /**
  8645. * Exit fullscreen.
  8646. */
  8647. ol.control.FullScreen.exitFullScreen = function() {
  8648. if (document.exitFullscreen) {
  8649. document.exitFullscreen();
  8650. } else if (document.msExitFullscreen) {
  8651. document.msExitFullscreen();
  8652. } else if (document.mozCancelFullScreen) {
  8653. document.mozCancelFullScreen();
  8654. } else if (document.webkitExitFullscreen) {
  8655. document.webkitExitFullscreen();
  8656. }
  8657. };
  8658. /**
  8659. * @return {string} Change type.
  8660. * @private
  8661. */
  8662. ol.control.FullScreen.getChangeType_ = (function() {
  8663. var changeType;
  8664. return function() {
  8665. if (!changeType) {
  8666. var body = document.body;
  8667. if (body.webkitRequestFullscreen) {
  8668. changeType = 'webkitfullscreenchange';
  8669. } else if (body.mozRequestFullScreen) {
  8670. changeType = 'mozfullscreenchange';
  8671. } else if (body.msRequestFullscreen) {
  8672. changeType = 'MSFullscreenChange';
  8673. } else if (body.requestFullscreen) {
  8674. changeType = 'fullscreenchange';
  8675. }
  8676. }
  8677. return changeType;
  8678. };
  8679. })();
  8680. // FIXME should listen on appropriate pane, once it is defined
  8681. goog.provide('ol.control.MousePosition');
  8682. goog.require('ol');
  8683. goog.require('ol.events');
  8684. goog.require('ol.events.EventType');
  8685. goog.require('ol.Object');
  8686. goog.require('ol.control.Control');
  8687. goog.require('ol.proj');
  8688. /**
  8689. * @classdesc
  8690. * A control to show the 2D coordinates of the mouse cursor. By default, these
  8691. * are in the view projection, but can be in any supported projection.
  8692. * By default the control is shown in the top right corner of the map, but this
  8693. * can be changed by using the css selector `.ol-mouse-position`.
  8694. *
  8695. * @constructor
  8696. * @extends {ol.control.Control}
  8697. * @param {olx.control.MousePositionOptions=} opt_options Mouse position
  8698. * options.
  8699. * @api
  8700. */
  8701. ol.control.MousePosition = function(opt_options) {
  8702. var options = opt_options ? opt_options : {};
  8703. var element = document.createElement('DIV');
  8704. element.className = options.className !== undefined ? options.className : 'ol-mouse-position';
  8705. var render = options.render ?
  8706. options.render : ol.control.MousePosition.render;
  8707. ol.control.Control.call(this, {
  8708. element: element,
  8709. render: render,
  8710. target: options.target
  8711. });
  8712. ol.events.listen(this,
  8713. ol.Object.getChangeEventType(ol.control.MousePosition.Property_.PROJECTION),
  8714. this.handleProjectionChanged_, this);
  8715. if (options.coordinateFormat) {
  8716. this.setCoordinateFormat(options.coordinateFormat);
  8717. }
  8718. if (options.projection) {
  8719. this.setProjection(options.projection);
  8720. }
  8721. /**
  8722. * @private
  8723. * @type {string}
  8724. */
  8725. this.undefinedHTML_ = options.undefinedHTML !== undefined ? options.undefinedHTML : '';
  8726. /**
  8727. * @private
  8728. * @type {string}
  8729. */
  8730. this.renderedHTML_ = element.innerHTML;
  8731. /**
  8732. * @private
  8733. * @type {ol.proj.Projection}
  8734. */
  8735. this.mapProjection_ = null;
  8736. /**
  8737. * @private
  8738. * @type {?ol.TransformFunction}
  8739. */
  8740. this.transform_ = null;
  8741. /**
  8742. * @private
  8743. * @type {ol.Pixel}
  8744. */
  8745. this.lastMouseMovePixel_ = null;
  8746. };
  8747. ol.inherits(ol.control.MousePosition, ol.control.Control);
  8748. /**
  8749. * Update the mouseposition element.
  8750. * @param {ol.MapEvent} mapEvent Map event.
  8751. * @this {ol.control.MousePosition}
  8752. * @api
  8753. */
  8754. ol.control.MousePosition.render = function(mapEvent) {
  8755. var frameState = mapEvent.frameState;
  8756. if (!frameState) {
  8757. this.mapProjection_ = null;
  8758. } else {
  8759. if (this.mapProjection_ != frameState.viewState.projection) {
  8760. this.mapProjection_ = frameState.viewState.projection;
  8761. this.transform_ = null;
  8762. }
  8763. }
  8764. this.updateHTML_(this.lastMouseMovePixel_);
  8765. };
  8766. /**
  8767. * @private
  8768. */
  8769. ol.control.MousePosition.prototype.handleProjectionChanged_ = function() {
  8770. this.transform_ = null;
  8771. };
  8772. /**
  8773. * Return the coordinate format type used to render the current position or
  8774. * undefined.
  8775. * @return {ol.CoordinateFormatType|undefined} The format to render the current
  8776. * position in.
  8777. * @observable
  8778. * @api
  8779. */
  8780. ol.control.MousePosition.prototype.getCoordinateFormat = function() {
  8781. return /** @type {ol.CoordinateFormatType|undefined} */ (
  8782. this.get(ol.control.MousePosition.Property_.COORDINATE_FORMAT));
  8783. };
  8784. /**
  8785. * Return the projection that is used to report the mouse position.
  8786. * @return {ol.proj.Projection|undefined} The projection to report mouse
  8787. * position in.
  8788. * @observable
  8789. * @api
  8790. */
  8791. ol.control.MousePosition.prototype.getProjection = function() {
  8792. return /** @type {ol.proj.Projection|undefined} */ (
  8793. this.get(ol.control.MousePosition.Property_.PROJECTION));
  8794. };
  8795. /**
  8796. * @param {Event} event Browser event.
  8797. * @protected
  8798. */
  8799. ol.control.MousePosition.prototype.handleMouseMove = function(event) {
  8800. var map = this.getMap();
  8801. this.lastMouseMovePixel_ = map.getEventPixel(event);
  8802. this.updateHTML_(this.lastMouseMovePixel_);
  8803. };
  8804. /**
  8805. * @param {Event} event Browser event.
  8806. * @protected
  8807. */
  8808. ol.control.MousePosition.prototype.handleMouseOut = function(event) {
  8809. this.updateHTML_(null);
  8810. this.lastMouseMovePixel_ = null;
  8811. };
  8812. /**
  8813. * @inheritDoc
  8814. * @api
  8815. */
  8816. ol.control.MousePosition.prototype.setMap = function(map) {
  8817. ol.control.Control.prototype.setMap.call(this, map);
  8818. if (map) {
  8819. var viewport = map.getViewport();
  8820. this.listenerKeys.push(
  8821. ol.events.listen(viewport, ol.events.EventType.MOUSEMOVE,
  8822. this.handleMouseMove, this),
  8823. ol.events.listen(viewport, ol.events.EventType.MOUSEOUT,
  8824. this.handleMouseOut, this)
  8825. );
  8826. }
  8827. };
  8828. /**
  8829. * Set the coordinate format type used to render the current position.
  8830. * @param {ol.CoordinateFormatType} format The format to render the current
  8831. * position in.
  8832. * @observable
  8833. * @api
  8834. */
  8835. ol.control.MousePosition.prototype.setCoordinateFormat = function(format) {
  8836. this.set(ol.control.MousePosition.Property_.COORDINATE_FORMAT, format);
  8837. };
  8838. /**
  8839. * Set the projection that is used to report the mouse position.
  8840. * @param {ol.ProjectionLike} projection The projection to report mouse
  8841. * position in.
  8842. * @observable
  8843. * @api
  8844. */
  8845. ol.control.MousePosition.prototype.setProjection = function(projection) {
  8846. this.set(ol.control.MousePosition.Property_.PROJECTION, ol.proj.get(projection));
  8847. };
  8848. /**
  8849. * @param {?ol.Pixel} pixel Pixel.
  8850. * @private
  8851. */
  8852. ol.control.MousePosition.prototype.updateHTML_ = function(pixel) {
  8853. var html = this.undefinedHTML_;
  8854. if (pixel && this.mapProjection_) {
  8855. if (!this.transform_) {
  8856. var projection = this.getProjection();
  8857. if (projection) {
  8858. this.transform_ = ol.proj.getTransformFromProjections(
  8859. this.mapProjection_, projection);
  8860. } else {
  8861. this.transform_ = ol.proj.identityTransform;
  8862. }
  8863. }
  8864. var map = this.getMap();
  8865. var coordinate = map.getCoordinateFromPixel(pixel);
  8866. if (coordinate) {
  8867. this.transform_(coordinate, coordinate);
  8868. var coordinateFormat = this.getCoordinateFormat();
  8869. if (coordinateFormat) {
  8870. html = coordinateFormat(coordinate);
  8871. } else {
  8872. html = coordinate.toString();
  8873. }
  8874. }
  8875. }
  8876. if (!this.renderedHTML_ || html != this.renderedHTML_) {
  8877. this.element.innerHTML = html;
  8878. this.renderedHTML_ = html;
  8879. }
  8880. };
  8881. /**
  8882. * @enum {string}
  8883. * @private
  8884. */
  8885. ol.control.MousePosition.Property_ = {
  8886. PROJECTION: 'projection',
  8887. COORDINATE_FORMAT: 'coordinateFormat'
  8888. };
  8889. goog.provide('ol.MapEvent');
  8890. goog.require('ol');
  8891. goog.require('ol.events.Event');
  8892. /**
  8893. * @classdesc
  8894. * Events emitted as map events are instances of this type.
  8895. * See {@link ol.Map} for which events trigger a map event.
  8896. *
  8897. * @constructor
  8898. * @extends {ol.events.Event}
  8899. * @implements {oli.MapEvent}
  8900. * @param {string} type Event type.
  8901. * @param {ol.Map} map Map.
  8902. * @param {?olx.FrameState=} opt_frameState Frame state.
  8903. */
  8904. ol.MapEvent = function(type, map, opt_frameState) {
  8905. ol.events.Event.call(this, type);
  8906. /**
  8907. * The map where the event occurred.
  8908. * @type {ol.Map}
  8909. * @api
  8910. */
  8911. this.map = map;
  8912. /**
  8913. * The frame state at the time of the event.
  8914. * @type {?olx.FrameState}
  8915. * @api
  8916. */
  8917. this.frameState = opt_frameState !== undefined ? opt_frameState : null;
  8918. };
  8919. ol.inherits(ol.MapEvent, ol.events.Event);
  8920. goog.provide('ol.MapBrowserEvent');
  8921. goog.require('ol');
  8922. goog.require('ol.MapEvent');
  8923. /**
  8924. * @classdesc
  8925. * Events emitted as map browser events are instances of this type.
  8926. * See {@link ol.Map} for which events trigger a map browser event.
  8927. *
  8928. * @constructor
  8929. * @extends {ol.MapEvent}
  8930. * @implements {oli.MapBrowserEvent}
  8931. * @param {string} type Event type.
  8932. * @param {ol.Map} map Map.
  8933. * @param {Event} browserEvent Browser event.
  8934. * @param {boolean=} opt_dragging Is the map currently being dragged?
  8935. * @param {?olx.FrameState=} opt_frameState Frame state.
  8936. */
  8937. ol.MapBrowserEvent = function(type, map, browserEvent, opt_dragging,
  8938. opt_frameState) {
  8939. ol.MapEvent.call(this, type, map, opt_frameState);
  8940. /**
  8941. * The original browser event.
  8942. * @const
  8943. * @type {Event}
  8944. * @api
  8945. */
  8946. this.originalEvent = browserEvent;
  8947. /**
  8948. * The map pixel relative to the viewport corresponding to the original browser event.
  8949. * @type {ol.Pixel}
  8950. * @api
  8951. */
  8952. this.pixel = map.getEventPixel(browserEvent);
  8953. /**
  8954. * The coordinate in view projection corresponding to the original browser event.
  8955. * @type {ol.Coordinate}
  8956. * @api
  8957. */
  8958. this.coordinate = map.getCoordinateFromPixel(this.pixel);
  8959. /**
  8960. * Indicates if the map is currently being dragged. Only set for
  8961. * `POINTERDRAG` and `POINTERMOVE` events. Default is `false`.
  8962. *
  8963. * @type {boolean}
  8964. * @api
  8965. */
  8966. this.dragging = opt_dragging !== undefined ? opt_dragging : false;
  8967. };
  8968. ol.inherits(ol.MapBrowserEvent, ol.MapEvent);
  8969. /**
  8970. * Prevents the default browser action.
  8971. * @see https://developer.mozilla.org/en-US/docs/Web/API/event.preventDefault
  8972. * @override
  8973. * @api
  8974. */
  8975. ol.MapBrowserEvent.prototype.preventDefault = function() {
  8976. ol.MapEvent.prototype.preventDefault.call(this);
  8977. this.originalEvent.preventDefault();
  8978. };
  8979. /**
  8980. * Prevents further propagation of the current event.
  8981. * @see https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation
  8982. * @override
  8983. * @api
  8984. */
  8985. ol.MapBrowserEvent.prototype.stopPropagation = function() {
  8986. ol.MapEvent.prototype.stopPropagation.call(this);
  8987. this.originalEvent.stopPropagation();
  8988. };
  8989. goog.provide('ol.webgl');
  8990. goog.require('ol');
  8991. if (ol.ENABLE_WEBGL) {
  8992. /** Constants taken from goog.webgl
  8993. */
  8994. /**
  8995. * @const
  8996. * @type {number}
  8997. */
  8998. ol.webgl.ONE = 1;
  8999. /**
  9000. * @const
  9001. * @type {number}
  9002. */
  9003. ol.webgl.SRC_ALPHA = 0x0302;
  9004. /**
  9005. * @const
  9006. * @type {number}
  9007. */
  9008. ol.webgl.COLOR_ATTACHMENT0 = 0x8CE0;
  9009. /**
  9010. * @const
  9011. * @type {number}
  9012. */
  9013. ol.webgl.COLOR_BUFFER_BIT = 0x00004000;
  9014. /**
  9015. * @const
  9016. * @type {number}
  9017. */
  9018. ol.webgl.TRIANGLES = 0x0004;
  9019. /**
  9020. * @const
  9021. * @type {number}
  9022. */
  9023. ol.webgl.TRIANGLE_STRIP = 0x0005;
  9024. /**
  9025. * @const
  9026. * @type {number}
  9027. */
  9028. ol.webgl.ONE_MINUS_SRC_ALPHA = 0x0303;
  9029. /**
  9030. * @const
  9031. * @type {number}
  9032. */
  9033. ol.webgl.ARRAY_BUFFER = 0x8892;
  9034. /**
  9035. * @const
  9036. * @type {number}
  9037. */
  9038. ol.webgl.ELEMENT_ARRAY_BUFFER = 0x8893;
  9039. /**
  9040. * @const
  9041. * @type {number}
  9042. */
  9043. ol.webgl.STREAM_DRAW = 0x88E0;
  9044. /**
  9045. * @const
  9046. * @type {number}
  9047. */
  9048. ol.webgl.STATIC_DRAW = 0x88E4;
  9049. /**
  9050. * @const
  9051. * @type {number}
  9052. */
  9053. ol.webgl.DYNAMIC_DRAW = 0x88E8;
  9054. /**
  9055. * @const
  9056. * @type {number}
  9057. */
  9058. ol.webgl.CULL_FACE = 0x0B44;
  9059. /**
  9060. * @const
  9061. * @type {number}
  9062. */
  9063. ol.webgl.BLEND = 0x0BE2;
  9064. /**
  9065. * @const
  9066. * @type {number}
  9067. */
  9068. ol.webgl.STENCIL_TEST = 0x0B90;
  9069. /**
  9070. * @const
  9071. * @type {number}
  9072. */
  9073. ol.webgl.DEPTH_TEST = 0x0B71;
  9074. /**
  9075. * @const
  9076. * @type {number}
  9077. */
  9078. ol.webgl.SCISSOR_TEST = 0x0C11;
  9079. /**
  9080. * @const
  9081. * @type {number}
  9082. */
  9083. ol.webgl.UNSIGNED_BYTE = 0x1401;
  9084. /**
  9085. * @const
  9086. * @type {number}
  9087. */
  9088. ol.webgl.UNSIGNED_SHORT = 0x1403;
  9089. /**
  9090. * @const
  9091. * @type {number}
  9092. */
  9093. ol.webgl.UNSIGNED_INT = 0x1405;
  9094. /**
  9095. * @const
  9096. * @type {number}
  9097. */
  9098. ol.webgl.FLOAT = 0x1406;
  9099. /**
  9100. * @const
  9101. * @type {number}
  9102. */
  9103. ol.webgl.RGBA = 0x1908;
  9104. /**
  9105. * @const
  9106. * @type {number}
  9107. */
  9108. ol.webgl.FRAGMENT_SHADER = 0x8B30;
  9109. /**
  9110. * @const
  9111. * @type {number}
  9112. */
  9113. ol.webgl.VERTEX_SHADER = 0x8B31;
  9114. /**
  9115. * @const
  9116. * @type {number}
  9117. */
  9118. ol.webgl.LINK_STATUS = 0x8B82;
  9119. /**
  9120. * @const
  9121. * @type {number}
  9122. */
  9123. ol.webgl.LINEAR = 0x2601;
  9124. /**
  9125. * @const
  9126. * @type {number}
  9127. */
  9128. ol.webgl.TEXTURE_MAG_FILTER = 0x2800;
  9129. /**
  9130. * @const
  9131. * @type {number}
  9132. */
  9133. ol.webgl.TEXTURE_MIN_FILTER = 0x2801;
  9134. /**
  9135. * @const
  9136. * @type {number}
  9137. */
  9138. ol.webgl.TEXTURE_WRAP_S = 0x2802;
  9139. /**
  9140. * @const
  9141. * @type {number}
  9142. */
  9143. ol.webgl.TEXTURE_WRAP_T = 0x2803;
  9144. /**
  9145. * @const
  9146. * @type {number}
  9147. */
  9148. ol.webgl.TEXTURE_2D = 0x0DE1;
  9149. /**
  9150. * @const
  9151. * @type {number}
  9152. */
  9153. ol.webgl.TEXTURE0 = 0x84C0;
  9154. /**
  9155. * @const
  9156. * @type {number}
  9157. */
  9158. ol.webgl.CLAMP_TO_EDGE = 0x812F;
  9159. /**
  9160. * @const
  9161. * @type {number}
  9162. */
  9163. ol.webgl.COMPILE_STATUS = 0x8B81;
  9164. /**
  9165. * @const
  9166. * @type {number}
  9167. */
  9168. ol.webgl.FRAMEBUFFER = 0x8D40;
  9169. /** end of goog.webgl constants
  9170. */
  9171. /**
  9172. * @const
  9173. * @private
  9174. * @type {Array.<string>}
  9175. */
  9176. ol.webgl.CONTEXT_IDS_ = [
  9177. 'experimental-webgl',
  9178. 'webgl',
  9179. 'webkit-3d',
  9180. 'moz-webgl'
  9181. ];
  9182. /**
  9183. * @param {HTMLCanvasElement} canvas Canvas.
  9184. * @param {Object=} opt_attributes Attributes.
  9185. * @return {WebGLRenderingContext} WebGL rendering context.
  9186. */
  9187. ol.webgl.getContext = function(canvas, opt_attributes) {
  9188. var context, i, ii = ol.webgl.CONTEXT_IDS_.length;
  9189. for (i = 0; i < ii; ++i) {
  9190. try {
  9191. context = canvas.getContext(ol.webgl.CONTEXT_IDS_[i], opt_attributes);
  9192. if (context) {
  9193. return /** @type {!WebGLRenderingContext} */ (context);
  9194. }
  9195. } catch (e) {
  9196. // pass
  9197. }
  9198. }
  9199. return null;
  9200. };
  9201. }
  9202. goog.provide('ol.has');
  9203. goog.require('ol');
  9204. goog.require('ol.webgl');
  9205. var ua = typeof navigator !== 'undefined' ?
  9206. navigator.userAgent.toLowerCase() : '';
  9207. /**
  9208. * User agent string says we are dealing with Firefox as browser.
  9209. * @type {boolean}
  9210. */
  9211. ol.has.FIREFOX = ua.indexOf('firefox') !== -1;
  9212. /**
  9213. * User agent string says we are dealing with Safari as browser.
  9214. * @type {boolean}
  9215. */
  9216. ol.has.SAFARI = ua.indexOf('safari') !== -1 && ua.indexOf('chrom') == -1;
  9217. /**
  9218. * User agent string says we are dealing with a WebKit engine.
  9219. * @type {boolean}
  9220. */
  9221. ol.has.WEBKIT = ua.indexOf('webkit') !== -1 && ua.indexOf('edge') == -1;
  9222. /**
  9223. * User agent string says we are dealing with a Mac as platform.
  9224. * @type {boolean}
  9225. */
  9226. ol.has.MAC = ua.indexOf('macintosh') !== -1;
  9227. /**
  9228. * The ratio between physical pixels and device-independent pixels
  9229. * (dips) on the device (`window.devicePixelRatio`).
  9230. * @const
  9231. * @type {number}
  9232. * @api
  9233. */
  9234. ol.has.DEVICE_PIXEL_RATIO = window.devicePixelRatio || 1;
  9235. /**
  9236. * True if the browser's Canvas implementation implements {get,set}LineDash.
  9237. * @type {boolean}
  9238. */
  9239. ol.has.CANVAS_LINE_DASH = false;
  9240. /**
  9241. * True if both the library and browser support Canvas. Always `false`
  9242. * if `ol.ENABLE_CANVAS` is set to `false` at compile time.
  9243. * @const
  9244. * @type {boolean}
  9245. * @api
  9246. */
  9247. ol.has.CANVAS = ol.ENABLE_CANVAS && (
  9248. /**
  9249. * @return {boolean} Canvas supported.
  9250. */
  9251. function() {
  9252. if (!('HTMLCanvasElement' in window)) {
  9253. return false;
  9254. }
  9255. try {
  9256. var context = document.createElement('CANVAS').getContext('2d');
  9257. if (!context) {
  9258. return false;
  9259. } else {
  9260. if (context.setLineDash !== undefined) {
  9261. ol.has.CANVAS_LINE_DASH = true;
  9262. }
  9263. return true;
  9264. }
  9265. } catch (e) {
  9266. return false;
  9267. }
  9268. })();
  9269. /**
  9270. * Indicates if DeviceOrientation is supported in the user's browser.
  9271. * @const
  9272. * @type {boolean}
  9273. * @api
  9274. */
  9275. ol.has.DEVICE_ORIENTATION = 'DeviceOrientationEvent' in window;
  9276. /**
  9277. * Is HTML5 geolocation supported in the current browser?
  9278. * @const
  9279. * @type {boolean}
  9280. * @api
  9281. */
  9282. ol.has.GEOLOCATION = 'geolocation' in navigator;
  9283. /**
  9284. * True if browser supports touch events.
  9285. * @const
  9286. * @type {boolean}
  9287. * @api
  9288. */
  9289. ol.has.TOUCH = ol.ASSUME_TOUCH || 'ontouchstart' in window;
  9290. /**
  9291. * True if browser supports pointer events.
  9292. * @const
  9293. * @type {boolean}
  9294. */
  9295. ol.has.POINTER = 'PointerEvent' in window;
  9296. /**
  9297. * True if browser supports ms pointer events (IE 10).
  9298. * @const
  9299. * @type {boolean}
  9300. */
  9301. ol.has.MSPOINTER = !!(navigator.msPointerEnabled);
  9302. /**
  9303. * True if both OpenLayers and browser support WebGL. Always `false`
  9304. * if `ol.ENABLE_WEBGL` is set to `false` at compile time.
  9305. * @const
  9306. * @type {boolean}
  9307. * @api
  9308. */
  9309. ol.has.WEBGL;
  9310. (function() {
  9311. if (ol.ENABLE_WEBGL) {
  9312. var hasWebGL = false;
  9313. var textureSize;
  9314. var /** @type {Array.<string>} */ extensions = [];
  9315. if ('WebGLRenderingContext' in window) {
  9316. try {
  9317. var canvas = /** @type {HTMLCanvasElement} */
  9318. (document.createElement('CANVAS'));
  9319. var gl = ol.webgl.getContext(canvas, {
  9320. failIfMajorPerformanceCaveat: true
  9321. });
  9322. if (gl) {
  9323. hasWebGL = true;
  9324. textureSize = /** @type {number} */
  9325. (gl.getParameter(gl.MAX_TEXTURE_SIZE));
  9326. extensions = gl.getSupportedExtensions();
  9327. }
  9328. } catch (e) {
  9329. // pass
  9330. }
  9331. }
  9332. ol.has.WEBGL = hasWebGL;
  9333. ol.WEBGL_EXTENSIONS = extensions;
  9334. ol.WEBGL_MAX_TEXTURE_SIZE = textureSize;
  9335. }
  9336. })();
  9337. goog.provide('ol.MapBrowserEventType');
  9338. goog.require('ol.events.EventType');
  9339. /**
  9340. * Constants for event names.
  9341. * @enum {string}
  9342. */
  9343. ol.MapBrowserEventType = {
  9344. /**
  9345. * A true single click with no dragging and no double click. Note that this
  9346. * event is delayed by 250 ms to ensure that it is not a double click.
  9347. * @event ol.MapBrowserEvent#singleclick
  9348. * @api
  9349. */
  9350. SINGLECLICK: 'singleclick',
  9351. /**
  9352. * A click with no dragging. A double click will fire two of this.
  9353. * @event ol.MapBrowserEvent#click
  9354. * @api
  9355. */
  9356. CLICK: ol.events.EventType.CLICK,
  9357. /**
  9358. * A true double click, with no dragging.
  9359. * @event ol.MapBrowserEvent#dblclick
  9360. * @api
  9361. */
  9362. DBLCLICK: ol.events.EventType.DBLCLICK,
  9363. /**
  9364. * Triggered when a pointer is dragged.
  9365. * @event ol.MapBrowserEvent#pointerdrag
  9366. * @api
  9367. */
  9368. POINTERDRAG: 'pointerdrag',
  9369. /**
  9370. * Triggered when a pointer is moved. Note that on touch devices this is
  9371. * triggered when the map is panned, so is not the same as mousemove.
  9372. * @event ol.MapBrowserEvent#pointermove
  9373. * @api
  9374. */
  9375. POINTERMOVE: 'pointermove',
  9376. POINTERDOWN: 'pointerdown',
  9377. POINTERUP: 'pointerup',
  9378. POINTEROVER: 'pointerover',
  9379. POINTEROUT: 'pointerout',
  9380. POINTERENTER: 'pointerenter',
  9381. POINTERLEAVE: 'pointerleave',
  9382. POINTERCANCEL: 'pointercancel'
  9383. };
  9384. goog.provide('ol.MapBrowserPointerEvent');
  9385. goog.require('ol');
  9386. goog.require('ol.MapBrowserEvent');
  9387. /**
  9388. * @constructor
  9389. * @extends {ol.MapBrowserEvent}
  9390. * @param {string} type Event type.
  9391. * @param {ol.Map} map Map.
  9392. * @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
  9393. * @param {boolean=} opt_dragging Is the map currently being dragged?
  9394. * @param {?olx.FrameState=} opt_frameState Frame state.
  9395. */
  9396. ol.MapBrowserPointerEvent = function(type, map, pointerEvent, opt_dragging,
  9397. opt_frameState) {
  9398. ol.MapBrowserEvent.call(this, type, map, pointerEvent.originalEvent, opt_dragging,
  9399. opt_frameState);
  9400. /**
  9401. * @const
  9402. * @type {ol.pointer.PointerEvent}
  9403. */
  9404. this.pointerEvent = pointerEvent;
  9405. };
  9406. ol.inherits(ol.MapBrowserPointerEvent, ol.MapBrowserEvent);
  9407. goog.provide('ol.pointer.EventType');
  9408. /**
  9409. * Constants for event names.
  9410. * @enum {string}
  9411. */
  9412. ol.pointer.EventType = {
  9413. POINTERMOVE: 'pointermove',
  9414. POINTERDOWN: 'pointerdown',
  9415. POINTERUP: 'pointerup',
  9416. POINTEROVER: 'pointerover',
  9417. POINTEROUT: 'pointerout',
  9418. POINTERENTER: 'pointerenter',
  9419. POINTERLEAVE: 'pointerleave',
  9420. POINTERCANCEL: 'pointercancel'
  9421. };
  9422. goog.provide('ol.pointer.EventSource');
  9423. /**
  9424. * @param {ol.pointer.PointerEventHandler} dispatcher Event handler.
  9425. * @param {!Object.<string, function(Event)>} mapping Event
  9426. * mapping.
  9427. * @constructor
  9428. */
  9429. ol.pointer.EventSource = function(dispatcher, mapping) {
  9430. /**
  9431. * @type {ol.pointer.PointerEventHandler}
  9432. */
  9433. this.dispatcher = dispatcher;
  9434. /**
  9435. * @private
  9436. * @const
  9437. * @type {!Object.<string, function(Event)>}
  9438. */
  9439. this.mapping_ = mapping;
  9440. };
  9441. /**
  9442. * List of events supported by this source.
  9443. * @return {Array.<string>} Event names
  9444. */
  9445. ol.pointer.EventSource.prototype.getEvents = function() {
  9446. return Object.keys(this.mapping_);
  9447. };
  9448. /**
  9449. * Returns the handler that should handle a given event type.
  9450. * @param {string} eventType The event type.
  9451. * @return {function(Event)} Handler
  9452. */
  9453. ol.pointer.EventSource.prototype.getHandlerForEvent = function(eventType) {
  9454. return this.mapping_[eventType];
  9455. };
  9456. // Based on https://github.com/Polymer/PointerEvents
  9457. // Copyright (c) 2013 The Polymer Authors. All rights reserved.
  9458. //
  9459. // Redistribution and use in source and binary forms, with or without
  9460. // modification, are permitted provided that the following conditions are
  9461. // met:
  9462. //
  9463. // * Redistributions of source code must retain the above copyright
  9464. // notice, this list of conditions and the following disclaimer.
  9465. // * Redistributions in binary form must reproduce the above
  9466. // copyright notice, this list of conditions and the following disclaimer
  9467. // in the documentation and/or other materials provided with the
  9468. // distribution.
  9469. // * Neither the name of Google Inc. nor the names of its
  9470. // contributors may be used to endorse or promote products derived from
  9471. // this software without specific prior written permission.
  9472. //
  9473. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  9474. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  9475. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  9476. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9477. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  9478. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9479. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  9480. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  9481. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  9482. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  9483. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  9484. goog.provide('ol.pointer.MouseSource');
  9485. goog.require('ol');
  9486. goog.require('ol.pointer.EventSource');
  9487. /**
  9488. * @param {ol.pointer.PointerEventHandler} dispatcher Event handler.
  9489. * @constructor
  9490. * @extends {ol.pointer.EventSource}
  9491. */
  9492. ol.pointer.MouseSource = function(dispatcher) {
  9493. var mapping = {
  9494. 'mousedown': this.mousedown,
  9495. 'mousemove': this.mousemove,
  9496. 'mouseup': this.mouseup,
  9497. 'mouseover': this.mouseover,
  9498. 'mouseout': this.mouseout
  9499. };
  9500. ol.pointer.EventSource.call(this, dispatcher, mapping);
  9501. /**
  9502. * @const
  9503. * @type {!Object.<string, Event|Object>}
  9504. */
  9505. this.pointerMap = dispatcher.pointerMap;
  9506. /**
  9507. * @const
  9508. * @type {Array.<ol.Pixel>}
  9509. */
  9510. this.lastTouches = [];
  9511. };
  9512. ol.inherits(ol.pointer.MouseSource, ol.pointer.EventSource);
  9513. /**
  9514. * @const
  9515. * @type {number}
  9516. */
  9517. ol.pointer.MouseSource.POINTER_ID = 1;
  9518. /**
  9519. * @const
  9520. * @type {string}
  9521. */
  9522. ol.pointer.MouseSource.POINTER_TYPE = 'mouse';
  9523. /**
  9524. * Radius around touchend that swallows mouse events.
  9525. *
  9526. * @const
  9527. * @type {number}
  9528. */
  9529. ol.pointer.MouseSource.DEDUP_DIST = 25;
  9530. /**
  9531. * Detect if a mouse event was simulated from a touch by
  9532. * checking if previously there was a touch event at the
  9533. * same position.
  9534. *
  9535. * FIXME - Known problem with the native Android browser on
  9536. * Samsung GT-I9100 (Android 4.1.2):
  9537. * In case the page is scrolled, this function does not work
  9538. * correctly when a canvas is used (WebGL or canvas renderer).
  9539. * Mouse listeners on canvas elements (for this browser), create
  9540. * two mouse events: One 'good' and one 'bad' one (on other browsers or
  9541. * when a div is used, there is only one event). For the 'bad' one,
  9542. * clientX/clientY and also pageX/pageY are wrong when the page
  9543. * is scrolled. Because of that, this function can not detect if
  9544. * the events were simulated from a touch event. As result, a
  9545. * pointer event at a wrong position is dispatched, which confuses
  9546. * the map interactions.
  9547. * It is unclear, how one can get the correct position for the event
  9548. * or detect that the positions are invalid.
  9549. *
  9550. * @private
  9551. * @param {Event} inEvent The in event.
  9552. * @return {boolean} True, if the event was generated by a touch.
  9553. */
  9554. ol.pointer.MouseSource.prototype.isEventSimulatedFromTouch_ = function(inEvent) {
  9555. var lts = this.lastTouches;
  9556. var x = inEvent.clientX, y = inEvent.clientY;
  9557. for (var i = 0, l = lts.length, t; i < l && (t = lts[i]); i++) {
  9558. // simulated mouse events will be swallowed near a primary touchend
  9559. var dx = Math.abs(x - t[0]), dy = Math.abs(y - t[1]);
  9560. if (dx <= ol.pointer.MouseSource.DEDUP_DIST &&
  9561. dy <= ol.pointer.MouseSource.DEDUP_DIST) {
  9562. return true;
  9563. }
  9564. }
  9565. return false;
  9566. };
  9567. /**
  9568. * Creates a copy of the original event that will be used
  9569. * for the fake pointer event.
  9570. *
  9571. * @param {Event} inEvent The in event.
  9572. * @param {ol.pointer.PointerEventHandler} dispatcher Event handler.
  9573. * @return {Object} The copied event.
  9574. */
  9575. ol.pointer.MouseSource.prepareEvent = function(inEvent, dispatcher) {
  9576. var e = dispatcher.cloneEvent(inEvent, inEvent);
  9577. // forward mouse preventDefault
  9578. var pd = e.preventDefault;
  9579. e.preventDefault = function() {
  9580. inEvent.preventDefault();
  9581. pd();
  9582. };
  9583. e.pointerId = ol.pointer.MouseSource.POINTER_ID;
  9584. e.isPrimary = true;
  9585. e.pointerType = ol.pointer.MouseSource.POINTER_TYPE;
  9586. return e;
  9587. };
  9588. /**
  9589. * Handler for `mousedown`.
  9590. *
  9591. * @param {Event} inEvent The in event.
  9592. */
  9593. ol.pointer.MouseSource.prototype.mousedown = function(inEvent) {
  9594. if (!this.isEventSimulatedFromTouch_(inEvent)) {
  9595. // TODO(dfreedman) workaround for some elements not sending mouseup
  9596. // http://crbug/149091
  9597. if (ol.pointer.MouseSource.POINTER_ID.toString() in this.pointerMap) {
  9598. this.cancel(inEvent);
  9599. }
  9600. var e = ol.pointer.MouseSource.prepareEvent(inEvent, this.dispatcher);
  9601. this.pointerMap[ol.pointer.MouseSource.POINTER_ID.toString()] = inEvent;
  9602. this.dispatcher.down(e, inEvent);
  9603. }
  9604. };
  9605. /**
  9606. * Handler for `mousemove`.
  9607. *
  9608. * @param {Event} inEvent The in event.
  9609. */
  9610. ol.pointer.MouseSource.prototype.mousemove = function(inEvent) {
  9611. if (!this.isEventSimulatedFromTouch_(inEvent)) {
  9612. var e = ol.pointer.MouseSource.prepareEvent(inEvent, this.dispatcher);
  9613. this.dispatcher.move(e, inEvent);
  9614. }
  9615. };
  9616. /**
  9617. * Handler for `mouseup`.
  9618. *
  9619. * @param {Event} inEvent The in event.
  9620. */
  9621. ol.pointer.MouseSource.prototype.mouseup = function(inEvent) {
  9622. if (!this.isEventSimulatedFromTouch_(inEvent)) {
  9623. var p = this.pointerMap[ol.pointer.MouseSource.POINTER_ID.toString()];
  9624. if (p && p.button === inEvent.button) {
  9625. var e = ol.pointer.MouseSource.prepareEvent(inEvent, this.dispatcher);
  9626. this.dispatcher.up(e, inEvent);
  9627. this.cleanupMouse();
  9628. }
  9629. }
  9630. };
  9631. /**
  9632. * Handler for `mouseover`.
  9633. *
  9634. * @param {Event} inEvent The in event.
  9635. */
  9636. ol.pointer.MouseSource.prototype.mouseover = function(inEvent) {
  9637. if (!this.isEventSimulatedFromTouch_(inEvent)) {
  9638. var e = ol.pointer.MouseSource.prepareEvent(inEvent, this.dispatcher);
  9639. this.dispatcher.enterOver(e, inEvent);
  9640. }
  9641. };
  9642. /**
  9643. * Handler for `mouseout`.
  9644. *
  9645. * @param {Event} inEvent The in event.
  9646. */
  9647. ol.pointer.MouseSource.prototype.mouseout = function(inEvent) {
  9648. if (!this.isEventSimulatedFromTouch_(inEvent)) {
  9649. var e = ol.pointer.MouseSource.prepareEvent(inEvent, this.dispatcher);
  9650. this.dispatcher.leaveOut(e, inEvent);
  9651. }
  9652. };
  9653. /**
  9654. * Dispatches a `pointercancel` event.
  9655. *
  9656. * @param {Event} inEvent The in event.
  9657. */
  9658. ol.pointer.MouseSource.prototype.cancel = function(inEvent) {
  9659. var e = ol.pointer.MouseSource.prepareEvent(inEvent, this.dispatcher);
  9660. this.dispatcher.cancel(e, inEvent);
  9661. this.cleanupMouse();
  9662. };
  9663. /**
  9664. * Remove the mouse from the list of active pointers.
  9665. */
  9666. ol.pointer.MouseSource.prototype.cleanupMouse = function() {
  9667. delete this.pointerMap[ol.pointer.MouseSource.POINTER_ID.toString()];
  9668. };
  9669. // Based on https://github.com/Polymer/PointerEvents
  9670. // Copyright (c) 2013 The Polymer Authors. All rights reserved.
  9671. //
  9672. // Redistribution and use in source and binary forms, with or without
  9673. // modification, are permitted provided that the following conditions are
  9674. // met:
  9675. //
  9676. // * Redistributions of source code must retain the above copyright
  9677. // notice, this list of conditions and the following disclaimer.
  9678. // * Redistributions in binary form must reproduce the above
  9679. // copyright notice, this list of conditions and the following disclaimer
  9680. // in the documentation and/or other materials provided with the
  9681. // distribution.
  9682. // * Neither the name of Google Inc. nor the names of its
  9683. // contributors may be used to endorse or promote products derived from
  9684. // this software without specific prior written permission.
  9685. //
  9686. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  9687. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  9688. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  9689. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9690. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  9691. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9692. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  9693. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  9694. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  9695. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  9696. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  9697. goog.provide('ol.pointer.MsSource');
  9698. goog.require('ol');
  9699. goog.require('ol.pointer.EventSource');
  9700. /**
  9701. * @param {ol.pointer.PointerEventHandler} dispatcher Event handler.
  9702. * @constructor
  9703. * @extends {ol.pointer.EventSource}
  9704. */
  9705. ol.pointer.MsSource = function(dispatcher) {
  9706. var mapping = {
  9707. 'MSPointerDown': this.msPointerDown,
  9708. 'MSPointerMove': this.msPointerMove,
  9709. 'MSPointerUp': this.msPointerUp,
  9710. 'MSPointerOut': this.msPointerOut,
  9711. 'MSPointerOver': this.msPointerOver,
  9712. 'MSPointerCancel': this.msPointerCancel,
  9713. 'MSGotPointerCapture': this.msGotPointerCapture,
  9714. 'MSLostPointerCapture': this.msLostPointerCapture
  9715. };
  9716. ol.pointer.EventSource.call(this, dispatcher, mapping);
  9717. /**
  9718. * @const
  9719. * @type {!Object.<string, Event|Object>}
  9720. */
  9721. this.pointerMap = dispatcher.pointerMap;
  9722. /**
  9723. * @const
  9724. * @type {Array.<string>}
  9725. */
  9726. this.POINTER_TYPES = [
  9727. '',
  9728. 'unavailable',
  9729. 'touch',
  9730. 'pen',
  9731. 'mouse'
  9732. ];
  9733. };
  9734. ol.inherits(ol.pointer.MsSource, ol.pointer.EventSource);
  9735. /**
  9736. * Creates a copy of the original event that will be used
  9737. * for the fake pointer event.
  9738. *
  9739. * @private
  9740. * @param {Event} inEvent The in event.
  9741. * @return {Object} The copied event.
  9742. */
  9743. ol.pointer.MsSource.prototype.prepareEvent_ = function(inEvent) {
  9744. var e = inEvent;
  9745. if (typeof inEvent.pointerType === 'number') {
  9746. e = this.dispatcher.cloneEvent(inEvent, inEvent);
  9747. e.pointerType = this.POINTER_TYPES[inEvent.pointerType];
  9748. }
  9749. return e;
  9750. };
  9751. /**
  9752. * Remove this pointer from the list of active pointers.
  9753. * @param {number} pointerId Pointer identifier.
  9754. */
  9755. ol.pointer.MsSource.prototype.cleanup = function(pointerId) {
  9756. delete this.pointerMap[pointerId.toString()];
  9757. };
  9758. /**
  9759. * Handler for `msPointerDown`.
  9760. *
  9761. * @param {Event} inEvent The in event.
  9762. */
  9763. ol.pointer.MsSource.prototype.msPointerDown = function(inEvent) {
  9764. this.pointerMap[inEvent.pointerId.toString()] = inEvent;
  9765. var e = this.prepareEvent_(inEvent);
  9766. this.dispatcher.down(e, inEvent);
  9767. };
  9768. /**
  9769. * Handler for `msPointerMove`.
  9770. *
  9771. * @param {Event} inEvent The in event.
  9772. */
  9773. ol.pointer.MsSource.prototype.msPointerMove = function(inEvent) {
  9774. var e = this.prepareEvent_(inEvent);
  9775. this.dispatcher.move(e, inEvent);
  9776. };
  9777. /**
  9778. * Handler for `msPointerUp`.
  9779. *
  9780. * @param {Event} inEvent The in event.
  9781. */
  9782. ol.pointer.MsSource.prototype.msPointerUp = function(inEvent) {
  9783. var e = this.prepareEvent_(inEvent);
  9784. this.dispatcher.up(e, inEvent);
  9785. this.cleanup(inEvent.pointerId);
  9786. };
  9787. /**
  9788. * Handler for `msPointerOut`.
  9789. *
  9790. * @param {Event} inEvent The in event.
  9791. */
  9792. ol.pointer.MsSource.prototype.msPointerOut = function(inEvent) {
  9793. var e = this.prepareEvent_(inEvent);
  9794. this.dispatcher.leaveOut(e, inEvent);
  9795. };
  9796. /**
  9797. * Handler for `msPointerOver`.
  9798. *
  9799. * @param {Event} inEvent The in event.
  9800. */
  9801. ol.pointer.MsSource.prototype.msPointerOver = function(inEvent) {
  9802. var e = this.prepareEvent_(inEvent);
  9803. this.dispatcher.enterOver(e, inEvent);
  9804. };
  9805. /**
  9806. * Handler for `msPointerCancel`.
  9807. *
  9808. * @param {Event} inEvent The in event.
  9809. */
  9810. ol.pointer.MsSource.prototype.msPointerCancel = function(inEvent) {
  9811. var e = this.prepareEvent_(inEvent);
  9812. this.dispatcher.cancel(e, inEvent);
  9813. this.cleanup(inEvent.pointerId);
  9814. };
  9815. /**
  9816. * Handler for `msLostPointerCapture`.
  9817. *
  9818. * @param {Event} inEvent The in event.
  9819. */
  9820. ol.pointer.MsSource.prototype.msLostPointerCapture = function(inEvent) {
  9821. var e = this.dispatcher.makeEvent('lostpointercapture',
  9822. inEvent, inEvent);
  9823. this.dispatcher.dispatchEvent(e);
  9824. };
  9825. /**
  9826. * Handler for `msGotPointerCapture`.
  9827. *
  9828. * @param {Event} inEvent The in event.
  9829. */
  9830. ol.pointer.MsSource.prototype.msGotPointerCapture = function(inEvent) {
  9831. var e = this.dispatcher.makeEvent('gotpointercapture',
  9832. inEvent, inEvent);
  9833. this.dispatcher.dispatchEvent(e);
  9834. };
  9835. // Based on https://github.com/Polymer/PointerEvents
  9836. // Copyright (c) 2013 The Polymer Authors. All rights reserved.
  9837. //
  9838. // Redistribution and use in source and binary forms, with or without
  9839. // modification, are permitted provided that the following conditions are
  9840. // met:
  9841. //
  9842. // * Redistributions of source code must retain the above copyright
  9843. // notice, this list of conditions and the following disclaimer.
  9844. // * Redistributions in binary form must reproduce the above
  9845. // copyright notice, this list of conditions and the following disclaimer
  9846. // in the documentation and/or other materials provided with the
  9847. // distribution.
  9848. // * Neither the name of Google Inc. nor the names of its
  9849. // contributors may be used to endorse or promote products derived from
  9850. // this software without specific prior written permission.
  9851. //
  9852. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  9853. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  9854. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  9855. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9856. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  9857. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9858. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  9859. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  9860. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  9861. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  9862. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  9863. goog.provide('ol.pointer.NativeSource');
  9864. goog.require('ol');
  9865. goog.require('ol.pointer.EventSource');
  9866. /**
  9867. * @param {ol.pointer.PointerEventHandler} dispatcher Event handler.
  9868. * @constructor
  9869. * @extends {ol.pointer.EventSource}
  9870. */
  9871. ol.pointer.NativeSource = function(dispatcher) {
  9872. var mapping = {
  9873. 'pointerdown': this.pointerDown,
  9874. 'pointermove': this.pointerMove,
  9875. 'pointerup': this.pointerUp,
  9876. 'pointerout': this.pointerOut,
  9877. 'pointerover': this.pointerOver,
  9878. 'pointercancel': this.pointerCancel,
  9879. 'gotpointercapture': this.gotPointerCapture,
  9880. 'lostpointercapture': this.lostPointerCapture
  9881. };
  9882. ol.pointer.EventSource.call(this, dispatcher, mapping);
  9883. };
  9884. ol.inherits(ol.pointer.NativeSource, ol.pointer.EventSource);
  9885. /**
  9886. * Handler for `pointerdown`.
  9887. *
  9888. * @param {Event} inEvent The in event.
  9889. */
  9890. ol.pointer.NativeSource.prototype.pointerDown = function(inEvent) {
  9891. this.dispatcher.fireNativeEvent(inEvent);
  9892. };
  9893. /**
  9894. * Handler for `pointermove`.
  9895. *
  9896. * @param {Event} inEvent The in event.
  9897. */
  9898. ol.pointer.NativeSource.prototype.pointerMove = function(inEvent) {
  9899. this.dispatcher.fireNativeEvent(inEvent);
  9900. };
  9901. /**
  9902. * Handler for `pointerup`.
  9903. *
  9904. * @param {Event} inEvent The in event.
  9905. */
  9906. ol.pointer.NativeSource.prototype.pointerUp = function(inEvent) {
  9907. this.dispatcher.fireNativeEvent(inEvent);
  9908. };
  9909. /**
  9910. * Handler for `pointerout`.
  9911. *
  9912. * @param {Event} inEvent The in event.
  9913. */
  9914. ol.pointer.NativeSource.prototype.pointerOut = function(inEvent) {
  9915. this.dispatcher.fireNativeEvent(inEvent);
  9916. };
  9917. /**
  9918. * Handler for `pointerover`.
  9919. *
  9920. * @param {Event} inEvent The in event.
  9921. */
  9922. ol.pointer.NativeSource.prototype.pointerOver = function(inEvent) {
  9923. this.dispatcher.fireNativeEvent(inEvent);
  9924. };
  9925. /**
  9926. * Handler for `pointercancel`.
  9927. *
  9928. * @param {Event} inEvent The in event.
  9929. */
  9930. ol.pointer.NativeSource.prototype.pointerCancel = function(inEvent) {
  9931. this.dispatcher.fireNativeEvent(inEvent);
  9932. };
  9933. /**
  9934. * Handler for `lostpointercapture`.
  9935. *
  9936. * @param {Event} inEvent The in event.
  9937. */
  9938. ol.pointer.NativeSource.prototype.lostPointerCapture = function(inEvent) {
  9939. this.dispatcher.fireNativeEvent(inEvent);
  9940. };
  9941. /**
  9942. * Handler for `gotpointercapture`.
  9943. *
  9944. * @param {Event} inEvent The in event.
  9945. */
  9946. ol.pointer.NativeSource.prototype.gotPointerCapture = function(inEvent) {
  9947. this.dispatcher.fireNativeEvent(inEvent);
  9948. };
  9949. // Based on https://github.com/Polymer/PointerEvents
  9950. // Copyright (c) 2013 The Polymer Authors. All rights reserved.
  9951. //
  9952. // Redistribution and use in source and binary forms, with or without
  9953. // modification, are permitted provided that the following conditions are
  9954. // met:
  9955. //
  9956. // * Redistributions of source code must retain the above copyright
  9957. // notice, this list of conditions and the following disclaimer.
  9958. // * Redistributions in binary form must reproduce the above
  9959. // copyright notice, this list of conditions and the following disclaimer
  9960. // in the documentation and/or other materials provided with the
  9961. // distribution.
  9962. // * Neither the name of Google Inc. nor the names of its
  9963. // contributors may be used to endorse or promote products derived from
  9964. // this software without specific prior written permission.
  9965. //
  9966. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  9967. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  9968. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  9969. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9970. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  9971. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9972. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  9973. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  9974. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  9975. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  9976. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  9977. goog.provide('ol.pointer.PointerEvent');
  9978. goog.require('ol');
  9979. goog.require('ol.events.Event');
  9980. /**
  9981. * A class for pointer events.
  9982. *
  9983. * This class is used as an abstraction for mouse events,
  9984. * touch events and even native pointer events.
  9985. *
  9986. * @constructor
  9987. * @extends {ol.events.Event}
  9988. * @param {string} type The type of the event to create.
  9989. * @param {Event} originalEvent The event.
  9990. * @param {Object.<string, ?>=} opt_eventDict An optional dictionary of
  9991. * initial event properties.
  9992. */
  9993. ol.pointer.PointerEvent = function(type, originalEvent, opt_eventDict) {
  9994. ol.events.Event.call(this, type);
  9995. /**
  9996. * @const
  9997. * @type {Event}
  9998. */
  9999. this.originalEvent = originalEvent;
  10000. var eventDict = opt_eventDict ? opt_eventDict : {};
  10001. /**
  10002. * @type {number}
  10003. */
  10004. this.buttons = this.getButtons_(eventDict);
  10005. /**
  10006. * @type {number}
  10007. */
  10008. this.pressure = this.getPressure_(eventDict, this.buttons);
  10009. // MouseEvent related properties
  10010. /**
  10011. * @type {boolean}
  10012. */
  10013. this.bubbles = 'bubbles' in eventDict ? eventDict['bubbles'] : false;
  10014. /**
  10015. * @type {boolean}
  10016. */
  10017. this.cancelable = 'cancelable' in eventDict ? eventDict['cancelable'] : false;
  10018. /**
  10019. * @type {Object}
  10020. */
  10021. this.view = 'view' in eventDict ? eventDict['view'] : null;
  10022. /**
  10023. * @type {number}
  10024. */
  10025. this.detail = 'detail' in eventDict ? eventDict['detail'] : null;
  10026. /**
  10027. * @type {number}
  10028. */
  10029. this.screenX = 'screenX' in eventDict ? eventDict['screenX'] : 0;
  10030. /**
  10031. * @type {number}
  10032. */
  10033. this.screenY = 'screenY' in eventDict ? eventDict['screenY'] : 0;
  10034. /**
  10035. * @type {number}
  10036. */
  10037. this.clientX = 'clientX' in eventDict ? eventDict['clientX'] : 0;
  10038. /**
  10039. * @type {number}
  10040. */
  10041. this.clientY = 'clientY' in eventDict ? eventDict['clientY'] : 0;
  10042. /**
  10043. * @type {boolean}
  10044. */
  10045. this.ctrlKey = 'ctrlKey' in eventDict ? eventDict['ctrlKey'] : false;
  10046. /**
  10047. * @type {boolean}
  10048. */
  10049. this.altKey = 'altKey' in eventDict ? eventDict['altKey'] : false;
  10050. /**
  10051. * @type {boolean}
  10052. */
  10053. this.shiftKey = 'shiftKey' in eventDict ? eventDict['shiftKey'] : false;
  10054. /**
  10055. * @type {boolean}
  10056. */
  10057. this.metaKey = 'metaKey' in eventDict ? eventDict['metaKey'] : false;
  10058. /**
  10059. * @type {number}
  10060. */
  10061. this.button = 'button' in eventDict ? eventDict['button'] : 0;
  10062. /**
  10063. * @type {Node}
  10064. */
  10065. this.relatedTarget = 'relatedTarget' in eventDict ?
  10066. eventDict['relatedTarget'] : null;
  10067. // PointerEvent related properties
  10068. /**
  10069. * @const
  10070. * @type {number}
  10071. */
  10072. this.pointerId = 'pointerId' in eventDict ? eventDict['pointerId'] : 0;
  10073. /**
  10074. * @type {number}
  10075. */
  10076. this.width = 'width' in eventDict ? eventDict['width'] : 0;
  10077. /**
  10078. * @type {number}
  10079. */
  10080. this.height = 'height' in eventDict ? eventDict['height'] : 0;
  10081. /**
  10082. * @type {number}
  10083. */
  10084. this.tiltX = 'tiltX' in eventDict ? eventDict['tiltX'] : 0;
  10085. /**
  10086. * @type {number}
  10087. */
  10088. this.tiltY = 'tiltY' in eventDict ? eventDict['tiltY'] : 0;
  10089. /**
  10090. * @type {string}
  10091. */
  10092. this.pointerType = 'pointerType' in eventDict ? eventDict['pointerType'] : '';
  10093. /**
  10094. * @type {number}
  10095. */
  10096. this.hwTimestamp = 'hwTimestamp' in eventDict ? eventDict['hwTimestamp'] : 0;
  10097. /**
  10098. * @type {boolean}
  10099. */
  10100. this.isPrimary = 'isPrimary' in eventDict ? eventDict['isPrimary'] : false;
  10101. // keep the semantics of preventDefault
  10102. if (originalEvent.preventDefault) {
  10103. this.preventDefault = function() {
  10104. originalEvent.preventDefault();
  10105. };
  10106. }
  10107. };
  10108. ol.inherits(ol.pointer.PointerEvent, ol.events.Event);
  10109. /**
  10110. * @private
  10111. * @param {Object.<string, ?>} eventDict The event dictionary.
  10112. * @return {number} Button indicator.
  10113. */
  10114. ol.pointer.PointerEvent.prototype.getButtons_ = function(eventDict) {
  10115. // According to the w3c spec,
  10116. // http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-button
  10117. // MouseEvent.button == 0 can mean either no mouse button depressed, or the
  10118. // left mouse button depressed.
  10119. //
  10120. // As of now, the only way to distinguish between the two states of
  10121. // MouseEvent.button is by using the deprecated MouseEvent.which property, as
  10122. // this maps mouse buttons to positive integers > 0, and uses 0 to mean that
  10123. // no mouse button is held.
  10124. //
  10125. // MouseEvent.which is derived from MouseEvent.button at MouseEvent creation,
  10126. // but initMouseEvent does not expose an argument with which to set
  10127. // MouseEvent.which. Calling initMouseEvent with a buttonArg of 0 will set
  10128. // MouseEvent.button == 0 and MouseEvent.which == 1, breaking the expectations
  10129. // of app developers.
  10130. //
  10131. // The only way to propagate the correct state of MouseEvent.which and
  10132. // MouseEvent.button to a new MouseEvent.button == 0 and MouseEvent.which == 0
  10133. // is to call initMouseEvent with a buttonArg value of -1.
  10134. //
  10135. // This is fixed with DOM Level 4's use of buttons
  10136. var buttons;
  10137. if (eventDict.buttons || ol.pointer.PointerEvent.HAS_BUTTONS) {
  10138. buttons = eventDict.buttons;
  10139. } else {
  10140. switch (eventDict.which) {
  10141. case 1: buttons = 1; break;
  10142. case 2: buttons = 4; break;
  10143. case 3: buttons = 2; break;
  10144. default: buttons = 0;
  10145. }
  10146. }
  10147. return buttons;
  10148. };
  10149. /**
  10150. * @private
  10151. * @param {Object.<string, ?>} eventDict The event dictionary.
  10152. * @param {number} buttons Button indicator.
  10153. * @return {number} The pressure.
  10154. */
  10155. ol.pointer.PointerEvent.prototype.getPressure_ = function(eventDict, buttons) {
  10156. // Spec requires that pointers without pressure specified use 0.5 for down
  10157. // state and 0 for up state.
  10158. var pressure = 0;
  10159. if (eventDict.pressure) {
  10160. pressure = eventDict.pressure;
  10161. } else {
  10162. pressure = buttons ? 0.5 : 0;
  10163. }
  10164. return pressure;
  10165. };
  10166. /**
  10167. * Is the `buttons` property supported?
  10168. * @type {boolean}
  10169. */
  10170. ol.pointer.PointerEvent.HAS_BUTTONS = false;
  10171. /**
  10172. * Checks if the `buttons` property is supported.
  10173. */
  10174. (function() {
  10175. try {
  10176. var ev = new MouseEvent('click', {buttons: 1});
  10177. ol.pointer.PointerEvent.HAS_BUTTONS = ev.buttons === 1;
  10178. } catch (e) {
  10179. // pass
  10180. }
  10181. })();
  10182. // Based on https://github.com/Polymer/PointerEvents
  10183. // Copyright (c) 2013 The Polymer Authors. All rights reserved.
  10184. //
  10185. // Redistribution and use in source and binary forms, with or without
  10186. // modification, are permitted provided that the following conditions are
  10187. // met:
  10188. //
  10189. // * Redistributions of source code must retain the above copyright
  10190. // notice, this list of conditions and the following disclaimer.
  10191. // * Redistributions in binary form must reproduce the above
  10192. // copyright notice, this list of conditions and the following disclaimer
  10193. // in the documentation and/or other materials provided with the
  10194. // distribution.
  10195. // * Neither the name of Google Inc. nor the names of its
  10196. // contributors may be used to endorse or promote products derived from
  10197. // this software without specific prior written permission.
  10198. //
  10199. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  10200. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  10201. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  10202. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  10203. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10204. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  10205. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10206. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  10207. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  10208. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  10209. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  10210. goog.provide('ol.pointer.TouchSource');
  10211. goog.require('ol');
  10212. goog.require('ol.array');
  10213. goog.require('ol.pointer.EventSource');
  10214. goog.require('ol.pointer.MouseSource');
  10215. /**
  10216. * @constructor
  10217. * @param {ol.pointer.PointerEventHandler} dispatcher The event handler.
  10218. * @param {ol.pointer.MouseSource} mouseSource Mouse source.
  10219. * @extends {ol.pointer.EventSource}
  10220. */
  10221. ol.pointer.TouchSource = function(dispatcher, mouseSource) {
  10222. var mapping = {
  10223. 'touchstart': this.touchstart,
  10224. 'touchmove': this.touchmove,
  10225. 'touchend': this.touchend,
  10226. 'touchcancel': this.touchcancel
  10227. };
  10228. ol.pointer.EventSource.call(this, dispatcher, mapping);
  10229. /**
  10230. * @const
  10231. * @type {!Object.<string, Event|Object>}
  10232. */
  10233. this.pointerMap = dispatcher.pointerMap;
  10234. /**
  10235. * @const
  10236. * @type {ol.pointer.MouseSource}
  10237. */
  10238. this.mouseSource = mouseSource;
  10239. /**
  10240. * @private
  10241. * @type {number|undefined}
  10242. */
  10243. this.firstTouchId_ = undefined;
  10244. /**
  10245. * @private
  10246. * @type {number}
  10247. */
  10248. this.clickCount_ = 0;
  10249. /**
  10250. * @private
  10251. * @type {number|undefined}
  10252. */
  10253. this.resetId_ = undefined;
  10254. };
  10255. ol.inherits(ol.pointer.TouchSource, ol.pointer.EventSource);
  10256. /**
  10257. * Mouse event timeout: This should be long enough to
  10258. * ignore compat mouse events made by touch.
  10259. * @const
  10260. * @type {number}
  10261. */
  10262. ol.pointer.TouchSource.DEDUP_TIMEOUT = 2500;
  10263. /**
  10264. * @const
  10265. * @type {number}
  10266. */
  10267. ol.pointer.TouchSource.CLICK_COUNT_TIMEOUT = 200;
  10268. /**
  10269. * @const
  10270. * @type {string}
  10271. */
  10272. ol.pointer.TouchSource.POINTER_TYPE = 'touch';
  10273. /**
  10274. * @private
  10275. * @param {Touch} inTouch The in touch.
  10276. * @return {boolean} True, if this is the primary touch.
  10277. */
  10278. ol.pointer.TouchSource.prototype.isPrimaryTouch_ = function(inTouch) {
  10279. return this.firstTouchId_ === inTouch.identifier;
  10280. };
  10281. /**
  10282. * Set primary touch if there are no pointers, or the only pointer is the mouse.
  10283. * @param {Touch} inTouch The in touch.
  10284. * @private
  10285. */
  10286. ol.pointer.TouchSource.prototype.setPrimaryTouch_ = function(inTouch) {
  10287. var count = Object.keys(this.pointerMap).length;
  10288. if (count === 0 || (count === 1 &&
  10289. ol.pointer.MouseSource.POINTER_ID.toString() in this.pointerMap)) {
  10290. this.firstTouchId_ = inTouch.identifier;
  10291. this.cancelResetClickCount_();
  10292. }
  10293. };
  10294. /**
  10295. * @private
  10296. * @param {Object} inPointer The in pointer object.
  10297. */
  10298. ol.pointer.TouchSource.prototype.removePrimaryPointer_ = function(inPointer) {
  10299. if (inPointer.isPrimary) {
  10300. this.firstTouchId_ = undefined;
  10301. this.resetClickCount_();
  10302. }
  10303. };
  10304. /**
  10305. * @private
  10306. */
  10307. ol.pointer.TouchSource.prototype.resetClickCount_ = function() {
  10308. this.resetId_ = setTimeout(
  10309. this.resetClickCountHandler_.bind(this),
  10310. ol.pointer.TouchSource.CLICK_COUNT_TIMEOUT);
  10311. };
  10312. /**
  10313. * @private
  10314. */
  10315. ol.pointer.TouchSource.prototype.resetClickCountHandler_ = function() {
  10316. this.clickCount_ = 0;
  10317. this.resetId_ = undefined;
  10318. };
  10319. /**
  10320. * @private
  10321. */
  10322. ol.pointer.TouchSource.prototype.cancelResetClickCount_ = function() {
  10323. if (this.resetId_ !== undefined) {
  10324. clearTimeout(this.resetId_);
  10325. }
  10326. };
  10327. /**
  10328. * @private
  10329. * @param {Event} browserEvent Browser event
  10330. * @param {Touch} inTouch Touch event
  10331. * @return {Object} A pointer object.
  10332. */
  10333. ol.pointer.TouchSource.prototype.touchToPointer_ = function(browserEvent, inTouch) {
  10334. var e = this.dispatcher.cloneEvent(browserEvent, inTouch);
  10335. // Spec specifies that pointerId 1 is reserved for Mouse.
  10336. // Touch identifiers can start at 0.
  10337. // Add 2 to the touch identifier for compatibility.
  10338. e.pointerId = inTouch.identifier + 2;
  10339. // TODO: check if this is necessary?
  10340. //e.target = findTarget(e);
  10341. e.bubbles = true;
  10342. e.cancelable = true;
  10343. e.detail = this.clickCount_;
  10344. e.button = 0;
  10345. e.buttons = 1;
  10346. e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0;
  10347. e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0;
  10348. e.pressure = inTouch.webkitForce || inTouch.force || 0.5;
  10349. e.isPrimary = this.isPrimaryTouch_(inTouch);
  10350. e.pointerType = ol.pointer.TouchSource.POINTER_TYPE;
  10351. // make sure that the properties that are different for
  10352. // each `Touch` object are not copied from the BrowserEvent object
  10353. e.clientX = inTouch.clientX;
  10354. e.clientY = inTouch.clientY;
  10355. e.screenX = inTouch.screenX;
  10356. e.screenY = inTouch.screenY;
  10357. return e;
  10358. };
  10359. /**
  10360. * @private
  10361. * @param {Event} inEvent Touch event
  10362. * @param {function(Event, Object)} inFunction In function.
  10363. */
  10364. ol.pointer.TouchSource.prototype.processTouches_ = function(inEvent, inFunction) {
  10365. var touches = Array.prototype.slice.call(
  10366. inEvent.changedTouches);
  10367. var count = touches.length;
  10368. function preventDefault() {
  10369. inEvent.preventDefault();
  10370. }
  10371. var i, pointer;
  10372. for (i = 0; i < count; ++i) {
  10373. pointer = this.touchToPointer_(inEvent, touches[i]);
  10374. // forward touch preventDefaults
  10375. pointer.preventDefault = preventDefault;
  10376. inFunction.call(this, inEvent, pointer);
  10377. }
  10378. };
  10379. /**
  10380. * @private
  10381. * @param {TouchList} touchList The touch list.
  10382. * @param {number} searchId Search identifier.
  10383. * @return {boolean} True, if the `Touch` with the given id is in the list.
  10384. */
  10385. ol.pointer.TouchSource.prototype.findTouch_ = function(touchList, searchId) {
  10386. var l = touchList.length;
  10387. var touch;
  10388. for (var i = 0; i < l; i++) {
  10389. touch = touchList[i];
  10390. if (touch.identifier === searchId) {
  10391. return true;
  10392. }
  10393. }
  10394. return false;
  10395. };
  10396. /**
  10397. * In some instances, a touchstart can happen without a touchend. This
  10398. * leaves the pointermap in a broken state.
  10399. * Therefore, on every touchstart, we remove the touches that did not fire a
  10400. * touchend event.
  10401. * To keep state globally consistent, we fire a pointercancel for
  10402. * this "abandoned" touch
  10403. *
  10404. * @private
  10405. * @param {Event} inEvent The in event.
  10406. */
  10407. ol.pointer.TouchSource.prototype.vacuumTouches_ = function(inEvent) {
  10408. var touchList = inEvent.touches;
  10409. // pointerMap.getCount() should be < touchList.length here,
  10410. // as the touchstart has not been processed yet.
  10411. var keys = Object.keys(this.pointerMap);
  10412. var count = keys.length;
  10413. if (count >= touchList.length) {
  10414. var d = [];
  10415. var i, key, value;
  10416. for (i = 0; i < count; ++i) {
  10417. key = keys[i];
  10418. value = this.pointerMap[key];
  10419. // Never remove pointerId == 1, which is mouse.
  10420. // Touch identifiers are 2 smaller than their pointerId, which is the
  10421. // index in pointermap.
  10422. if (key != ol.pointer.MouseSource.POINTER_ID &&
  10423. !this.findTouch_(touchList, key - 2)) {
  10424. d.push(value.out);
  10425. }
  10426. }
  10427. for (i = 0; i < d.length; ++i) {
  10428. this.cancelOut_(inEvent, d[i]);
  10429. }
  10430. }
  10431. };
  10432. /**
  10433. * Handler for `touchstart`, triggers `pointerover`,
  10434. * `pointerenter` and `pointerdown` events.
  10435. *
  10436. * @param {Event} inEvent The in event.
  10437. */
  10438. ol.pointer.TouchSource.prototype.touchstart = function(inEvent) {
  10439. this.vacuumTouches_(inEvent);
  10440. this.setPrimaryTouch_(inEvent.changedTouches[0]);
  10441. this.dedupSynthMouse_(inEvent);
  10442. this.clickCount_++;
  10443. this.processTouches_(inEvent, this.overDown_);
  10444. };
  10445. /**
  10446. * @private
  10447. * @param {Event} browserEvent The event.
  10448. * @param {Object} inPointer The in pointer object.
  10449. */
  10450. ol.pointer.TouchSource.prototype.overDown_ = function(browserEvent, inPointer) {
  10451. this.pointerMap[inPointer.pointerId] = {
  10452. target: inPointer.target,
  10453. out: inPointer,
  10454. outTarget: inPointer.target
  10455. };
  10456. this.dispatcher.over(inPointer, browserEvent);
  10457. this.dispatcher.enter(inPointer, browserEvent);
  10458. this.dispatcher.down(inPointer, browserEvent);
  10459. };
  10460. /**
  10461. * Handler for `touchmove`.
  10462. *
  10463. * @param {Event} inEvent The in event.
  10464. */
  10465. ol.pointer.TouchSource.prototype.touchmove = function(inEvent) {
  10466. inEvent.preventDefault();
  10467. this.processTouches_(inEvent, this.moveOverOut_);
  10468. };
  10469. /**
  10470. * @private
  10471. * @param {Event} browserEvent The event.
  10472. * @param {Object} inPointer The in pointer.
  10473. */
  10474. ol.pointer.TouchSource.prototype.moveOverOut_ = function(browserEvent, inPointer) {
  10475. var event = inPointer;
  10476. var pointer = this.pointerMap[event.pointerId];
  10477. // a finger drifted off the screen, ignore it
  10478. if (!pointer) {
  10479. return;
  10480. }
  10481. var outEvent = pointer.out;
  10482. var outTarget = pointer.outTarget;
  10483. this.dispatcher.move(event, browserEvent);
  10484. if (outEvent && outTarget !== event.target) {
  10485. outEvent.relatedTarget = event.target;
  10486. event.relatedTarget = outTarget;
  10487. // recover from retargeting by shadow
  10488. outEvent.target = outTarget;
  10489. if (event.target) {
  10490. this.dispatcher.leaveOut(outEvent, browserEvent);
  10491. this.dispatcher.enterOver(event, browserEvent);
  10492. } else {
  10493. // clean up case when finger leaves the screen
  10494. event.target = outTarget;
  10495. event.relatedTarget = null;
  10496. this.cancelOut_(browserEvent, event);
  10497. }
  10498. }
  10499. pointer.out = event;
  10500. pointer.outTarget = event.target;
  10501. };
  10502. /**
  10503. * Handler for `touchend`, triggers `pointerup`,
  10504. * `pointerout` and `pointerleave` events.
  10505. *
  10506. * @param {Event} inEvent The event.
  10507. */
  10508. ol.pointer.TouchSource.prototype.touchend = function(inEvent) {
  10509. this.dedupSynthMouse_(inEvent);
  10510. this.processTouches_(inEvent, this.upOut_);
  10511. };
  10512. /**
  10513. * @private
  10514. * @param {Event} browserEvent An event.
  10515. * @param {Object} inPointer The inPointer object.
  10516. */
  10517. ol.pointer.TouchSource.prototype.upOut_ = function(browserEvent, inPointer) {
  10518. this.dispatcher.up(inPointer, browserEvent);
  10519. this.dispatcher.out(inPointer, browserEvent);
  10520. this.dispatcher.leave(inPointer, browserEvent);
  10521. this.cleanUpPointer_(inPointer);
  10522. };
  10523. /**
  10524. * Handler for `touchcancel`, triggers `pointercancel`,
  10525. * `pointerout` and `pointerleave` events.
  10526. *
  10527. * @param {Event} inEvent The in event.
  10528. */
  10529. ol.pointer.TouchSource.prototype.touchcancel = function(inEvent) {
  10530. this.processTouches_(inEvent, this.cancelOut_);
  10531. };
  10532. /**
  10533. * @private
  10534. * @param {Event} browserEvent The event.
  10535. * @param {Object} inPointer The in pointer.
  10536. */
  10537. ol.pointer.TouchSource.prototype.cancelOut_ = function(browserEvent, inPointer) {
  10538. this.dispatcher.cancel(inPointer, browserEvent);
  10539. this.dispatcher.out(inPointer, browserEvent);
  10540. this.dispatcher.leave(inPointer, browserEvent);
  10541. this.cleanUpPointer_(inPointer);
  10542. };
  10543. /**
  10544. * @private
  10545. * @param {Object} inPointer The inPointer object.
  10546. */
  10547. ol.pointer.TouchSource.prototype.cleanUpPointer_ = function(inPointer) {
  10548. delete this.pointerMap[inPointer.pointerId];
  10549. this.removePrimaryPointer_(inPointer);
  10550. };
  10551. /**
  10552. * Prevent synth mouse events from creating pointer events.
  10553. *
  10554. * @private
  10555. * @param {Event} inEvent The in event.
  10556. */
  10557. ol.pointer.TouchSource.prototype.dedupSynthMouse_ = function(inEvent) {
  10558. var lts = this.mouseSource.lastTouches;
  10559. var t = inEvent.changedTouches[0];
  10560. // only the primary finger will synth mouse events
  10561. if (this.isPrimaryTouch_(t)) {
  10562. // remember x/y of last touch
  10563. var lt = [t.clientX, t.clientY];
  10564. lts.push(lt);
  10565. setTimeout(function() {
  10566. // remove touch after timeout
  10567. ol.array.remove(lts, lt);
  10568. }, ol.pointer.TouchSource.DEDUP_TIMEOUT);
  10569. }
  10570. };
  10571. // Based on https://github.com/Polymer/PointerEvents
  10572. // Copyright (c) 2013 The Polymer Authors. All rights reserved.
  10573. //
  10574. // Redistribution and use in source and binary forms, with or without
  10575. // modification, are permitted provided that the following conditions are
  10576. // met:
  10577. //
  10578. // * Redistributions of source code must retain the above copyright
  10579. // notice, this list of conditions and the following disclaimer.
  10580. // * Redistributions in binary form must reproduce the above
  10581. // copyright notice, this list of conditions and the following disclaimer
  10582. // in the documentation and/or other materials provided with the
  10583. // distribution.
  10584. // * Neither the name of Google Inc. nor the names of its
  10585. // contributors may be used to endorse or promote products derived from
  10586. // this software without specific prior written permission.
  10587. //
  10588. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  10589. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  10590. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  10591. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  10592. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10593. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  10594. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10595. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  10596. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  10597. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  10598. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  10599. goog.provide('ol.pointer.PointerEventHandler');
  10600. goog.require('ol');
  10601. goog.require('ol.events');
  10602. goog.require('ol.events.EventTarget');
  10603. goog.require('ol.has');
  10604. goog.require('ol.pointer.EventType');
  10605. goog.require('ol.pointer.MouseSource');
  10606. goog.require('ol.pointer.MsSource');
  10607. goog.require('ol.pointer.NativeSource');
  10608. goog.require('ol.pointer.PointerEvent');
  10609. goog.require('ol.pointer.TouchSource');
  10610. /**
  10611. * @constructor
  10612. * @extends {ol.events.EventTarget}
  10613. * @param {Element|HTMLDocument} element Viewport element.
  10614. */
  10615. ol.pointer.PointerEventHandler = function(element) {
  10616. ol.events.EventTarget.call(this);
  10617. /**
  10618. * @const
  10619. * @private
  10620. * @type {Element|HTMLDocument}
  10621. */
  10622. this.element_ = element;
  10623. /**
  10624. * @const
  10625. * @type {!Object.<string, Event|Object>}
  10626. */
  10627. this.pointerMap = {};
  10628. /**
  10629. * @type {Object.<string, function(Event)>}
  10630. * @private
  10631. */
  10632. this.eventMap_ = {};
  10633. /**
  10634. * @type {Array.<ol.pointer.EventSource>}
  10635. * @private
  10636. */
  10637. this.eventSourceList_ = [];
  10638. this.registerSources();
  10639. };
  10640. ol.inherits(ol.pointer.PointerEventHandler, ol.events.EventTarget);
  10641. /**
  10642. * Set up the event sources (mouse, touch and native pointers)
  10643. * that generate pointer events.
  10644. */
  10645. ol.pointer.PointerEventHandler.prototype.registerSources = function() {
  10646. if (ol.has.POINTER) {
  10647. this.registerSource('native', new ol.pointer.NativeSource(this));
  10648. } else if (ol.has.MSPOINTER) {
  10649. this.registerSource('ms', new ol.pointer.MsSource(this));
  10650. } else {
  10651. var mouseSource = new ol.pointer.MouseSource(this);
  10652. this.registerSource('mouse', mouseSource);
  10653. if (ol.has.TOUCH) {
  10654. this.registerSource('touch',
  10655. new ol.pointer.TouchSource(this, mouseSource));
  10656. }
  10657. }
  10658. // register events on the viewport element
  10659. this.register_();
  10660. };
  10661. /**
  10662. * Add a new event source that will generate pointer events.
  10663. *
  10664. * @param {string} name A name for the event source
  10665. * @param {ol.pointer.EventSource} source The source event.
  10666. */
  10667. ol.pointer.PointerEventHandler.prototype.registerSource = function(name, source) {
  10668. var s = source;
  10669. var newEvents = s.getEvents();
  10670. if (newEvents) {
  10671. newEvents.forEach(function(e) {
  10672. var handler = s.getHandlerForEvent(e);
  10673. if (handler) {
  10674. this.eventMap_[e] = handler.bind(s);
  10675. }
  10676. }, this);
  10677. this.eventSourceList_.push(s);
  10678. }
  10679. };
  10680. /**
  10681. * Set up the events for all registered event sources.
  10682. * @private
  10683. */
  10684. ol.pointer.PointerEventHandler.prototype.register_ = function() {
  10685. var l = this.eventSourceList_.length;
  10686. var eventSource;
  10687. for (var i = 0; i < l; i++) {
  10688. eventSource = this.eventSourceList_[i];
  10689. this.addEvents_(eventSource.getEvents());
  10690. }
  10691. };
  10692. /**
  10693. * Remove all registered events.
  10694. * @private
  10695. */
  10696. ol.pointer.PointerEventHandler.prototype.unregister_ = function() {
  10697. var l = this.eventSourceList_.length;
  10698. var eventSource;
  10699. for (var i = 0; i < l; i++) {
  10700. eventSource = this.eventSourceList_[i];
  10701. this.removeEvents_(eventSource.getEvents());
  10702. }
  10703. };
  10704. /**
  10705. * Calls the right handler for a new event.
  10706. * @private
  10707. * @param {Event} inEvent Browser event.
  10708. */
  10709. ol.pointer.PointerEventHandler.prototype.eventHandler_ = function(inEvent) {
  10710. var type = inEvent.type;
  10711. var handler = this.eventMap_[type];
  10712. if (handler) {
  10713. handler(inEvent);
  10714. }
  10715. };
  10716. /**
  10717. * Setup listeners for the given events.
  10718. * @private
  10719. * @param {Array.<string>} events List of events.
  10720. */
  10721. ol.pointer.PointerEventHandler.prototype.addEvents_ = function(events) {
  10722. events.forEach(function(eventName) {
  10723. ol.events.listen(this.element_, eventName, this.eventHandler_, this);
  10724. }, this);
  10725. };
  10726. /**
  10727. * Unregister listeners for the given events.
  10728. * @private
  10729. * @param {Array.<string>} events List of events.
  10730. */
  10731. ol.pointer.PointerEventHandler.prototype.removeEvents_ = function(events) {
  10732. events.forEach(function(e) {
  10733. ol.events.unlisten(this.element_, e, this.eventHandler_, this);
  10734. }, this);
  10735. };
  10736. /**
  10737. * Returns a snapshot of inEvent, with writable properties.
  10738. *
  10739. * @param {Event} event Browser event.
  10740. * @param {Event|Touch} inEvent An event that contains
  10741. * properties to copy.
  10742. * @return {Object} An object containing shallow copies of
  10743. * `inEvent`'s properties.
  10744. */
  10745. ol.pointer.PointerEventHandler.prototype.cloneEvent = function(event, inEvent) {
  10746. var eventCopy = {}, p;
  10747. for (var i = 0, ii = ol.pointer.PointerEventHandler.CLONE_PROPS.length; i < ii; i++) {
  10748. p = ol.pointer.PointerEventHandler.CLONE_PROPS[i][0];
  10749. eventCopy[p] = event[p] || inEvent[p] || ol.pointer.PointerEventHandler.CLONE_PROPS[i][1];
  10750. }
  10751. return eventCopy;
  10752. };
  10753. // EVENTS
  10754. /**
  10755. * Triggers a 'pointerdown' event.
  10756. * @param {Object} data Pointer event data.
  10757. * @param {Event} event The event.
  10758. */
  10759. ol.pointer.PointerEventHandler.prototype.down = function(data, event) {
  10760. this.fireEvent(ol.pointer.EventType.POINTERDOWN, data, event);
  10761. };
  10762. /**
  10763. * Triggers a 'pointermove' event.
  10764. * @param {Object} data Pointer event data.
  10765. * @param {Event} event The event.
  10766. */
  10767. ol.pointer.PointerEventHandler.prototype.move = function(data, event) {
  10768. this.fireEvent(ol.pointer.EventType.POINTERMOVE, data, event);
  10769. };
  10770. /**
  10771. * Triggers a 'pointerup' event.
  10772. * @param {Object} data Pointer event data.
  10773. * @param {Event} event The event.
  10774. */
  10775. ol.pointer.PointerEventHandler.prototype.up = function(data, event) {
  10776. this.fireEvent(ol.pointer.EventType.POINTERUP, data, event);
  10777. };
  10778. /**
  10779. * Triggers a 'pointerenter' event.
  10780. * @param {Object} data Pointer event data.
  10781. * @param {Event} event The event.
  10782. */
  10783. ol.pointer.PointerEventHandler.prototype.enter = function(data, event) {
  10784. data.bubbles = false;
  10785. this.fireEvent(ol.pointer.EventType.POINTERENTER, data, event);
  10786. };
  10787. /**
  10788. * Triggers a 'pointerleave' event.
  10789. * @param {Object} data Pointer event data.
  10790. * @param {Event} event The event.
  10791. */
  10792. ol.pointer.PointerEventHandler.prototype.leave = function(data, event) {
  10793. data.bubbles = false;
  10794. this.fireEvent(ol.pointer.EventType.POINTERLEAVE, data, event);
  10795. };
  10796. /**
  10797. * Triggers a 'pointerover' event.
  10798. * @param {Object} data Pointer event data.
  10799. * @param {Event} event The event.
  10800. */
  10801. ol.pointer.PointerEventHandler.prototype.over = function(data, event) {
  10802. data.bubbles = true;
  10803. this.fireEvent(ol.pointer.EventType.POINTEROVER, data, event);
  10804. };
  10805. /**
  10806. * Triggers a 'pointerout' event.
  10807. * @param {Object} data Pointer event data.
  10808. * @param {Event} event The event.
  10809. */
  10810. ol.pointer.PointerEventHandler.prototype.out = function(data, event) {
  10811. data.bubbles = true;
  10812. this.fireEvent(ol.pointer.EventType.POINTEROUT, data, event);
  10813. };
  10814. /**
  10815. * Triggers a 'pointercancel' event.
  10816. * @param {Object} data Pointer event data.
  10817. * @param {Event} event The event.
  10818. */
  10819. ol.pointer.PointerEventHandler.prototype.cancel = function(data, event) {
  10820. this.fireEvent(ol.pointer.EventType.POINTERCANCEL, data, event);
  10821. };
  10822. /**
  10823. * Triggers a combination of 'pointerout' and 'pointerleave' events.
  10824. * @param {Object} data Pointer event data.
  10825. * @param {Event} event The event.
  10826. */
  10827. ol.pointer.PointerEventHandler.prototype.leaveOut = function(data, event) {
  10828. this.out(data, event);
  10829. if (!this.contains_(data.target, data.relatedTarget)) {
  10830. this.leave(data, event);
  10831. }
  10832. };
  10833. /**
  10834. * Triggers a combination of 'pointerover' and 'pointerevents' events.
  10835. * @param {Object} data Pointer event data.
  10836. * @param {Event} event The event.
  10837. */
  10838. ol.pointer.PointerEventHandler.prototype.enterOver = function(data, event) {
  10839. this.over(data, event);
  10840. if (!this.contains_(data.target, data.relatedTarget)) {
  10841. this.enter(data, event);
  10842. }
  10843. };
  10844. /**
  10845. * @private
  10846. * @param {Element} container The container element.
  10847. * @param {Element} contained The contained element.
  10848. * @return {boolean} Returns true if the container element
  10849. * contains the other element.
  10850. */
  10851. ol.pointer.PointerEventHandler.prototype.contains_ = function(container, contained) {
  10852. if (!container || !contained) {
  10853. return false;
  10854. }
  10855. return container.contains(contained);
  10856. };
  10857. // EVENT CREATION AND TRACKING
  10858. /**
  10859. * Creates a new Event of type `inType`, based on the information in
  10860. * `data`.
  10861. *
  10862. * @param {string} inType A string representing the type of event to create.
  10863. * @param {Object} data Pointer event data.
  10864. * @param {Event} event The event.
  10865. * @return {ol.pointer.PointerEvent} A PointerEvent of type `inType`.
  10866. */
  10867. ol.pointer.PointerEventHandler.prototype.makeEvent = function(inType, data, event) {
  10868. return new ol.pointer.PointerEvent(inType, event, data);
  10869. };
  10870. /**
  10871. * Make and dispatch an event in one call.
  10872. * @param {string} inType A string representing the type of event.
  10873. * @param {Object} data Pointer event data.
  10874. * @param {Event} event The event.
  10875. */
  10876. ol.pointer.PointerEventHandler.prototype.fireEvent = function(inType, data, event) {
  10877. var e = this.makeEvent(inType, data, event);
  10878. this.dispatchEvent(e);
  10879. };
  10880. /**
  10881. * Creates a pointer event from a native pointer event
  10882. * and dispatches this event.
  10883. * @param {Event} event A platform event with a target.
  10884. */
  10885. ol.pointer.PointerEventHandler.prototype.fireNativeEvent = function(event) {
  10886. var e = this.makeEvent(event.type, event, event);
  10887. this.dispatchEvent(e);
  10888. };
  10889. /**
  10890. * Wrap a native mouse event into a pointer event.
  10891. * This proxy method is required for the legacy IE support.
  10892. * @param {string} eventType The pointer event type.
  10893. * @param {Event} event The event.
  10894. * @return {ol.pointer.PointerEvent} The wrapped event.
  10895. */
  10896. ol.pointer.PointerEventHandler.prototype.wrapMouseEvent = function(eventType, event) {
  10897. var pointerEvent = this.makeEvent(
  10898. eventType, ol.pointer.MouseSource.prepareEvent(event, this), event);
  10899. return pointerEvent;
  10900. };
  10901. /**
  10902. * @inheritDoc
  10903. */
  10904. ol.pointer.PointerEventHandler.prototype.disposeInternal = function() {
  10905. this.unregister_();
  10906. ol.events.EventTarget.prototype.disposeInternal.call(this);
  10907. };
  10908. /**
  10909. * Properties to copy when cloning an event, with default values.
  10910. * @type {Array.<Array>}
  10911. */
  10912. ol.pointer.PointerEventHandler.CLONE_PROPS = [
  10913. // MouseEvent
  10914. ['bubbles', false],
  10915. ['cancelable', false],
  10916. ['view', null],
  10917. ['detail', null],
  10918. ['screenX', 0],
  10919. ['screenY', 0],
  10920. ['clientX', 0],
  10921. ['clientY', 0],
  10922. ['ctrlKey', false],
  10923. ['altKey', false],
  10924. ['shiftKey', false],
  10925. ['metaKey', false],
  10926. ['button', 0],
  10927. ['relatedTarget', null],
  10928. // DOM Level 3
  10929. ['buttons', 0],
  10930. // PointerEvent
  10931. ['pointerId', 0],
  10932. ['width', 0],
  10933. ['height', 0],
  10934. ['pressure', 0],
  10935. ['tiltX', 0],
  10936. ['tiltY', 0],
  10937. ['pointerType', ''],
  10938. ['hwTimestamp', 0],
  10939. ['isPrimary', false],
  10940. // event instance
  10941. ['type', ''],
  10942. ['target', null],
  10943. ['currentTarget', null],
  10944. ['which', 0]
  10945. ];
  10946. goog.provide('ol.MapBrowserEventHandler');
  10947. goog.require('ol');
  10948. goog.require('ol.has');
  10949. goog.require('ol.MapBrowserEventType');
  10950. goog.require('ol.MapBrowserPointerEvent');
  10951. goog.require('ol.events');
  10952. goog.require('ol.events.EventTarget');
  10953. goog.require('ol.pointer.EventType');
  10954. goog.require('ol.pointer.PointerEventHandler');
  10955. /**
  10956. * @param {ol.Map} map The map with the viewport to listen to events on.
  10957. * @param {number|undefined} moveTolerance The minimal distance the pointer must travel to trigger a move.
  10958. * @constructor
  10959. * @extends {ol.events.EventTarget}
  10960. */
  10961. ol.MapBrowserEventHandler = function(map, moveTolerance) {
  10962. ol.events.EventTarget.call(this);
  10963. /**
  10964. * This is the element that we will listen to the real events on.
  10965. * @type {ol.Map}
  10966. * @private
  10967. */
  10968. this.map_ = map;
  10969. /**
  10970. * @type {number}
  10971. * @private
  10972. */
  10973. this.clickTimeoutId_ = 0;
  10974. /**
  10975. * @type {boolean}
  10976. * @private
  10977. */
  10978. this.dragging_ = false;
  10979. /**
  10980. * @type {!Array.<ol.EventsKey>}
  10981. * @private
  10982. */
  10983. this.dragListenerKeys_ = [];
  10984. /**
  10985. * @type {number}
  10986. * @private
  10987. */
  10988. this.moveTolerance_ = moveTolerance ?
  10989. moveTolerance * ol.has.DEVICE_PIXEL_RATIO : ol.has.DEVICE_PIXEL_RATIO;
  10990. /**
  10991. * The most recent "down" type event (or null if none have occurred).
  10992. * Set on pointerdown.
  10993. * @type {ol.pointer.PointerEvent}
  10994. * @private
  10995. */
  10996. this.down_ = null;
  10997. var element = this.map_.getViewport();
  10998. /**
  10999. * @type {number}
  11000. * @private
  11001. */
  11002. this.activePointers_ = 0;
  11003. /**
  11004. * @type {!Object.<number, boolean>}
  11005. * @private
  11006. */
  11007. this.trackedTouches_ = {};
  11008. /**
  11009. * Event handler which generates pointer events for
  11010. * the viewport element.
  11011. *
  11012. * @type {ol.pointer.PointerEventHandler}
  11013. * @private
  11014. */
  11015. this.pointerEventHandler_ = new ol.pointer.PointerEventHandler(element);
  11016. /**
  11017. * Event handler which generates pointer events for
  11018. * the document (used when dragging).
  11019. *
  11020. * @type {ol.pointer.PointerEventHandler}
  11021. * @private
  11022. */
  11023. this.documentPointerEventHandler_ = null;
  11024. /**
  11025. * @type {?ol.EventsKey}
  11026. * @private
  11027. */
  11028. this.pointerdownListenerKey_ = ol.events.listen(this.pointerEventHandler_,
  11029. ol.pointer.EventType.POINTERDOWN,
  11030. this.handlePointerDown_, this);
  11031. /**
  11032. * @type {?ol.EventsKey}
  11033. * @private
  11034. */
  11035. this.relayedListenerKey_ = ol.events.listen(this.pointerEventHandler_,
  11036. ol.pointer.EventType.POINTERMOVE,
  11037. this.relayEvent_, this);
  11038. };
  11039. ol.inherits(ol.MapBrowserEventHandler, ol.events.EventTarget);
  11040. /**
  11041. * @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
  11042. * @private
  11043. */
  11044. ol.MapBrowserEventHandler.prototype.emulateClick_ = function(pointerEvent) {
  11045. var newEvent = new ol.MapBrowserPointerEvent(
  11046. ol.MapBrowserEventType.CLICK, this.map_, pointerEvent);
  11047. this.dispatchEvent(newEvent);
  11048. if (this.clickTimeoutId_ !== 0) {
  11049. // double-click
  11050. clearTimeout(this.clickTimeoutId_);
  11051. this.clickTimeoutId_ = 0;
  11052. newEvent = new ol.MapBrowserPointerEvent(
  11053. ol.MapBrowserEventType.DBLCLICK, this.map_, pointerEvent);
  11054. this.dispatchEvent(newEvent);
  11055. } else {
  11056. // click
  11057. this.clickTimeoutId_ = setTimeout(function() {
  11058. this.clickTimeoutId_ = 0;
  11059. var newEvent = new ol.MapBrowserPointerEvent(
  11060. ol.MapBrowserEventType.SINGLECLICK, this.map_, pointerEvent);
  11061. this.dispatchEvent(newEvent);
  11062. }.bind(this), 250);
  11063. }
  11064. };
  11065. /**
  11066. * Keeps track on how many pointers are currently active.
  11067. *
  11068. * @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
  11069. * @private
  11070. */
  11071. ol.MapBrowserEventHandler.prototype.updateActivePointers_ = function(pointerEvent) {
  11072. var event = pointerEvent;
  11073. if (event.type == ol.MapBrowserEventType.POINTERUP ||
  11074. event.type == ol.MapBrowserEventType.POINTERCANCEL) {
  11075. delete this.trackedTouches_[event.pointerId];
  11076. } else if (event.type == ol.MapBrowserEventType.POINTERDOWN) {
  11077. this.trackedTouches_[event.pointerId] = true;
  11078. }
  11079. this.activePointers_ = Object.keys(this.trackedTouches_).length;
  11080. };
  11081. /**
  11082. * @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
  11083. * @private
  11084. */
  11085. ol.MapBrowserEventHandler.prototype.handlePointerUp_ = function(pointerEvent) {
  11086. this.updateActivePointers_(pointerEvent);
  11087. var newEvent = new ol.MapBrowserPointerEvent(
  11088. ol.MapBrowserEventType.POINTERUP, this.map_, pointerEvent);
  11089. this.dispatchEvent(newEvent);
  11090. // We emulate click events on left mouse button click, touch contact, and pen
  11091. // contact. isMouseActionButton returns true in these cases (evt.button is set
  11092. // to 0).
  11093. // See http://www.w3.org/TR/pointerevents/#button-states
  11094. if (!this.dragging_ && this.isMouseActionButton_(pointerEvent)) {
  11095. this.emulateClick_(this.down_);
  11096. }
  11097. if (this.activePointers_ === 0) {
  11098. this.dragListenerKeys_.forEach(ol.events.unlistenByKey);
  11099. this.dragListenerKeys_.length = 0;
  11100. this.dragging_ = false;
  11101. this.down_ = null;
  11102. this.documentPointerEventHandler_.dispose();
  11103. this.documentPointerEventHandler_ = null;
  11104. }
  11105. };
  11106. /**
  11107. * @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
  11108. * @return {boolean} If the left mouse button was pressed.
  11109. * @private
  11110. */
  11111. ol.MapBrowserEventHandler.prototype.isMouseActionButton_ = function(pointerEvent) {
  11112. return pointerEvent.button === 0;
  11113. };
  11114. /**
  11115. * @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
  11116. * @private
  11117. */
  11118. ol.MapBrowserEventHandler.prototype.handlePointerDown_ = function(pointerEvent) {
  11119. this.updateActivePointers_(pointerEvent);
  11120. var newEvent = new ol.MapBrowserPointerEvent(
  11121. ol.MapBrowserEventType.POINTERDOWN, this.map_, pointerEvent);
  11122. this.dispatchEvent(newEvent);
  11123. this.down_ = pointerEvent;
  11124. if (this.dragListenerKeys_.length === 0) {
  11125. /* Set up a pointer event handler on the `document`,
  11126. * which is required when the pointer is moved outside
  11127. * the viewport when dragging.
  11128. */
  11129. this.documentPointerEventHandler_ =
  11130. new ol.pointer.PointerEventHandler(document);
  11131. this.dragListenerKeys_.push(
  11132. ol.events.listen(this.documentPointerEventHandler_,
  11133. ol.MapBrowserEventType.POINTERMOVE,
  11134. this.handlePointerMove_, this),
  11135. ol.events.listen(this.documentPointerEventHandler_,
  11136. ol.MapBrowserEventType.POINTERUP,
  11137. this.handlePointerUp_, this),
  11138. /* Note that the listener for `pointercancel is set up on
  11139. * `pointerEventHandler_` and not `documentPointerEventHandler_` like
  11140. * the `pointerup` and `pointermove` listeners.
  11141. *
  11142. * The reason for this is the following: `TouchSource.vacuumTouches_()`
  11143. * issues `pointercancel` events, when there was no `touchend` for a
  11144. * `touchstart`. Now, let's say a first `touchstart` is registered on
  11145. * `pointerEventHandler_`. The `documentPointerEventHandler_` is set up.
  11146. * But `documentPointerEventHandler_` doesn't know about the first
  11147. * `touchstart`. If there is no `touchend` for the `touchstart`, we can
  11148. * only receive a `touchcancel` from `pointerEventHandler_`, because it is
  11149. * only registered there.
  11150. */
  11151. ol.events.listen(this.pointerEventHandler_,
  11152. ol.MapBrowserEventType.POINTERCANCEL,
  11153. this.handlePointerUp_, this)
  11154. );
  11155. }
  11156. };
  11157. /**
  11158. * @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
  11159. * @private
  11160. */
  11161. ol.MapBrowserEventHandler.prototype.handlePointerMove_ = function(pointerEvent) {
  11162. // Between pointerdown and pointerup, pointermove events are triggered.
  11163. // To avoid a 'false' touchmove event to be dispatched, we test if the pointer
  11164. // moved a significant distance.
  11165. if (this.isMoving_(pointerEvent)) {
  11166. this.dragging_ = true;
  11167. var newEvent = new ol.MapBrowserPointerEvent(
  11168. ol.MapBrowserEventType.POINTERDRAG, this.map_, pointerEvent,
  11169. this.dragging_);
  11170. this.dispatchEvent(newEvent);
  11171. }
  11172. // Some native android browser triggers mousemove events during small period
  11173. // of time. See: https://code.google.com/p/android/issues/detail?id=5491 or
  11174. // https://code.google.com/p/android/issues/detail?id=19827
  11175. // ex: Galaxy Tab P3110 + Android 4.1.1
  11176. pointerEvent.preventDefault();
  11177. };
  11178. /**
  11179. * Wrap and relay a pointer event. Note that this requires that the type
  11180. * string for the MapBrowserPointerEvent matches the PointerEvent type.
  11181. * @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
  11182. * @private
  11183. */
  11184. ol.MapBrowserEventHandler.prototype.relayEvent_ = function(pointerEvent) {
  11185. var dragging = !!(this.down_ && this.isMoving_(pointerEvent));
  11186. this.dispatchEvent(new ol.MapBrowserPointerEvent(
  11187. pointerEvent.type, this.map_, pointerEvent, dragging));
  11188. };
  11189. /**
  11190. * @param {ol.pointer.PointerEvent} pointerEvent Pointer event.
  11191. * @return {boolean} Is moving.
  11192. * @private
  11193. */
  11194. ol.MapBrowserEventHandler.prototype.isMoving_ = function(pointerEvent) {
  11195. return Math.abs(pointerEvent.clientX - this.down_.clientX) > this.moveTolerance_ ||
  11196. Math.abs(pointerEvent.clientY - this.down_.clientY) > this.moveTolerance_;
  11197. };
  11198. /**
  11199. * @inheritDoc
  11200. */
  11201. ol.MapBrowserEventHandler.prototype.disposeInternal = function() {
  11202. if (this.relayedListenerKey_) {
  11203. ol.events.unlistenByKey(this.relayedListenerKey_);
  11204. this.relayedListenerKey_ = null;
  11205. }
  11206. if (this.pointerdownListenerKey_) {
  11207. ol.events.unlistenByKey(this.pointerdownListenerKey_);
  11208. this.pointerdownListenerKey_ = null;
  11209. }
  11210. this.dragListenerKeys_.forEach(ol.events.unlistenByKey);
  11211. this.dragListenerKeys_.length = 0;
  11212. if (this.documentPointerEventHandler_) {
  11213. this.documentPointerEventHandler_.dispose();
  11214. this.documentPointerEventHandler_ = null;
  11215. }
  11216. if (this.pointerEventHandler_) {
  11217. this.pointerEventHandler_.dispose();
  11218. this.pointerEventHandler_ = null;
  11219. }
  11220. ol.events.EventTarget.prototype.disposeInternal.call(this);
  11221. };
  11222. goog.provide('ol.MapProperty');
  11223. /**
  11224. * @enum {string}
  11225. */
  11226. ol.MapProperty = {
  11227. LAYERGROUP: 'layergroup',
  11228. SIZE: 'size',
  11229. TARGET: 'target',
  11230. VIEW: 'view'
  11231. };
  11232. goog.provide('ol.TileState');
  11233. /**
  11234. * @enum {number}
  11235. */
  11236. ol.TileState = {
  11237. IDLE: 0,
  11238. LOADING: 1,
  11239. LOADED: 2,
  11240. ERROR: 3,
  11241. EMPTY: 4,
  11242. ABORT: 5
  11243. };
  11244. goog.provide('ol.structs.PriorityQueue');
  11245. goog.require('ol.asserts');
  11246. goog.require('ol.obj');
  11247. /**
  11248. * Priority queue.
  11249. *
  11250. * The implementation is inspired from the Closure Library's Heap class and
  11251. * Python's heapq module.
  11252. *
  11253. * @see http://closure-library.googlecode.com/svn/docs/closure_goog_structs_heap.js.source.html
  11254. * @see http://hg.python.org/cpython/file/2.7/Lib/heapq.py
  11255. *
  11256. * @constructor
  11257. * @param {function(T): number} priorityFunction Priority function.
  11258. * @param {function(T): string} keyFunction Key function.
  11259. * @struct
  11260. * @template T
  11261. */
  11262. ol.structs.PriorityQueue = function(priorityFunction, keyFunction) {
  11263. /**
  11264. * @type {function(T): number}
  11265. * @private
  11266. */
  11267. this.priorityFunction_ = priorityFunction;
  11268. /**
  11269. * @type {function(T): string}
  11270. * @private
  11271. */
  11272. this.keyFunction_ = keyFunction;
  11273. /**
  11274. * @type {Array.<T>}
  11275. * @private
  11276. */
  11277. this.elements_ = [];
  11278. /**
  11279. * @type {Array.<number>}
  11280. * @private
  11281. */
  11282. this.priorities_ = [];
  11283. /**
  11284. * @type {Object.<string, boolean>}
  11285. * @private
  11286. */
  11287. this.queuedElements_ = {};
  11288. };
  11289. /**
  11290. * @const
  11291. * @type {number}
  11292. */
  11293. ol.structs.PriorityQueue.DROP = Infinity;
  11294. /**
  11295. * FIXME empty description for jsdoc
  11296. */
  11297. ol.structs.PriorityQueue.prototype.clear = function() {
  11298. this.elements_.length = 0;
  11299. this.priorities_.length = 0;
  11300. ol.obj.clear(this.queuedElements_);
  11301. };
  11302. /**
  11303. * Remove and return the highest-priority element. O(log N).
  11304. * @return {T} Element.
  11305. */
  11306. ol.structs.PriorityQueue.prototype.dequeue = function() {
  11307. var elements = this.elements_;
  11308. var priorities = this.priorities_;
  11309. var element = elements[0];
  11310. if (elements.length == 1) {
  11311. elements.length = 0;
  11312. priorities.length = 0;
  11313. } else {
  11314. elements[0] = elements.pop();
  11315. priorities[0] = priorities.pop();
  11316. this.siftUp_(0);
  11317. }
  11318. var elementKey = this.keyFunction_(element);
  11319. delete this.queuedElements_[elementKey];
  11320. return element;
  11321. };
  11322. /**
  11323. * Enqueue an element. O(log N).
  11324. * @param {T} element Element.
  11325. * @return {boolean} The element was added to the queue.
  11326. */
  11327. ol.structs.PriorityQueue.prototype.enqueue = function(element) {
  11328. ol.asserts.assert(!(this.keyFunction_(element) in this.queuedElements_),
  11329. 31); // Tried to enqueue an `element` that was already added to the queue
  11330. var priority = this.priorityFunction_(element);
  11331. if (priority != ol.structs.PriorityQueue.DROP) {
  11332. this.elements_.push(element);
  11333. this.priorities_.push(priority);
  11334. this.queuedElements_[this.keyFunction_(element)] = true;
  11335. this.siftDown_(0, this.elements_.length - 1);
  11336. return true;
  11337. }
  11338. return false;
  11339. };
  11340. /**
  11341. * @return {number} Count.
  11342. */
  11343. ol.structs.PriorityQueue.prototype.getCount = function() {
  11344. return this.elements_.length;
  11345. };
  11346. /**
  11347. * Gets the index of the left child of the node at the given index.
  11348. * @param {number} index The index of the node to get the left child for.
  11349. * @return {number} The index of the left child.
  11350. * @private
  11351. */
  11352. ol.structs.PriorityQueue.prototype.getLeftChildIndex_ = function(index) {
  11353. return index * 2 + 1;
  11354. };
  11355. /**
  11356. * Gets the index of the right child of the node at the given index.
  11357. * @param {number} index The index of the node to get the right child for.
  11358. * @return {number} The index of the right child.
  11359. * @private
  11360. */
  11361. ol.structs.PriorityQueue.prototype.getRightChildIndex_ = function(index) {
  11362. return index * 2 + 2;
  11363. };
  11364. /**
  11365. * Gets the index of the parent of the node at the given index.
  11366. * @param {number} index The index of the node to get the parent for.
  11367. * @return {number} The index of the parent.
  11368. * @private
  11369. */
  11370. ol.structs.PriorityQueue.prototype.getParentIndex_ = function(index) {
  11371. return (index - 1) >> 1;
  11372. };
  11373. /**
  11374. * Make this a heap. O(N).
  11375. * @private
  11376. */
  11377. ol.structs.PriorityQueue.prototype.heapify_ = function() {
  11378. var i;
  11379. for (i = (this.elements_.length >> 1) - 1; i >= 0; i--) {
  11380. this.siftUp_(i);
  11381. }
  11382. };
  11383. /**
  11384. * @return {boolean} Is empty.
  11385. */
  11386. ol.structs.PriorityQueue.prototype.isEmpty = function() {
  11387. return this.elements_.length === 0;
  11388. };
  11389. /**
  11390. * @param {string} key Key.
  11391. * @return {boolean} Is key queued.
  11392. */
  11393. ol.structs.PriorityQueue.prototype.isKeyQueued = function(key) {
  11394. return key in this.queuedElements_;
  11395. };
  11396. /**
  11397. * @param {T} element Element.
  11398. * @return {boolean} Is queued.
  11399. */
  11400. ol.structs.PriorityQueue.prototype.isQueued = function(element) {
  11401. return this.isKeyQueued(this.keyFunction_(element));
  11402. };
  11403. /**
  11404. * @param {number} index The index of the node to move down.
  11405. * @private
  11406. */
  11407. ol.structs.PriorityQueue.prototype.siftUp_ = function(index) {
  11408. var elements = this.elements_;
  11409. var priorities = this.priorities_;
  11410. var count = elements.length;
  11411. var element = elements[index];
  11412. var priority = priorities[index];
  11413. var startIndex = index;
  11414. while (index < (count >> 1)) {
  11415. var lIndex = this.getLeftChildIndex_(index);
  11416. var rIndex = this.getRightChildIndex_(index);
  11417. var smallerChildIndex = rIndex < count &&
  11418. priorities[rIndex] < priorities[lIndex] ?
  11419. rIndex : lIndex;
  11420. elements[index] = elements[smallerChildIndex];
  11421. priorities[index] = priorities[smallerChildIndex];
  11422. index = smallerChildIndex;
  11423. }
  11424. elements[index] = element;
  11425. priorities[index] = priority;
  11426. this.siftDown_(startIndex, index);
  11427. };
  11428. /**
  11429. * @param {number} startIndex The index of the root.
  11430. * @param {number} index The index of the node to move up.
  11431. * @private
  11432. */
  11433. ol.structs.PriorityQueue.prototype.siftDown_ = function(startIndex, index) {
  11434. var elements = this.elements_;
  11435. var priorities = this.priorities_;
  11436. var element = elements[index];
  11437. var priority = priorities[index];
  11438. while (index > startIndex) {
  11439. var parentIndex = this.getParentIndex_(index);
  11440. if (priorities[parentIndex] > priority) {
  11441. elements[index] = elements[parentIndex];
  11442. priorities[index] = priorities[parentIndex];
  11443. index = parentIndex;
  11444. } else {
  11445. break;
  11446. }
  11447. }
  11448. elements[index] = element;
  11449. priorities[index] = priority;
  11450. };
  11451. /**
  11452. * FIXME empty description for jsdoc
  11453. */
  11454. ol.structs.PriorityQueue.prototype.reprioritize = function() {
  11455. var priorityFunction = this.priorityFunction_;
  11456. var elements = this.elements_;
  11457. var priorities = this.priorities_;
  11458. var index = 0;
  11459. var n = elements.length;
  11460. var element, i, priority;
  11461. for (i = 0; i < n; ++i) {
  11462. element = elements[i];
  11463. priority = priorityFunction(element);
  11464. if (priority == ol.structs.PriorityQueue.DROP) {
  11465. delete this.queuedElements_[this.keyFunction_(element)];
  11466. } else {
  11467. priorities[index] = priority;
  11468. elements[index++] = element;
  11469. }
  11470. }
  11471. elements.length = index;
  11472. priorities.length = index;
  11473. this.heapify_();
  11474. };
  11475. goog.provide('ol.TileQueue');
  11476. goog.require('ol');
  11477. goog.require('ol.TileState');
  11478. goog.require('ol.events');
  11479. goog.require('ol.events.EventType');
  11480. goog.require('ol.structs.PriorityQueue');
  11481. /**
  11482. * @constructor
  11483. * @extends {ol.structs.PriorityQueue.<Array>}
  11484. * @param {ol.TilePriorityFunction} tilePriorityFunction
  11485. * Tile priority function.
  11486. * @param {function(): ?} tileChangeCallback
  11487. * Function called on each tile change event.
  11488. * @struct
  11489. */
  11490. ol.TileQueue = function(tilePriorityFunction, tileChangeCallback) {
  11491. ol.structs.PriorityQueue.call(
  11492. this,
  11493. /**
  11494. * @param {Array} element Element.
  11495. * @return {number} Priority.
  11496. */
  11497. function(element) {
  11498. return tilePriorityFunction.apply(null, element);
  11499. },
  11500. /**
  11501. * @param {Array} element Element.
  11502. * @return {string} Key.
  11503. */
  11504. function(element) {
  11505. return /** @type {ol.Tile} */ (element[0]).getKey();
  11506. });
  11507. /**
  11508. * @private
  11509. * @type {function(): ?}
  11510. */
  11511. this.tileChangeCallback_ = tileChangeCallback;
  11512. /**
  11513. * @private
  11514. * @type {number}
  11515. */
  11516. this.tilesLoading_ = 0;
  11517. /**
  11518. * @private
  11519. * @type {!Object.<string,boolean>}
  11520. */
  11521. this.tilesLoadingKeys_ = {};
  11522. };
  11523. ol.inherits(ol.TileQueue, ol.structs.PriorityQueue);
  11524. /**
  11525. * @inheritDoc
  11526. */
  11527. ol.TileQueue.prototype.enqueue = function(element) {
  11528. var added = ol.structs.PriorityQueue.prototype.enqueue.call(this, element);
  11529. if (added) {
  11530. var tile = element[0];
  11531. ol.events.listen(tile, ol.events.EventType.CHANGE,
  11532. this.handleTileChange, this);
  11533. }
  11534. return added;
  11535. };
  11536. /**
  11537. * @return {number} Number of tiles loading.
  11538. */
  11539. ol.TileQueue.prototype.getTilesLoading = function() {
  11540. return this.tilesLoading_;
  11541. };
  11542. /**
  11543. * @param {ol.events.Event} event Event.
  11544. * @protected
  11545. */
  11546. ol.TileQueue.prototype.handleTileChange = function(event) {
  11547. var tile = /** @type {ol.Tile} */ (event.target);
  11548. var state = tile.getState();
  11549. if (state === ol.TileState.LOADED || state === ol.TileState.ERROR ||
  11550. state === ol.TileState.EMPTY || state === ol.TileState.ABORT) {
  11551. ol.events.unlisten(tile, ol.events.EventType.CHANGE,
  11552. this.handleTileChange, this);
  11553. var tileKey = tile.getKey();
  11554. if (tileKey in this.tilesLoadingKeys_) {
  11555. delete this.tilesLoadingKeys_[tileKey];
  11556. --this.tilesLoading_;
  11557. }
  11558. this.tileChangeCallback_();
  11559. }
  11560. };
  11561. /**
  11562. * @param {number} maxTotalLoading Maximum number tiles to load simultaneously.
  11563. * @param {number} maxNewLoads Maximum number of new tiles to load.
  11564. */
  11565. ol.TileQueue.prototype.loadMoreTiles = function(maxTotalLoading, maxNewLoads) {
  11566. var newLoads = 0;
  11567. var abortedTiles = false;
  11568. var state, tile, tileKey;
  11569. while (this.tilesLoading_ < maxTotalLoading && newLoads < maxNewLoads &&
  11570. this.getCount() > 0) {
  11571. tile = /** @type {ol.Tile} */ (this.dequeue()[0]);
  11572. tileKey = tile.getKey();
  11573. state = tile.getState();
  11574. if (state === ol.TileState.ABORT) {
  11575. abortedTiles = true;
  11576. } else if (state === ol.TileState.IDLE && !(tileKey in this.tilesLoadingKeys_)) {
  11577. this.tilesLoadingKeys_[tileKey] = true;
  11578. ++this.tilesLoading_;
  11579. ++newLoads;
  11580. tile.load();
  11581. }
  11582. }
  11583. if (newLoads === 0 && abortedTiles) {
  11584. // Do not stop the render loop when all wanted tiles were aborted due to
  11585. // a small, saturated tile cache.
  11586. this.tileChangeCallback_();
  11587. }
  11588. };
  11589. goog.provide('ol.ResolutionConstraint');
  11590. goog.require('ol.array');
  11591. goog.require('ol.math');
  11592. /**
  11593. * @param {Array.<number>} resolutions Resolutions.
  11594. * @return {ol.ResolutionConstraintType} Zoom function.
  11595. */
  11596. ol.ResolutionConstraint.createSnapToResolutions = function(resolutions) {
  11597. return (
  11598. /**
  11599. * @param {number|undefined} resolution Resolution.
  11600. * @param {number} delta Delta.
  11601. * @param {number} direction Direction.
  11602. * @return {number|undefined} Resolution.
  11603. */
  11604. function(resolution, delta, direction) {
  11605. if (resolution !== undefined) {
  11606. var z =
  11607. ol.array.linearFindNearest(resolutions, resolution, direction);
  11608. z = ol.math.clamp(z + delta, 0, resolutions.length - 1);
  11609. var index = Math.floor(z);
  11610. if (z != index && index < resolutions.length - 1) {
  11611. var power = resolutions[index] / resolutions[index + 1];
  11612. return resolutions[index] / Math.pow(power, z - index);
  11613. } else {
  11614. return resolutions[index];
  11615. }
  11616. } else {
  11617. return undefined;
  11618. }
  11619. });
  11620. };
  11621. /**
  11622. * @param {number} power Power.
  11623. * @param {number} maxResolution Maximum resolution.
  11624. * @param {number=} opt_maxLevel Maximum level.
  11625. * @return {ol.ResolutionConstraintType} Zoom function.
  11626. */
  11627. ol.ResolutionConstraint.createSnapToPower = function(power, maxResolution, opt_maxLevel) {
  11628. return (
  11629. /**
  11630. * @param {number|undefined} resolution Resolution.
  11631. * @param {number} delta Delta.
  11632. * @param {number} direction Direction.
  11633. * @return {number|undefined} Resolution.
  11634. */
  11635. function(resolution, delta, direction) {
  11636. if (resolution !== undefined) {
  11637. var offset = -direction / 2 + 0.5;
  11638. var oldLevel = Math.floor(
  11639. Math.log(maxResolution / resolution) / Math.log(power) + offset);
  11640. var newLevel = Math.max(oldLevel + delta, 0);
  11641. if (opt_maxLevel !== undefined) {
  11642. newLevel = Math.min(newLevel, opt_maxLevel);
  11643. }
  11644. return maxResolution / Math.pow(power, newLevel);
  11645. } else {
  11646. return undefined;
  11647. }
  11648. });
  11649. };
  11650. goog.provide('ol.RotationConstraint');
  11651. goog.require('ol.math');
  11652. /**
  11653. * @param {number|undefined} rotation Rotation.
  11654. * @param {number} delta Delta.
  11655. * @return {number|undefined} Rotation.
  11656. */
  11657. ol.RotationConstraint.disable = function(rotation, delta) {
  11658. if (rotation !== undefined) {
  11659. return 0;
  11660. } else {
  11661. return undefined;
  11662. }
  11663. };
  11664. /**
  11665. * @param {number|undefined} rotation Rotation.
  11666. * @param {number} delta Delta.
  11667. * @return {number|undefined} Rotation.
  11668. */
  11669. ol.RotationConstraint.none = function(rotation, delta) {
  11670. if (rotation !== undefined) {
  11671. return rotation + delta;
  11672. } else {
  11673. return undefined;
  11674. }
  11675. };
  11676. /**
  11677. * @param {number} n N.
  11678. * @return {ol.RotationConstraintType} Rotation constraint.
  11679. */
  11680. ol.RotationConstraint.createSnapToN = function(n) {
  11681. var theta = 2 * Math.PI / n;
  11682. return (
  11683. /**
  11684. * @param {number|undefined} rotation Rotation.
  11685. * @param {number} delta Delta.
  11686. * @return {number|undefined} Rotation.
  11687. */
  11688. function(rotation, delta) {
  11689. if (rotation !== undefined) {
  11690. rotation = Math.floor((rotation + delta) / theta + 0.5) * theta;
  11691. return rotation;
  11692. } else {
  11693. return undefined;
  11694. }
  11695. });
  11696. };
  11697. /**
  11698. * @param {number=} opt_tolerance Tolerance.
  11699. * @return {ol.RotationConstraintType} Rotation constraint.
  11700. */
  11701. ol.RotationConstraint.createSnapToZero = function(opt_tolerance) {
  11702. var tolerance = opt_tolerance || ol.math.toRadians(5);
  11703. return (
  11704. /**
  11705. * @param {number|undefined} rotation Rotation.
  11706. * @param {number} delta Delta.
  11707. * @return {number|undefined} Rotation.
  11708. */
  11709. function(rotation, delta) {
  11710. if (rotation !== undefined) {
  11711. if (Math.abs(rotation + delta) <= tolerance) {
  11712. return 0;
  11713. } else {
  11714. return rotation + delta;
  11715. }
  11716. } else {
  11717. return undefined;
  11718. }
  11719. });
  11720. };
  11721. goog.provide('ol.ViewHint');
  11722. /**
  11723. * @enum {number}
  11724. */
  11725. ol.ViewHint = {
  11726. ANIMATING: 0,
  11727. INTERACTING: 1
  11728. };
  11729. goog.provide('ol.ViewProperty');
  11730. /**
  11731. * @enum {string}
  11732. */
  11733. ol.ViewProperty = {
  11734. CENTER: 'center',
  11735. RESOLUTION: 'resolution',
  11736. ROTATION: 'rotation'
  11737. };
  11738. goog.provide('ol.string');
  11739. /**
  11740. * @param {number} number Number to be formatted
  11741. * @param {number} width The desired width
  11742. * @param {number=} opt_precision Precision of the output string (i.e. number of decimal places)
  11743. * @returns {string} Formatted string
  11744. */
  11745. ol.string.padNumber = function(number, width, opt_precision) {
  11746. var numberString = opt_precision !== undefined ? number.toFixed(opt_precision) : '' + number;
  11747. var decimal = numberString.indexOf('.');
  11748. decimal = decimal === -1 ? numberString.length : decimal;
  11749. return decimal > width ? numberString : new Array(1 + width - decimal).join('0') + numberString;
  11750. };
  11751. /**
  11752. * Adapted from https://github.com/omichelsen/compare-versions/blob/master/index.js
  11753. * @param {string|number} v1 First version
  11754. * @param {string|number} v2 Second version
  11755. * @returns {number} Value
  11756. */
  11757. ol.string.compareVersions = function(v1, v2) {
  11758. var s1 = ('' + v1).split('.');
  11759. var s2 = ('' + v2).split('.');
  11760. for (var i = 0; i < Math.max(s1.length, s2.length); i++) {
  11761. var n1 = parseInt(s1[i] || '0', 10);
  11762. var n2 = parseInt(s2[i] || '0', 10);
  11763. if (n1 > n2) {
  11764. return 1;
  11765. }
  11766. if (n2 > n1) {
  11767. return -1;
  11768. }
  11769. }
  11770. return 0;
  11771. };
  11772. goog.provide('ol.coordinate');
  11773. goog.require('ol.math');
  11774. goog.require('ol.string');
  11775. /**
  11776. * Add `delta` to `coordinate`. `coordinate` is modified in place and returned
  11777. * by the function.
  11778. *
  11779. * Example:
  11780. *
  11781. * var coord = [7.85, 47.983333];
  11782. * ol.coordinate.add(coord, [-2, 4]);
  11783. * // coord is now [5.85, 51.983333]
  11784. *
  11785. * @param {ol.Coordinate} coordinate Coordinate.
  11786. * @param {ol.Coordinate} delta Delta.
  11787. * @return {ol.Coordinate} The input coordinate adjusted by the given delta.
  11788. * @api
  11789. */
  11790. ol.coordinate.add = function(coordinate, delta) {
  11791. coordinate[0] += delta[0];
  11792. coordinate[1] += delta[1];
  11793. return coordinate;
  11794. };
  11795. /**
  11796. * Calculates the point closest to the passed coordinate on the passed circle.
  11797. *
  11798. * @param {ol.Coordinate} coordinate The coordinate.
  11799. * @param {ol.geom.Circle} circle The circle.
  11800. * @return {ol.Coordinate} Closest point on the circumference
  11801. */
  11802. ol.coordinate.closestOnCircle = function(coordinate, circle) {
  11803. var r = circle.getRadius();
  11804. var center = circle.getCenter();
  11805. var x0 = center[0];
  11806. var y0 = center[1];
  11807. var x1 = coordinate[0];
  11808. var y1 = coordinate[1];
  11809. var dx = x1 - x0;
  11810. var dy = y1 - y0;
  11811. if (dx === 0 && dy === 0) {
  11812. dx = 1;
  11813. }
  11814. var d = Math.sqrt(dx * dx + dy * dy);
  11815. var x, y;
  11816. x = x0 + r * dx / d;
  11817. y = y0 + r * dy / d;
  11818. return [x, y];
  11819. };
  11820. /**
  11821. * Calculates the point closest to the passed coordinate on the passed segment.
  11822. * This is the foot of the perpendicular of the coordinate to the segment when
  11823. * the foot is on the segment, or the closest segment coordinate when the foot
  11824. * is outside the segment.
  11825. *
  11826. * @param {ol.Coordinate} coordinate The coordinate.
  11827. * @param {Array.<ol.Coordinate>} segment The two coordinates of the segment.
  11828. * @return {ol.Coordinate} The foot of the perpendicular of the coordinate to
  11829. * the segment.
  11830. */
  11831. ol.coordinate.closestOnSegment = function(coordinate, segment) {
  11832. var x0 = coordinate[0];
  11833. var y0 = coordinate[1];
  11834. var start = segment[0];
  11835. var end = segment[1];
  11836. var x1 = start[0];
  11837. var y1 = start[1];
  11838. var x2 = end[0];
  11839. var y2 = end[1];
  11840. var dx = x2 - x1;
  11841. var dy = y2 - y1;
  11842. var along = (dx === 0 && dy === 0) ? 0 :
  11843. ((dx * (x0 - x1)) + (dy * (y0 - y1))) / ((dx * dx + dy * dy) || 0);
  11844. var x, y;
  11845. if (along <= 0) {
  11846. x = x1;
  11847. y = y1;
  11848. } else if (along >= 1) {
  11849. x = x2;
  11850. y = y2;
  11851. } else {
  11852. x = x1 + along * dx;
  11853. y = y1 + along * dy;
  11854. }
  11855. return [x, y];
  11856. };
  11857. /**
  11858. * Returns a {@link ol.CoordinateFormatType} function that can be used to format
  11859. * a {ol.Coordinate} to a string.
  11860. *
  11861. * Example without specifying the fractional digits:
  11862. *
  11863. * var coord = [7.85, 47.983333];
  11864. * var stringifyFunc = ol.coordinate.createStringXY();
  11865. * var out = stringifyFunc(coord);
  11866. * // out is now '8, 48'
  11867. *
  11868. * Example with explicitly specifying 2 fractional digits:
  11869. *
  11870. * var coord = [7.85, 47.983333];
  11871. * var stringifyFunc = ol.coordinate.createStringXY(2);
  11872. * var out = stringifyFunc(coord);
  11873. * // out is now '7.85, 47.98'
  11874. *
  11875. * @param {number=} opt_fractionDigits The number of digits to include
  11876. * after the decimal point. Default is `0`.
  11877. * @return {ol.CoordinateFormatType} Coordinate format.
  11878. * @api
  11879. */
  11880. ol.coordinate.createStringXY = function(opt_fractionDigits) {
  11881. return (
  11882. /**
  11883. * @param {ol.Coordinate|undefined} coordinate Coordinate.
  11884. * @return {string} String XY.
  11885. */
  11886. function(coordinate) {
  11887. return ol.coordinate.toStringXY(coordinate, opt_fractionDigits);
  11888. });
  11889. };
  11890. /**
  11891. * @param {string} hemispheres Hemispheres.
  11892. * @param {number} degrees Degrees.
  11893. * @param {number=} opt_fractionDigits The number of digits to include
  11894. * after the decimal point. Default is `0`.
  11895. * @return {string} String.
  11896. */
  11897. ol.coordinate.degreesToStringHDMS = function(hemispheres, degrees, opt_fractionDigits) {
  11898. var normalizedDegrees = ol.math.modulo(degrees + 180, 360) - 180;
  11899. var x = Math.abs(3600 * normalizedDegrees);
  11900. var dflPrecision = opt_fractionDigits || 0;
  11901. var precision = Math.pow(10, dflPrecision);
  11902. var deg = Math.floor(x / 3600);
  11903. var min = Math.floor((x - deg * 3600) / 60);
  11904. var sec = x - (deg * 3600) - (min * 60);
  11905. sec = Math.ceil(sec * precision) / precision;
  11906. if (sec >= 60) {
  11907. sec = 0;
  11908. min += 1;
  11909. }
  11910. if (min >= 60) {
  11911. min = 0;
  11912. deg += 1;
  11913. }
  11914. return deg + '\u00b0 ' + ol.string.padNumber(min, 2) + '\u2032 ' +
  11915. ol.string.padNumber(sec, 2, dflPrecision) + '\u2033' +
  11916. (normalizedDegrees == 0 ? '' : ' ' + hemispheres.charAt(normalizedDegrees < 0 ? 1 : 0));
  11917. };
  11918. /**
  11919. * Transforms the given {@link ol.Coordinate} to a string using the given string
  11920. * template. The strings `{x}` and `{y}` in the template will be replaced with
  11921. * the first and second coordinate values respectively.
  11922. *
  11923. * Example without specifying the fractional digits:
  11924. *
  11925. * var coord = [7.85, 47.983333];
  11926. * var template = 'Coordinate is ({x}|{y}).';
  11927. * var out = ol.coordinate.format(coord, template);
  11928. * // out is now 'Coordinate is (8|48).'
  11929. *
  11930. * Example explicitly specifying the fractional digits:
  11931. *
  11932. * var coord = [7.85, 47.983333];
  11933. * var template = 'Coordinate is ({x}|{y}).';
  11934. * var out = ol.coordinate.format(coord, template, 2);
  11935. * // out is now 'Coordinate is (7.85|47.98).'
  11936. *
  11937. * @param {ol.Coordinate|undefined} coordinate Coordinate.
  11938. * @param {string} template A template string with `{x}` and `{y}` placeholders
  11939. * that will be replaced by first and second coordinate values.
  11940. * @param {number=} opt_fractionDigits The number of digits to include
  11941. * after the decimal point. Default is `0`.
  11942. * @return {string} Formatted coordinate.
  11943. * @api
  11944. */
  11945. ol.coordinate.format = function(coordinate, template, opt_fractionDigits) {
  11946. if (coordinate) {
  11947. return template
  11948. .replace('{x}', coordinate[0].toFixed(opt_fractionDigits))
  11949. .replace('{y}', coordinate[1].toFixed(opt_fractionDigits));
  11950. } else {
  11951. return '';
  11952. }
  11953. };
  11954. /**
  11955. * @param {ol.Coordinate} coordinate1 First coordinate.
  11956. * @param {ol.Coordinate} coordinate2 Second coordinate.
  11957. * @return {boolean} Whether the passed coordinates are equal.
  11958. */
  11959. ol.coordinate.equals = function(coordinate1, coordinate2) {
  11960. var equals = true;
  11961. for (var i = coordinate1.length - 1; i >= 0; --i) {
  11962. if (coordinate1[i] != coordinate2[i]) {
  11963. equals = false;
  11964. break;
  11965. }
  11966. }
  11967. return equals;
  11968. };
  11969. /**
  11970. * Rotate `coordinate` by `angle`. `coordinate` is modified in place and
  11971. * returned by the function.
  11972. *
  11973. * Example:
  11974. *
  11975. * var coord = [7.85, 47.983333];
  11976. * var rotateRadians = Math.PI / 2; // 90 degrees
  11977. * ol.coordinate.rotate(coord, rotateRadians);
  11978. * // coord is now [-47.983333, 7.85]
  11979. *
  11980. * @param {ol.Coordinate} coordinate Coordinate.
  11981. * @param {number} angle Angle in radian.
  11982. * @return {ol.Coordinate} Coordinate.
  11983. * @api
  11984. */
  11985. ol.coordinate.rotate = function(coordinate, angle) {
  11986. var cosAngle = Math.cos(angle);
  11987. var sinAngle = Math.sin(angle);
  11988. var x = coordinate[0] * cosAngle - coordinate[1] * sinAngle;
  11989. var y = coordinate[1] * cosAngle + coordinate[0] * sinAngle;
  11990. coordinate[0] = x;
  11991. coordinate[1] = y;
  11992. return coordinate;
  11993. };
  11994. /**
  11995. * Scale `coordinate` by `scale`. `coordinate` is modified in place and returned
  11996. * by the function.
  11997. *
  11998. * Example:
  11999. *
  12000. * var coord = [7.85, 47.983333];
  12001. * var scale = 1.2;
  12002. * ol.coordinate.scale(coord, scale);
  12003. * // coord is now [9.42, 57.5799996]
  12004. *
  12005. * @param {ol.Coordinate} coordinate Coordinate.
  12006. * @param {number} scale Scale factor.
  12007. * @return {ol.Coordinate} Coordinate.
  12008. */
  12009. ol.coordinate.scale = function(coordinate, scale) {
  12010. coordinate[0] *= scale;
  12011. coordinate[1] *= scale;
  12012. return coordinate;
  12013. };
  12014. /**
  12015. * Subtract `delta` to `coordinate`. `coordinate` is modified in place and
  12016. * returned by the function.
  12017. *
  12018. * @param {ol.Coordinate} coordinate Coordinate.
  12019. * @param {ol.Coordinate} delta Delta.
  12020. * @return {ol.Coordinate} Coordinate.
  12021. */
  12022. ol.coordinate.sub = function(coordinate, delta) {
  12023. coordinate[0] -= delta[0];
  12024. coordinate[1] -= delta[1];
  12025. return coordinate;
  12026. };
  12027. /**
  12028. * @param {ol.Coordinate} coord1 First coordinate.
  12029. * @param {ol.Coordinate} coord2 Second coordinate.
  12030. * @return {number} Squared distance between coord1 and coord2.
  12031. */
  12032. ol.coordinate.squaredDistance = function(coord1, coord2) {
  12033. var dx = coord1[0] - coord2[0];
  12034. var dy = coord1[1] - coord2[1];
  12035. return dx * dx + dy * dy;
  12036. };
  12037. /**
  12038. * @param {ol.Coordinate} coord1 First coordinate.
  12039. * @param {ol.Coordinate} coord2 Second coordinate.
  12040. * @return {number} Distance between coord1 and coord2.
  12041. */
  12042. ol.coordinate.distance = function(coord1, coord2) {
  12043. return Math.sqrt(ol.coordinate.squaredDistance(coord1, coord2));
  12044. };
  12045. /**
  12046. * Calculate the squared distance from a coordinate to a line segment.
  12047. *
  12048. * @param {ol.Coordinate} coordinate Coordinate of the point.
  12049. * @param {Array.<ol.Coordinate>} segment Line segment (2 coordinates).
  12050. * @return {number} Squared distance from the point to the line segment.
  12051. */
  12052. ol.coordinate.squaredDistanceToSegment = function(coordinate, segment) {
  12053. return ol.coordinate.squaredDistance(coordinate,
  12054. ol.coordinate.closestOnSegment(coordinate, segment));
  12055. };
  12056. /**
  12057. * Format a geographic coordinate with the hemisphere, degrees, minutes, and
  12058. * seconds.
  12059. *
  12060. * Example without specifying fractional digits:
  12061. *
  12062. * var coord = [7.85, 47.983333];
  12063. * var out = ol.coordinate.toStringHDMS(coord);
  12064. * // out is now '47° 58′ 60″ N 7° 50′ 60″ E'
  12065. *
  12066. * Example explicitly specifying 1 fractional digit:
  12067. *
  12068. * var coord = [7.85, 47.983333];
  12069. * var out = ol.coordinate.toStringHDMS(coord, 1);
  12070. * // out is now '47° 58′ 60.0″ N 7° 50′ 60.0″ E'
  12071. *
  12072. * @param {ol.Coordinate|undefined} coordinate Coordinate.
  12073. * @param {number=} opt_fractionDigits The number of digits to include
  12074. * after the decimal point. Default is `0`.
  12075. * @return {string} Hemisphere, degrees, minutes and seconds.
  12076. * @api
  12077. */
  12078. ol.coordinate.toStringHDMS = function(coordinate, opt_fractionDigits) {
  12079. if (coordinate) {
  12080. return ol.coordinate.degreesToStringHDMS('NS', coordinate[1], opt_fractionDigits) + ' ' +
  12081. ol.coordinate.degreesToStringHDMS('EW', coordinate[0], opt_fractionDigits);
  12082. } else {
  12083. return '';
  12084. }
  12085. };
  12086. /**
  12087. * Format a coordinate as a comma delimited string.
  12088. *
  12089. * Example without specifying fractional digits:
  12090. *
  12091. * var coord = [7.85, 47.983333];
  12092. * var out = ol.coordinate.toStringXY(coord);
  12093. * // out is now '8, 48'
  12094. *
  12095. * Example explicitly specifying 1 fractional digit:
  12096. *
  12097. * var coord = [7.85, 47.983333];
  12098. * var out = ol.coordinate.toStringXY(coord, 1);
  12099. * // out is now '7.8, 48.0'
  12100. *
  12101. * @param {ol.Coordinate|undefined} coordinate Coordinate.
  12102. * @param {number=} opt_fractionDigits The number of digits to include
  12103. * after the decimal point. Default is `0`.
  12104. * @return {string} XY.
  12105. * @api
  12106. */
  12107. ol.coordinate.toStringXY = function(coordinate, opt_fractionDigits) {
  12108. return ol.coordinate.format(coordinate, '{x}, {y}', opt_fractionDigits);
  12109. };
  12110. goog.provide('ol.geom.GeometryLayout');
  12111. /**
  12112. * The coordinate layout for geometries, indicating whether a 3rd or 4th z ('Z')
  12113. * or measure ('M') coordinate is available. Supported values are `'XY'`,
  12114. * `'XYZ'`, `'XYM'`, `'XYZM'`.
  12115. * @enum {string}
  12116. */
  12117. ol.geom.GeometryLayout = {
  12118. XY: 'XY',
  12119. XYZ: 'XYZ',
  12120. XYM: 'XYM',
  12121. XYZM: 'XYZM'
  12122. };
  12123. goog.provide('ol.functions');
  12124. /**
  12125. * Always returns true.
  12126. * @returns {boolean} true.
  12127. */
  12128. ol.functions.TRUE = function() {
  12129. return true;
  12130. };
  12131. /**
  12132. * Always returns false.
  12133. * @returns {boolean} false.
  12134. */
  12135. ol.functions.FALSE = function() {
  12136. return false;
  12137. };
  12138. goog.provide('ol.geom.Geometry');
  12139. goog.require('ol');
  12140. goog.require('ol.Object');
  12141. goog.require('ol.extent');
  12142. goog.require('ol.functions');
  12143. goog.require('ol.proj');
  12144. /**
  12145. * @classdesc
  12146. * Abstract base class; normally only used for creating subclasses and not
  12147. * instantiated in apps.
  12148. * Base class for vector geometries.
  12149. *
  12150. * To get notified of changes to the geometry, register a listener for the
  12151. * generic `change` event on your geometry instance.
  12152. *
  12153. * @constructor
  12154. * @abstract
  12155. * @extends {ol.Object}
  12156. * @api
  12157. */
  12158. ol.geom.Geometry = function() {
  12159. ol.Object.call(this);
  12160. /**
  12161. * @private
  12162. * @type {ol.Extent}
  12163. */
  12164. this.extent_ = ol.extent.createEmpty();
  12165. /**
  12166. * @private
  12167. * @type {number}
  12168. */
  12169. this.extentRevision_ = -1;
  12170. /**
  12171. * @protected
  12172. * @type {Object.<string, ol.geom.Geometry>}
  12173. */
  12174. this.simplifiedGeometryCache = {};
  12175. /**
  12176. * @protected
  12177. * @type {number}
  12178. */
  12179. this.simplifiedGeometryMaxMinSquaredTolerance = 0;
  12180. /**
  12181. * @protected
  12182. * @type {number}
  12183. */
  12184. this.simplifiedGeometryRevision = 0;
  12185. };
  12186. ol.inherits(ol.geom.Geometry, ol.Object);
  12187. /**
  12188. * Make a complete copy of the geometry.
  12189. * @abstract
  12190. * @return {!ol.geom.Geometry} Clone.
  12191. */
  12192. ol.geom.Geometry.prototype.clone = function() {};
  12193. /**
  12194. * @abstract
  12195. * @param {number} x X.
  12196. * @param {number} y Y.
  12197. * @param {ol.Coordinate} closestPoint Closest point.
  12198. * @param {number} minSquaredDistance Minimum squared distance.
  12199. * @return {number} Minimum squared distance.
  12200. */
  12201. ol.geom.Geometry.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {};
  12202. /**
  12203. * Return the closest point of the geometry to the passed point as
  12204. * {@link ol.Coordinate coordinate}.
  12205. * @param {ol.Coordinate} point Point.
  12206. * @param {ol.Coordinate=} opt_closestPoint Closest point.
  12207. * @return {ol.Coordinate} Closest point.
  12208. * @api
  12209. */
  12210. ol.geom.Geometry.prototype.getClosestPoint = function(point, opt_closestPoint) {
  12211. var closestPoint = opt_closestPoint ? opt_closestPoint : [NaN, NaN];
  12212. this.closestPointXY(point[0], point[1], closestPoint, Infinity);
  12213. return closestPoint;
  12214. };
  12215. /**
  12216. * Returns true if this geometry includes the specified coordinate. If the
  12217. * coordinate is on the boundary of the geometry, returns false.
  12218. * @param {ol.Coordinate} coordinate Coordinate.
  12219. * @return {boolean} Contains coordinate.
  12220. * @api
  12221. */
  12222. ol.geom.Geometry.prototype.intersectsCoordinate = function(coordinate) {
  12223. return this.containsXY(coordinate[0], coordinate[1]);
  12224. };
  12225. /**
  12226. * @abstract
  12227. * @param {ol.Extent} extent Extent.
  12228. * @protected
  12229. * @return {ol.Extent} extent Extent.
  12230. */
  12231. ol.geom.Geometry.prototype.computeExtent = function(extent) {};
  12232. /**
  12233. * @param {number} x X.
  12234. * @param {number} y Y.
  12235. * @return {boolean} Contains (x, y).
  12236. */
  12237. ol.geom.Geometry.prototype.containsXY = ol.functions.FALSE;
  12238. /**
  12239. * Get the extent of the geometry.
  12240. * @param {ol.Extent=} opt_extent Extent.
  12241. * @return {ol.Extent} extent Extent.
  12242. * @api
  12243. */
  12244. ol.geom.Geometry.prototype.getExtent = function(opt_extent) {
  12245. if (this.extentRevision_ != this.getRevision()) {
  12246. this.extent_ = this.computeExtent(this.extent_);
  12247. this.extentRevision_ = this.getRevision();
  12248. }
  12249. return ol.extent.returnOrUpdate(this.extent_, opt_extent);
  12250. };
  12251. /**
  12252. * Rotate the geometry around a given coordinate. This modifies the geometry
  12253. * coordinates in place.
  12254. * @abstract
  12255. * @param {number} angle Rotation angle in radians.
  12256. * @param {ol.Coordinate} anchor The rotation center.
  12257. * @api
  12258. */
  12259. ol.geom.Geometry.prototype.rotate = function(angle, anchor) {};
  12260. /**
  12261. * Scale the geometry (with an optional origin). This modifies the geometry
  12262. * coordinates in place.
  12263. * @abstract
  12264. * @param {number} sx The scaling factor in the x-direction.
  12265. * @param {number=} opt_sy The scaling factor in the y-direction (defaults to
  12266. * sx).
  12267. * @param {ol.Coordinate=} opt_anchor The scale origin (defaults to the center
  12268. * of the geometry extent).
  12269. * @api
  12270. */
  12271. ol.geom.Geometry.prototype.scale = function(sx, opt_sy, opt_anchor) {};
  12272. /**
  12273. * Create a simplified version of this geometry. For linestrings, this uses
  12274. * the the {@link
  12275. * https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
  12276. * Douglas Peucker} algorithm. For polygons, a quantization-based
  12277. * simplification is used to preserve topology.
  12278. * @function
  12279. * @param {number} tolerance The tolerance distance for simplification.
  12280. * @return {ol.geom.Geometry} A new, simplified version of the original
  12281. * geometry.
  12282. * @api
  12283. */
  12284. ol.geom.Geometry.prototype.simplify = function(tolerance) {
  12285. return this.getSimplifiedGeometry(tolerance * tolerance);
  12286. };
  12287. /**
  12288. * Create a simplified version of this geometry using the Douglas Peucker
  12289. * algorithm.
  12290. * @see https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
  12291. * @abstract
  12292. * @param {number} squaredTolerance Squared tolerance.
  12293. * @return {ol.geom.Geometry} Simplified geometry.
  12294. */
  12295. ol.geom.Geometry.prototype.getSimplifiedGeometry = function(squaredTolerance) {};
  12296. /**
  12297. * Get the type of this geometry.
  12298. * @abstract
  12299. * @return {ol.geom.GeometryType} Geometry type.
  12300. */
  12301. ol.geom.Geometry.prototype.getType = function() {};
  12302. /**
  12303. * Apply a transform function to each coordinate of the geometry.
  12304. * The geometry is modified in place.
  12305. * If you do not want the geometry modified in place, first `clone()` it and
  12306. * then use this function on the clone.
  12307. * @abstract
  12308. * @param {ol.TransformFunction} transformFn Transform.
  12309. */
  12310. ol.geom.Geometry.prototype.applyTransform = function(transformFn) {};
  12311. /**
  12312. * Test if the geometry and the passed extent intersect.
  12313. * @abstract
  12314. * @param {ol.Extent} extent Extent.
  12315. * @return {boolean} `true` if the geometry and the extent intersect.
  12316. */
  12317. ol.geom.Geometry.prototype.intersectsExtent = function(extent) {};
  12318. /**
  12319. * Translate the geometry. This modifies the geometry coordinates in place. If
  12320. * instead you want a new geometry, first `clone()` this geometry.
  12321. * @abstract
  12322. * @param {number} deltaX Delta X.
  12323. * @param {number} deltaY Delta Y.
  12324. */
  12325. ol.geom.Geometry.prototype.translate = function(deltaX, deltaY) {};
  12326. /**
  12327. * Transform each coordinate of the geometry from one coordinate reference
  12328. * system to another. The geometry is modified in place.
  12329. * For example, a line will be transformed to a line and a circle to a circle.
  12330. * If you do not want the geometry modified in place, first `clone()` it and
  12331. * then use this function on the clone.
  12332. *
  12333. * @param {ol.ProjectionLike} source The current projection. Can be a
  12334. * string identifier or a {@link ol.proj.Projection} object.
  12335. * @param {ol.ProjectionLike} destination The desired projection. Can be a
  12336. * string identifier or a {@link ol.proj.Projection} object.
  12337. * @return {ol.geom.Geometry} This geometry. Note that original geometry is
  12338. * modified in place.
  12339. * @api
  12340. */
  12341. ol.geom.Geometry.prototype.transform = function(source, destination) {
  12342. this.applyTransform(ol.proj.getTransform(source, destination));
  12343. return this;
  12344. };
  12345. goog.provide('ol.geom.flat.transform');
  12346. /**
  12347. * @param {Array.<number>} flatCoordinates Flat coordinates.
  12348. * @param {number} offset Offset.
  12349. * @param {number} end End.
  12350. * @param {number} stride Stride.
  12351. * @param {ol.Transform} transform Transform.
  12352. * @param {Array.<number>=} opt_dest Destination.
  12353. * @return {Array.<number>} Transformed coordinates.
  12354. */
  12355. ol.geom.flat.transform.transform2D = function(flatCoordinates, offset, end, stride, transform, opt_dest) {
  12356. var dest = opt_dest ? opt_dest : [];
  12357. var i = 0;
  12358. var j;
  12359. for (j = offset; j < end; j += stride) {
  12360. var x = flatCoordinates[j];
  12361. var y = flatCoordinates[j + 1];
  12362. dest[i++] = transform[0] * x + transform[2] * y + transform[4];
  12363. dest[i++] = transform[1] * x + transform[3] * y + transform[5];
  12364. }
  12365. if (opt_dest && dest.length != i) {
  12366. dest.length = i;
  12367. }
  12368. return dest;
  12369. };
  12370. /**
  12371. * @param {Array.<number>} flatCoordinates Flat coordinates.
  12372. * @param {number} offset Offset.
  12373. * @param {number} end End.
  12374. * @param {number} stride Stride.
  12375. * @param {number} angle Angle.
  12376. * @param {Array.<number>} anchor Rotation anchor point.
  12377. * @param {Array.<number>=} opt_dest Destination.
  12378. * @return {Array.<number>} Transformed coordinates.
  12379. */
  12380. ol.geom.flat.transform.rotate = function(flatCoordinates, offset, end, stride, angle, anchor, opt_dest) {
  12381. var dest = opt_dest ? opt_dest : [];
  12382. var cos = Math.cos(angle);
  12383. var sin = Math.sin(angle);
  12384. var anchorX = anchor[0];
  12385. var anchorY = anchor[1];
  12386. var i = 0;
  12387. for (var j = offset; j < end; j += stride) {
  12388. var deltaX = flatCoordinates[j] - anchorX;
  12389. var deltaY = flatCoordinates[j + 1] - anchorY;
  12390. dest[i++] = anchorX + deltaX * cos - deltaY * sin;
  12391. dest[i++] = anchorY + deltaX * sin + deltaY * cos;
  12392. for (var k = j + 2; k < j + stride; ++k) {
  12393. dest[i++] = flatCoordinates[k];
  12394. }
  12395. }
  12396. if (opt_dest && dest.length != i) {
  12397. dest.length = i;
  12398. }
  12399. return dest;
  12400. };
  12401. /**
  12402. * Scale the coordinates.
  12403. * @param {Array.<number>} flatCoordinates Flat coordinates.
  12404. * @param {number} offset Offset.
  12405. * @param {number} end End.
  12406. * @param {number} stride Stride.
  12407. * @param {number} sx Scale factor in the x-direction.
  12408. * @param {number} sy Scale factor in the y-direction.
  12409. * @param {Array.<number>} anchor Scale anchor point.
  12410. * @param {Array.<number>=} opt_dest Destination.
  12411. * @return {Array.<number>} Transformed coordinates.
  12412. */
  12413. ol.geom.flat.transform.scale = function(flatCoordinates, offset, end, stride, sx, sy, anchor, opt_dest) {
  12414. var dest = opt_dest ? opt_dest : [];
  12415. var anchorX = anchor[0];
  12416. var anchorY = anchor[1];
  12417. var i = 0;
  12418. for (var j = offset; j < end; j += stride) {
  12419. var deltaX = flatCoordinates[j] - anchorX;
  12420. var deltaY = flatCoordinates[j + 1] - anchorY;
  12421. dest[i++] = anchorX + sx * deltaX;
  12422. dest[i++] = anchorY + sy * deltaY;
  12423. for (var k = j + 2; k < j + stride; ++k) {
  12424. dest[i++] = flatCoordinates[k];
  12425. }
  12426. }
  12427. if (opt_dest && dest.length != i) {
  12428. dest.length = i;
  12429. }
  12430. return dest;
  12431. };
  12432. /**
  12433. * @param {Array.<number>} flatCoordinates Flat coordinates.
  12434. * @param {number} offset Offset.
  12435. * @param {number} end End.
  12436. * @param {number} stride Stride.
  12437. * @param {number} deltaX Delta X.
  12438. * @param {number} deltaY Delta Y.
  12439. * @param {Array.<number>=} opt_dest Destination.
  12440. * @return {Array.<number>} Transformed coordinates.
  12441. */
  12442. ol.geom.flat.transform.translate = function(flatCoordinates, offset, end, stride, deltaX, deltaY, opt_dest) {
  12443. var dest = opt_dest ? opt_dest : [];
  12444. var i = 0;
  12445. var j, k;
  12446. for (j = offset; j < end; j += stride) {
  12447. dest[i++] = flatCoordinates[j] + deltaX;
  12448. dest[i++] = flatCoordinates[j + 1] + deltaY;
  12449. for (k = j + 2; k < j + stride; ++k) {
  12450. dest[i++] = flatCoordinates[k];
  12451. }
  12452. }
  12453. if (opt_dest && dest.length != i) {
  12454. dest.length = i;
  12455. }
  12456. return dest;
  12457. };
  12458. goog.provide('ol.geom.SimpleGeometry');
  12459. goog.require('ol');
  12460. goog.require('ol.functions');
  12461. goog.require('ol.extent');
  12462. goog.require('ol.geom.Geometry');
  12463. goog.require('ol.geom.GeometryLayout');
  12464. goog.require('ol.geom.flat.transform');
  12465. goog.require('ol.obj');
  12466. /**
  12467. * @classdesc
  12468. * Abstract base class; only used for creating subclasses; do not instantiate
  12469. * in apps, as cannot be rendered.
  12470. *
  12471. * @constructor
  12472. * @abstract
  12473. * @extends {ol.geom.Geometry}
  12474. * @api
  12475. */
  12476. ol.geom.SimpleGeometry = function() {
  12477. ol.geom.Geometry.call(this);
  12478. /**
  12479. * @protected
  12480. * @type {ol.geom.GeometryLayout}
  12481. */
  12482. this.layout = ol.geom.GeometryLayout.XY;
  12483. /**
  12484. * @protected
  12485. * @type {number}
  12486. */
  12487. this.stride = 2;
  12488. /**
  12489. * @protected
  12490. * @type {Array.<number>}
  12491. */
  12492. this.flatCoordinates = null;
  12493. };
  12494. ol.inherits(ol.geom.SimpleGeometry, ol.geom.Geometry);
  12495. /**
  12496. * @param {number} stride Stride.
  12497. * @private
  12498. * @return {ol.geom.GeometryLayout} layout Layout.
  12499. */
  12500. ol.geom.SimpleGeometry.getLayoutForStride_ = function(stride) {
  12501. var layout;
  12502. if (stride == 2) {
  12503. layout = ol.geom.GeometryLayout.XY;
  12504. } else if (stride == 3) {
  12505. layout = ol.geom.GeometryLayout.XYZ;
  12506. } else if (stride == 4) {
  12507. layout = ol.geom.GeometryLayout.XYZM;
  12508. }
  12509. return /** @type {ol.geom.GeometryLayout} */ (layout);
  12510. };
  12511. /**
  12512. * @param {ol.geom.GeometryLayout} layout Layout.
  12513. * @return {number} Stride.
  12514. */
  12515. ol.geom.SimpleGeometry.getStrideForLayout = function(layout) {
  12516. var stride;
  12517. if (layout == ol.geom.GeometryLayout.XY) {
  12518. stride = 2;
  12519. } else if (layout == ol.geom.GeometryLayout.XYZ || layout == ol.geom.GeometryLayout.XYM) {
  12520. stride = 3;
  12521. } else if (layout == ol.geom.GeometryLayout.XYZM) {
  12522. stride = 4;
  12523. }
  12524. return /** @type {number} */ (stride);
  12525. };
  12526. /**
  12527. * @inheritDoc
  12528. */
  12529. ol.geom.SimpleGeometry.prototype.containsXY = ol.functions.FALSE;
  12530. /**
  12531. * @inheritDoc
  12532. */
  12533. ol.geom.SimpleGeometry.prototype.computeExtent = function(extent) {
  12534. return ol.extent.createOrUpdateFromFlatCoordinates(
  12535. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
  12536. extent);
  12537. };
  12538. /**
  12539. * @abstract
  12540. * @return {Array} Coordinates.
  12541. */
  12542. ol.geom.SimpleGeometry.prototype.getCoordinates = function() {};
  12543. /**
  12544. * Return the first coordinate of the geometry.
  12545. * @return {ol.Coordinate} First coordinate.
  12546. * @api
  12547. */
  12548. ol.geom.SimpleGeometry.prototype.getFirstCoordinate = function() {
  12549. return this.flatCoordinates.slice(0, this.stride);
  12550. };
  12551. /**
  12552. * @return {Array.<number>} Flat coordinates.
  12553. */
  12554. ol.geom.SimpleGeometry.prototype.getFlatCoordinates = function() {
  12555. return this.flatCoordinates;
  12556. };
  12557. /**
  12558. * Return the last coordinate of the geometry.
  12559. * @return {ol.Coordinate} Last point.
  12560. * @api
  12561. */
  12562. ol.geom.SimpleGeometry.prototype.getLastCoordinate = function() {
  12563. return this.flatCoordinates.slice(this.flatCoordinates.length - this.stride);
  12564. };
  12565. /**
  12566. * Return the {@link ol.geom.GeometryLayout layout} of the geometry.
  12567. * @return {ol.geom.GeometryLayout} Layout.
  12568. * @api
  12569. */
  12570. ol.geom.SimpleGeometry.prototype.getLayout = function() {
  12571. return this.layout;
  12572. };
  12573. /**
  12574. * @inheritDoc
  12575. */
  12576. ol.geom.SimpleGeometry.prototype.getSimplifiedGeometry = function(squaredTolerance) {
  12577. if (this.simplifiedGeometryRevision != this.getRevision()) {
  12578. ol.obj.clear(this.simplifiedGeometryCache);
  12579. this.simplifiedGeometryMaxMinSquaredTolerance = 0;
  12580. this.simplifiedGeometryRevision = this.getRevision();
  12581. }
  12582. // If squaredTolerance is negative or if we know that simplification will not
  12583. // have any effect then just return this.
  12584. if (squaredTolerance < 0 ||
  12585. (this.simplifiedGeometryMaxMinSquaredTolerance !== 0 &&
  12586. squaredTolerance <= this.simplifiedGeometryMaxMinSquaredTolerance)) {
  12587. return this;
  12588. }
  12589. var key = squaredTolerance.toString();
  12590. if (this.simplifiedGeometryCache.hasOwnProperty(key)) {
  12591. return this.simplifiedGeometryCache[key];
  12592. } else {
  12593. var simplifiedGeometry =
  12594. this.getSimplifiedGeometryInternal(squaredTolerance);
  12595. var simplifiedFlatCoordinates = simplifiedGeometry.getFlatCoordinates();
  12596. if (simplifiedFlatCoordinates.length < this.flatCoordinates.length) {
  12597. this.simplifiedGeometryCache[key] = simplifiedGeometry;
  12598. return simplifiedGeometry;
  12599. } else {
  12600. // Simplification did not actually remove any coordinates. We now know
  12601. // that any calls to getSimplifiedGeometry with a squaredTolerance less
  12602. // than or equal to the current squaredTolerance will also not have any
  12603. // effect. This allows us to short circuit simplification (saving CPU
  12604. // cycles) and prevents the cache of simplified geometries from filling
  12605. // up with useless identical copies of this geometry (saving memory).
  12606. this.simplifiedGeometryMaxMinSquaredTolerance = squaredTolerance;
  12607. return this;
  12608. }
  12609. }
  12610. };
  12611. /**
  12612. * @param {number} squaredTolerance Squared tolerance.
  12613. * @return {ol.geom.SimpleGeometry} Simplified geometry.
  12614. * @protected
  12615. */
  12616. ol.geom.SimpleGeometry.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
  12617. return this;
  12618. };
  12619. /**
  12620. * @return {number} Stride.
  12621. */
  12622. ol.geom.SimpleGeometry.prototype.getStride = function() {
  12623. return this.stride;
  12624. };
  12625. /**
  12626. * @param {ol.geom.GeometryLayout} layout Layout.
  12627. * @param {Array.<number>} flatCoordinates Flat coordinates.
  12628. * @protected
  12629. */
  12630. ol.geom.SimpleGeometry.prototype.setFlatCoordinatesInternal = function(layout, flatCoordinates) {
  12631. this.stride = ol.geom.SimpleGeometry.getStrideForLayout(layout);
  12632. this.layout = layout;
  12633. this.flatCoordinates = flatCoordinates;
  12634. };
  12635. /**
  12636. * @abstract
  12637. * @param {Array} coordinates Coordinates.
  12638. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  12639. */
  12640. ol.geom.SimpleGeometry.prototype.setCoordinates = function(coordinates, opt_layout) {};
  12641. /**
  12642. * @param {ol.geom.GeometryLayout|undefined} layout Layout.
  12643. * @param {Array} coordinates Coordinates.
  12644. * @param {number} nesting Nesting.
  12645. * @protected
  12646. */
  12647. ol.geom.SimpleGeometry.prototype.setLayout = function(layout, coordinates, nesting) {
  12648. /** @type {number} */
  12649. var stride;
  12650. if (layout) {
  12651. stride = ol.geom.SimpleGeometry.getStrideForLayout(layout);
  12652. } else {
  12653. var i;
  12654. for (i = 0; i < nesting; ++i) {
  12655. if (coordinates.length === 0) {
  12656. this.layout = ol.geom.GeometryLayout.XY;
  12657. this.stride = 2;
  12658. return;
  12659. } else {
  12660. coordinates = /** @type {Array} */ (coordinates[0]);
  12661. }
  12662. }
  12663. stride = coordinates.length;
  12664. layout = ol.geom.SimpleGeometry.getLayoutForStride_(stride);
  12665. }
  12666. this.layout = layout;
  12667. this.stride = stride;
  12668. };
  12669. /**
  12670. * @inheritDoc
  12671. * @api
  12672. */
  12673. ol.geom.SimpleGeometry.prototype.applyTransform = function(transformFn) {
  12674. if (this.flatCoordinates) {
  12675. transformFn(this.flatCoordinates, this.flatCoordinates, this.stride);
  12676. this.changed();
  12677. }
  12678. };
  12679. /**
  12680. * @inheritDoc
  12681. * @api
  12682. */
  12683. ol.geom.SimpleGeometry.prototype.rotate = function(angle, anchor) {
  12684. var flatCoordinates = this.getFlatCoordinates();
  12685. if (flatCoordinates) {
  12686. var stride = this.getStride();
  12687. ol.geom.flat.transform.rotate(
  12688. flatCoordinates, 0, flatCoordinates.length,
  12689. stride, angle, anchor, flatCoordinates);
  12690. this.changed();
  12691. }
  12692. };
  12693. /**
  12694. * @inheritDoc
  12695. * @api
  12696. */
  12697. ol.geom.SimpleGeometry.prototype.scale = function(sx, opt_sy, opt_anchor) {
  12698. var sy = opt_sy;
  12699. if (sy === undefined) {
  12700. sy = sx;
  12701. }
  12702. var anchor = opt_anchor;
  12703. if (!anchor) {
  12704. anchor = ol.extent.getCenter(this.getExtent());
  12705. }
  12706. var flatCoordinates = this.getFlatCoordinates();
  12707. if (flatCoordinates) {
  12708. var stride = this.getStride();
  12709. ol.geom.flat.transform.scale(
  12710. flatCoordinates, 0, flatCoordinates.length,
  12711. stride, sx, sy, anchor, flatCoordinates);
  12712. this.changed();
  12713. }
  12714. };
  12715. /**
  12716. * @inheritDoc
  12717. * @api
  12718. */
  12719. ol.geom.SimpleGeometry.prototype.translate = function(deltaX, deltaY) {
  12720. var flatCoordinates = this.getFlatCoordinates();
  12721. if (flatCoordinates) {
  12722. var stride = this.getStride();
  12723. ol.geom.flat.transform.translate(
  12724. flatCoordinates, 0, flatCoordinates.length, stride,
  12725. deltaX, deltaY, flatCoordinates);
  12726. this.changed();
  12727. }
  12728. };
  12729. /**
  12730. * @param {ol.geom.SimpleGeometry} simpleGeometry Simple geometry.
  12731. * @param {ol.Transform} transform Transform.
  12732. * @param {Array.<number>=} opt_dest Destination.
  12733. * @return {Array.<number>} Transformed flat coordinates.
  12734. */
  12735. ol.geom.SimpleGeometry.transform2D = function(simpleGeometry, transform, opt_dest) {
  12736. var flatCoordinates = simpleGeometry.getFlatCoordinates();
  12737. if (!flatCoordinates) {
  12738. return null;
  12739. } else {
  12740. var stride = simpleGeometry.getStride();
  12741. return ol.geom.flat.transform.transform2D(
  12742. flatCoordinates, 0, flatCoordinates.length, stride,
  12743. transform, opt_dest);
  12744. }
  12745. };
  12746. goog.provide('ol.geom.flat.area');
  12747. /**
  12748. * @param {Array.<number>} flatCoordinates Flat coordinates.
  12749. * @param {number} offset Offset.
  12750. * @param {number} end End.
  12751. * @param {number} stride Stride.
  12752. * @return {number} Area.
  12753. */
  12754. ol.geom.flat.area.linearRing = function(flatCoordinates, offset, end, stride) {
  12755. var twiceArea = 0;
  12756. var x1 = flatCoordinates[end - stride];
  12757. var y1 = flatCoordinates[end - stride + 1];
  12758. for (; offset < end; offset += stride) {
  12759. var x2 = flatCoordinates[offset];
  12760. var y2 = flatCoordinates[offset + 1];
  12761. twiceArea += y1 * x2 - x1 * y2;
  12762. x1 = x2;
  12763. y1 = y2;
  12764. }
  12765. return twiceArea / 2;
  12766. };
  12767. /**
  12768. * @param {Array.<number>} flatCoordinates Flat coordinates.
  12769. * @param {number} offset Offset.
  12770. * @param {Array.<number>} ends Ends.
  12771. * @param {number} stride Stride.
  12772. * @return {number} Area.
  12773. */
  12774. ol.geom.flat.area.linearRings = function(flatCoordinates, offset, ends, stride) {
  12775. var area = 0;
  12776. var i, ii;
  12777. for (i = 0, ii = ends.length; i < ii; ++i) {
  12778. var end = ends[i];
  12779. area += ol.geom.flat.area.linearRing(flatCoordinates, offset, end, stride);
  12780. offset = end;
  12781. }
  12782. return area;
  12783. };
  12784. /**
  12785. * @param {Array.<number>} flatCoordinates Flat coordinates.
  12786. * @param {number} offset Offset.
  12787. * @param {Array.<Array.<number>>} endss Endss.
  12788. * @param {number} stride Stride.
  12789. * @return {number} Area.
  12790. */
  12791. ol.geom.flat.area.linearRingss = function(flatCoordinates, offset, endss, stride) {
  12792. var area = 0;
  12793. var i, ii;
  12794. for (i = 0, ii = endss.length; i < ii; ++i) {
  12795. var ends = endss[i];
  12796. area +=
  12797. ol.geom.flat.area.linearRings(flatCoordinates, offset, ends, stride);
  12798. offset = ends[ends.length - 1];
  12799. }
  12800. return area;
  12801. };
  12802. goog.provide('ol.geom.flat.closest');
  12803. goog.require('ol.math');
  12804. /**
  12805. * Returns the point on the 2D line segment flatCoordinates[offset1] to
  12806. * flatCoordinates[offset2] that is closest to the point (x, y). Extra
  12807. * dimensions are linearly interpolated.
  12808. * @param {Array.<number>} flatCoordinates Flat coordinates.
  12809. * @param {number} offset1 Offset 1.
  12810. * @param {number} offset2 Offset 2.
  12811. * @param {number} stride Stride.
  12812. * @param {number} x X.
  12813. * @param {number} y Y.
  12814. * @param {Array.<number>} closestPoint Closest point.
  12815. */
  12816. ol.geom.flat.closest.point = function(flatCoordinates, offset1, offset2, stride, x, y, closestPoint) {
  12817. var x1 = flatCoordinates[offset1];
  12818. var y1 = flatCoordinates[offset1 + 1];
  12819. var dx = flatCoordinates[offset2] - x1;
  12820. var dy = flatCoordinates[offset2 + 1] - y1;
  12821. var i, offset;
  12822. if (dx === 0 && dy === 0) {
  12823. offset = offset1;
  12824. } else {
  12825. var t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy);
  12826. if (t > 1) {
  12827. offset = offset2;
  12828. } else if (t > 0) {
  12829. for (i = 0; i < stride; ++i) {
  12830. closestPoint[i] = ol.math.lerp(flatCoordinates[offset1 + i],
  12831. flatCoordinates[offset2 + i], t);
  12832. }
  12833. closestPoint.length = stride;
  12834. return;
  12835. } else {
  12836. offset = offset1;
  12837. }
  12838. }
  12839. for (i = 0; i < stride; ++i) {
  12840. closestPoint[i] = flatCoordinates[offset + i];
  12841. }
  12842. closestPoint.length = stride;
  12843. };
  12844. /**
  12845. * Return the squared of the largest distance between any pair of consecutive
  12846. * coordinates.
  12847. * @param {Array.<number>} flatCoordinates Flat coordinates.
  12848. * @param {number} offset Offset.
  12849. * @param {number} end End.
  12850. * @param {number} stride Stride.
  12851. * @param {number} maxSquaredDelta Max squared delta.
  12852. * @return {number} Max squared delta.
  12853. */
  12854. ol.geom.flat.closest.getMaxSquaredDelta = function(flatCoordinates, offset, end, stride, maxSquaredDelta) {
  12855. var x1 = flatCoordinates[offset];
  12856. var y1 = flatCoordinates[offset + 1];
  12857. for (offset += stride; offset < end; offset += stride) {
  12858. var x2 = flatCoordinates[offset];
  12859. var y2 = flatCoordinates[offset + 1];
  12860. var squaredDelta = ol.math.squaredDistance(x1, y1, x2, y2);
  12861. if (squaredDelta > maxSquaredDelta) {
  12862. maxSquaredDelta = squaredDelta;
  12863. }
  12864. x1 = x2;
  12865. y1 = y2;
  12866. }
  12867. return maxSquaredDelta;
  12868. };
  12869. /**
  12870. * @param {Array.<number>} flatCoordinates Flat coordinates.
  12871. * @param {number} offset Offset.
  12872. * @param {Array.<number>} ends Ends.
  12873. * @param {number} stride Stride.
  12874. * @param {number} maxSquaredDelta Max squared delta.
  12875. * @return {number} Max squared delta.
  12876. */
  12877. ol.geom.flat.closest.getsMaxSquaredDelta = function(flatCoordinates, offset, ends, stride, maxSquaredDelta) {
  12878. var i, ii;
  12879. for (i = 0, ii = ends.length; i < ii; ++i) {
  12880. var end = ends[i];
  12881. maxSquaredDelta = ol.geom.flat.closest.getMaxSquaredDelta(
  12882. flatCoordinates, offset, end, stride, maxSquaredDelta);
  12883. offset = end;
  12884. }
  12885. return maxSquaredDelta;
  12886. };
  12887. /**
  12888. * @param {Array.<number>} flatCoordinates Flat coordinates.
  12889. * @param {number} offset Offset.
  12890. * @param {Array.<Array.<number>>} endss Endss.
  12891. * @param {number} stride Stride.
  12892. * @param {number} maxSquaredDelta Max squared delta.
  12893. * @return {number} Max squared delta.
  12894. */
  12895. ol.geom.flat.closest.getssMaxSquaredDelta = function(flatCoordinates, offset, endss, stride, maxSquaredDelta) {
  12896. var i, ii;
  12897. for (i = 0, ii = endss.length; i < ii; ++i) {
  12898. var ends = endss[i];
  12899. maxSquaredDelta = ol.geom.flat.closest.getsMaxSquaredDelta(
  12900. flatCoordinates, offset, ends, stride, maxSquaredDelta);
  12901. offset = ends[ends.length - 1];
  12902. }
  12903. return maxSquaredDelta;
  12904. };
  12905. /**
  12906. * @param {Array.<number>} flatCoordinates Flat coordinates.
  12907. * @param {number} offset Offset.
  12908. * @param {number} end End.
  12909. * @param {number} stride Stride.
  12910. * @param {number} maxDelta Max delta.
  12911. * @param {boolean} isRing Is ring.
  12912. * @param {number} x X.
  12913. * @param {number} y Y.
  12914. * @param {Array.<number>} closestPoint Closest point.
  12915. * @param {number} minSquaredDistance Minimum squared distance.
  12916. * @param {Array.<number>=} opt_tmpPoint Temporary point object.
  12917. * @return {number} Minimum squared distance.
  12918. */
  12919. ol.geom.flat.closest.getClosestPoint = function(flatCoordinates, offset, end,
  12920. stride, maxDelta, isRing, x, y, closestPoint, minSquaredDistance,
  12921. opt_tmpPoint) {
  12922. if (offset == end) {
  12923. return minSquaredDistance;
  12924. }
  12925. var i, squaredDistance;
  12926. if (maxDelta === 0) {
  12927. // All points are identical, so just test the first point.
  12928. squaredDistance = ol.math.squaredDistance(
  12929. x, y, flatCoordinates[offset], flatCoordinates[offset + 1]);
  12930. if (squaredDistance < minSquaredDistance) {
  12931. for (i = 0; i < stride; ++i) {
  12932. closestPoint[i] = flatCoordinates[offset + i];
  12933. }
  12934. closestPoint.length = stride;
  12935. return squaredDistance;
  12936. } else {
  12937. return minSquaredDistance;
  12938. }
  12939. }
  12940. var tmpPoint = opt_tmpPoint ? opt_tmpPoint : [NaN, NaN];
  12941. var index = offset + stride;
  12942. while (index < end) {
  12943. ol.geom.flat.closest.point(
  12944. flatCoordinates, index - stride, index, stride, x, y, tmpPoint);
  12945. squaredDistance = ol.math.squaredDistance(x, y, tmpPoint[0], tmpPoint[1]);
  12946. if (squaredDistance < minSquaredDistance) {
  12947. minSquaredDistance = squaredDistance;
  12948. for (i = 0; i < stride; ++i) {
  12949. closestPoint[i] = tmpPoint[i];
  12950. }
  12951. closestPoint.length = stride;
  12952. index += stride;
  12953. } else {
  12954. // Skip ahead multiple points, because we know that all the skipped
  12955. // points cannot be any closer than the closest point we have found so
  12956. // far. We know this because we know how close the current point is, how
  12957. // close the closest point we have found so far is, and the maximum
  12958. // distance between consecutive points. For example, if we're currently
  12959. // at distance 10, the best we've found so far is 3, and that the maximum
  12960. // distance between consecutive points is 2, then we'll need to skip at
  12961. // least (10 - 3) / 2 == 3 (rounded down) points to have any chance of
  12962. // finding a closer point. We use Math.max(..., 1) to ensure that we
  12963. // always advance at least one point, to avoid an infinite loop.
  12964. index += stride * Math.max(
  12965. ((Math.sqrt(squaredDistance) -
  12966. Math.sqrt(minSquaredDistance)) / maxDelta) | 0, 1);
  12967. }
  12968. }
  12969. if (isRing) {
  12970. // Check the closing segment.
  12971. ol.geom.flat.closest.point(
  12972. flatCoordinates, end - stride, offset, stride, x, y, tmpPoint);
  12973. squaredDistance = ol.math.squaredDistance(x, y, tmpPoint[0], tmpPoint[1]);
  12974. if (squaredDistance < minSquaredDistance) {
  12975. minSquaredDistance = squaredDistance;
  12976. for (i = 0; i < stride; ++i) {
  12977. closestPoint[i] = tmpPoint[i];
  12978. }
  12979. closestPoint.length = stride;
  12980. }
  12981. }
  12982. return minSquaredDistance;
  12983. };
  12984. /**
  12985. * @param {Array.<number>} flatCoordinates Flat coordinates.
  12986. * @param {number} offset Offset.
  12987. * @param {Array.<number>} ends Ends.
  12988. * @param {number} stride Stride.
  12989. * @param {number} maxDelta Max delta.
  12990. * @param {boolean} isRing Is ring.
  12991. * @param {number} x X.
  12992. * @param {number} y Y.
  12993. * @param {Array.<number>} closestPoint Closest point.
  12994. * @param {number} minSquaredDistance Minimum squared distance.
  12995. * @param {Array.<number>=} opt_tmpPoint Temporary point object.
  12996. * @return {number} Minimum squared distance.
  12997. */
  12998. ol.geom.flat.closest.getsClosestPoint = function(flatCoordinates, offset, ends,
  12999. stride, maxDelta, isRing, x, y, closestPoint, minSquaredDistance,
  13000. opt_tmpPoint) {
  13001. var tmpPoint = opt_tmpPoint ? opt_tmpPoint : [NaN, NaN];
  13002. var i, ii;
  13003. for (i = 0, ii = ends.length; i < ii; ++i) {
  13004. var end = ends[i];
  13005. minSquaredDistance = ol.geom.flat.closest.getClosestPoint(
  13006. flatCoordinates, offset, end, stride,
  13007. maxDelta, isRing, x, y, closestPoint, minSquaredDistance, tmpPoint);
  13008. offset = end;
  13009. }
  13010. return minSquaredDistance;
  13011. };
  13012. /**
  13013. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13014. * @param {number} offset Offset.
  13015. * @param {Array.<Array.<number>>} endss Endss.
  13016. * @param {number} stride Stride.
  13017. * @param {number} maxDelta Max delta.
  13018. * @param {boolean} isRing Is ring.
  13019. * @param {number} x X.
  13020. * @param {number} y Y.
  13021. * @param {Array.<number>} closestPoint Closest point.
  13022. * @param {number} minSquaredDistance Minimum squared distance.
  13023. * @param {Array.<number>=} opt_tmpPoint Temporary point object.
  13024. * @return {number} Minimum squared distance.
  13025. */
  13026. ol.geom.flat.closest.getssClosestPoint = function(flatCoordinates, offset,
  13027. endss, stride, maxDelta, isRing, x, y, closestPoint, minSquaredDistance,
  13028. opt_tmpPoint) {
  13029. var tmpPoint = opt_tmpPoint ? opt_tmpPoint : [NaN, NaN];
  13030. var i, ii;
  13031. for (i = 0, ii = endss.length; i < ii; ++i) {
  13032. var ends = endss[i];
  13033. minSquaredDistance = ol.geom.flat.closest.getsClosestPoint(
  13034. flatCoordinates, offset, ends, stride,
  13035. maxDelta, isRing, x, y, closestPoint, minSquaredDistance, tmpPoint);
  13036. offset = ends[ends.length - 1];
  13037. }
  13038. return minSquaredDistance;
  13039. };
  13040. goog.provide('ol.geom.flat.deflate');
  13041. /**
  13042. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13043. * @param {number} offset Offset.
  13044. * @param {ol.Coordinate} coordinate Coordinate.
  13045. * @param {number} stride Stride.
  13046. * @return {number} offset Offset.
  13047. */
  13048. ol.geom.flat.deflate.coordinate = function(flatCoordinates, offset, coordinate, stride) {
  13049. var i, ii;
  13050. for (i = 0, ii = coordinate.length; i < ii; ++i) {
  13051. flatCoordinates[offset++] = coordinate[i];
  13052. }
  13053. return offset;
  13054. };
  13055. /**
  13056. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13057. * @param {number} offset Offset.
  13058. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  13059. * @param {number} stride Stride.
  13060. * @return {number} offset Offset.
  13061. */
  13062. ol.geom.flat.deflate.coordinates = function(flatCoordinates, offset, coordinates, stride) {
  13063. var i, ii;
  13064. for (i = 0, ii = coordinates.length; i < ii; ++i) {
  13065. var coordinate = coordinates[i];
  13066. var j;
  13067. for (j = 0; j < stride; ++j) {
  13068. flatCoordinates[offset++] = coordinate[j];
  13069. }
  13070. }
  13071. return offset;
  13072. };
  13073. /**
  13074. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13075. * @param {number} offset Offset.
  13076. * @param {Array.<Array.<ol.Coordinate>>} coordinatess Coordinatess.
  13077. * @param {number} stride Stride.
  13078. * @param {Array.<number>=} opt_ends Ends.
  13079. * @return {Array.<number>} Ends.
  13080. */
  13081. ol.geom.flat.deflate.coordinatess = function(flatCoordinates, offset, coordinatess, stride, opt_ends) {
  13082. var ends = opt_ends ? opt_ends : [];
  13083. var i = 0;
  13084. var j, jj;
  13085. for (j = 0, jj = coordinatess.length; j < jj; ++j) {
  13086. var end = ol.geom.flat.deflate.coordinates(
  13087. flatCoordinates, offset, coordinatess[j], stride);
  13088. ends[i++] = end;
  13089. offset = end;
  13090. }
  13091. ends.length = i;
  13092. return ends;
  13093. };
  13094. /**
  13095. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13096. * @param {number} offset Offset.
  13097. * @param {Array.<Array.<Array.<ol.Coordinate>>>} coordinatesss Coordinatesss.
  13098. * @param {number} stride Stride.
  13099. * @param {Array.<Array.<number>>=} opt_endss Endss.
  13100. * @return {Array.<Array.<number>>} Endss.
  13101. */
  13102. ol.geom.flat.deflate.coordinatesss = function(flatCoordinates, offset, coordinatesss, stride, opt_endss) {
  13103. var endss = opt_endss ? opt_endss : [];
  13104. var i = 0;
  13105. var j, jj;
  13106. for (j = 0, jj = coordinatesss.length; j < jj; ++j) {
  13107. var ends = ol.geom.flat.deflate.coordinatess(
  13108. flatCoordinates, offset, coordinatesss[j], stride, endss[i]);
  13109. endss[i++] = ends;
  13110. offset = ends[ends.length - 1];
  13111. }
  13112. endss.length = i;
  13113. return endss;
  13114. };
  13115. goog.provide('ol.geom.flat.inflate');
  13116. /**
  13117. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13118. * @param {number} offset Offset.
  13119. * @param {number} end End.
  13120. * @param {number} stride Stride.
  13121. * @param {Array.<ol.Coordinate>=} opt_coordinates Coordinates.
  13122. * @return {Array.<ol.Coordinate>} Coordinates.
  13123. */
  13124. ol.geom.flat.inflate.coordinates = function(flatCoordinates, offset, end, stride, opt_coordinates) {
  13125. var coordinates = opt_coordinates !== undefined ? opt_coordinates : [];
  13126. var i = 0;
  13127. var j;
  13128. for (j = offset; j < end; j += stride) {
  13129. coordinates[i++] = flatCoordinates.slice(j, j + stride);
  13130. }
  13131. coordinates.length = i;
  13132. return coordinates;
  13133. };
  13134. /**
  13135. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13136. * @param {number} offset Offset.
  13137. * @param {Array.<number>} ends Ends.
  13138. * @param {number} stride Stride.
  13139. * @param {Array.<Array.<ol.Coordinate>>=} opt_coordinatess Coordinatess.
  13140. * @return {Array.<Array.<ol.Coordinate>>} Coordinatess.
  13141. */
  13142. ol.geom.flat.inflate.coordinatess = function(flatCoordinates, offset, ends, stride, opt_coordinatess) {
  13143. var coordinatess = opt_coordinatess !== undefined ? opt_coordinatess : [];
  13144. var i = 0;
  13145. var j, jj;
  13146. for (j = 0, jj = ends.length; j < jj; ++j) {
  13147. var end = ends[j];
  13148. coordinatess[i++] = ol.geom.flat.inflate.coordinates(
  13149. flatCoordinates, offset, end, stride, coordinatess[i]);
  13150. offset = end;
  13151. }
  13152. coordinatess.length = i;
  13153. return coordinatess;
  13154. };
  13155. /**
  13156. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13157. * @param {number} offset Offset.
  13158. * @param {Array.<Array.<number>>} endss Endss.
  13159. * @param {number} stride Stride.
  13160. * @param {Array.<Array.<Array.<ol.Coordinate>>>=} opt_coordinatesss
  13161. * Coordinatesss.
  13162. * @return {Array.<Array.<Array.<ol.Coordinate>>>} Coordinatesss.
  13163. */
  13164. ol.geom.flat.inflate.coordinatesss = function(flatCoordinates, offset, endss, stride, opt_coordinatesss) {
  13165. var coordinatesss = opt_coordinatesss !== undefined ? opt_coordinatesss : [];
  13166. var i = 0;
  13167. var j, jj;
  13168. for (j = 0, jj = endss.length; j < jj; ++j) {
  13169. var ends = endss[j];
  13170. coordinatesss[i++] = ol.geom.flat.inflate.coordinatess(
  13171. flatCoordinates, offset, ends, stride, coordinatesss[i]);
  13172. offset = ends[ends.length - 1];
  13173. }
  13174. coordinatesss.length = i;
  13175. return coordinatesss;
  13176. };
  13177. // Based on simplify-js https://github.com/mourner/simplify-js
  13178. // Copyright (c) 2012, Vladimir Agafonkin
  13179. // All rights reserved.
  13180. //
  13181. // Redistribution and use in source and binary forms, with or without
  13182. // modification, are permitted provided that the following conditions are met:
  13183. //
  13184. // 1. Redistributions of source code must retain the above copyright notice,
  13185. // this list of conditions and the following disclaimer.
  13186. //
  13187. // 2. Redistributions in binary form must reproduce the above copyright
  13188. // notice, this list of conditions and the following disclaimer in the
  13189. // documentation and/or other materials provided with the distribution.
  13190. //
  13191. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  13192. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  13193. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  13194. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  13195. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  13196. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  13197. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  13198. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  13199. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  13200. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  13201. // POSSIBILITY OF SUCH DAMAGE.
  13202. goog.provide('ol.geom.flat.simplify');
  13203. goog.require('ol.math');
  13204. /**
  13205. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13206. * @param {number} offset Offset.
  13207. * @param {number} end End.
  13208. * @param {number} stride Stride.
  13209. * @param {number} squaredTolerance Squared tolerance.
  13210. * @param {boolean} highQuality Highest quality.
  13211. * @param {Array.<number>=} opt_simplifiedFlatCoordinates Simplified flat
  13212. * coordinates.
  13213. * @return {Array.<number>} Simplified line string.
  13214. */
  13215. ol.geom.flat.simplify.lineString = function(flatCoordinates, offset, end,
  13216. stride, squaredTolerance, highQuality, opt_simplifiedFlatCoordinates) {
  13217. var simplifiedFlatCoordinates = opt_simplifiedFlatCoordinates !== undefined ?
  13218. opt_simplifiedFlatCoordinates : [];
  13219. if (!highQuality) {
  13220. end = ol.geom.flat.simplify.radialDistance(flatCoordinates, offset, end,
  13221. stride, squaredTolerance,
  13222. simplifiedFlatCoordinates, 0);
  13223. flatCoordinates = simplifiedFlatCoordinates;
  13224. offset = 0;
  13225. stride = 2;
  13226. }
  13227. simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeucker(
  13228. flatCoordinates, offset, end, stride, squaredTolerance,
  13229. simplifiedFlatCoordinates, 0);
  13230. return simplifiedFlatCoordinates;
  13231. };
  13232. /**
  13233. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13234. * @param {number} offset Offset.
  13235. * @param {number} end End.
  13236. * @param {number} stride Stride.
  13237. * @param {number} squaredTolerance Squared tolerance.
  13238. * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
  13239. * coordinates.
  13240. * @param {number} simplifiedOffset Simplified offset.
  13241. * @return {number} Simplified offset.
  13242. */
  13243. ol.geom.flat.simplify.douglasPeucker = function(flatCoordinates, offset, end,
  13244. stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset) {
  13245. var n = (end - offset) / stride;
  13246. if (n < 3) {
  13247. for (; offset < end; offset += stride) {
  13248. simplifiedFlatCoordinates[simplifiedOffset++] =
  13249. flatCoordinates[offset];
  13250. simplifiedFlatCoordinates[simplifiedOffset++] =
  13251. flatCoordinates[offset + 1];
  13252. }
  13253. return simplifiedOffset;
  13254. }
  13255. /** @type {Array.<number>} */
  13256. var markers = new Array(n);
  13257. markers[0] = 1;
  13258. markers[n - 1] = 1;
  13259. /** @type {Array.<number>} */
  13260. var stack = [offset, end - stride];
  13261. var index = 0;
  13262. var i;
  13263. while (stack.length > 0) {
  13264. var last = stack.pop();
  13265. var first = stack.pop();
  13266. var maxSquaredDistance = 0;
  13267. var x1 = flatCoordinates[first];
  13268. var y1 = flatCoordinates[first + 1];
  13269. var x2 = flatCoordinates[last];
  13270. var y2 = flatCoordinates[last + 1];
  13271. for (i = first + stride; i < last; i += stride) {
  13272. var x = flatCoordinates[i];
  13273. var y = flatCoordinates[i + 1];
  13274. var squaredDistance = ol.math.squaredSegmentDistance(
  13275. x, y, x1, y1, x2, y2);
  13276. if (squaredDistance > maxSquaredDistance) {
  13277. index = i;
  13278. maxSquaredDistance = squaredDistance;
  13279. }
  13280. }
  13281. if (maxSquaredDistance > squaredTolerance) {
  13282. markers[(index - offset) / stride] = 1;
  13283. if (first + stride < index) {
  13284. stack.push(first, index);
  13285. }
  13286. if (index + stride < last) {
  13287. stack.push(index, last);
  13288. }
  13289. }
  13290. }
  13291. for (i = 0; i < n; ++i) {
  13292. if (markers[i]) {
  13293. simplifiedFlatCoordinates[simplifiedOffset++] =
  13294. flatCoordinates[offset + i * stride];
  13295. simplifiedFlatCoordinates[simplifiedOffset++] =
  13296. flatCoordinates[offset + i * stride + 1];
  13297. }
  13298. }
  13299. return simplifiedOffset;
  13300. };
  13301. /**
  13302. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13303. * @param {number} offset Offset.
  13304. * @param {Array.<number>} ends Ends.
  13305. * @param {number} stride Stride.
  13306. * @param {number} squaredTolerance Squared tolerance.
  13307. * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
  13308. * coordinates.
  13309. * @param {number} simplifiedOffset Simplified offset.
  13310. * @param {Array.<number>} simplifiedEnds Simplified ends.
  13311. * @return {number} Simplified offset.
  13312. */
  13313. ol.geom.flat.simplify.douglasPeuckers = function(flatCoordinates, offset,
  13314. ends, stride, squaredTolerance, simplifiedFlatCoordinates,
  13315. simplifiedOffset, simplifiedEnds) {
  13316. var i, ii;
  13317. for (i = 0, ii = ends.length; i < ii; ++i) {
  13318. var end = ends[i];
  13319. simplifiedOffset = ol.geom.flat.simplify.douglasPeucker(
  13320. flatCoordinates, offset, end, stride, squaredTolerance,
  13321. simplifiedFlatCoordinates, simplifiedOffset);
  13322. simplifiedEnds.push(simplifiedOffset);
  13323. offset = end;
  13324. }
  13325. return simplifiedOffset;
  13326. };
  13327. /**
  13328. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13329. * @param {number} offset Offset.
  13330. * @param {Array.<Array.<number>>} endss Endss.
  13331. * @param {number} stride Stride.
  13332. * @param {number} squaredTolerance Squared tolerance.
  13333. * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
  13334. * coordinates.
  13335. * @param {number} simplifiedOffset Simplified offset.
  13336. * @param {Array.<Array.<number>>} simplifiedEndss Simplified endss.
  13337. * @return {number} Simplified offset.
  13338. */
  13339. ol.geom.flat.simplify.douglasPeuckerss = function(
  13340. flatCoordinates, offset, endss, stride, squaredTolerance,
  13341. simplifiedFlatCoordinates, simplifiedOffset, simplifiedEndss) {
  13342. var i, ii;
  13343. for (i = 0, ii = endss.length; i < ii; ++i) {
  13344. var ends = endss[i];
  13345. var simplifiedEnds = [];
  13346. simplifiedOffset = ol.geom.flat.simplify.douglasPeuckers(
  13347. flatCoordinates, offset, ends, stride, squaredTolerance,
  13348. simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds);
  13349. simplifiedEndss.push(simplifiedEnds);
  13350. offset = ends[ends.length - 1];
  13351. }
  13352. return simplifiedOffset;
  13353. };
  13354. /**
  13355. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13356. * @param {number} offset Offset.
  13357. * @param {number} end End.
  13358. * @param {number} stride Stride.
  13359. * @param {number} squaredTolerance Squared tolerance.
  13360. * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
  13361. * coordinates.
  13362. * @param {number} simplifiedOffset Simplified offset.
  13363. * @return {number} Simplified offset.
  13364. */
  13365. ol.geom.flat.simplify.radialDistance = function(flatCoordinates, offset, end,
  13366. stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset) {
  13367. if (end <= offset + stride) {
  13368. // zero or one point, no simplification possible, so copy and return
  13369. for (; offset < end; offset += stride) {
  13370. simplifiedFlatCoordinates[simplifiedOffset++] = flatCoordinates[offset];
  13371. simplifiedFlatCoordinates[simplifiedOffset++] =
  13372. flatCoordinates[offset + 1];
  13373. }
  13374. return simplifiedOffset;
  13375. }
  13376. var x1 = flatCoordinates[offset];
  13377. var y1 = flatCoordinates[offset + 1];
  13378. // copy first point
  13379. simplifiedFlatCoordinates[simplifiedOffset++] = x1;
  13380. simplifiedFlatCoordinates[simplifiedOffset++] = y1;
  13381. var x2 = x1;
  13382. var y2 = y1;
  13383. for (offset += stride; offset < end; offset += stride) {
  13384. x2 = flatCoordinates[offset];
  13385. y2 = flatCoordinates[offset + 1];
  13386. if (ol.math.squaredDistance(x1, y1, x2, y2) > squaredTolerance) {
  13387. // copy point at offset
  13388. simplifiedFlatCoordinates[simplifiedOffset++] = x2;
  13389. simplifiedFlatCoordinates[simplifiedOffset++] = y2;
  13390. x1 = x2;
  13391. y1 = y2;
  13392. }
  13393. }
  13394. if (x2 != x1 || y2 != y1) {
  13395. // copy last point
  13396. simplifiedFlatCoordinates[simplifiedOffset++] = x2;
  13397. simplifiedFlatCoordinates[simplifiedOffset++] = y2;
  13398. }
  13399. return simplifiedOffset;
  13400. };
  13401. /**
  13402. * @param {number} value Value.
  13403. * @param {number} tolerance Tolerance.
  13404. * @return {number} Rounded value.
  13405. */
  13406. ol.geom.flat.simplify.snap = function(value, tolerance) {
  13407. return tolerance * Math.round(value / tolerance);
  13408. };
  13409. /**
  13410. * Simplifies a line string using an algorithm designed by Tim Schaub.
  13411. * Coordinates are snapped to the nearest value in a virtual grid and
  13412. * consecutive duplicate coordinates are discarded. This effectively preserves
  13413. * topology as the simplification of any subsection of a line string is
  13414. * independent of the rest of the line string. This means that, for examples,
  13415. * the common edge between two polygons will be simplified to the same line
  13416. * string independently in both polygons. This implementation uses a single
  13417. * pass over the coordinates and eliminates intermediate collinear points.
  13418. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13419. * @param {number} offset Offset.
  13420. * @param {number} end End.
  13421. * @param {number} stride Stride.
  13422. * @param {number} tolerance Tolerance.
  13423. * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
  13424. * coordinates.
  13425. * @param {number} simplifiedOffset Simplified offset.
  13426. * @return {number} Simplified offset.
  13427. */
  13428. ol.geom.flat.simplify.quantize = function(flatCoordinates, offset, end, stride,
  13429. tolerance, simplifiedFlatCoordinates, simplifiedOffset) {
  13430. // do nothing if the line is empty
  13431. if (offset == end) {
  13432. return simplifiedOffset;
  13433. }
  13434. // snap the first coordinate (P1)
  13435. var x1 = ol.geom.flat.simplify.snap(flatCoordinates[offset], tolerance);
  13436. var y1 = ol.geom.flat.simplify.snap(flatCoordinates[offset + 1], tolerance);
  13437. offset += stride;
  13438. // add the first coordinate to the output
  13439. simplifiedFlatCoordinates[simplifiedOffset++] = x1;
  13440. simplifiedFlatCoordinates[simplifiedOffset++] = y1;
  13441. // find the next coordinate that does not snap to the same value as the first
  13442. // coordinate (P2)
  13443. var x2, y2;
  13444. do {
  13445. x2 = ol.geom.flat.simplify.snap(flatCoordinates[offset], tolerance);
  13446. y2 = ol.geom.flat.simplify.snap(flatCoordinates[offset + 1], tolerance);
  13447. offset += stride;
  13448. if (offset == end) {
  13449. // all coordinates snap to the same value, the line collapses to a point
  13450. // push the last snapped value anyway to ensure that the output contains
  13451. // at least two points
  13452. // FIXME should we really return at least two points anyway?
  13453. simplifiedFlatCoordinates[simplifiedOffset++] = x2;
  13454. simplifiedFlatCoordinates[simplifiedOffset++] = y2;
  13455. return simplifiedOffset;
  13456. }
  13457. } while (x2 == x1 && y2 == y1);
  13458. while (offset < end) {
  13459. var x3, y3;
  13460. // snap the next coordinate (P3)
  13461. x3 = ol.geom.flat.simplify.snap(flatCoordinates[offset], tolerance);
  13462. y3 = ol.geom.flat.simplify.snap(flatCoordinates[offset + 1], tolerance);
  13463. offset += stride;
  13464. // skip P3 if it is equal to P2
  13465. if (x3 == x2 && y3 == y2) {
  13466. continue;
  13467. }
  13468. // calculate the delta between P1 and P2
  13469. var dx1 = x2 - x1;
  13470. var dy1 = y2 - y1;
  13471. // calculate the delta between P3 and P1
  13472. var dx2 = x3 - x1;
  13473. var dy2 = y3 - y1;
  13474. // if P1, P2, and P3 are colinear and P3 is further from P1 than P2 is from
  13475. // P1 in the same direction then P2 is on the straight line between P1 and
  13476. // P3
  13477. if ((dx1 * dy2 == dy1 * dx2) &&
  13478. ((dx1 < 0 && dx2 < dx1) || dx1 == dx2 || (dx1 > 0 && dx2 > dx1)) &&
  13479. ((dy1 < 0 && dy2 < dy1) || dy1 == dy2 || (dy1 > 0 && dy2 > dy1))) {
  13480. // discard P2 and set P2 = P3
  13481. x2 = x3;
  13482. y2 = y3;
  13483. continue;
  13484. }
  13485. // either P1, P2, and P3 are not colinear, or they are colinear but P3 is
  13486. // between P3 and P1 or on the opposite half of the line to P2. add P2,
  13487. // and continue with P1 = P2 and P2 = P3
  13488. simplifiedFlatCoordinates[simplifiedOffset++] = x2;
  13489. simplifiedFlatCoordinates[simplifiedOffset++] = y2;
  13490. x1 = x2;
  13491. y1 = y2;
  13492. x2 = x3;
  13493. y2 = y3;
  13494. }
  13495. // add the last point (P2)
  13496. simplifiedFlatCoordinates[simplifiedOffset++] = x2;
  13497. simplifiedFlatCoordinates[simplifiedOffset++] = y2;
  13498. return simplifiedOffset;
  13499. };
  13500. /**
  13501. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13502. * @param {number} offset Offset.
  13503. * @param {Array.<number>} ends Ends.
  13504. * @param {number} stride Stride.
  13505. * @param {number} tolerance Tolerance.
  13506. * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
  13507. * coordinates.
  13508. * @param {number} simplifiedOffset Simplified offset.
  13509. * @param {Array.<number>} simplifiedEnds Simplified ends.
  13510. * @return {number} Simplified offset.
  13511. */
  13512. ol.geom.flat.simplify.quantizes = function(
  13513. flatCoordinates, offset, ends, stride,
  13514. tolerance,
  13515. simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds) {
  13516. var i, ii;
  13517. for (i = 0, ii = ends.length; i < ii; ++i) {
  13518. var end = ends[i];
  13519. simplifiedOffset = ol.geom.flat.simplify.quantize(
  13520. flatCoordinates, offset, end, stride,
  13521. tolerance,
  13522. simplifiedFlatCoordinates, simplifiedOffset);
  13523. simplifiedEnds.push(simplifiedOffset);
  13524. offset = end;
  13525. }
  13526. return simplifiedOffset;
  13527. };
  13528. /**
  13529. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13530. * @param {number} offset Offset.
  13531. * @param {Array.<Array.<number>>} endss Endss.
  13532. * @param {number} stride Stride.
  13533. * @param {number} tolerance Tolerance.
  13534. * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
  13535. * coordinates.
  13536. * @param {number} simplifiedOffset Simplified offset.
  13537. * @param {Array.<Array.<number>>} simplifiedEndss Simplified endss.
  13538. * @return {number} Simplified offset.
  13539. */
  13540. ol.geom.flat.simplify.quantizess = function(
  13541. flatCoordinates, offset, endss, stride,
  13542. tolerance,
  13543. simplifiedFlatCoordinates, simplifiedOffset, simplifiedEndss) {
  13544. var i, ii;
  13545. for (i = 0, ii = endss.length; i < ii; ++i) {
  13546. var ends = endss[i];
  13547. var simplifiedEnds = [];
  13548. simplifiedOffset = ol.geom.flat.simplify.quantizes(
  13549. flatCoordinates, offset, ends, stride,
  13550. tolerance,
  13551. simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds);
  13552. simplifiedEndss.push(simplifiedEnds);
  13553. offset = ends[ends.length - 1];
  13554. }
  13555. return simplifiedOffset;
  13556. };
  13557. goog.provide('ol.geom.LinearRing');
  13558. goog.require('ol');
  13559. goog.require('ol.extent');
  13560. goog.require('ol.geom.GeometryLayout');
  13561. goog.require('ol.geom.GeometryType');
  13562. goog.require('ol.geom.SimpleGeometry');
  13563. goog.require('ol.geom.flat.area');
  13564. goog.require('ol.geom.flat.closest');
  13565. goog.require('ol.geom.flat.deflate');
  13566. goog.require('ol.geom.flat.inflate');
  13567. goog.require('ol.geom.flat.simplify');
  13568. /**
  13569. * @classdesc
  13570. * Linear ring geometry. Only used as part of polygon; cannot be rendered
  13571. * on its own.
  13572. *
  13573. * @constructor
  13574. * @extends {ol.geom.SimpleGeometry}
  13575. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  13576. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  13577. * @api
  13578. */
  13579. ol.geom.LinearRing = function(coordinates, opt_layout) {
  13580. ol.geom.SimpleGeometry.call(this);
  13581. /**
  13582. * @private
  13583. * @type {number}
  13584. */
  13585. this.maxDelta_ = -1;
  13586. /**
  13587. * @private
  13588. * @type {number}
  13589. */
  13590. this.maxDeltaRevision_ = -1;
  13591. this.setCoordinates(coordinates, opt_layout);
  13592. };
  13593. ol.inherits(ol.geom.LinearRing, ol.geom.SimpleGeometry);
  13594. /**
  13595. * Make a complete copy of the geometry.
  13596. * @return {!ol.geom.LinearRing} Clone.
  13597. * @override
  13598. * @api
  13599. */
  13600. ol.geom.LinearRing.prototype.clone = function() {
  13601. var linearRing = new ol.geom.LinearRing(null);
  13602. linearRing.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
  13603. return linearRing;
  13604. };
  13605. /**
  13606. * @inheritDoc
  13607. */
  13608. ol.geom.LinearRing.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  13609. if (minSquaredDistance <
  13610. ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
  13611. return minSquaredDistance;
  13612. }
  13613. if (this.maxDeltaRevision_ != this.getRevision()) {
  13614. this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getMaxSquaredDelta(
  13615. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, 0));
  13616. this.maxDeltaRevision_ = this.getRevision();
  13617. }
  13618. return ol.geom.flat.closest.getClosestPoint(
  13619. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
  13620. this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);
  13621. };
  13622. /**
  13623. * Return the area of the linear ring on projected plane.
  13624. * @return {number} Area (on projected plane).
  13625. * @api
  13626. */
  13627. ol.geom.LinearRing.prototype.getArea = function() {
  13628. return ol.geom.flat.area.linearRing(
  13629. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
  13630. };
  13631. /**
  13632. * Return the coordinates of the linear ring.
  13633. * @return {Array.<ol.Coordinate>} Coordinates.
  13634. * @override
  13635. * @api
  13636. */
  13637. ol.geom.LinearRing.prototype.getCoordinates = function() {
  13638. return ol.geom.flat.inflate.coordinates(
  13639. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
  13640. };
  13641. /**
  13642. * @inheritDoc
  13643. */
  13644. ol.geom.LinearRing.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
  13645. var simplifiedFlatCoordinates = [];
  13646. simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeucker(
  13647. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
  13648. squaredTolerance, simplifiedFlatCoordinates, 0);
  13649. var simplifiedLinearRing = new ol.geom.LinearRing(null);
  13650. simplifiedLinearRing.setFlatCoordinates(
  13651. ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates);
  13652. return simplifiedLinearRing;
  13653. };
  13654. /**
  13655. * @inheritDoc
  13656. * @api
  13657. */
  13658. ol.geom.LinearRing.prototype.getType = function() {
  13659. return ol.geom.GeometryType.LINEAR_RING;
  13660. };
  13661. /**
  13662. * @inheritDoc
  13663. */
  13664. ol.geom.LinearRing.prototype.intersectsExtent = function(extent) {};
  13665. /**
  13666. * Set the coordinates of the linear ring.
  13667. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  13668. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  13669. * @override
  13670. * @api
  13671. */
  13672. ol.geom.LinearRing.prototype.setCoordinates = function(coordinates, opt_layout) {
  13673. if (!coordinates) {
  13674. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
  13675. } else {
  13676. this.setLayout(opt_layout, coordinates, 1);
  13677. if (!this.flatCoordinates) {
  13678. this.flatCoordinates = [];
  13679. }
  13680. this.flatCoordinates.length = ol.geom.flat.deflate.coordinates(
  13681. this.flatCoordinates, 0, coordinates, this.stride);
  13682. this.changed();
  13683. }
  13684. };
  13685. /**
  13686. * @param {ol.geom.GeometryLayout} layout Layout.
  13687. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13688. */
  13689. ol.geom.LinearRing.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
  13690. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  13691. this.changed();
  13692. };
  13693. goog.provide('ol.geom.Point');
  13694. goog.require('ol');
  13695. goog.require('ol.extent');
  13696. goog.require('ol.geom.GeometryLayout');
  13697. goog.require('ol.geom.GeometryType');
  13698. goog.require('ol.geom.SimpleGeometry');
  13699. goog.require('ol.geom.flat.deflate');
  13700. goog.require('ol.math');
  13701. /**
  13702. * @classdesc
  13703. * Point geometry.
  13704. *
  13705. * @constructor
  13706. * @extends {ol.geom.SimpleGeometry}
  13707. * @param {ol.Coordinate} coordinates Coordinates.
  13708. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  13709. * @api
  13710. */
  13711. ol.geom.Point = function(coordinates, opt_layout) {
  13712. ol.geom.SimpleGeometry.call(this);
  13713. this.setCoordinates(coordinates, opt_layout);
  13714. };
  13715. ol.inherits(ol.geom.Point, ol.geom.SimpleGeometry);
  13716. /**
  13717. * Make a complete copy of the geometry.
  13718. * @return {!ol.geom.Point} Clone.
  13719. * @override
  13720. * @api
  13721. */
  13722. ol.geom.Point.prototype.clone = function() {
  13723. var point = new ol.geom.Point(null);
  13724. point.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
  13725. return point;
  13726. };
  13727. /**
  13728. * @inheritDoc
  13729. */
  13730. ol.geom.Point.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  13731. var flatCoordinates = this.flatCoordinates;
  13732. var squaredDistance = ol.math.squaredDistance(
  13733. x, y, flatCoordinates[0], flatCoordinates[1]);
  13734. if (squaredDistance < minSquaredDistance) {
  13735. var stride = this.stride;
  13736. var i;
  13737. for (i = 0; i < stride; ++i) {
  13738. closestPoint[i] = flatCoordinates[i];
  13739. }
  13740. closestPoint.length = stride;
  13741. return squaredDistance;
  13742. } else {
  13743. return minSquaredDistance;
  13744. }
  13745. };
  13746. /**
  13747. * Return the coordinate of the point.
  13748. * @return {ol.Coordinate} Coordinates.
  13749. * @override
  13750. * @api
  13751. */
  13752. ol.geom.Point.prototype.getCoordinates = function() {
  13753. return !this.flatCoordinates ? [] : this.flatCoordinates.slice();
  13754. };
  13755. /**
  13756. * @inheritDoc
  13757. */
  13758. ol.geom.Point.prototype.computeExtent = function(extent) {
  13759. return ol.extent.createOrUpdateFromCoordinate(this.flatCoordinates, extent);
  13760. };
  13761. /**
  13762. * @inheritDoc
  13763. * @api
  13764. */
  13765. ol.geom.Point.prototype.getType = function() {
  13766. return ol.geom.GeometryType.POINT;
  13767. };
  13768. /**
  13769. * @inheritDoc
  13770. * @api
  13771. */
  13772. ol.geom.Point.prototype.intersectsExtent = function(extent) {
  13773. return ol.extent.containsXY(extent,
  13774. this.flatCoordinates[0], this.flatCoordinates[1]);
  13775. };
  13776. /**
  13777. * @inheritDoc
  13778. * @api
  13779. */
  13780. ol.geom.Point.prototype.setCoordinates = function(coordinates, opt_layout) {
  13781. if (!coordinates) {
  13782. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
  13783. } else {
  13784. this.setLayout(opt_layout, coordinates, 0);
  13785. if (!this.flatCoordinates) {
  13786. this.flatCoordinates = [];
  13787. }
  13788. this.flatCoordinates.length = ol.geom.flat.deflate.coordinate(
  13789. this.flatCoordinates, 0, coordinates, this.stride);
  13790. this.changed();
  13791. }
  13792. };
  13793. /**
  13794. * @param {ol.geom.GeometryLayout} layout Layout.
  13795. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13796. */
  13797. ol.geom.Point.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
  13798. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  13799. this.changed();
  13800. };
  13801. goog.provide('ol.geom.flat.contains');
  13802. goog.require('ol.extent');
  13803. /**
  13804. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13805. * @param {number} offset Offset.
  13806. * @param {number} end End.
  13807. * @param {number} stride Stride.
  13808. * @param {ol.Extent} extent Extent.
  13809. * @return {boolean} Contains extent.
  13810. */
  13811. ol.geom.flat.contains.linearRingContainsExtent = function(flatCoordinates, offset, end, stride, extent) {
  13812. var outside = ol.extent.forEachCorner(extent,
  13813. /**
  13814. * @param {ol.Coordinate} coordinate Coordinate.
  13815. * @return {boolean} Contains (x, y).
  13816. */
  13817. function(coordinate) {
  13818. return !ol.geom.flat.contains.linearRingContainsXY(flatCoordinates,
  13819. offset, end, stride, coordinate[0], coordinate[1]);
  13820. });
  13821. return !outside;
  13822. };
  13823. /**
  13824. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13825. * @param {number} offset Offset.
  13826. * @param {number} end End.
  13827. * @param {number} stride Stride.
  13828. * @param {number} x X.
  13829. * @param {number} y Y.
  13830. * @return {boolean} Contains (x, y).
  13831. */
  13832. ol.geom.flat.contains.linearRingContainsXY = function(flatCoordinates, offset, end, stride, x, y) {
  13833. // http://geomalgorithms.com/a03-_inclusion.html
  13834. // Copyright 2000 softSurfer, 2012 Dan Sunday
  13835. // This code may be freely used and modified for any purpose
  13836. // providing that this copyright notice is included with it.
  13837. // SoftSurfer makes no warranty for this code, and cannot be held
  13838. // liable for any real or imagined damage resulting from its use.
  13839. // Users of this code must verify correctness for their application.
  13840. var wn = 0;
  13841. var x1 = flatCoordinates[end - stride];
  13842. var y1 = flatCoordinates[end - stride + 1];
  13843. for (; offset < end; offset += stride) {
  13844. var x2 = flatCoordinates[offset];
  13845. var y2 = flatCoordinates[offset + 1];
  13846. if (y1 <= y) {
  13847. if (y2 > y && ((x2 - x1) * (y - y1)) - ((x - x1) * (y2 - y1)) > 0) {
  13848. wn++;
  13849. }
  13850. } else if (y2 <= y && ((x2 - x1) * (y - y1)) - ((x - x1) * (y2 - y1)) < 0) {
  13851. wn--;
  13852. }
  13853. x1 = x2;
  13854. y1 = y2;
  13855. }
  13856. return wn !== 0;
  13857. };
  13858. /**
  13859. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13860. * @param {number} offset Offset.
  13861. * @param {Array.<number>} ends Ends.
  13862. * @param {number} stride Stride.
  13863. * @param {number} x X.
  13864. * @param {number} y Y.
  13865. * @return {boolean} Contains (x, y).
  13866. */
  13867. ol.geom.flat.contains.linearRingsContainsXY = function(flatCoordinates, offset, ends, stride, x, y) {
  13868. if (ends.length === 0) {
  13869. return false;
  13870. }
  13871. if (!ol.geom.flat.contains.linearRingContainsXY(
  13872. flatCoordinates, offset, ends[0], stride, x, y)) {
  13873. return false;
  13874. }
  13875. var i, ii;
  13876. for (i = 1, ii = ends.length; i < ii; ++i) {
  13877. if (ol.geom.flat.contains.linearRingContainsXY(
  13878. flatCoordinates, ends[i - 1], ends[i], stride, x, y)) {
  13879. return false;
  13880. }
  13881. }
  13882. return true;
  13883. };
  13884. /**
  13885. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13886. * @param {number} offset Offset.
  13887. * @param {Array.<Array.<number>>} endss Endss.
  13888. * @param {number} stride Stride.
  13889. * @param {number} x X.
  13890. * @param {number} y Y.
  13891. * @return {boolean} Contains (x, y).
  13892. */
  13893. ol.geom.flat.contains.linearRingssContainsXY = function(flatCoordinates, offset, endss, stride, x, y) {
  13894. if (endss.length === 0) {
  13895. return false;
  13896. }
  13897. var i, ii;
  13898. for (i = 0, ii = endss.length; i < ii; ++i) {
  13899. var ends = endss[i];
  13900. if (ol.geom.flat.contains.linearRingsContainsXY(
  13901. flatCoordinates, offset, ends, stride, x, y)) {
  13902. return true;
  13903. }
  13904. offset = ends[ends.length - 1];
  13905. }
  13906. return false;
  13907. };
  13908. goog.provide('ol.geom.flat.interiorpoint');
  13909. goog.require('ol.array');
  13910. goog.require('ol.geom.flat.contains');
  13911. /**
  13912. * Calculates a point that is likely to lie in the interior of the linear rings.
  13913. * Inspired by JTS's com.vividsolutions.jts.geom.Geometry#getInteriorPoint.
  13914. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13915. * @param {number} offset Offset.
  13916. * @param {Array.<number>} ends Ends.
  13917. * @param {number} stride Stride.
  13918. * @param {Array.<number>} flatCenters Flat centers.
  13919. * @param {number} flatCentersOffset Flat center offset.
  13920. * @param {Array.<number>=} opt_dest Destination.
  13921. * @return {Array.<number>} Destination.
  13922. */
  13923. ol.geom.flat.interiorpoint.linearRings = function(flatCoordinates, offset,
  13924. ends, stride, flatCenters, flatCentersOffset, opt_dest) {
  13925. var i, ii, x, x1, x2, y1, y2;
  13926. var y = flatCenters[flatCentersOffset + 1];
  13927. /** @type {Array.<number>} */
  13928. var intersections = [];
  13929. // Calculate intersections with the horizontal line
  13930. var end = ends[0];
  13931. x1 = flatCoordinates[end - stride];
  13932. y1 = flatCoordinates[end - stride + 1];
  13933. for (i = offset; i < end; i += stride) {
  13934. x2 = flatCoordinates[i];
  13935. y2 = flatCoordinates[i + 1];
  13936. if ((y <= y1 && y2 <= y) || (y1 <= y && y <= y2)) {
  13937. x = (y - y1) / (y2 - y1) * (x2 - x1) + x1;
  13938. intersections.push(x);
  13939. }
  13940. x1 = x2;
  13941. y1 = y2;
  13942. }
  13943. // Find the longest segment of the horizontal line that has its center point
  13944. // inside the linear ring.
  13945. var pointX = NaN;
  13946. var maxSegmentLength = -Infinity;
  13947. intersections.sort(ol.array.numberSafeCompareFunction);
  13948. x1 = intersections[0];
  13949. for (i = 1, ii = intersections.length; i < ii; ++i) {
  13950. x2 = intersections[i];
  13951. var segmentLength = Math.abs(x2 - x1);
  13952. if (segmentLength > maxSegmentLength) {
  13953. x = (x1 + x2) / 2;
  13954. if (ol.geom.flat.contains.linearRingsContainsXY(
  13955. flatCoordinates, offset, ends, stride, x, y)) {
  13956. pointX = x;
  13957. maxSegmentLength = segmentLength;
  13958. }
  13959. }
  13960. x1 = x2;
  13961. }
  13962. if (isNaN(pointX)) {
  13963. // There is no horizontal line that has its center point inside the linear
  13964. // ring. Use the center of the the linear ring's extent.
  13965. pointX = flatCenters[flatCentersOffset];
  13966. }
  13967. if (opt_dest) {
  13968. opt_dest.push(pointX, y);
  13969. return opt_dest;
  13970. } else {
  13971. return [pointX, y];
  13972. }
  13973. };
  13974. /**
  13975. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13976. * @param {number} offset Offset.
  13977. * @param {Array.<Array.<number>>} endss Endss.
  13978. * @param {number} stride Stride.
  13979. * @param {Array.<number>} flatCenters Flat centers.
  13980. * @return {Array.<number>} Interior points.
  13981. */
  13982. ol.geom.flat.interiorpoint.linearRingss = function(flatCoordinates, offset, endss, stride, flatCenters) {
  13983. var interiorPoints = [];
  13984. var i, ii;
  13985. for (i = 0, ii = endss.length; i < ii; ++i) {
  13986. var ends = endss[i];
  13987. interiorPoints = ol.geom.flat.interiorpoint.linearRings(flatCoordinates,
  13988. offset, ends, stride, flatCenters, 2 * i, interiorPoints);
  13989. offset = ends[ends.length - 1];
  13990. }
  13991. return interiorPoints;
  13992. };
  13993. goog.provide('ol.geom.flat.segments');
  13994. /**
  13995. * This function calls `callback` for each segment of the flat coordinates
  13996. * array. If the callback returns a truthy value the function returns that
  13997. * value immediately. Otherwise the function returns `false`.
  13998. * @param {Array.<number>} flatCoordinates Flat coordinates.
  13999. * @param {number} offset Offset.
  14000. * @param {number} end End.
  14001. * @param {number} stride Stride.
  14002. * @param {function(this: S, ol.Coordinate, ol.Coordinate): T} callback Function
  14003. * called for each segment.
  14004. * @param {S=} opt_this The object to be used as the value of 'this'
  14005. * within callback.
  14006. * @return {T|boolean} Value.
  14007. * @template T,S
  14008. */
  14009. ol.geom.flat.segments.forEach = function(flatCoordinates, offset, end, stride, callback, opt_this) {
  14010. var point1 = [flatCoordinates[offset], flatCoordinates[offset + 1]];
  14011. var point2 = [];
  14012. var ret;
  14013. for (; (offset + stride) < end; offset += stride) {
  14014. point2[0] = flatCoordinates[offset + stride];
  14015. point2[1] = flatCoordinates[offset + stride + 1];
  14016. ret = callback.call(opt_this, point1, point2);
  14017. if (ret) {
  14018. return ret;
  14019. }
  14020. point1[0] = point2[0];
  14021. point1[1] = point2[1];
  14022. }
  14023. return false;
  14024. };
  14025. goog.provide('ol.geom.flat.intersectsextent');
  14026. goog.require('ol.extent');
  14027. goog.require('ol.geom.flat.contains');
  14028. goog.require('ol.geom.flat.segments');
  14029. /**
  14030. * @param {Array.<number>} flatCoordinates Flat coordinates.
  14031. * @param {number} offset Offset.
  14032. * @param {number} end End.
  14033. * @param {number} stride Stride.
  14034. * @param {ol.Extent} extent Extent.
  14035. * @return {boolean} True if the geometry and the extent intersect.
  14036. */
  14037. ol.geom.flat.intersectsextent.lineString = function(flatCoordinates, offset, end, stride, extent) {
  14038. var coordinatesExtent = ol.extent.extendFlatCoordinates(
  14039. ol.extent.createEmpty(), flatCoordinates, offset, end, stride);
  14040. if (!ol.extent.intersects(extent, coordinatesExtent)) {
  14041. return false;
  14042. }
  14043. if (ol.extent.containsExtent(extent, coordinatesExtent)) {
  14044. return true;
  14045. }
  14046. if (coordinatesExtent[0] >= extent[0] &&
  14047. coordinatesExtent[2] <= extent[2]) {
  14048. return true;
  14049. }
  14050. if (coordinatesExtent[1] >= extent[1] &&
  14051. coordinatesExtent[3] <= extent[3]) {
  14052. return true;
  14053. }
  14054. return ol.geom.flat.segments.forEach(flatCoordinates, offset, end, stride,
  14055. /**
  14056. * @param {ol.Coordinate} point1 Start point.
  14057. * @param {ol.Coordinate} point2 End point.
  14058. * @return {boolean} `true` if the segment and the extent intersect,
  14059. * `false` otherwise.
  14060. */
  14061. function(point1, point2) {
  14062. return ol.extent.intersectsSegment(extent, point1, point2);
  14063. });
  14064. };
  14065. /**
  14066. * @param {Array.<number>} flatCoordinates Flat coordinates.
  14067. * @param {number} offset Offset.
  14068. * @param {Array.<number>} ends Ends.
  14069. * @param {number} stride Stride.
  14070. * @param {ol.Extent} extent Extent.
  14071. * @return {boolean} True if the geometry and the extent intersect.
  14072. */
  14073. ol.geom.flat.intersectsextent.lineStrings = function(flatCoordinates, offset, ends, stride, extent) {
  14074. var i, ii;
  14075. for (i = 0, ii = ends.length; i < ii; ++i) {
  14076. if (ol.geom.flat.intersectsextent.lineString(
  14077. flatCoordinates, offset, ends[i], stride, extent)) {
  14078. return true;
  14079. }
  14080. offset = ends[i];
  14081. }
  14082. return false;
  14083. };
  14084. /**
  14085. * @param {Array.<number>} flatCoordinates Flat coordinates.
  14086. * @param {number} offset Offset.
  14087. * @param {number} end End.
  14088. * @param {number} stride Stride.
  14089. * @param {ol.Extent} extent Extent.
  14090. * @return {boolean} True if the geometry and the extent intersect.
  14091. */
  14092. ol.geom.flat.intersectsextent.linearRing = function(flatCoordinates, offset, end, stride, extent) {
  14093. if (ol.geom.flat.intersectsextent.lineString(
  14094. flatCoordinates, offset, end, stride, extent)) {
  14095. return true;
  14096. }
  14097. if (ol.geom.flat.contains.linearRingContainsXY(
  14098. flatCoordinates, offset, end, stride, extent[0], extent[1])) {
  14099. return true;
  14100. }
  14101. if (ol.geom.flat.contains.linearRingContainsXY(
  14102. flatCoordinates, offset, end, stride, extent[0], extent[3])) {
  14103. return true;
  14104. }
  14105. if (ol.geom.flat.contains.linearRingContainsXY(
  14106. flatCoordinates, offset, end, stride, extent[2], extent[1])) {
  14107. return true;
  14108. }
  14109. if (ol.geom.flat.contains.linearRingContainsXY(
  14110. flatCoordinates, offset, end, stride, extent[2], extent[3])) {
  14111. return true;
  14112. }
  14113. return false;
  14114. };
  14115. /**
  14116. * @param {Array.<number>} flatCoordinates Flat coordinates.
  14117. * @param {number} offset Offset.
  14118. * @param {Array.<number>} ends Ends.
  14119. * @param {number} stride Stride.
  14120. * @param {ol.Extent} extent Extent.
  14121. * @return {boolean} True if the geometry and the extent intersect.
  14122. */
  14123. ol.geom.flat.intersectsextent.linearRings = function(flatCoordinates, offset, ends, stride, extent) {
  14124. if (!ol.geom.flat.intersectsextent.linearRing(
  14125. flatCoordinates, offset, ends[0], stride, extent)) {
  14126. return false;
  14127. }
  14128. if (ends.length === 1) {
  14129. return true;
  14130. }
  14131. var i, ii;
  14132. for (i = 1, ii = ends.length; i < ii; ++i) {
  14133. if (ol.geom.flat.contains.linearRingContainsExtent(
  14134. flatCoordinates, ends[i - 1], ends[i], stride, extent)) {
  14135. return false;
  14136. }
  14137. }
  14138. return true;
  14139. };
  14140. /**
  14141. * @param {Array.<number>} flatCoordinates Flat coordinates.
  14142. * @param {number} offset Offset.
  14143. * @param {Array.<Array.<number>>} endss Endss.
  14144. * @param {number} stride Stride.
  14145. * @param {ol.Extent} extent Extent.
  14146. * @return {boolean} True if the geometry and the extent intersect.
  14147. */
  14148. ol.geom.flat.intersectsextent.linearRingss = function(flatCoordinates, offset, endss, stride, extent) {
  14149. var i, ii;
  14150. for (i = 0, ii = endss.length; i < ii; ++i) {
  14151. var ends = endss[i];
  14152. if (ol.geom.flat.intersectsextent.linearRings(
  14153. flatCoordinates, offset, ends, stride, extent)) {
  14154. return true;
  14155. }
  14156. offset = ends[ends.length - 1];
  14157. }
  14158. return false;
  14159. };
  14160. goog.provide('ol.geom.flat.reverse');
  14161. /**
  14162. * @param {Array.<number>} flatCoordinates Flat coordinates.
  14163. * @param {number} offset Offset.
  14164. * @param {number} end End.
  14165. * @param {number} stride Stride.
  14166. */
  14167. ol.geom.flat.reverse.coordinates = function(flatCoordinates, offset, end, stride) {
  14168. while (offset < end - stride) {
  14169. var i;
  14170. for (i = 0; i < stride; ++i) {
  14171. var tmp = flatCoordinates[offset + i];
  14172. flatCoordinates[offset + i] = flatCoordinates[end - stride + i];
  14173. flatCoordinates[end - stride + i] = tmp;
  14174. }
  14175. offset += stride;
  14176. end -= stride;
  14177. }
  14178. };
  14179. goog.provide('ol.geom.flat.orient');
  14180. goog.require('ol.geom.flat.reverse');
  14181. /**
  14182. * @param {Array.<number>} flatCoordinates Flat coordinates.
  14183. * @param {number} offset Offset.
  14184. * @param {number} end End.
  14185. * @param {number} stride Stride.
  14186. * @return {boolean} Is clockwise.
  14187. */
  14188. ol.geom.flat.orient.linearRingIsClockwise = function(flatCoordinates, offset, end, stride) {
  14189. // http://tinyurl.com/clockwise-method
  14190. // https://github.com/OSGeo/gdal/blob/trunk/gdal/ogr/ogrlinearring.cpp
  14191. var edge = 0;
  14192. var x1 = flatCoordinates[end - stride];
  14193. var y1 = flatCoordinates[end - stride + 1];
  14194. for (; offset < end; offset += stride) {
  14195. var x2 = flatCoordinates[offset];
  14196. var y2 = flatCoordinates[offset + 1];
  14197. edge += (x2 - x1) * (y2 + y1);
  14198. x1 = x2;
  14199. y1 = y2;
  14200. }
  14201. return edge > 0;
  14202. };
  14203. /**
  14204. * Determines if linear rings are oriented. By default, left-hand orientation
  14205. * is tested (first ring must be clockwise, remaining rings counter-clockwise).
  14206. * To test for right-hand orientation, use the `opt_right` argument.
  14207. *
  14208. * @param {Array.<number>} flatCoordinates Flat coordinates.
  14209. * @param {number} offset Offset.
  14210. * @param {Array.<number>} ends Array of end indexes.
  14211. * @param {number} stride Stride.
  14212. * @param {boolean=} opt_right Test for right-hand orientation
  14213. * (counter-clockwise exterior ring and clockwise interior rings).
  14214. * @return {boolean} Rings are correctly oriented.
  14215. */
  14216. ol.geom.flat.orient.linearRingsAreOriented = function(flatCoordinates, offset, ends, stride, opt_right) {
  14217. var right = opt_right !== undefined ? opt_right : false;
  14218. var i, ii;
  14219. for (i = 0, ii = ends.length; i < ii; ++i) {
  14220. var end = ends[i];
  14221. var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(
  14222. flatCoordinates, offset, end, stride);
  14223. if (i === 0) {
  14224. if ((right && isClockwise) || (!right && !isClockwise)) {
  14225. return false;
  14226. }
  14227. } else {
  14228. if ((right && !isClockwise) || (!right && isClockwise)) {
  14229. return false;
  14230. }
  14231. }
  14232. offset = end;
  14233. }
  14234. return true;
  14235. };
  14236. /**
  14237. * Determines if linear rings are oriented. By default, left-hand orientation
  14238. * is tested (first ring must be clockwise, remaining rings counter-clockwise).
  14239. * To test for right-hand orientation, use the `opt_right` argument.
  14240. *
  14241. * @param {Array.<number>} flatCoordinates Flat coordinates.
  14242. * @param {number} offset Offset.
  14243. * @param {Array.<Array.<number>>} endss Array of array of end indexes.
  14244. * @param {number} stride Stride.
  14245. * @param {boolean=} opt_right Test for right-hand orientation
  14246. * (counter-clockwise exterior ring and clockwise interior rings).
  14247. * @return {boolean} Rings are correctly oriented.
  14248. */
  14249. ol.geom.flat.orient.linearRingssAreOriented = function(flatCoordinates, offset, endss, stride, opt_right) {
  14250. var i, ii;
  14251. for (i = 0, ii = endss.length; i < ii; ++i) {
  14252. if (!ol.geom.flat.orient.linearRingsAreOriented(
  14253. flatCoordinates, offset, endss[i], stride, opt_right)) {
  14254. return false;
  14255. }
  14256. }
  14257. return true;
  14258. };
  14259. /**
  14260. * Orient coordinates in a flat array of linear rings. By default, rings
  14261. * are oriented following the left-hand rule (clockwise for exterior and
  14262. * counter-clockwise for interior rings). To orient according to the
  14263. * right-hand rule, use the `opt_right` argument.
  14264. *
  14265. * @param {Array.<number>} flatCoordinates Flat coordinates.
  14266. * @param {number} offset Offset.
  14267. * @param {Array.<number>} ends Ends.
  14268. * @param {number} stride Stride.
  14269. * @param {boolean=} opt_right Follow the right-hand rule for orientation.
  14270. * @return {number} End.
  14271. */
  14272. ol.geom.flat.orient.orientLinearRings = function(flatCoordinates, offset, ends, stride, opt_right) {
  14273. var right = opt_right !== undefined ? opt_right : false;
  14274. var i, ii;
  14275. for (i = 0, ii = ends.length; i < ii; ++i) {
  14276. var end = ends[i];
  14277. var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(
  14278. flatCoordinates, offset, end, stride);
  14279. var reverse = i === 0 ?
  14280. (right && isClockwise) || (!right && !isClockwise) :
  14281. (right && !isClockwise) || (!right && isClockwise);
  14282. if (reverse) {
  14283. ol.geom.flat.reverse.coordinates(flatCoordinates, offset, end, stride);
  14284. }
  14285. offset = end;
  14286. }
  14287. return offset;
  14288. };
  14289. /**
  14290. * Orient coordinates in a flat array of linear rings. By default, rings
  14291. * are oriented following the left-hand rule (clockwise for exterior and
  14292. * counter-clockwise for interior rings). To orient according to the
  14293. * right-hand rule, use the `opt_right` argument.
  14294. *
  14295. * @param {Array.<number>} flatCoordinates Flat coordinates.
  14296. * @param {number} offset Offset.
  14297. * @param {Array.<Array.<number>>} endss Array of array of end indexes.
  14298. * @param {number} stride Stride.
  14299. * @param {boolean=} opt_right Follow the right-hand rule for orientation.
  14300. * @return {number} End.
  14301. */
  14302. ol.geom.flat.orient.orientLinearRingss = function(flatCoordinates, offset, endss, stride, opt_right) {
  14303. var i, ii;
  14304. for (i = 0, ii = endss.length; i < ii; ++i) {
  14305. offset = ol.geom.flat.orient.orientLinearRings(
  14306. flatCoordinates, offset, endss[i], stride, opt_right);
  14307. }
  14308. return offset;
  14309. };
  14310. goog.provide('ol.geom.Polygon');
  14311. goog.require('ol');
  14312. goog.require('ol.array');
  14313. goog.require('ol.extent');
  14314. goog.require('ol.geom.GeometryLayout');
  14315. goog.require('ol.geom.GeometryType');
  14316. goog.require('ol.geom.LinearRing');
  14317. goog.require('ol.geom.Point');
  14318. goog.require('ol.geom.SimpleGeometry');
  14319. goog.require('ol.geom.flat.area');
  14320. goog.require('ol.geom.flat.closest');
  14321. goog.require('ol.geom.flat.contains');
  14322. goog.require('ol.geom.flat.deflate');
  14323. goog.require('ol.geom.flat.inflate');
  14324. goog.require('ol.geom.flat.interiorpoint');
  14325. goog.require('ol.geom.flat.intersectsextent');
  14326. goog.require('ol.geom.flat.orient');
  14327. goog.require('ol.geom.flat.simplify');
  14328. goog.require('ol.math');
  14329. /**
  14330. * @classdesc
  14331. * Polygon geometry.
  14332. *
  14333. * @constructor
  14334. * @extends {ol.geom.SimpleGeometry}
  14335. * @param {Array.<Array.<ol.Coordinate>>} coordinates Array of linear
  14336. * rings that define the polygon. The first linear ring of the array
  14337. * defines the outer-boundary or surface of the polygon. Each subsequent
  14338. * linear ring defines a hole in the surface of the polygon. A linear ring
  14339. * is an array of vertices' coordinates where the first coordinate and the
  14340. * last are equivalent.
  14341. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  14342. * @api
  14343. */
  14344. ol.geom.Polygon = function(coordinates, opt_layout) {
  14345. ol.geom.SimpleGeometry.call(this);
  14346. /**
  14347. * @type {Array.<number>}
  14348. * @private
  14349. */
  14350. this.ends_ = [];
  14351. /**
  14352. * @private
  14353. * @type {number}
  14354. */
  14355. this.flatInteriorPointRevision_ = -1;
  14356. /**
  14357. * @private
  14358. * @type {ol.Coordinate}
  14359. */
  14360. this.flatInteriorPoint_ = null;
  14361. /**
  14362. * @private
  14363. * @type {number}
  14364. */
  14365. this.maxDelta_ = -1;
  14366. /**
  14367. * @private
  14368. * @type {number}
  14369. */
  14370. this.maxDeltaRevision_ = -1;
  14371. /**
  14372. * @private
  14373. * @type {number}
  14374. */
  14375. this.orientedRevision_ = -1;
  14376. /**
  14377. * @private
  14378. * @type {Array.<number>}
  14379. */
  14380. this.orientedFlatCoordinates_ = null;
  14381. this.setCoordinates(coordinates, opt_layout);
  14382. };
  14383. ol.inherits(ol.geom.Polygon, ol.geom.SimpleGeometry);
  14384. /**
  14385. * Append the passed linear ring to this polygon.
  14386. * @param {ol.geom.LinearRing} linearRing Linear ring.
  14387. * @api
  14388. */
  14389. ol.geom.Polygon.prototype.appendLinearRing = function(linearRing) {
  14390. if (!this.flatCoordinates) {
  14391. this.flatCoordinates = linearRing.getFlatCoordinates().slice();
  14392. } else {
  14393. ol.array.extend(this.flatCoordinates, linearRing.getFlatCoordinates());
  14394. }
  14395. this.ends_.push(this.flatCoordinates.length);
  14396. this.changed();
  14397. };
  14398. /**
  14399. * Make a complete copy of the geometry.
  14400. * @return {!ol.geom.Polygon} Clone.
  14401. * @override
  14402. * @api
  14403. */
  14404. ol.geom.Polygon.prototype.clone = function() {
  14405. var polygon = new ol.geom.Polygon(null);
  14406. polygon.setFlatCoordinates(
  14407. this.layout, this.flatCoordinates.slice(), this.ends_.slice());
  14408. return polygon;
  14409. };
  14410. /**
  14411. * @inheritDoc
  14412. */
  14413. ol.geom.Polygon.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  14414. if (minSquaredDistance <
  14415. ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
  14416. return minSquaredDistance;
  14417. }
  14418. if (this.maxDeltaRevision_ != this.getRevision()) {
  14419. this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getsMaxSquaredDelta(
  14420. this.flatCoordinates, 0, this.ends_, this.stride, 0));
  14421. this.maxDeltaRevision_ = this.getRevision();
  14422. }
  14423. return ol.geom.flat.closest.getsClosestPoint(
  14424. this.flatCoordinates, 0, this.ends_, this.stride,
  14425. this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);
  14426. };
  14427. /**
  14428. * @inheritDoc
  14429. */
  14430. ol.geom.Polygon.prototype.containsXY = function(x, y) {
  14431. return ol.geom.flat.contains.linearRingsContainsXY(
  14432. this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, x, y);
  14433. };
  14434. /**
  14435. * Return the area of the polygon on projected plane.
  14436. * @return {number} Area (on projected plane).
  14437. * @api
  14438. */
  14439. ol.geom.Polygon.prototype.getArea = function() {
  14440. return ol.geom.flat.area.linearRings(
  14441. this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride);
  14442. };
  14443. /**
  14444. * Get the coordinate array for this geometry. This array has the structure
  14445. * of a GeoJSON coordinate array for polygons.
  14446. *
  14447. * @param {boolean=} opt_right Orient coordinates according to the right-hand
  14448. * rule (counter-clockwise for exterior and clockwise for interior rings).
  14449. * If `false`, coordinates will be oriented according to the left-hand rule
  14450. * (clockwise for exterior and counter-clockwise for interior rings).
  14451. * By default, coordinate orientation will depend on how the geometry was
  14452. * constructed.
  14453. * @return {Array.<Array.<ol.Coordinate>>} Coordinates.
  14454. * @override
  14455. * @api
  14456. */
  14457. ol.geom.Polygon.prototype.getCoordinates = function(opt_right) {
  14458. var flatCoordinates;
  14459. if (opt_right !== undefined) {
  14460. flatCoordinates = this.getOrientedFlatCoordinates().slice();
  14461. ol.geom.flat.orient.orientLinearRings(
  14462. flatCoordinates, 0, this.ends_, this.stride, opt_right);
  14463. } else {
  14464. flatCoordinates = this.flatCoordinates;
  14465. }
  14466. return ol.geom.flat.inflate.coordinatess(
  14467. flatCoordinates, 0, this.ends_, this.stride);
  14468. };
  14469. /**
  14470. * @return {Array.<number>} Ends.
  14471. */
  14472. ol.geom.Polygon.prototype.getEnds = function() {
  14473. return this.ends_;
  14474. };
  14475. /**
  14476. * @return {Array.<number>} Interior point.
  14477. */
  14478. ol.geom.Polygon.prototype.getFlatInteriorPoint = function() {
  14479. if (this.flatInteriorPointRevision_ != this.getRevision()) {
  14480. var flatCenter = ol.extent.getCenter(this.getExtent());
  14481. this.flatInteriorPoint_ = ol.geom.flat.interiorpoint.linearRings(
  14482. this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride,
  14483. flatCenter, 0);
  14484. this.flatInteriorPointRevision_ = this.getRevision();
  14485. }
  14486. return this.flatInteriorPoint_;
  14487. };
  14488. /**
  14489. * Return an interior point of the polygon.
  14490. * @return {ol.geom.Point} Interior point.
  14491. * @api
  14492. */
  14493. ol.geom.Polygon.prototype.getInteriorPoint = function() {
  14494. return new ol.geom.Point(this.getFlatInteriorPoint());
  14495. };
  14496. /**
  14497. * Return the number of rings of the polygon, this includes the exterior
  14498. * ring and any interior rings.
  14499. *
  14500. * @return {number} Number of rings.
  14501. * @api
  14502. */
  14503. ol.geom.Polygon.prototype.getLinearRingCount = function() {
  14504. return this.ends_.length;
  14505. };
  14506. /**
  14507. * Return the Nth linear ring of the polygon geometry. Return `null` if the
  14508. * given index is out of range.
  14509. * The exterior linear ring is available at index `0` and the interior rings
  14510. * at index `1` and beyond.
  14511. *
  14512. * @param {number} index Index.
  14513. * @return {ol.geom.LinearRing} Linear ring.
  14514. * @api
  14515. */
  14516. ol.geom.Polygon.prototype.getLinearRing = function(index) {
  14517. if (index < 0 || this.ends_.length <= index) {
  14518. return null;
  14519. }
  14520. var linearRing = new ol.geom.LinearRing(null);
  14521. linearRing.setFlatCoordinates(this.layout, this.flatCoordinates.slice(
  14522. index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]));
  14523. return linearRing;
  14524. };
  14525. /**
  14526. * Return the linear rings of the polygon.
  14527. * @return {Array.<ol.geom.LinearRing>} Linear rings.
  14528. * @api
  14529. */
  14530. ol.geom.Polygon.prototype.getLinearRings = function() {
  14531. var layout = this.layout;
  14532. var flatCoordinates = this.flatCoordinates;
  14533. var ends = this.ends_;
  14534. var linearRings = [];
  14535. var offset = 0;
  14536. var i, ii;
  14537. for (i = 0, ii = ends.length; i < ii; ++i) {
  14538. var end = ends[i];
  14539. var linearRing = new ol.geom.LinearRing(null);
  14540. linearRing.setFlatCoordinates(layout, flatCoordinates.slice(offset, end));
  14541. linearRings.push(linearRing);
  14542. offset = end;
  14543. }
  14544. return linearRings;
  14545. };
  14546. /**
  14547. * @return {Array.<number>} Oriented flat coordinates.
  14548. */
  14549. ol.geom.Polygon.prototype.getOrientedFlatCoordinates = function() {
  14550. if (this.orientedRevision_ != this.getRevision()) {
  14551. var flatCoordinates = this.flatCoordinates;
  14552. if (ol.geom.flat.orient.linearRingsAreOriented(
  14553. flatCoordinates, 0, this.ends_, this.stride)) {
  14554. this.orientedFlatCoordinates_ = flatCoordinates;
  14555. } else {
  14556. this.orientedFlatCoordinates_ = flatCoordinates.slice();
  14557. this.orientedFlatCoordinates_.length =
  14558. ol.geom.flat.orient.orientLinearRings(
  14559. this.orientedFlatCoordinates_, 0, this.ends_, this.stride);
  14560. }
  14561. this.orientedRevision_ = this.getRevision();
  14562. }
  14563. return this.orientedFlatCoordinates_;
  14564. };
  14565. /**
  14566. * @inheritDoc
  14567. */
  14568. ol.geom.Polygon.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
  14569. var simplifiedFlatCoordinates = [];
  14570. var simplifiedEnds = [];
  14571. simplifiedFlatCoordinates.length = ol.geom.flat.simplify.quantizes(
  14572. this.flatCoordinates, 0, this.ends_, this.stride,
  14573. Math.sqrt(squaredTolerance),
  14574. simplifiedFlatCoordinates, 0, simplifiedEnds);
  14575. var simplifiedPolygon = new ol.geom.Polygon(null);
  14576. simplifiedPolygon.setFlatCoordinates(
  14577. ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates, simplifiedEnds);
  14578. return simplifiedPolygon;
  14579. };
  14580. /**
  14581. * @inheritDoc
  14582. * @api
  14583. */
  14584. ol.geom.Polygon.prototype.getType = function() {
  14585. return ol.geom.GeometryType.POLYGON;
  14586. };
  14587. /**
  14588. * @inheritDoc
  14589. * @api
  14590. */
  14591. ol.geom.Polygon.prototype.intersectsExtent = function(extent) {
  14592. return ol.geom.flat.intersectsextent.linearRings(
  14593. this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, extent);
  14594. };
  14595. /**
  14596. * Set the coordinates of the polygon.
  14597. * @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
  14598. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  14599. * @override
  14600. * @api
  14601. */
  14602. ol.geom.Polygon.prototype.setCoordinates = function(coordinates, opt_layout) {
  14603. if (!coordinates) {
  14604. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.ends_);
  14605. } else {
  14606. this.setLayout(opt_layout, coordinates, 2);
  14607. if (!this.flatCoordinates) {
  14608. this.flatCoordinates = [];
  14609. }
  14610. var ends = ol.geom.flat.deflate.coordinatess(
  14611. this.flatCoordinates, 0, coordinates, this.stride, this.ends_);
  14612. this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1];
  14613. this.changed();
  14614. }
  14615. };
  14616. /**
  14617. * @param {ol.geom.GeometryLayout} layout Layout.
  14618. * @param {Array.<number>} flatCoordinates Flat coordinates.
  14619. * @param {Array.<number>} ends Ends.
  14620. */
  14621. ol.geom.Polygon.prototype.setFlatCoordinates = function(layout, flatCoordinates, ends) {
  14622. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  14623. this.ends_ = ends;
  14624. this.changed();
  14625. };
  14626. /**
  14627. * Create an approximation of a circle on the surface of a sphere.
  14628. * @param {ol.Sphere} sphere The sphere.
  14629. * @param {ol.Coordinate} center Center (`[lon, lat]` in degrees).
  14630. * @param {number} radius The great-circle distance from the center to
  14631. * the polygon vertices.
  14632. * @param {number=} opt_n Optional number of vertices for the resulting
  14633. * polygon. Default is `32`.
  14634. * @return {ol.geom.Polygon} The "circular" polygon.
  14635. * @api
  14636. */
  14637. ol.geom.Polygon.circular = function(sphere, center, radius, opt_n) {
  14638. var n = opt_n ? opt_n : 32;
  14639. /** @type {Array.<number>} */
  14640. var flatCoordinates = [];
  14641. var i;
  14642. for (i = 0; i < n; ++i) {
  14643. ol.array.extend(
  14644. flatCoordinates, sphere.offset(center, radius, 2 * Math.PI * i / n));
  14645. }
  14646. flatCoordinates.push(flatCoordinates[0], flatCoordinates[1]);
  14647. var polygon = new ol.geom.Polygon(null);
  14648. polygon.setFlatCoordinates(
  14649. ol.geom.GeometryLayout.XY, flatCoordinates, [flatCoordinates.length]);
  14650. return polygon;
  14651. };
  14652. /**
  14653. * Create a polygon from an extent. The layout used is `XY`.
  14654. * @param {ol.Extent} extent The extent.
  14655. * @return {ol.geom.Polygon} The polygon.
  14656. * @api
  14657. */
  14658. ol.geom.Polygon.fromExtent = function(extent) {
  14659. var minX = extent[0];
  14660. var minY = extent[1];
  14661. var maxX = extent[2];
  14662. var maxY = extent[3];
  14663. var flatCoordinates =
  14664. [minX, minY, minX, maxY, maxX, maxY, maxX, minY, minX, minY];
  14665. var polygon = new ol.geom.Polygon(null);
  14666. polygon.setFlatCoordinates(
  14667. ol.geom.GeometryLayout.XY, flatCoordinates, [flatCoordinates.length]);
  14668. return polygon;
  14669. };
  14670. /**
  14671. * Create a regular polygon from a circle.
  14672. * @param {ol.geom.Circle} circle Circle geometry.
  14673. * @param {number=} opt_sides Number of sides of the polygon. Default is 32.
  14674. * @param {number=} opt_angle Start angle for the first vertex of the polygon in
  14675. * radians. Default is 0.
  14676. * @return {ol.geom.Polygon} Polygon geometry.
  14677. * @api
  14678. */
  14679. ol.geom.Polygon.fromCircle = function(circle, opt_sides, opt_angle) {
  14680. var sides = opt_sides ? opt_sides : 32;
  14681. var stride = circle.getStride();
  14682. var layout = circle.getLayout();
  14683. var polygon = new ol.geom.Polygon(null, layout);
  14684. var arrayLength = stride * (sides + 1);
  14685. var flatCoordinates = new Array(arrayLength);
  14686. for (var i = 0; i < arrayLength; i++) {
  14687. flatCoordinates[i] = 0;
  14688. }
  14689. var ends = [flatCoordinates.length];
  14690. polygon.setFlatCoordinates(layout, flatCoordinates, ends);
  14691. ol.geom.Polygon.makeRegular(
  14692. polygon, circle.getCenter(), circle.getRadius(), opt_angle);
  14693. return polygon;
  14694. };
  14695. /**
  14696. * Modify the coordinates of a polygon to make it a regular polygon.
  14697. * @param {ol.geom.Polygon} polygon Polygon geometry.
  14698. * @param {ol.Coordinate} center Center of the regular polygon.
  14699. * @param {number} radius Radius of the regular polygon.
  14700. * @param {number=} opt_angle Start angle for the first vertex of the polygon in
  14701. * radians. Default is 0.
  14702. */
  14703. ol.geom.Polygon.makeRegular = function(polygon, center, radius, opt_angle) {
  14704. var flatCoordinates = polygon.getFlatCoordinates();
  14705. var layout = polygon.getLayout();
  14706. var stride = polygon.getStride();
  14707. var ends = polygon.getEnds();
  14708. var sides = flatCoordinates.length / stride - 1;
  14709. var startAngle = opt_angle ? opt_angle : 0;
  14710. var angle, offset;
  14711. for (var i = 0; i <= sides; ++i) {
  14712. offset = i * stride;
  14713. angle = startAngle + (ol.math.modulo(i, sides) * 2 * Math.PI / sides);
  14714. flatCoordinates[offset] = center[0] + (radius * Math.cos(angle));
  14715. flatCoordinates[offset + 1] = center[1] + (radius * Math.sin(angle));
  14716. }
  14717. polygon.setFlatCoordinates(layout, flatCoordinates, ends);
  14718. };
  14719. goog.provide('ol.View');
  14720. goog.require('ol');
  14721. goog.require('ol.CenterConstraint');
  14722. goog.require('ol.Object');
  14723. goog.require('ol.ResolutionConstraint');
  14724. goog.require('ol.RotationConstraint');
  14725. goog.require('ol.ViewHint');
  14726. goog.require('ol.ViewProperty');
  14727. goog.require('ol.array');
  14728. goog.require('ol.asserts');
  14729. goog.require('ol.coordinate');
  14730. goog.require('ol.easing');
  14731. goog.require('ol.extent');
  14732. goog.require('ol.geom.GeometryType');
  14733. goog.require('ol.geom.Polygon');
  14734. goog.require('ol.geom.SimpleGeometry');
  14735. goog.require('ol.math');
  14736. goog.require('ol.obj');
  14737. goog.require('ol.proj');
  14738. goog.require('ol.proj.Units');
  14739. /**
  14740. * @classdesc
  14741. * An ol.View object represents a simple 2D view of the map.
  14742. *
  14743. * This is the object to act upon to change the center, resolution,
  14744. * and rotation of the map.
  14745. *
  14746. * ### The view states
  14747. *
  14748. * An `ol.View` is determined by three states: `center`, `resolution`,
  14749. * and `rotation`. Each state has a corresponding getter and setter, e.g.
  14750. * `getCenter` and `setCenter` for the `center` state.
  14751. *
  14752. * An `ol.View` has a `projection`. The projection determines the
  14753. * coordinate system of the center, and its units determine the units of the
  14754. * resolution (projection units per pixel). The default projection is
  14755. * Spherical Mercator (EPSG:3857).
  14756. *
  14757. * ### The constraints
  14758. *
  14759. * `setCenter`, `setResolution` and `setRotation` can be used to change the
  14760. * states of the view. Any value can be passed to the setters. And the value
  14761. * that is passed to a setter will effectively be the value set in the view,
  14762. * and returned by the corresponding getter.
  14763. *
  14764. * But an `ol.View` object also has a *resolution constraint*, a
  14765. * *rotation constraint* and a *center constraint*.
  14766. *
  14767. * As said above, no constraints are applied when the setters are used to set
  14768. * new states for the view. Applying constraints is done explicitly through
  14769. * the use of the `constrain*` functions (`constrainResolution` and
  14770. * `constrainRotation` and `constrainCenter`).
  14771. *
  14772. * The main users of the constraints are the interactions and the
  14773. * controls. For example, double-clicking on the map changes the view to
  14774. * the "next" resolution. And releasing the fingers after pinch-zooming
  14775. * snaps to the closest resolution (with an animation).
  14776. *
  14777. * The *resolution constraint* snaps to specific resolutions. It is
  14778. * determined by the following options: `resolutions`, `maxResolution`,
  14779. * `maxZoom`, and `zoomFactor`. If `resolutions` is set, the other three
  14780. * options are ignored. See documentation for each option for more
  14781. * information.
  14782. *
  14783. * The *rotation constraint* snaps to specific angles. It is determined
  14784. * by the following options: `enableRotation` and `constrainRotation`.
  14785. * By default the rotation value is snapped to zero when approaching the
  14786. * horizontal.
  14787. *
  14788. * The *center constraint* is determined by the `extent` option. By
  14789. * default the center is not constrained at all.
  14790. *
  14791. * @constructor
  14792. * @extends {ol.Object}
  14793. * @param {olx.ViewOptions=} opt_options View options.
  14794. * @api
  14795. */
  14796. ol.View = function(opt_options) {
  14797. ol.Object.call(this);
  14798. var options = ol.obj.assign({}, opt_options);
  14799. /**
  14800. * @private
  14801. * @type {Array.<number>}
  14802. */
  14803. this.hints_ = [0, 0];
  14804. /**
  14805. * @private
  14806. * @type {Array.<Array.<ol.ViewAnimation>>}
  14807. */
  14808. this.animations_ = [];
  14809. /**
  14810. * @private
  14811. * @type {number|undefined}
  14812. */
  14813. this.updateAnimationKey_;
  14814. this.updateAnimations_ = this.updateAnimations_.bind(this);
  14815. /**
  14816. * @private
  14817. * @const
  14818. * @type {ol.proj.Projection}
  14819. */
  14820. this.projection_ = ol.proj.createProjection(options.projection, 'EPSG:3857');
  14821. this.applyOptions_(options);
  14822. };
  14823. ol.inherits(ol.View, ol.Object);
  14824. /**
  14825. * Set up the view with the given options.
  14826. * @param {olx.ViewOptions} options View options.
  14827. */
  14828. ol.View.prototype.applyOptions_ = function(options) {
  14829. /**
  14830. * @type {Object.<string, *>}
  14831. */
  14832. var properties = {};
  14833. properties[ol.ViewProperty.CENTER] = options.center !== undefined ?
  14834. options.center : null;
  14835. var resolutionConstraintInfo = ol.View.createResolutionConstraint_(
  14836. options);
  14837. /**
  14838. * @private
  14839. * @type {number}
  14840. */
  14841. this.maxResolution_ = resolutionConstraintInfo.maxResolution;
  14842. /**
  14843. * @private
  14844. * @type {number}
  14845. */
  14846. this.minResolution_ = resolutionConstraintInfo.minResolution;
  14847. /**
  14848. * @private
  14849. * @type {number}
  14850. */
  14851. this.zoomFactor_ = resolutionConstraintInfo.zoomFactor;
  14852. /**
  14853. * @private
  14854. * @type {Array.<number>|undefined}
  14855. */
  14856. this.resolutions_ = options.resolutions;
  14857. /**
  14858. * @private
  14859. * @type {number}
  14860. */
  14861. this.minZoom_ = resolutionConstraintInfo.minZoom;
  14862. var centerConstraint = ol.View.createCenterConstraint_(options);
  14863. var resolutionConstraint = resolutionConstraintInfo.constraint;
  14864. var rotationConstraint = ol.View.createRotationConstraint_(options);
  14865. /**
  14866. * @private
  14867. * @type {ol.Constraints}
  14868. */
  14869. this.constraints_ = {
  14870. center: centerConstraint,
  14871. resolution: resolutionConstraint,
  14872. rotation: rotationConstraint
  14873. };
  14874. if (options.resolution !== undefined) {
  14875. properties[ol.ViewProperty.RESOLUTION] = options.resolution;
  14876. } else if (options.zoom !== undefined) {
  14877. properties[ol.ViewProperty.RESOLUTION] = this.constrainResolution(
  14878. this.maxResolution_, options.zoom - this.minZoom_);
  14879. }
  14880. properties[ol.ViewProperty.ROTATION] =
  14881. options.rotation !== undefined ? options.rotation : 0;
  14882. this.setProperties(properties);
  14883. /**
  14884. * @private
  14885. * @type {olx.ViewOptions}
  14886. */
  14887. this.options_ = options;
  14888. };
  14889. /**
  14890. * Get an updated version of the view options used to construct the view. The
  14891. * current resolution (or zoom), center, and rotation are applied to any stored
  14892. * options. The provided options can be uesd to apply new min/max zoom or
  14893. * resolution limits.
  14894. * @param {olx.ViewOptions} newOptions New options to be applied.
  14895. * @return {olx.ViewOptions} New options updated with the current view state.
  14896. */
  14897. ol.View.prototype.getUpdatedOptions_ = function(newOptions) {
  14898. var options = ol.obj.assign({}, this.options_);
  14899. // preserve resolution (or zoom)
  14900. if (options.resolution !== undefined) {
  14901. options.resolution = this.getResolution();
  14902. } else {
  14903. options.zoom = this.getZoom();
  14904. }
  14905. // preserve center
  14906. options.center = this.getCenter();
  14907. // preserve rotation
  14908. options.rotation = this.getRotation();
  14909. return ol.obj.assign({}, options, newOptions);
  14910. };
  14911. /**
  14912. * Animate the view. The view's center, zoom (or resolution), and rotation
  14913. * can be animated for smooth transitions between view states. For example,
  14914. * to animate the view to a new zoom level:
  14915. *
  14916. * view.animate({zoom: view.getZoom() + 1});
  14917. *
  14918. * By default, the animation lasts one second and uses in-and-out easing. You
  14919. * can customize this behavior by including `duration` (in milliseconds) and
  14920. * `easing` options (see {@link ol.easing}).
  14921. *
  14922. * To chain together multiple animations, call the method with multiple
  14923. * animation objects. For example, to first zoom and then pan:
  14924. *
  14925. * view.animate({zoom: 10}, {center: [0, 0]});
  14926. *
  14927. * If you provide a function as the last argument to the animate method, it
  14928. * will get called at the end of an animation series. The callback will be
  14929. * called with `true` if the animation series completed on its own or `false`
  14930. * if it was cancelled.
  14931. *
  14932. * Animations are cancelled by user interactions (e.g. dragging the map) or by
  14933. * calling `view.setCenter()`, `view.setResolution()`, or `view.setRotation()`
  14934. * (or another method that calls one of these).
  14935. *
  14936. * @param {...(olx.AnimationOptions|function(boolean))} var_args Animation
  14937. * options. Multiple animations can be run in series by passing multiple
  14938. * options objects. To run multiple animations in parallel, call the method
  14939. * multiple times. An optional callback can be provided as a final
  14940. * argument. The callback will be called with a boolean indicating whether
  14941. * the animation completed without being cancelled.
  14942. * @api
  14943. */
  14944. ol.View.prototype.animate = function(var_args) {
  14945. var start = Date.now();
  14946. var center = this.getCenter().slice();
  14947. var resolution = this.getResolution();
  14948. var rotation = this.getRotation();
  14949. var animationCount = arguments.length;
  14950. var callback;
  14951. if (animationCount > 1 && typeof arguments[animationCount - 1] === 'function') {
  14952. callback = arguments[animationCount - 1];
  14953. --animationCount;
  14954. }
  14955. var series = [];
  14956. for (var i = 0; i < animationCount; ++i) {
  14957. var options = /** @type {olx.AnimationOptions} */ (arguments[i]);
  14958. var animation = /** @type {ol.ViewAnimation} */ ({
  14959. start: start,
  14960. complete: false,
  14961. anchor: options.anchor,
  14962. duration: options.duration !== undefined ? options.duration : 1000,
  14963. easing: options.easing || ol.easing.inAndOut
  14964. });
  14965. if (options.center) {
  14966. animation.sourceCenter = center;
  14967. animation.targetCenter = options.center;
  14968. center = animation.targetCenter;
  14969. }
  14970. if (options.zoom !== undefined) {
  14971. animation.sourceResolution = resolution;
  14972. animation.targetResolution = this.constrainResolution(
  14973. this.maxResolution_, options.zoom - this.minZoom_, 0);
  14974. resolution = animation.targetResolution;
  14975. } else if (options.resolution) {
  14976. animation.sourceResolution = resolution;
  14977. animation.targetResolution = options.resolution;
  14978. resolution = animation.targetResolution;
  14979. }
  14980. if (options.rotation !== undefined) {
  14981. animation.sourceRotation = rotation;
  14982. var delta = ol.math.modulo(options.rotation - rotation + Math.PI, 2 * Math.PI) - Math.PI;
  14983. animation.targetRotation = rotation + delta;
  14984. rotation = animation.targetRotation;
  14985. }
  14986. animation.callback = callback;
  14987. // check if animation is a no-op
  14988. if (ol.View.isNoopAnimation(animation)) {
  14989. animation.complete = true;
  14990. // we still push it onto the series for callback handling
  14991. } else {
  14992. start += animation.duration;
  14993. }
  14994. series.push(animation);
  14995. }
  14996. this.animations_.push(series);
  14997. this.setHint(ol.ViewHint.ANIMATING, 1);
  14998. this.updateAnimations_();
  14999. };
  15000. /**
  15001. * Determine if the view is being animated.
  15002. * @return {boolean} The view is being animated.
  15003. * @api
  15004. */
  15005. ol.View.prototype.getAnimating = function() {
  15006. return this.getHints()[ol.ViewHint.ANIMATING] > 0;
  15007. };
  15008. /**
  15009. * Determine if the user is interacting with the view, such as panning or zooming.
  15010. * @return {boolean} The view is being interacted with.
  15011. * @api
  15012. */
  15013. ol.View.prototype.getInteracting = function() {
  15014. return this.getHints()[ol.ViewHint.INTERACTING] > 0;
  15015. };
  15016. /**
  15017. * Cancel any ongoing animations.
  15018. * @api
  15019. */
  15020. ol.View.prototype.cancelAnimations = function() {
  15021. this.setHint(ol.ViewHint.ANIMATING, -this.getHints()[ol.ViewHint.ANIMATING]);
  15022. for (var i = 0, ii = this.animations_.length; i < ii; ++i) {
  15023. var series = this.animations_[i];
  15024. if (series[0].callback) {
  15025. series[0].callback(false);
  15026. }
  15027. }
  15028. this.animations_.length = 0;
  15029. };
  15030. /**
  15031. * Update all animations.
  15032. */
  15033. ol.View.prototype.updateAnimations_ = function() {
  15034. if (this.updateAnimationKey_ !== undefined) {
  15035. cancelAnimationFrame(this.updateAnimationKey_);
  15036. this.updateAnimationKey_ = undefined;
  15037. }
  15038. if (!this.getAnimating()) {
  15039. return;
  15040. }
  15041. var now = Date.now();
  15042. var more = false;
  15043. for (var i = this.animations_.length - 1; i >= 0; --i) {
  15044. var series = this.animations_[i];
  15045. var seriesComplete = true;
  15046. for (var j = 0, jj = series.length; j < jj; ++j) {
  15047. var animation = series[j];
  15048. if (animation.complete) {
  15049. continue;
  15050. }
  15051. var elapsed = now - animation.start;
  15052. var fraction = animation.duration > 0 ? elapsed / animation.duration : 1;
  15053. if (fraction >= 1) {
  15054. animation.complete = true;
  15055. fraction = 1;
  15056. } else {
  15057. seriesComplete = false;
  15058. }
  15059. var progress = animation.easing(fraction);
  15060. if (animation.sourceCenter) {
  15061. var x0 = animation.sourceCenter[0];
  15062. var y0 = animation.sourceCenter[1];
  15063. var x1 = animation.targetCenter[0];
  15064. var y1 = animation.targetCenter[1];
  15065. var x = x0 + progress * (x1 - x0);
  15066. var y = y0 + progress * (y1 - y0);
  15067. this.set(ol.ViewProperty.CENTER, [x, y]);
  15068. }
  15069. if (animation.sourceResolution && animation.targetResolution) {
  15070. var resolution = progress === 1 ?
  15071. animation.targetResolution :
  15072. animation.sourceResolution + progress * (animation.targetResolution - animation.sourceResolution);
  15073. if (animation.anchor) {
  15074. this.set(ol.ViewProperty.CENTER,
  15075. this.calculateCenterZoom(resolution, animation.anchor));
  15076. }
  15077. this.set(ol.ViewProperty.RESOLUTION, resolution);
  15078. }
  15079. if (animation.sourceRotation !== undefined && animation.targetRotation !== undefined) {
  15080. var rotation = progress === 1 ?
  15081. ol.math.modulo(animation.targetRotation + Math.PI, 2 * Math.PI) - Math.PI :
  15082. animation.sourceRotation + progress * (animation.targetRotation - animation.sourceRotation);
  15083. if (animation.anchor) {
  15084. this.set(ol.ViewProperty.CENTER,
  15085. this.calculateCenterRotate(rotation, animation.anchor));
  15086. }
  15087. this.set(ol.ViewProperty.ROTATION, rotation);
  15088. }
  15089. more = true;
  15090. if (!animation.complete) {
  15091. break;
  15092. }
  15093. }
  15094. if (seriesComplete) {
  15095. this.animations_[i] = null;
  15096. this.setHint(ol.ViewHint.ANIMATING, -1);
  15097. var callback = series[0].callback;
  15098. if (callback) {
  15099. callback(true);
  15100. }
  15101. }
  15102. }
  15103. // prune completed series
  15104. this.animations_ = this.animations_.filter(Boolean);
  15105. if (more && this.updateAnimationKey_ === undefined) {
  15106. this.updateAnimationKey_ = requestAnimationFrame(this.updateAnimations_);
  15107. }
  15108. };
  15109. /**
  15110. * @param {number} rotation Target rotation.
  15111. * @param {ol.Coordinate} anchor Rotation anchor.
  15112. * @return {ol.Coordinate|undefined} Center for rotation and anchor.
  15113. */
  15114. ol.View.prototype.calculateCenterRotate = function(rotation, anchor) {
  15115. var center;
  15116. var currentCenter = this.getCenter();
  15117. if (currentCenter !== undefined) {
  15118. center = [currentCenter[0] - anchor[0], currentCenter[1] - anchor[1]];
  15119. ol.coordinate.rotate(center, rotation - this.getRotation());
  15120. ol.coordinate.add(center, anchor);
  15121. }
  15122. return center;
  15123. };
  15124. /**
  15125. * @param {number} resolution Target resolution.
  15126. * @param {ol.Coordinate} anchor Zoom anchor.
  15127. * @return {ol.Coordinate|undefined} Center for resolution and anchor.
  15128. */
  15129. ol.View.prototype.calculateCenterZoom = function(resolution, anchor) {
  15130. var center;
  15131. var currentCenter = this.getCenter();
  15132. var currentResolution = this.getResolution();
  15133. if (currentCenter !== undefined && currentResolution !== undefined) {
  15134. var x = anchor[0] -
  15135. resolution * (anchor[0] - currentCenter[0]) / currentResolution;
  15136. var y = anchor[1] -
  15137. resolution * (anchor[1] - currentCenter[1]) / currentResolution;
  15138. center = [x, y];
  15139. }
  15140. return center;
  15141. };
  15142. /**
  15143. * @private
  15144. * @return {ol.Size} Viewport size or `[100, 100]` when no viewport is found.
  15145. */
  15146. ol.View.prototype.getSizeFromViewport_ = function() {
  15147. var size = [100, 100];
  15148. var selector = '.ol-viewport[data-view="' + ol.getUid(this) + '"]';
  15149. var element = document.querySelector(selector);
  15150. if (element) {
  15151. var metrics = getComputedStyle(element);
  15152. size[0] = parseInt(metrics.width, 10);
  15153. size[1] = parseInt(metrics.height, 10);
  15154. }
  15155. return size;
  15156. };
  15157. /**
  15158. * Get the constrained center of this view.
  15159. * @param {ol.Coordinate|undefined} center Center.
  15160. * @return {ol.Coordinate|undefined} Constrained center.
  15161. * @api
  15162. */
  15163. ol.View.prototype.constrainCenter = function(center) {
  15164. return this.constraints_.center(center);
  15165. };
  15166. /**
  15167. * Get the constrained resolution of this view.
  15168. * @param {number|undefined} resolution Resolution.
  15169. * @param {number=} opt_delta Delta. Default is `0`.
  15170. * @param {number=} opt_direction Direction. Default is `0`.
  15171. * @return {number|undefined} Constrained resolution.
  15172. * @api
  15173. */
  15174. ol.View.prototype.constrainResolution = function(
  15175. resolution, opt_delta, opt_direction) {
  15176. var delta = opt_delta || 0;
  15177. var direction = opt_direction || 0;
  15178. return this.constraints_.resolution(resolution, delta, direction);
  15179. };
  15180. /**
  15181. * Get the constrained rotation of this view.
  15182. * @param {number|undefined} rotation Rotation.
  15183. * @param {number=} opt_delta Delta. Default is `0`.
  15184. * @return {number|undefined} Constrained rotation.
  15185. * @api
  15186. */
  15187. ol.View.prototype.constrainRotation = function(rotation, opt_delta) {
  15188. var delta = opt_delta || 0;
  15189. return this.constraints_.rotation(rotation, delta);
  15190. };
  15191. /**
  15192. * Get the view center.
  15193. * @return {ol.Coordinate|undefined} The center of the view.
  15194. * @observable
  15195. * @api
  15196. */
  15197. ol.View.prototype.getCenter = function() {
  15198. return /** @type {ol.Coordinate|undefined} */ (
  15199. this.get(ol.ViewProperty.CENTER));
  15200. };
  15201. /**
  15202. * @return {ol.Constraints} Constraints.
  15203. */
  15204. ol.View.prototype.getConstraints = function() {
  15205. return this.constraints_;
  15206. };
  15207. /**
  15208. * @param {Array.<number>=} opt_hints Destination array.
  15209. * @return {Array.<number>} Hint.
  15210. */
  15211. ol.View.prototype.getHints = function(opt_hints) {
  15212. if (opt_hints !== undefined) {
  15213. opt_hints[0] = this.hints_[0];
  15214. opt_hints[1] = this.hints_[1];
  15215. return opt_hints;
  15216. } else {
  15217. return this.hints_.slice();
  15218. }
  15219. };
  15220. /**
  15221. * Calculate the extent for the current view state and the passed size.
  15222. * The size is the pixel dimensions of the box into which the calculated extent
  15223. * should fit. In most cases you want to get the extent of the entire map,
  15224. * that is `map.getSize()`.
  15225. * @param {ol.Size=} opt_size Box pixel size. If not provided, the size of the
  15226. * first map that uses this view will be used.
  15227. * @return {ol.Extent} Extent.
  15228. * @api
  15229. */
  15230. ol.View.prototype.calculateExtent = function(opt_size) {
  15231. var size = opt_size || this.getSizeFromViewport_();
  15232. var center = /** @type {!ol.Coordinate} */ (this.getCenter());
  15233. ol.asserts.assert(center, 1); // The view center is not defined
  15234. var resolution = /** @type {!number} */ (this.getResolution());
  15235. ol.asserts.assert(resolution !== undefined, 2); // The view resolution is not defined
  15236. var rotation = /** @type {!number} */ (this.getRotation());
  15237. ol.asserts.assert(rotation !== undefined, 3); // The view rotation is not defined
  15238. return ol.extent.getForViewAndSize(center, resolution, rotation, size);
  15239. };
  15240. /**
  15241. * Get the maximum resolution of the view.
  15242. * @return {number} The maximum resolution of the view.
  15243. * @api
  15244. */
  15245. ol.View.prototype.getMaxResolution = function() {
  15246. return this.maxResolution_;
  15247. };
  15248. /**
  15249. * Get the minimum resolution of the view.
  15250. * @return {number} The minimum resolution of the view.
  15251. * @api
  15252. */
  15253. ol.View.prototype.getMinResolution = function() {
  15254. return this.minResolution_;
  15255. };
  15256. /**
  15257. * Get the maximum zoom level for the view.
  15258. * @return {number} The maximum zoom level.
  15259. * @api
  15260. */
  15261. ol.View.prototype.getMaxZoom = function() {
  15262. return /** @type {number} */ (this.getZoomForResolution(this.minResolution_));
  15263. };
  15264. /**
  15265. * Set a new maximum zoom level for the view.
  15266. * @param {number} zoom The maximum zoom level.
  15267. * @api
  15268. */
  15269. ol.View.prototype.setMaxZoom = function(zoom) {
  15270. this.applyOptions_(this.getUpdatedOptions_({maxZoom: zoom}));
  15271. };
  15272. /**
  15273. * Get the minimum zoom level for the view.
  15274. * @return {number} The minimum zoom level.
  15275. * @api
  15276. */
  15277. ol.View.prototype.getMinZoom = function() {
  15278. return /** @type {number} */ (this.getZoomForResolution(this.maxResolution_));
  15279. };
  15280. /**
  15281. * Set a new minimum zoom level for the view.
  15282. * @param {number} zoom The minimum zoom level.
  15283. * @api
  15284. */
  15285. ol.View.prototype.setMinZoom = function(zoom) {
  15286. this.applyOptions_(this.getUpdatedOptions_({minZoom: zoom}));
  15287. };
  15288. /**
  15289. * Get the view projection.
  15290. * @return {ol.proj.Projection} The projection of the view.
  15291. * @api
  15292. */
  15293. ol.View.prototype.getProjection = function() {
  15294. return this.projection_;
  15295. };
  15296. /**
  15297. * Get the view resolution.
  15298. * @return {number|undefined} The resolution of the view.
  15299. * @observable
  15300. * @api
  15301. */
  15302. ol.View.prototype.getResolution = function() {
  15303. return /** @type {number|undefined} */ (
  15304. this.get(ol.ViewProperty.RESOLUTION));
  15305. };
  15306. /**
  15307. * Get the resolutions for the view. This returns the array of resolutions
  15308. * passed to the constructor of the {ol.View}, or undefined if none were given.
  15309. * @return {Array.<number>|undefined} The resolutions of the view.
  15310. * @api
  15311. */
  15312. ol.View.prototype.getResolutions = function() {
  15313. return this.resolutions_;
  15314. };
  15315. /**
  15316. * Get the resolution for a provided extent (in map units) and size (in pixels).
  15317. * @param {ol.Extent} extent Extent.
  15318. * @param {ol.Size=} opt_size Box pixel size.
  15319. * @return {number} The resolution at which the provided extent will render at
  15320. * the given size.
  15321. * @api
  15322. */
  15323. ol.View.prototype.getResolutionForExtent = function(extent, opt_size) {
  15324. var size = opt_size || this.getSizeFromViewport_();
  15325. var xResolution = ol.extent.getWidth(extent) / size[0];
  15326. var yResolution = ol.extent.getHeight(extent) / size[1];
  15327. return Math.max(xResolution, yResolution);
  15328. };
  15329. /**
  15330. * Return a function that returns a value between 0 and 1 for a
  15331. * resolution. Exponential scaling is assumed.
  15332. * @param {number=} opt_power Power.
  15333. * @return {function(number): number} Resolution for value function.
  15334. */
  15335. ol.View.prototype.getResolutionForValueFunction = function(opt_power) {
  15336. var power = opt_power || 2;
  15337. var maxResolution = this.maxResolution_;
  15338. var minResolution = this.minResolution_;
  15339. var max = Math.log(maxResolution / minResolution) / Math.log(power);
  15340. return (
  15341. /**
  15342. * @param {number} value Value.
  15343. * @return {number} Resolution.
  15344. */
  15345. function(value) {
  15346. var resolution = maxResolution / Math.pow(power, value * max);
  15347. return resolution;
  15348. });
  15349. };
  15350. /**
  15351. * Get the view rotation.
  15352. * @return {number} The rotation of the view in radians.
  15353. * @observable
  15354. * @api
  15355. */
  15356. ol.View.prototype.getRotation = function() {
  15357. return /** @type {number} */ (this.get(ol.ViewProperty.ROTATION));
  15358. };
  15359. /**
  15360. * Return a function that returns a resolution for a value between
  15361. * 0 and 1. Exponential scaling is assumed.
  15362. * @param {number=} opt_power Power.
  15363. * @return {function(number): number} Value for resolution function.
  15364. */
  15365. ol.View.prototype.getValueForResolutionFunction = function(opt_power) {
  15366. var power = opt_power || 2;
  15367. var maxResolution = this.maxResolution_;
  15368. var minResolution = this.minResolution_;
  15369. var max = Math.log(maxResolution / minResolution) / Math.log(power);
  15370. return (
  15371. /**
  15372. * @param {number} resolution Resolution.
  15373. * @return {number} Value.
  15374. */
  15375. function(resolution) {
  15376. var value =
  15377. (Math.log(maxResolution / resolution) / Math.log(power)) / max;
  15378. return value;
  15379. });
  15380. };
  15381. /**
  15382. * @return {olx.ViewState} View state.
  15383. */
  15384. ol.View.prototype.getState = function() {
  15385. var center = /** @type {ol.Coordinate} */ (this.getCenter());
  15386. var projection = this.getProjection();
  15387. var resolution = /** @type {number} */ (this.getResolution());
  15388. var rotation = this.getRotation();
  15389. return /** @type {olx.ViewState} */ ({
  15390. center: center.slice(),
  15391. projection: projection !== undefined ? projection : null,
  15392. resolution: resolution,
  15393. rotation: rotation
  15394. });
  15395. };
  15396. /**
  15397. * Get the current zoom level. Return undefined if the current
  15398. * resolution is undefined or not within the "resolution constraints".
  15399. * @return {number|undefined} Zoom.
  15400. * @api
  15401. */
  15402. ol.View.prototype.getZoom = function() {
  15403. var zoom;
  15404. var resolution = this.getResolution();
  15405. if (resolution !== undefined) {
  15406. zoom = this.getZoomForResolution(resolution);
  15407. }
  15408. return zoom;
  15409. };
  15410. /**
  15411. * Get the zoom level for a resolution.
  15412. * @param {number} resolution The resolution.
  15413. * @return {number|undefined} The zoom level for the provided resolution.
  15414. * @api
  15415. */
  15416. ol.View.prototype.getZoomForResolution = function(resolution) {
  15417. var zoom;
  15418. if (resolution >= this.minResolution_ && resolution <= this.maxResolution_) {
  15419. var offset = this.minZoom_ || 0;
  15420. var max, zoomFactor;
  15421. if (this.resolutions_) {
  15422. var nearest = ol.array.linearFindNearest(this.resolutions_, resolution, 1);
  15423. offset += nearest;
  15424. if (nearest == this.resolutions_.length - 1) {
  15425. return offset;
  15426. }
  15427. max = this.resolutions_[nearest];
  15428. zoomFactor = max / this.resolutions_[nearest + 1];
  15429. } else {
  15430. max = this.maxResolution_;
  15431. zoomFactor = this.zoomFactor_;
  15432. }
  15433. zoom = offset + Math.log(max / resolution) / Math.log(zoomFactor);
  15434. }
  15435. return zoom;
  15436. };
  15437. /**
  15438. * Get the resolution for a zoom level.
  15439. * @param {number} zoom Zoom level.
  15440. * @return {number} The view resolution for the provided zoom level.
  15441. * @api
  15442. */
  15443. ol.View.prototype.getResolutionForZoom = function(zoom) {
  15444. return /** @type {number} */ (this.constrainResolution(
  15445. this.maxResolution_, zoom - this.minZoom_, 0));
  15446. };
  15447. /**
  15448. * Fit the given geometry or extent based on the given map size and border.
  15449. * The size is pixel dimensions of the box to fit the extent into.
  15450. * In most cases you will want to use the map size, that is `map.getSize()`.
  15451. * Takes care of the map angle.
  15452. * @param {ol.geom.SimpleGeometry|ol.Extent} geometryOrExtent The geometry or
  15453. * extent to fit the view to.
  15454. * @param {olx.view.FitOptions=} opt_options Options.
  15455. * @api
  15456. */
  15457. ol.View.prototype.fit = function(geometryOrExtent, opt_options) {
  15458. var options = opt_options || {};
  15459. var size = options.size;
  15460. if (!size) {
  15461. size = this.getSizeFromViewport_();
  15462. }
  15463. /** @type {ol.geom.SimpleGeometry} */
  15464. var geometry;
  15465. if (!(geometryOrExtent instanceof ol.geom.SimpleGeometry)) {
  15466. ol.asserts.assert(Array.isArray(geometryOrExtent),
  15467. 24); // Invalid extent or geometry provided as `geometry`
  15468. ol.asserts.assert(!ol.extent.isEmpty(geometryOrExtent),
  15469. 25); // Cannot fit empty extent provided as `geometry`
  15470. geometry = ol.geom.Polygon.fromExtent(geometryOrExtent);
  15471. } else if (geometryOrExtent.getType() === ol.geom.GeometryType.CIRCLE) {
  15472. geometryOrExtent = geometryOrExtent.getExtent();
  15473. geometry = ol.geom.Polygon.fromExtent(geometryOrExtent);
  15474. geometry.rotate(this.getRotation(), ol.extent.getCenter(geometryOrExtent));
  15475. } else {
  15476. geometry = geometryOrExtent;
  15477. }
  15478. var padding = options.padding !== undefined ? options.padding : [0, 0, 0, 0];
  15479. var constrainResolution = options.constrainResolution !== undefined ?
  15480. options.constrainResolution : true;
  15481. var nearest = options.nearest !== undefined ? options.nearest : false;
  15482. var minResolution;
  15483. if (options.minResolution !== undefined) {
  15484. minResolution = options.minResolution;
  15485. } else if (options.maxZoom !== undefined) {
  15486. minResolution = this.constrainResolution(
  15487. this.maxResolution_, options.maxZoom - this.minZoom_, 0);
  15488. } else {
  15489. minResolution = 0;
  15490. }
  15491. var coords = geometry.getFlatCoordinates();
  15492. // calculate rotated extent
  15493. var rotation = this.getRotation();
  15494. var cosAngle = Math.cos(-rotation);
  15495. var sinAngle = Math.sin(-rotation);
  15496. var minRotX = +Infinity;
  15497. var minRotY = +Infinity;
  15498. var maxRotX = -Infinity;
  15499. var maxRotY = -Infinity;
  15500. var stride = geometry.getStride();
  15501. for (var i = 0, ii = coords.length; i < ii; i += stride) {
  15502. var rotX = coords[i] * cosAngle - coords[i + 1] * sinAngle;
  15503. var rotY = coords[i] * sinAngle + coords[i + 1] * cosAngle;
  15504. minRotX = Math.min(minRotX, rotX);
  15505. minRotY = Math.min(minRotY, rotY);
  15506. maxRotX = Math.max(maxRotX, rotX);
  15507. maxRotY = Math.max(maxRotY, rotY);
  15508. }
  15509. // calculate resolution
  15510. var resolution = this.getResolutionForExtent(
  15511. [minRotX, minRotY, maxRotX, maxRotY],
  15512. [size[0] - padding[1] - padding[3], size[1] - padding[0] - padding[2]]);
  15513. resolution = isNaN(resolution) ? minResolution :
  15514. Math.max(resolution, minResolution);
  15515. if (constrainResolution) {
  15516. var constrainedResolution = this.constrainResolution(resolution, 0, 0);
  15517. if (!nearest && constrainedResolution < resolution) {
  15518. constrainedResolution = this.constrainResolution(
  15519. constrainedResolution, -1, 0);
  15520. }
  15521. resolution = constrainedResolution;
  15522. }
  15523. // calculate center
  15524. sinAngle = -sinAngle; // go back to original rotation
  15525. var centerRotX = (minRotX + maxRotX) / 2;
  15526. var centerRotY = (minRotY + maxRotY) / 2;
  15527. centerRotX += (padding[1] - padding[3]) / 2 * resolution;
  15528. centerRotY += (padding[0] - padding[2]) / 2 * resolution;
  15529. var centerX = centerRotX * cosAngle - centerRotY * sinAngle;
  15530. var centerY = centerRotY * cosAngle + centerRotX * sinAngle;
  15531. var center = [centerX, centerY];
  15532. var callback = options.callback ? options.callback : ol.nullFunction;
  15533. if (options.duration !== undefined) {
  15534. this.animate({
  15535. resolution: resolution,
  15536. center: center,
  15537. duration: options.duration,
  15538. easing: options.easing
  15539. }, callback);
  15540. } else {
  15541. this.setResolution(resolution);
  15542. this.setCenter(center);
  15543. setTimeout(callback.bind(undefined, true), 0);
  15544. }
  15545. };
  15546. /**
  15547. * Center on coordinate and view position.
  15548. * @param {ol.Coordinate} coordinate Coordinate.
  15549. * @param {ol.Size} size Box pixel size.
  15550. * @param {ol.Pixel} position Position on the view to center on.
  15551. * @api
  15552. */
  15553. ol.View.prototype.centerOn = function(coordinate, size, position) {
  15554. // calculate rotated position
  15555. var rotation = this.getRotation();
  15556. var cosAngle = Math.cos(-rotation);
  15557. var sinAngle = Math.sin(-rotation);
  15558. var rotX = coordinate[0] * cosAngle - coordinate[1] * sinAngle;
  15559. var rotY = coordinate[1] * cosAngle + coordinate[0] * sinAngle;
  15560. var resolution = this.getResolution();
  15561. rotX += (size[0] / 2 - position[0]) * resolution;
  15562. rotY += (position[1] - size[1] / 2) * resolution;
  15563. // go back to original angle
  15564. sinAngle = -sinAngle; // go back to original rotation
  15565. var centerX = rotX * cosAngle - rotY * sinAngle;
  15566. var centerY = rotY * cosAngle + rotX * sinAngle;
  15567. this.setCenter([centerX, centerY]);
  15568. };
  15569. /**
  15570. * @return {boolean} Is defined.
  15571. */
  15572. ol.View.prototype.isDef = function() {
  15573. return !!this.getCenter() && this.getResolution() !== undefined;
  15574. };
  15575. /**
  15576. * Rotate the view around a given coordinate.
  15577. * @param {number} rotation New rotation value for the view.
  15578. * @param {ol.Coordinate=} opt_anchor The rotation center.
  15579. * @api
  15580. */
  15581. ol.View.prototype.rotate = function(rotation, opt_anchor) {
  15582. if (opt_anchor !== undefined) {
  15583. var center = this.calculateCenterRotate(rotation, opt_anchor);
  15584. this.setCenter(center);
  15585. }
  15586. this.setRotation(rotation);
  15587. };
  15588. /**
  15589. * Set the center of the current view.
  15590. * @param {ol.Coordinate|undefined} center The center of the view.
  15591. * @observable
  15592. * @api
  15593. */
  15594. ol.View.prototype.setCenter = function(center) {
  15595. this.set(ol.ViewProperty.CENTER, center);
  15596. if (this.getAnimating()) {
  15597. this.cancelAnimations();
  15598. }
  15599. };
  15600. /**
  15601. * @param {ol.ViewHint} hint Hint.
  15602. * @param {number} delta Delta.
  15603. * @return {number} New value.
  15604. */
  15605. ol.View.prototype.setHint = function(hint, delta) {
  15606. this.hints_[hint] += delta;
  15607. this.changed();
  15608. return this.hints_[hint];
  15609. };
  15610. /**
  15611. * Set the resolution for this view.
  15612. * @param {number|undefined} resolution The resolution of the view.
  15613. * @observable
  15614. * @api
  15615. */
  15616. ol.View.prototype.setResolution = function(resolution) {
  15617. this.set(ol.ViewProperty.RESOLUTION, resolution);
  15618. if (this.getAnimating()) {
  15619. this.cancelAnimations();
  15620. }
  15621. };
  15622. /**
  15623. * Set the rotation for this view.
  15624. * @param {number} rotation The rotation of the view in radians.
  15625. * @observable
  15626. * @api
  15627. */
  15628. ol.View.prototype.setRotation = function(rotation) {
  15629. this.set(ol.ViewProperty.ROTATION, rotation);
  15630. if (this.getAnimating()) {
  15631. this.cancelAnimations();
  15632. }
  15633. };
  15634. /**
  15635. * Zoom to a specific zoom level.
  15636. * @param {number} zoom Zoom level.
  15637. * @api
  15638. */
  15639. ol.View.prototype.setZoom = function(zoom) {
  15640. this.setResolution(this.getResolutionForZoom(zoom));
  15641. };
  15642. /**
  15643. * @param {olx.ViewOptions} options View options.
  15644. * @private
  15645. * @return {ol.CenterConstraintType} The constraint.
  15646. */
  15647. ol.View.createCenterConstraint_ = function(options) {
  15648. if (options.extent !== undefined) {
  15649. return ol.CenterConstraint.createExtent(options.extent);
  15650. } else {
  15651. return ol.CenterConstraint.none;
  15652. }
  15653. };
  15654. /**
  15655. * @private
  15656. * @param {olx.ViewOptions} options View options.
  15657. * @return {{constraint: ol.ResolutionConstraintType, maxResolution: number,
  15658. * minResolution: number, zoomFactor: number}} The constraint.
  15659. */
  15660. ol.View.createResolutionConstraint_ = function(options) {
  15661. var resolutionConstraint;
  15662. var maxResolution;
  15663. var minResolution;
  15664. // TODO: move these to be ol constants
  15665. // see https://github.com/openlayers/openlayers/issues/2076
  15666. var defaultMaxZoom = 28;
  15667. var defaultZoomFactor = 2;
  15668. var minZoom = options.minZoom !== undefined ?
  15669. options.minZoom : ol.DEFAULT_MIN_ZOOM;
  15670. var maxZoom = options.maxZoom !== undefined ?
  15671. options.maxZoom : defaultMaxZoom;
  15672. var zoomFactor = options.zoomFactor !== undefined ?
  15673. options.zoomFactor : defaultZoomFactor;
  15674. if (options.resolutions !== undefined) {
  15675. var resolutions = options.resolutions;
  15676. maxResolution = resolutions[0];
  15677. minResolution = resolutions[resolutions.length - 1];
  15678. resolutionConstraint = ol.ResolutionConstraint.createSnapToResolutions(
  15679. resolutions);
  15680. } else {
  15681. // calculate the default min and max resolution
  15682. var projection = ol.proj.createProjection(options.projection, 'EPSG:3857');
  15683. var extent = projection.getExtent();
  15684. var size = !extent ?
  15685. // use an extent that can fit the whole world if need be
  15686. 360 * ol.proj.METERS_PER_UNIT[ol.proj.Units.DEGREES] /
  15687. projection.getMetersPerUnit() :
  15688. Math.max(ol.extent.getWidth(extent), ol.extent.getHeight(extent));
  15689. var defaultMaxResolution = size / ol.DEFAULT_TILE_SIZE / Math.pow(
  15690. defaultZoomFactor, ol.DEFAULT_MIN_ZOOM);
  15691. var defaultMinResolution = defaultMaxResolution / Math.pow(
  15692. defaultZoomFactor, defaultMaxZoom - ol.DEFAULT_MIN_ZOOM);
  15693. // user provided maxResolution takes precedence
  15694. maxResolution = options.maxResolution;
  15695. if (maxResolution !== undefined) {
  15696. minZoom = 0;
  15697. } else {
  15698. maxResolution = defaultMaxResolution / Math.pow(zoomFactor, minZoom);
  15699. }
  15700. // user provided minResolution takes precedence
  15701. minResolution = options.minResolution;
  15702. if (minResolution === undefined) {
  15703. if (options.maxZoom !== undefined) {
  15704. if (options.maxResolution !== undefined) {
  15705. minResolution = maxResolution / Math.pow(zoomFactor, maxZoom);
  15706. } else {
  15707. minResolution = defaultMaxResolution / Math.pow(zoomFactor, maxZoom);
  15708. }
  15709. } else {
  15710. minResolution = defaultMinResolution;
  15711. }
  15712. }
  15713. // given discrete zoom levels, minResolution may be different than provided
  15714. maxZoom = minZoom + Math.floor(
  15715. Math.log(maxResolution / minResolution) / Math.log(zoomFactor));
  15716. minResolution = maxResolution / Math.pow(zoomFactor, maxZoom - minZoom);
  15717. resolutionConstraint = ol.ResolutionConstraint.createSnapToPower(
  15718. zoomFactor, maxResolution, maxZoom - minZoom);
  15719. }
  15720. return {constraint: resolutionConstraint, maxResolution: maxResolution,
  15721. minResolution: minResolution, minZoom: minZoom, zoomFactor: zoomFactor};
  15722. };
  15723. /**
  15724. * @private
  15725. * @param {olx.ViewOptions} options View options.
  15726. * @return {ol.RotationConstraintType} Rotation constraint.
  15727. */
  15728. ol.View.createRotationConstraint_ = function(options) {
  15729. var enableRotation = options.enableRotation !== undefined ?
  15730. options.enableRotation : true;
  15731. if (enableRotation) {
  15732. var constrainRotation = options.constrainRotation;
  15733. if (constrainRotation === undefined || constrainRotation === true) {
  15734. return ol.RotationConstraint.createSnapToZero();
  15735. } else if (constrainRotation === false) {
  15736. return ol.RotationConstraint.none;
  15737. } else if (typeof constrainRotation === 'number') {
  15738. return ol.RotationConstraint.createSnapToN(constrainRotation);
  15739. } else {
  15740. return ol.RotationConstraint.none;
  15741. }
  15742. } else {
  15743. return ol.RotationConstraint.disable;
  15744. }
  15745. };
  15746. /**
  15747. * Determine if an animation involves no view change.
  15748. * @param {ol.ViewAnimation} animation The animation.
  15749. * @return {boolean} The animation involves no view change.
  15750. */
  15751. ol.View.isNoopAnimation = function(animation) {
  15752. if (animation.sourceCenter && animation.targetCenter) {
  15753. if (!ol.coordinate.equals(animation.sourceCenter, animation.targetCenter)) {
  15754. return false;
  15755. }
  15756. }
  15757. if (animation.sourceResolution !== animation.targetResolution) {
  15758. return false;
  15759. }
  15760. if (animation.sourceRotation !== animation.targetRotation) {
  15761. return false;
  15762. }
  15763. return true;
  15764. };
  15765. goog.provide('ol.Kinetic');
  15766. /**
  15767. * @classdesc
  15768. * Implementation of inertial deceleration for map movement.
  15769. *
  15770. * @constructor
  15771. * @param {number} decay Rate of decay (must be negative).
  15772. * @param {number} minVelocity Minimum velocity (pixels/millisecond).
  15773. * @param {number} delay Delay to consider to calculate the kinetic
  15774. * initial values (milliseconds).
  15775. * @struct
  15776. * @api
  15777. */
  15778. ol.Kinetic = function(decay, minVelocity, delay) {
  15779. /**
  15780. * @private
  15781. * @type {number}
  15782. */
  15783. this.decay_ = decay;
  15784. /**
  15785. * @private
  15786. * @type {number}
  15787. */
  15788. this.minVelocity_ = minVelocity;
  15789. /**
  15790. * @private
  15791. * @type {number}
  15792. */
  15793. this.delay_ = delay;
  15794. /**
  15795. * @private
  15796. * @type {Array.<number>}
  15797. */
  15798. this.points_ = [];
  15799. /**
  15800. * @private
  15801. * @type {number}
  15802. */
  15803. this.angle_ = 0;
  15804. /**
  15805. * @private
  15806. * @type {number}
  15807. */
  15808. this.initialVelocity_ = 0;
  15809. };
  15810. /**
  15811. * FIXME empty description for jsdoc
  15812. */
  15813. ol.Kinetic.prototype.begin = function() {
  15814. this.points_.length = 0;
  15815. this.angle_ = 0;
  15816. this.initialVelocity_ = 0;
  15817. };
  15818. /**
  15819. * @param {number} x X.
  15820. * @param {number} y Y.
  15821. */
  15822. ol.Kinetic.prototype.update = function(x, y) {
  15823. this.points_.push(x, y, Date.now());
  15824. };
  15825. /**
  15826. * @return {boolean} Whether we should do kinetic animation.
  15827. */
  15828. ol.Kinetic.prototype.end = function() {
  15829. if (this.points_.length < 6) {
  15830. // at least 2 points are required (i.e. there must be at least 6 elements
  15831. // in the array)
  15832. return false;
  15833. }
  15834. var delay = Date.now() - this.delay_;
  15835. var lastIndex = this.points_.length - 3;
  15836. if (this.points_[lastIndex + 2] < delay) {
  15837. // the last tracked point is too old, which means that the user stopped
  15838. // panning before releasing the map
  15839. return false;
  15840. }
  15841. // get the first point which still falls into the delay time
  15842. var firstIndex = lastIndex - 3;
  15843. while (firstIndex > 0 && this.points_[firstIndex + 2] > delay) {
  15844. firstIndex -= 3;
  15845. }
  15846. var duration = this.points_[lastIndex + 2] - this.points_[firstIndex + 2];
  15847. // we don't want a duration of 0 (divide by zero)
  15848. // we also make sure the user panned for a duration of at least one frame
  15849. // (1/60s) to compute sane displacement values
  15850. if (duration < 1000 / 60) {
  15851. return false;
  15852. }
  15853. var dx = this.points_[lastIndex] - this.points_[firstIndex];
  15854. var dy = this.points_[lastIndex + 1] - this.points_[firstIndex + 1];
  15855. this.angle_ = Math.atan2(dy, dx);
  15856. this.initialVelocity_ = Math.sqrt(dx * dx + dy * dy) / duration;
  15857. return this.initialVelocity_ > this.minVelocity_;
  15858. };
  15859. /**
  15860. * @return {number} Total distance travelled (pixels).
  15861. */
  15862. ol.Kinetic.prototype.getDistance = function() {
  15863. return (this.minVelocity_ - this.initialVelocity_) / this.decay_;
  15864. };
  15865. /**
  15866. * @return {number} Angle of the kinetic panning animation (radians).
  15867. */
  15868. ol.Kinetic.prototype.getAngle = function() {
  15869. return this.angle_;
  15870. };
  15871. goog.provide('ol.interaction.Property');
  15872. /**
  15873. * @enum {string}
  15874. */
  15875. ol.interaction.Property = {
  15876. ACTIVE: 'active'
  15877. };
  15878. // FIXME factor out key precondition (shift et. al)
  15879. goog.provide('ol.interaction.Interaction');
  15880. goog.require('ol');
  15881. goog.require('ol.Object');
  15882. goog.require('ol.easing');
  15883. goog.require('ol.interaction.Property');
  15884. /**
  15885. * @classdesc
  15886. * Abstract base class; normally only used for creating subclasses and not
  15887. * instantiated in apps.
  15888. * User actions that change the state of the map. Some are similar to controls,
  15889. * but are not associated with a DOM element.
  15890. * For example, {@link ol.interaction.KeyboardZoom} is functionally the same as
  15891. * {@link ol.control.Zoom}, but triggered by a keyboard event not a button
  15892. * element event.
  15893. * Although interactions do not have a DOM element, some of them do render
  15894. * vectors and so are visible on the screen.
  15895. *
  15896. * @constructor
  15897. * @param {olx.interaction.InteractionOptions} options Options.
  15898. * @extends {ol.Object}
  15899. * @api
  15900. */
  15901. ol.interaction.Interaction = function(options) {
  15902. ol.Object.call(this);
  15903. /**
  15904. * @private
  15905. * @type {ol.Map}
  15906. */
  15907. this.map_ = null;
  15908. this.setActive(true);
  15909. /**
  15910. * @type {function(ol.MapBrowserEvent):boolean}
  15911. */
  15912. this.handleEvent = options.handleEvent;
  15913. };
  15914. ol.inherits(ol.interaction.Interaction, ol.Object);
  15915. /**
  15916. * Return whether the interaction is currently active.
  15917. * @return {boolean} `true` if the interaction is active, `false` otherwise.
  15918. * @observable
  15919. * @api
  15920. */
  15921. ol.interaction.Interaction.prototype.getActive = function() {
  15922. return /** @type {boolean} */ (
  15923. this.get(ol.interaction.Property.ACTIVE));
  15924. };
  15925. /**
  15926. * Get the map associated with this interaction.
  15927. * @return {ol.Map} Map.
  15928. * @api
  15929. */
  15930. ol.interaction.Interaction.prototype.getMap = function() {
  15931. return this.map_;
  15932. };
  15933. /**
  15934. * Activate or deactivate the interaction.
  15935. * @param {boolean} active Active.
  15936. * @observable
  15937. * @api
  15938. */
  15939. ol.interaction.Interaction.prototype.setActive = function(active) {
  15940. this.set(ol.interaction.Property.ACTIVE, active);
  15941. };
  15942. /**
  15943. * Remove the interaction from its current map and attach it to the new map.
  15944. * Subclasses may set up event handlers to get notified about changes to
  15945. * the map here.
  15946. * @param {ol.Map} map Map.
  15947. */
  15948. ol.interaction.Interaction.prototype.setMap = function(map) {
  15949. this.map_ = map;
  15950. };
  15951. /**
  15952. * @param {ol.View} view View.
  15953. * @param {ol.Coordinate} delta Delta.
  15954. * @param {number=} opt_duration Duration.
  15955. */
  15956. ol.interaction.Interaction.pan = function(view, delta, opt_duration) {
  15957. var currentCenter = view.getCenter();
  15958. if (currentCenter) {
  15959. var center = view.constrainCenter(
  15960. [currentCenter[0] + delta[0], currentCenter[1] + delta[1]]);
  15961. if (opt_duration) {
  15962. view.animate({
  15963. duration: opt_duration,
  15964. easing: ol.easing.linear,
  15965. center: center
  15966. });
  15967. } else {
  15968. view.setCenter(center);
  15969. }
  15970. }
  15971. };
  15972. /**
  15973. * @param {ol.View} view View.
  15974. * @param {number|undefined} rotation Rotation.
  15975. * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
  15976. * @param {number=} opt_duration Duration.
  15977. */
  15978. ol.interaction.Interaction.rotate = function(view, rotation, opt_anchor, opt_duration) {
  15979. rotation = view.constrainRotation(rotation, 0);
  15980. ol.interaction.Interaction.rotateWithoutConstraints(
  15981. view, rotation, opt_anchor, opt_duration);
  15982. };
  15983. /**
  15984. * @param {ol.View} view View.
  15985. * @param {number|undefined} rotation Rotation.
  15986. * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
  15987. * @param {number=} opt_duration Duration.
  15988. */
  15989. ol.interaction.Interaction.rotateWithoutConstraints = function(view, rotation, opt_anchor, opt_duration) {
  15990. if (rotation !== undefined) {
  15991. var currentRotation = view.getRotation();
  15992. var currentCenter = view.getCenter();
  15993. if (currentRotation !== undefined && currentCenter && opt_duration > 0) {
  15994. view.animate({
  15995. rotation: rotation,
  15996. anchor: opt_anchor,
  15997. duration: opt_duration,
  15998. easing: ol.easing.easeOut
  15999. });
  16000. } else {
  16001. view.rotate(rotation, opt_anchor);
  16002. }
  16003. }
  16004. };
  16005. /**
  16006. * @param {ol.View} view View.
  16007. * @param {number|undefined} resolution Resolution to go to.
  16008. * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
  16009. * @param {number=} opt_duration Duration.
  16010. * @param {number=} opt_direction Zooming direction; > 0 indicates
  16011. * zooming out, in which case the constraints system will select
  16012. * the largest nearest resolution; < 0 indicates zooming in, in
  16013. * which case the constraints system will select the smallest
  16014. * nearest resolution; == 0 indicates that the zooming direction
  16015. * is unknown/not relevant, in which case the constraints system
  16016. * will select the nearest resolution. If not defined 0 is
  16017. * assumed.
  16018. */
  16019. ol.interaction.Interaction.zoom = function(view, resolution, opt_anchor, opt_duration, opt_direction) {
  16020. resolution = view.constrainResolution(resolution, 0, opt_direction);
  16021. ol.interaction.Interaction.zoomWithoutConstraints(
  16022. view, resolution, opt_anchor, opt_duration);
  16023. };
  16024. /**
  16025. * @param {ol.View} view View.
  16026. * @param {number} delta Delta from previous zoom level.
  16027. * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
  16028. * @param {number=} opt_duration Duration.
  16029. */
  16030. ol.interaction.Interaction.zoomByDelta = function(view, delta, opt_anchor, opt_duration) {
  16031. var currentResolution = view.getResolution();
  16032. var resolution = view.constrainResolution(currentResolution, delta, 0);
  16033. // If we have a constraint on center, we need to change the anchor so that the
  16034. // new center is within the extent. We first calculate the new center, apply
  16035. // the constraint to it, and then calculate back the anchor
  16036. if (opt_anchor && resolution !== undefined && resolution !== currentResolution) {
  16037. var currentCenter = view.getCenter();
  16038. var center = view.calculateCenterZoom(resolution, opt_anchor);
  16039. center = view.constrainCenter(center);
  16040. opt_anchor = [
  16041. (resolution * currentCenter[0] - currentResolution * center[0]) /
  16042. (resolution - currentResolution),
  16043. (resolution * currentCenter[1] - currentResolution * center[1]) /
  16044. (resolution - currentResolution)
  16045. ];
  16046. }
  16047. ol.interaction.Interaction.zoomWithoutConstraints(
  16048. view, resolution, opt_anchor, opt_duration);
  16049. };
  16050. /**
  16051. * @param {ol.View} view View.
  16052. * @param {number|undefined} resolution Resolution to go to.
  16053. * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
  16054. * @param {number=} opt_duration Duration.
  16055. */
  16056. ol.interaction.Interaction.zoomWithoutConstraints = function(view, resolution, opt_anchor, opt_duration) {
  16057. if (resolution) {
  16058. var currentResolution = view.getResolution();
  16059. var currentCenter = view.getCenter();
  16060. if (currentResolution !== undefined && currentCenter &&
  16061. resolution !== currentResolution && opt_duration) {
  16062. view.animate({
  16063. resolution: resolution,
  16064. anchor: opt_anchor,
  16065. duration: opt_duration,
  16066. easing: ol.easing.easeOut
  16067. });
  16068. } else {
  16069. if (opt_anchor) {
  16070. var center = view.calculateCenterZoom(resolution, opt_anchor);
  16071. view.setCenter(center);
  16072. }
  16073. view.setResolution(resolution);
  16074. }
  16075. }
  16076. };
  16077. goog.provide('ol.interaction.DoubleClickZoom');
  16078. goog.require('ol');
  16079. goog.require('ol.MapBrowserEventType');
  16080. goog.require('ol.interaction.Interaction');
  16081. /**
  16082. * @classdesc
  16083. * Allows the user to zoom by double-clicking on the map.
  16084. *
  16085. * @constructor
  16086. * @extends {ol.interaction.Interaction}
  16087. * @param {olx.interaction.DoubleClickZoomOptions=} opt_options Options.
  16088. * @api
  16089. */
  16090. ol.interaction.DoubleClickZoom = function(opt_options) {
  16091. var options = opt_options ? opt_options : {};
  16092. /**
  16093. * @private
  16094. * @type {number}
  16095. */
  16096. this.delta_ = options.delta ? options.delta : 1;
  16097. ol.interaction.Interaction.call(this, {
  16098. handleEvent: ol.interaction.DoubleClickZoom.handleEvent
  16099. });
  16100. /**
  16101. * @private
  16102. * @type {number}
  16103. */
  16104. this.duration_ = options.duration !== undefined ? options.duration : 250;
  16105. };
  16106. ol.inherits(ol.interaction.DoubleClickZoom, ol.interaction.Interaction);
  16107. /**
  16108. * Handles the {@link ol.MapBrowserEvent map browser event} (if it was a
  16109. * doubleclick) and eventually zooms the map.
  16110. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16111. * @return {boolean} `false` to stop event propagation.
  16112. * @this {ol.interaction.DoubleClickZoom}
  16113. * @api
  16114. */
  16115. ol.interaction.DoubleClickZoom.handleEvent = function(mapBrowserEvent) {
  16116. var stopEvent = false;
  16117. var browserEvent = mapBrowserEvent.originalEvent;
  16118. if (mapBrowserEvent.type == ol.MapBrowserEventType.DBLCLICK) {
  16119. var map = mapBrowserEvent.map;
  16120. var anchor = mapBrowserEvent.coordinate;
  16121. var delta = browserEvent.shiftKey ? -this.delta_ : this.delta_;
  16122. var view = map.getView();
  16123. ol.interaction.Interaction.zoomByDelta(
  16124. view, delta, anchor, this.duration_);
  16125. mapBrowserEvent.preventDefault();
  16126. stopEvent = true;
  16127. }
  16128. return !stopEvent;
  16129. };
  16130. goog.provide('ol.events.condition');
  16131. goog.require('ol.MapBrowserEventType');
  16132. goog.require('ol.asserts');
  16133. goog.require('ol.functions');
  16134. goog.require('ol.has');
  16135. /**
  16136. * Return `true` if only the alt-key is pressed, `false` otherwise (e.g. when
  16137. * additionally the shift-key is pressed).
  16138. *
  16139. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16140. * @return {boolean} True if only the alt key is pressed.
  16141. * @api
  16142. */
  16143. ol.events.condition.altKeyOnly = function(mapBrowserEvent) {
  16144. var originalEvent = mapBrowserEvent.originalEvent;
  16145. return (
  16146. originalEvent.altKey &&
  16147. !(originalEvent.metaKey || originalEvent.ctrlKey) &&
  16148. !originalEvent.shiftKey);
  16149. };
  16150. /**
  16151. * Return `true` if only the alt-key and shift-key is pressed, `false` otherwise
  16152. * (e.g. when additionally the platform-modifier-key is pressed).
  16153. *
  16154. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16155. * @return {boolean} True if only the alt and shift keys are pressed.
  16156. * @api
  16157. */
  16158. ol.events.condition.altShiftKeysOnly = function(mapBrowserEvent) {
  16159. var originalEvent = mapBrowserEvent.originalEvent;
  16160. return (
  16161. originalEvent.altKey &&
  16162. !(originalEvent.metaKey || originalEvent.ctrlKey) &&
  16163. originalEvent.shiftKey);
  16164. };
  16165. /**
  16166. * Return always true.
  16167. *
  16168. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16169. * @return {boolean} True.
  16170. * @function
  16171. * @api
  16172. */
  16173. ol.events.condition.always = ol.functions.TRUE;
  16174. /**
  16175. * Return `true` if the event is a `click` event, `false` otherwise.
  16176. *
  16177. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16178. * @return {boolean} True if the event is a map `click` event.
  16179. * @api
  16180. */
  16181. ol.events.condition.click = function(mapBrowserEvent) {
  16182. return mapBrowserEvent.type == ol.MapBrowserEventType.CLICK;
  16183. };
  16184. /**
  16185. * Return `true` if the event has an "action"-producing mouse button.
  16186. *
  16187. * By definition, this includes left-click on windows/linux, and left-click
  16188. * without the ctrl key on Macs.
  16189. *
  16190. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16191. * @return {boolean} The result.
  16192. */
  16193. ol.events.condition.mouseActionButton = function(mapBrowserEvent) {
  16194. var originalEvent = mapBrowserEvent.originalEvent;
  16195. return originalEvent.button == 0 &&
  16196. !(ol.has.WEBKIT && ol.has.MAC && originalEvent.ctrlKey);
  16197. };
  16198. /**
  16199. * Return always false.
  16200. *
  16201. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16202. * @return {boolean} False.
  16203. * @function
  16204. * @api
  16205. */
  16206. ol.events.condition.never = ol.functions.FALSE;
  16207. /**
  16208. * Return `true` if the browser event is a `pointermove` event, `false`
  16209. * otherwise.
  16210. *
  16211. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16212. * @return {boolean} True if the browser event is a `pointermove` event.
  16213. * @api
  16214. */
  16215. ol.events.condition.pointerMove = function(mapBrowserEvent) {
  16216. return mapBrowserEvent.type == 'pointermove';
  16217. };
  16218. /**
  16219. * Return `true` if the event is a map `singleclick` event, `false` otherwise.
  16220. *
  16221. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16222. * @return {boolean} True if the event is a map `singleclick` event.
  16223. * @api
  16224. */
  16225. ol.events.condition.singleClick = function(mapBrowserEvent) {
  16226. return mapBrowserEvent.type == ol.MapBrowserEventType.SINGLECLICK;
  16227. };
  16228. /**
  16229. * Return `true` if the event is a map `dblclick` event, `false` otherwise.
  16230. *
  16231. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16232. * @return {boolean} True if the event is a map `dblclick` event.
  16233. * @api
  16234. */
  16235. ol.events.condition.doubleClick = function(mapBrowserEvent) {
  16236. return mapBrowserEvent.type == ol.MapBrowserEventType.DBLCLICK;
  16237. };
  16238. /**
  16239. * Return `true` if no modifier key (alt-, shift- or platform-modifier-key) is
  16240. * pressed.
  16241. *
  16242. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16243. * @return {boolean} True only if there no modifier keys are pressed.
  16244. * @api
  16245. */
  16246. ol.events.condition.noModifierKeys = function(mapBrowserEvent) {
  16247. var originalEvent = mapBrowserEvent.originalEvent;
  16248. return (
  16249. !originalEvent.altKey &&
  16250. !(originalEvent.metaKey || originalEvent.ctrlKey) &&
  16251. !originalEvent.shiftKey);
  16252. };
  16253. /**
  16254. * Return `true` if only the platform-modifier-key (the meta-key on Mac,
  16255. * ctrl-key otherwise) is pressed, `false` otherwise (e.g. when additionally
  16256. * the shift-key is pressed).
  16257. *
  16258. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16259. * @return {boolean} True if only the platform modifier key is pressed.
  16260. * @api
  16261. */
  16262. ol.events.condition.platformModifierKeyOnly = function(mapBrowserEvent) {
  16263. var originalEvent = mapBrowserEvent.originalEvent;
  16264. return (
  16265. !originalEvent.altKey &&
  16266. (ol.has.MAC ? originalEvent.metaKey : originalEvent.ctrlKey) &&
  16267. !originalEvent.shiftKey);
  16268. };
  16269. /**
  16270. * Return `true` if only the shift-key is pressed, `false` otherwise (e.g. when
  16271. * additionally the alt-key is pressed).
  16272. *
  16273. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16274. * @return {boolean} True if only the shift key is pressed.
  16275. * @api
  16276. */
  16277. ol.events.condition.shiftKeyOnly = function(mapBrowserEvent) {
  16278. var originalEvent = mapBrowserEvent.originalEvent;
  16279. return (
  16280. !originalEvent.altKey &&
  16281. !(originalEvent.metaKey || originalEvent.ctrlKey) &&
  16282. originalEvent.shiftKey);
  16283. };
  16284. /**
  16285. * Return `true` if the target element is not editable, i.e. not a `<input>`-,
  16286. * `<select>`- or `<textarea>`-element, `false` otherwise.
  16287. *
  16288. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16289. * @return {boolean} True only if the target element is not editable.
  16290. * @api
  16291. */
  16292. ol.events.condition.targetNotEditable = function(mapBrowserEvent) {
  16293. var target = mapBrowserEvent.originalEvent.target;
  16294. var tagName = target.tagName;
  16295. return (
  16296. tagName !== 'INPUT' &&
  16297. tagName !== 'SELECT' &&
  16298. tagName !== 'TEXTAREA');
  16299. };
  16300. /**
  16301. * Return `true` if the event originates from a mouse device.
  16302. *
  16303. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16304. * @return {boolean} True if the event originates from a mouse device.
  16305. * @api
  16306. */
  16307. ol.events.condition.mouseOnly = function(mapBrowserEvent) {
  16308. ol.asserts.assert(mapBrowserEvent.pointerEvent, 56); // mapBrowserEvent must originate from a pointer event
  16309. // see http://www.w3.org/TR/pointerevents/#widl-PointerEvent-pointerType
  16310. return /** @type {ol.MapBrowserEvent} */ (mapBrowserEvent).pointerEvent.pointerType == 'mouse';
  16311. };
  16312. /**
  16313. * Return `true` if the event originates from a primary pointer in
  16314. * contact with the surface or if the left mouse button is pressed.
  16315. * @see http://www.w3.org/TR/pointerevents/#button-states
  16316. *
  16317. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16318. * @return {boolean} True if the event originates from a primary pointer.
  16319. * @api
  16320. */
  16321. ol.events.condition.primaryAction = function(mapBrowserEvent) {
  16322. var pointerEvent = mapBrowserEvent.pointerEvent;
  16323. return pointerEvent.isPrimary && pointerEvent.button === 0;
  16324. };
  16325. goog.provide('ol.interaction.Pointer');
  16326. goog.require('ol');
  16327. goog.require('ol.functions');
  16328. goog.require('ol.MapBrowserEventType');
  16329. goog.require('ol.MapBrowserPointerEvent');
  16330. goog.require('ol.interaction.Interaction');
  16331. goog.require('ol.obj');
  16332. /**
  16333. * @classdesc
  16334. * Base class that calls user-defined functions on `down`, `move` and `up`
  16335. * events. This class also manages "drag sequences".
  16336. *
  16337. * When the `handleDownEvent` user function returns `true` a drag sequence is
  16338. * started. During a drag sequence the `handleDragEvent` user function is
  16339. * called on `move` events. The drag sequence ends when the `handleUpEvent`
  16340. * user function is called and returns `false`.
  16341. *
  16342. * @constructor
  16343. * @param {olx.interaction.PointerOptions=} opt_options Options.
  16344. * @extends {ol.interaction.Interaction}
  16345. * @api
  16346. */
  16347. ol.interaction.Pointer = function(opt_options) {
  16348. var options = opt_options ? opt_options : {};
  16349. var handleEvent = options.handleEvent ?
  16350. options.handleEvent : ol.interaction.Pointer.handleEvent;
  16351. ol.interaction.Interaction.call(this, {
  16352. handleEvent: handleEvent
  16353. });
  16354. /**
  16355. * @type {function(ol.MapBrowserPointerEvent):boolean}
  16356. * @private
  16357. */
  16358. this.handleDownEvent_ = options.handleDownEvent ?
  16359. options.handleDownEvent : ol.interaction.Pointer.handleDownEvent;
  16360. /**
  16361. * @type {function(ol.MapBrowserPointerEvent)}
  16362. * @private
  16363. */
  16364. this.handleDragEvent_ = options.handleDragEvent ?
  16365. options.handleDragEvent : ol.interaction.Pointer.handleDragEvent;
  16366. /**
  16367. * @type {function(ol.MapBrowserPointerEvent)}
  16368. * @private
  16369. */
  16370. this.handleMoveEvent_ = options.handleMoveEvent ?
  16371. options.handleMoveEvent : ol.interaction.Pointer.handleMoveEvent;
  16372. /**
  16373. * @type {function(ol.MapBrowserPointerEvent):boolean}
  16374. * @private
  16375. */
  16376. this.handleUpEvent_ = options.handleUpEvent ?
  16377. options.handleUpEvent : ol.interaction.Pointer.handleUpEvent;
  16378. /**
  16379. * @type {boolean}
  16380. * @protected
  16381. */
  16382. this.handlingDownUpSequence = false;
  16383. /**
  16384. * @type {Object.<number, ol.pointer.PointerEvent>}
  16385. * @private
  16386. */
  16387. this.trackedPointers_ = {};
  16388. /**
  16389. * @type {Array.<ol.pointer.PointerEvent>}
  16390. * @protected
  16391. */
  16392. this.targetPointers = [];
  16393. };
  16394. ol.inherits(ol.interaction.Pointer, ol.interaction.Interaction);
  16395. /**
  16396. * @param {Array.<ol.pointer.PointerEvent>} pointerEvents List of events.
  16397. * @return {ol.Pixel} Centroid pixel.
  16398. */
  16399. ol.interaction.Pointer.centroid = function(pointerEvents) {
  16400. var length = pointerEvents.length;
  16401. var clientX = 0;
  16402. var clientY = 0;
  16403. for (var i = 0; i < length; i++) {
  16404. clientX += pointerEvents[i].clientX;
  16405. clientY += pointerEvents[i].clientY;
  16406. }
  16407. return [clientX / length, clientY / length];
  16408. };
  16409. /**
  16410. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  16411. * @return {boolean} Whether the event is a pointerdown, pointerdrag
  16412. * or pointerup event.
  16413. * @private
  16414. */
  16415. ol.interaction.Pointer.prototype.isPointerDraggingEvent_ = function(mapBrowserEvent) {
  16416. var type = mapBrowserEvent.type;
  16417. return (
  16418. type === ol.MapBrowserEventType.POINTERDOWN ||
  16419. type === ol.MapBrowserEventType.POINTERDRAG ||
  16420. type === ol.MapBrowserEventType.POINTERUP);
  16421. };
  16422. /**
  16423. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  16424. * @private
  16425. */
  16426. ol.interaction.Pointer.prototype.updateTrackedPointers_ = function(mapBrowserEvent) {
  16427. if (this.isPointerDraggingEvent_(mapBrowserEvent)) {
  16428. var event = mapBrowserEvent.pointerEvent;
  16429. if (mapBrowserEvent.type == ol.MapBrowserEventType.POINTERUP) {
  16430. delete this.trackedPointers_[event.pointerId];
  16431. } else if (mapBrowserEvent.type ==
  16432. ol.MapBrowserEventType.POINTERDOWN) {
  16433. this.trackedPointers_[event.pointerId] = event;
  16434. } else if (event.pointerId in this.trackedPointers_) {
  16435. // update only when there was a pointerdown event for this pointer
  16436. this.trackedPointers_[event.pointerId] = event;
  16437. }
  16438. this.targetPointers = ol.obj.getValues(this.trackedPointers_);
  16439. }
  16440. };
  16441. /**
  16442. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  16443. * @this {ol.interaction.Pointer}
  16444. */
  16445. ol.interaction.Pointer.handleDragEvent = ol.nullFunction;
  16446. /**
  16447. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  16448. * @return {boolean} Capture dragging.
  16449. * @this {ol.interaction.Pointer}
  16450. */
  16451. ol.interaction.Pointer.handleUpEvent = ol.functions.FALSE;
  16452. /**
  16453. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  16454. * @return {boolean} Capture dragging.
  16455. * @this {ol.interaction.Pointer}
  16456. */
  16457. ol.interaction.Pointer.handleDownEvent = ol.functions.FALSE;
  16458. /**
  16459. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  16460. * @this {ol.interaction.Pointer}
  16461. */
  16462. ol.interaction.Pointer.handleMoveEvent = ol.nullFunction;
  16463. /**
  16464. * Handles the {@link ol.MapBrowserEvent map browser event} and may call into
  16465. * other functions, if event sequences like e.g. 'drag' or 'down-up' etc. are
  16466. * detected.
  16467. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16468. * @return {boolean} `false` to stop event propagation.
  16469. * @this {ol.interaction.Pointer}
  16470. * @api
  16471. */
  16472. ol.interaction.Pointer.handleEvent = function(mapBrowserEvent) {
  16473. if (!(mapBrowserEvent instanceof ol.MapBrowserPointerEvent)) {
  16474. return true;
  16475. }
  16476. var stopEvent = false;
  16477. this.updateTrackedPointers_(mapBrowserEvent);
  16478. if (this.handlingDownUpSequence) {
  16479. if (mapBrowserEvent.type == ol.MapBrowserEventType.POINTERDRAG) {
  16480. this.handleDragEvent_(mapBrowserEvent);
  16481. } else if (mapBrowserEvent.type == ol.MapBrowserEventType.POINTERUP) {
  16482. var handledUp = this.handleUpEvent_(mapBrowserEvent);
  16483. this.handlingDownUpSequence = handledUp && this.targetPointers.length > 0;
  16484. }
  16485. } else {
  16486. if (mapBrowserEvent.type == ol.MapBrowserEventType.POINTERDOWN) {
  16487. var handled = this.handleDownEvent_(mapBrowserEvent);
  16488. this.handlingDownUpSequence = handled;
  16489. stopEvent = this.shouldStopEvent(handled);
  16490. } else if (mapBrowserEvent.type == ol.MapBrowserEventType.POINTERMOVE) {
  16491. this.handleMoveEvent_(mapBrowserEvent);
  16492. }
  16493. }
  16494. return !stopEvent;
  16495. };
  16496. /**
  16497. * This method is used to determine if "down" events should be propagated to
  16498. * other interactions or should be stopped.
  16499. *
  16500. * The method receives the return code of the "handleDownEvent" function.
  16501. *
  16502. * By default this function is the "identity" function. It's overidden in
  16503. * child classes.
  16504. *
  16505. * @param {boolean} handled Was the event handled by the interaction?
  16506. * @return {boolean} Should the event be stopped?
  16507. * @protected
  16508. */
  16509. ol.interaction.Pointer.prototype.shouldStopEvent = function(handled) {
  16510. return handled;
  16511. };
  16512. goog.provide('ol.interaction.DragPan');
  16513. goog.require('ol');
  16514. goog.require('ol.ViewHint');
  16515. goog.require('ol.coordinate');
  16516. goog.require('ol.easing');
  16517. goog.require('ol.events.condition');
  16518. goog.require('ol.functions');
  16519. goog.require('ol.interaction.Pointer');
  16520. /**
  16521. * @classdesc
  16522. * Allows the user to pan the map by dragging the map.
  16523. *
  16524. * @constructor
  16525. * @extends {ol.interaction.Pointer}
  16526. * @param {olx.interaction.DragPanOptions=} opt_options Options.
  16527. * @api
  16528. */
  16529. ol.interaction.DragPan = function(opt_options) {
  16530. ol.interaction.Pointer.call(this, {
  16531. handleDownEvent: ol.interaction.DragPan.handleDownEvent_,
  16532. handleDragEvent: ol.interaction.DragPan.handleDragEvent_,
  16533. handleUpEvent: ol.interaction.DragPan.handleUpEvent_
  16534. });
  16535. var options = opt_options ? opt_options : {};
  16536. /**
  16537. * @private
  16538. * @type {ol.Kinetic|undefined}
  16539. */
  16540. this.kinetic_ = options.kinetic;
  16541. /**
  16542. * @type {ol.Pixel}
  16543. */
  16544. this.lastCentroid = null;
  16545. /**
  16546. * @type {number}
  16547. */
  16548. this.lastPointersCount_;
  16549. /**
  16550. * @private
  16551. * @type {ol.EventsConditionType}
  16552. */
  16553. this.condition_ = options.condition ?
  16554. options.condition : ol.events.condition.noModifierKeys;
  16555. /**
  16556. * @private
  16557. * @type {boolean}
  16558. */
  16559. this.noKinetic_ = false;
  16560. };
  16561. ol.inherits(ol.interaction.DragPan, ol.interaction.Pointer);
  16562. /**
  16563. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  16564. * @this {ol.interaction.DragPan}
  16565. * @private
  16566. */
  16567. ol.interaction.DragPan.handleDragEvent_ = function(mapBrowserEvent) {
  16568. var targetPointers = this.targetPointers;
  16569. var centroid =
  16570. ol.interaction.Pointer.centroid(targetPointers);
  16571. if (targetPointers.length == this.lastPointersCount_) {
  16572. if (this.kinetic_) {
  16573. this.kinetic_.update(centroid[0], centroid[1]);
  16574. }
  16575. if (this.lastCentroid) {
  16576. var deltaX = this.lastCentroid[0] - centroid[0];
  16577. var deltaY = centroid[1] - this.lastCentroid[1];
  16578. var map = mapBrowserEvent.map;
  16579. var view = map.getView();
  16580. var viewState = view.getState();
  16581. var center = [deltaX, deltaY];
  16582. ol.coordinate.scale(center, viewState.resolution);
  16583. ol.coordinate.rotate(center, viewState.rotation);
  16584. ol.coordinate.add(center, viewState.center);
  16585. center = view.constrainCenter(center);
  16586. view.setCenter(center);
  16587. }
  16588. } else if (this.kinetic_) {
  16589. // reset so we don't overestimate the kinetic energy after
  16590. // after one finger down, tiny drag, second finger down
  16591. this.kinetic_.begin();
  16592. }
  16593. this.lastCentroid = centroid;
  16594. this.lastPointersCount_ = targetPointers.length;
  16595. };
  16596. /**
  16597. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  16598. * @return {boolean} Stop drag sequence?
  16599. * @this {ol.interaction.DragPan}
  16600. * @private
  16601. */
  16602. ol.interaction.DragPan.handleUpEvent_ = function(mapBrowserEvent) {
  16603. var map = mapBrowserEvent.map;
  16604. var view = map.getView();
  16605. if (this.targetPointers.length === 0) {
  16606. if (!this.noKinetic_ && this.kinetic_ && this.kinetic_.end()) {
  16607. var distance = this.kinetic_.getDistance();
  16608. var angle = this.kinetic_.getAngle();
  16609. var center = /** @type {!ol.Coordinate} */ (view.getCenter());
  16610. var centerpx = map.getPixelFromCoordinate(center);
  16611. var dest = map.getCoordinateFromPixel([
  16612. centerpx[0] - distance * Math.cos(angle),
  16613. centerpx[1] - distance * Math.sin(angle)
  16614. ]);
  16615. view.animate({
  16616. center: view.constrainCenter(dest),
  16617. duration: 500,
  16618. easing: ol.easing.easeOut
  16619. });
  16620. }
  16621. view.setHint(ol.ViewHint.INTERACTING, -1);
  16622. return false;
  16623. } else {
  16624. if (this.kinetic_) {
  16625. // reset so we don't overestimate the kinetic energy after
  16626. // after one finger up, tiny drag, second finger up
  16627. this.kinetic_.begin();
  16628. }
  16629. this.lastCentroid = null;
  16630. return true;
  16631. }
  16632. };
  16633. /**
  16634. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  16635. * @return {boolean} Start drag sequence?
  16636. * @this {ol.interaction.DragPan}
  16637. * @private
  16638. */
  16639. ol.interaction.DragPan.handleDownEvent_ = function(mapBrowserEvent) {
  16640. if (this.targetPointers.length > 0 && this.condition_(mapBrowserEvent)) {
  16641. var map = mapBrowserEvent.map;
  16642. var view = map.getView();
  16643. this.lastCentroid = null;
  16644. if (!this.handlingDownUpSequence) {
  16645. view.setHint(ol.ViewHint.INTERACTING, 1);
  16646. }
  16647. // stop any current animation
  16648. if (view.getHints()[ol.ViewHint.ANIMATING]) {
  16649. view.setCenter(mapBrowserEvent.frameState.viewState.center);
  16650. }
  16651. if (this.kinetic_) {
  16652. this.kinetic_.begin();
  16653. }
  16654. // No kinetic as soon as more than one pointer on the screen is
  16655. // detected. This is to prevent nasty pans after pinch.
  16656. this.noKinetic_ = this.targetPointers.length > 1;
  16657. return true;
  16658. } else {
  16659. return false;
  16660. }
  16661. };
  16662. /**
  16663. * @inheritDoc
  16664. */
  16665. ol.interaction.DragPan.prototype.shouldStopEvent = ol.functions.FALSE;
  16666. goog.provide('ol.interaction.DragRotate');
  16667. goog.require('ol');
  16668. goog.require('ol.RotationConstraint');
  16669. goog.require('ol.ViewHint');
  16670. goog.require('ol.events.condition');
  16671. goog.require('ol.functions');
  16672. goog.require('ol.interaction.Interaction');
  16673. goog.require('ol.interaction.Pointer');
  16674. /**
  16675. * @classdesc
  16676. * Allows the user to rotate the map by clicking and dragging on the map,
  16677. * normally combined with an {@link ol.events.condition} that limits
  16678. * it to when the alt and shift keys are held down.
  16679. *
  16680. * This interaction is only supported for mouse devices.
  16681. *
  16682. * @constructor
  16683. * @extends {ol.interaction.Pointer}
  16684. * @param {olx.interaction.DragRotateOptions=} opt_options Options.
  16685. * @api
  16686. */
  16687. ol.interaction.DragRotate = function(opt_options) {
  16688. var options = opt_options ? opt_options : {};
  16689. ol.interaction.Pointer.call(this, {
  16690. handleDownEvent: ol.interaction.DragRotate.handleDownEvent_,
  16691. handleDragEvent: ol.interaction.DragRotate.handleDragEvent_,
  16692. handleUpEvent: ol.interaction.DragRotate.handleUpEvent_
  16693. });
  16694. /**
  16695. * @private
  16696. * @type {ol.EventsConditionType}
  16697. */
  16698. this.condition_ = options.condition ?
  16699. options.condition : ol.events.condition.altShiftKeysOnly;
  16700. /**
  16701. * @private
  16702. * @type {number|undefined}
  16703. */
  16704. this.lastAngle_ = undefined;
  16705. /**
  16706. * @private
  16707. * @type {number}
  16708. */
  16709. this.duration_ = options.duration !== undefined ? options.duration : 250;
  16710. };
  16711. ol.inherits(ol.interaction.DragRotate, ol.interaction.Pointer);
  16712. /**
  16713. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  16714. * @this {ol.interaction.DragRotate}
  16715. * @private
  16716. */
  16717. ol.interaction.DragRotate.handleDragEvent_ = function(mapBrowserEvent) {
  16718. if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
  16719. return;
  16720. }
  16721. var map = mapBrowserEvent.map;
  16722. var view = map.getView();
  16723. if (view.getConstraints().rotation === ol.RotationConstraint.disable) {
  16724. return;
  16725. }
  16726. var size = map.getSize();
  16727. var offset = mapBrowserEvent.pixel;
  16728. var theta =
  16729. Math.atan2(size[1] / 2 - offset[1], offset[0] - size[0] / 2);
  16730. if (this.lastAngle_ !== undefined) {
  16731. var delta = theta - this.lastAngle_;
  16732. var rotation = view.getRotation();
  16733. ol.interaction.Interaction.rotateWithoutConstraints(
  16734. view, rotation - delta);
  16735. }
  16736. this.lastAngle_ = theta;
  16737. };
  16738. /**
  16739. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  16740. * @return {boolean} Stop drag sequence?
  16741. * @this {ol.interaction.DragRotate}
  16742. * @private
  16743. */
  16744. ol.interaction.DragRotate.handleUpEvent_ = function(mapBrowserEvent) {
  16745. if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
  16746. return true;
  16747. }
  16748. var map = mapBrowserEvent.map;
  16749. var view = map.getView();
  16750. view.setHint(ol.ViewHint.INTERACTING, -1);
  16751. var rotation = view.getRotation();
  16752. ol.interaction.Interaction.rotate(view, rotation,
  16753. undefined, this.duration_);
  16754. return false;
  16755. };
  16756. /**
  16757. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  16758. * @return {boolean} Start drag sequence?
  16759. * @this {ol.interaction.DragRotate}
  16760. * @private
  16761. */
  16762. ol.interaction.DragRotate.handleDownEvent_ = function(mapBrowserEvent) {
  16763. if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
  16764. return false;
  16765. }
  16766. if (ol.events.condition.mouseActionButton(mapBrowserEvent) &&
  16767. this.condition_(mapBrowserEvent)) {
  16768. var map = mapBrowserEvent.map;
  16769. map.getView().setHint(ol.ViewHint.INTERACTING, 1);
  16770. this.lastAngle_ = undefined;
  16771. return true;
  16772. } else {
  16773. return false;
  16774. }
  16775. };
  16776. /**
  16777. * @inheritDoc
  16778. */
  16779. ol.interaction.DragRotate.prototype.shouldStopEvent = ol.functions.FALSE;
  16780. // FIXME add rotation
  16781. goog.provide('ol.render.Box');
  16782. goog.require('ol');
  16783. goog.require('ol.Disposable');
  16784. goog.require('ol.geom.Polygon');
  16785. /**
  16786. * @constructor
  16787. * @extends {ol.Disposable}
  16788. * @param {string} className CSS class name.
  16789. */
  16790. ol.render.Box = function(className) {
  16791. /**
  16792. * @type {ol.geom.Polygon}
  16793. * @private
  16794. */
  16795. this.geometry_ = null;
  16796. /**
  16797. * @type {HTMLDivElement}
  16798. * @private
  16799. */
  16800. this.element_ = /** @type {HTMLDivElement} */ (document.createElement('div'));
  16801. this.element_.style.position = 'absolute';
  16802. this.element_.className = 'ol-box ' + className;
  16803. /**
  16804. * @private
  16805. * @type {ol.Map}
  16806. */
  16807. this.map_ = null;
  16808. /**
  16809. * @private
  16810. * @type {ol.Pixel}
  16811. */
  16812. this.startPixel_ = null;
  16813. /**
  16814. * @private
  16815. * @type {ol.Pixel}
  16816. */
  16817. this.endPixel_ = null;
  16818. };
  16819. ol.inherits(ol.render.Box, ol.Disposable);
  16820. /**
  16821. * @inheritDoc
  16822. */
  16823. ol.render.Box.prototype.disposeInternal = function() {
  16824. this.setMap(null);
  16825. };
  16826. /**
  16827. * @private
  16828. */
  16829. ol.render.Box.prototype.render_ = function() {
  16830. var startPixel = this.startPixel_;
  16831. var endPixel = this.endPixel_;
  16832. var px = 'px';
  16833. var style = this.element_.style;
  16834. style.left = Math.min(startPixel[0], endPixel[0]) + px;
  16835. style.top = Math.min(startPixel[1], endPixel[1]) + px;
  16836. style.width = Math.abs(endPixel[0] - startPixel[0]) + px;
  16837. style.height = Math.abs(endPixel[1] - startPixel[1]) + px;
  16838. };
  16839. /**
  16840. * @param {ol.Map} map Map.
  16841. */
  16842. ol.render.Box.prototype.setMap = function(map) {
  16843. if (this.map_) {
  16844. this.map_.getOverlayContainer().removeChild(this.element_);
  16845. var style = this.element_.style;
  16846. style.left = style.top = style.width = style.height = 'inherit';
  16847. }
  16848. this.map_ = map;
  16849. if (this.map_) {
  16850. this.map_.getOverlayContainer().appendChild(this.element_);
  16851. }
  16852. };
  16853. /**
  16854. * @param {ol.Pixel} startPixel Start pixel.
  16855. * @param {ol.Pixel} endPixel End pixel.
  16856. */
  16857. ol.render.Box.prototype.setPixels = function(startPixel, endPixel) {
  16858. this.startPixel_ = startPixel;
  16859. this.endPixel_ = endPixel;
  16860. this.createOrUpdateGeometry();
  16861. this.render_();
  16862. };
  16863. /**
  16864. * Creates or updates the cached geometry.
  16865. */
  16866. ol.render.Box.prototype.createOrUpdateGeometry = function() {
  16867. var startPixel = this.startPixel_;
  16868. var endPixel = this.endPixel_;
  16869. var pixels = [
  16870. startPixel,
  16871. [startPixel[0], endPixel[1]],
  16872. endPixel,
  16873. [endPixel[0], startPixel[1]]
  16874. ];
  16875. var coordinates = pixels.map(this.map_.getCoordinateFromPixel, this.map_);
  16876. // close the polygon
  16877. coordinates[4] = coordinates[0].slice();
  16878. if (!this.geometry_) {
  16879. this.geometry_ = new ol.geom.Polygon([coordinates]);
  16880. } else {
  16881. this.geometry_.setCoordinates([coordinates]);
  16882. }
  16883. };
  16884. /**
  16885. * @return {ol.geom.Polygon} Geometry.
  16886. */
  16887. ol.render.Box.prototype.getGeometry = function() {
  16888. return this.geometry_;
  16889. };
  16890. // FIXME draw drag box
  16891. goog.provide('ol.interaction.DragBox');
  16892. goog.require('ol.events.Event');
  16893. goog.require('ol');
  16894. goog.require('ol.events.condition');
  16895. goog.require('ol.interaction.Pointer');
  16896. goog.require('ol.render.Box');
  16897. /**
  16898. * @classdesc
  16899. * Allows the user to draw a vector box by clicking and dragging on the map,
  16900. * normally combined with an {@link ol.events.condition} that limits
  16901. * it to when the shift or other key is held down. This is used, for example,
  16902. * for zooming to a specific area of the map
  16903. * (see {@link ol.interaction.DragZoom} and
  16904. * {@link ol.interaction.DragRotateAndZoom}).
  16905. *
  16906. * This interaction is only supported for mouse devices.
  16907. *
  16908. * @constructor
  16909. * @extends {ol.interaction.Pointer}
  16910. * @fires ol.interaction.DragBox.Event
  16911. * @param {olx.interaction.DragBoxOptions=} opt_options Options.
  16912. * @api
  16913. */
  16914. ol.interaction.DragBox = function(opt_options) {
  16915. ol.interaction.Pointer.call(this, {
  16916. handleDownEvent: ol.interaction.DragBox.handleDownEvent_,
  16917. handleDragEvent: ol.interaction.DragBox.handleDragEvent_,
  16918. handleUpEvent: ol.interaction.DragBox.handleUpEvent_
  16919. });
  16920. var options = opt_options ? opt_options : {};
  16921. /**
  16922. * @type {ol.render.Box}
  16923. * @private
  16924. */
  16925. this.box_ = new ol.render.Box(options.className || 'ol-dragbox');
  16926. /**
  16927. * @type {number}
  16928. * @private
  16929. */
  16930. this.minArea_ = options.minArea !== undefined ? options.minArea : 64;
  16931. /**
  16932. * @type {ol.Pixel}
  16933. * @private
  16934. */
  16935. this.startPixel_ = null;
  16936. /**
  16937. * @private
  16938. * @type {ol.EventsConditionType}
  16939. */
  16940. this.condition_ = options.condition ?
  16941. options.condition : ol.events.condition.always;
  16942. /**
  16943. * @private
  16944. * @type {ol.DragBoxEndConditionType}
  16945. */
  16946. this.boxEndCondition_ = options.boxEndCondition ?
  16947. options.boxEndCondition : ol.interaction.DragBox.defaultBoxEndCondition;
  16948. };
  16949. ol.inherits(ol.interaction.DragBox, ol.interaction.Pointer);
  16950. /**
  16951. * The default condition for determining whether the boxend event
  16952. * should fire.
  16953. * @param {ol.MapBrowserEvent} mapBrowserEvent The originating MapBrowserEvent
  16954. * leading to the box end.
  16955. * @param {ol.Pixel} startPixel The starting pixel of the box.
  16956. * @param {ol.Pixel} endPixel The end pixel of the box.
  16957. * @return {boolean} Whether or not the boxend condition should be fired.
  16958. * @this {ol.interaction.DragBox}
  16959. */
  16960. ol.interaction.DragBox.defaultBoxEndCondition = function(mapBrowserEvent, startPixel, endPixel) {
  16961. var width = endPixel[0] - startPixel[0];
  16962. var height = endPixel[1] - startPixel[1];
  16963. return width * width + height * height >= this.minArea_;
  16964. };
  16965. /**
  16966. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  16967. * @this {ol.interaction.DragBox}
  16968. * @private
  16969. */
  16970. ol.interaction.DragBox.handleDragEvent_ = function(mapBrowserEvent) {
  16971. if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
  16972. return;
  16973. }
  16974. this.box_.setPixels(this.startPixel_, mapBrowserEvent.pixel);
  16975. this.dispatchEvent(new ol.interaction.DragBox.Event(ol.interaction.DragBox.EventType_.BOXDRAG,
  16976. mapBrowserEvent.coordinate, mapBrowserEvent));
  16977. };
  16978. /**
  16979. * Returns geometry of last drawn box.
  16980. * @return {ol.geom.Polygon} Geometry.
  16981. * @api
  16982. */
  16983. ol.interaction.DragBox.prototype.getGeometry = function() {
  16984. return this.box_.getGeometry();
  16985. };
  16986. /**
  16987. * To be overridden by child classes.
  16988. * FIXME: use constructor option instead of relying on overriding.
  16989. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  16990. * @protected
  16991. */
  16992. ol.interaction.DragBox.prototype.onBoxEnd = ol.nullFunction;
  16993. /**
  16994. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  16995. * @return {boolean} Stop drag sequence?
  16996. * @this {ol.interaction.DragBox}
  16997. * @private
  16998. */
  16999. ol.interaction.DragBox.handleUpEvent_ = function(mapBrowserEvent) {
  17000. if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
  17001. return true;
  17002. }
  17003. this.box_.setMap(null);
  17004. if (this.boxEndCondition_(mapBrowserEvent,
  17005. this.startPixel_, mapBrowserEvent.pixel)) {
  17006. this.onBoxEnd(mapBrowserEvent);
  17007. this.dispatchEvent(new ol.interaction.DragBox.Event(ol.interaction.DragBox.EventType_.BOXEND,
  17008. mapBrowserEvent.coordinate, mapBrowserEvent));
  17009. }
  17010. return false;
  17011. };
  17012. /**
  17013. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  17014. * @return {boolean} Start drag sequence?
  17015. * @this {ol.interaction.DragBox}
  17016. * @private
  17017. */
  17018. ol.interaction.DragBox.handleDownEvent_ = function(mapBrowserEvent) {
  17019. if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
  17020. return false;
  17021. }
  17022. if (ol.events.condition.mouseActionButton(mapBrowserEvent) &&
  17023. this.condition_(mapBrowserEvent)) {
  17024. this.startPixel_ = mapBrowserEvent.pixel;
  17025. this.box_.setMap(mapBrowserEvent.map);
  17026. this.box_.setPixels(this.startPixel_, this.startPixel_);
  17027. this.dispatchEvent(new ol.interaction.DragBox.Event(ol.interaction.DragBox.EventType_.BOXSTART,
  17028. mapBrowserEvent.coordinate, mapBrowserEvent));
  17029. return true;
  17030. } else {
  17031. return false;
  17032. }
  17033. };
  17034. /**
  17035. * @enum {string}
  17036. * @private
  17037. */
  17038. ol.interaction.DragBox.EventType_ = {
  17039. /**
  17040. * Triggered upon drag box start.
  17041. * @event ol.interaction.DragBox.Event#boxstart
  17042. * @api
  17043. */
  17044. BOXSTART: 'boxstart',
  17045. /**
  17046. * Triggered on drag when box is active.
  17047. * @event ol.interaction.DragBox.Event#boxdrag
  17048. * @api
  17049. */
  17050. BOXDRAG: 'boxdrag',
  17051. /**
  17052. * Triggered upon drag box end.
  17053. * @event ol.interaction.DragBox.Event#boxend
  17054. * @api
  17055. */
  17056. BOXEND: 'boxend'
  17057. };
  17058. /**
  17059. * @classdesc
  17060. * Events emitted by {@link ol.interaction.DragBox} instances are instances of
  17061. * this type.
  17062. *
  17063. * @param {string} type The event type.
  17064. * @param {ol.Coordinate} coordinate The event coordinate.
  17065. * @param {ol.MapBrowserEvent} mapBrowserEvent Originating event.
  17066. * @extends {ol.events.Event}
  17067. * @constructor
  17068. * @implements {oli.DragBoxEvent}
  17069. */
  17070. ol.interaction.DragBox.Event = function(type, coordinate, mapBrowserEvent) {
  17071. ol.events.Event.call(this, type);
  17072. /**
  17073. * The coordinate of the drag event.
  17074. * @const
  17075. * @type {ol.Coordinate}
  17076. * @api
  17077. */
  17078. this.coordinate = coordinate;
  17079. /**
  17080. * @const
  17081. * @type {ol.MapBrowserEvent}
  17082. * @api
  17083. */
  17084. this.mapBrowserEvent = mapBrowserEvent;
  17085. };
  17086. ol.inherits(ol.interaction.DragBox.Event, ol.events.Event);
  17087. goog.provide('ol.interaction.DragZoom');
  17088. goog.require('ol');
  17089. goog.require('ol.easing');
  17090. goog.require('ol.events.condition');
  17091. goog.require('ol.extent');
  17092. goog.require('ol.interaction.DragBox');
  17093. /**
  17094. * @classdesc
  17095. * Allows the user to zoom the map by clicking and dragging on the map,
  17096. * normally combined with an {@link ol.events.condition} that limits
  17097. * it to when a key, shift by default, is held down.
  17098. *
  17099. * To change the style of the box, use CSS and the `.ol-dragzoom` selector, or
  17100. * your custom one configured with `className`.
  17101. *
  17102. * @constructor
  17103. * @extends {ol.interaction.DragBox}
  17104. * @param {olx.interaction.DragZoomOptions=} opt_options Options.
  17105. * @api
  17106. */
  17107. ol.interaction.DragZoom = function(opt_options) {
  17108. var options = opt_options ? opt_options : {};
  17109. var condition = options.condition ?
  17110. options.condition : ol.events.condition.shiftKeyOnly;
  17111. /**
  17112. * @private
  17113. * @type {number}
  17114. */
  17115. this.duration_ = options.duration !== undefined ? options.duration : 200;
  17116. /**
  17117. * @private
  17118. * @type {boolean}
  17119. */
  17120. this.out_ = options.out !== undefined ? options.out : false;
  17121. ol.interaction.DragBox.call(this, {
  17122. condition: condition,
  17123. className: options.className || 'ol-dragzoom'
  17124. });
  17125. };
  17126. ol.inherits(ol.interaction.DragZoom, ol.interaction.DragBox);
  17127. /**
  17128. * @inheritDoc
  17129. */
  17130. ol.interaction.DragZoom.prototype.onBoxEnd = function() {
  17131. var map = this.getMap();
  17132. var view = /** @type {!ol.View} */ (map.getView());
  17133. var size = /** @type {!ol.Size} */ (map.getSize());
  17134. var extent = this.getGeometry().getExtent();
  17135. if (this.out_) {
  17136. var mapExtent = view.calculateExtent(size);
  17137. var boxPixelExtent = ol.extent.createOrUpdateFromCoordinates([
  17138. map.getPixelFromCoordinate(ol.extent.getBottomLeft(extent)),
  17139. map.getPixelFromCoordinate(ol.extent.getTopRight(extent))]);
  17140. var factor = view.getResolutionForExtent(boxPixelExtent, size);
  17141. ol.extent.scaleFromCenter(mapExtent, 1 / factor);
  17142. extent = mapExtent;
  17143. }
  17144. var resolution = view.constrainResolution(
  17145. view.getResolutionForExtent(extent, size));
  17146. var center = ol.extent.getCenter(extent);
  17147. center = view.constrainCenter(center);
  17148. view.animate({
  17149. resolution: resolution,
  17150. center: center,
  17151. duration: this.duration_,
  17152. easing: ol.easing.easeOut
  17153. });
  17154. };
  17155. goog.provide('ol.events.KeyCode');
  17156. /**
  17157. * @enum {number}
  17158. * @const
  17159. */
  17160. ol.events.KeyCode = {
  17161. LEFT: 37,
  17162. UP: 38,
  17163. RIGHT: 39,
  17164. DOWN: 40
  17165. };
  17166. goog.provide('ol.interaction.KeyboardPan');
  17167. goog.require('ol');
  17168. goog.require('ol.coordinate');
  17169. goog.require('ol.events.EventType');
  17170. goog.require('ol.events.KeyCode');
  17171. goog.require('ol.events.condition');
  17172. goog.require('ol.interaction.Interaction');
  17173. /**
  17174. * @classdesc
  17175. * Allows the user to pan the map using keyboard arrows.
  17176. * Note that, although this interaction is by default included in maps,
  17177. * the keys can only be used when browser focus is on the element to which
  17178. * the keyboard events are attached. By default, this is the map div,
  17179. * though you can change this with the `keyboardEventTarget` in
  17180. * {@link ol.Map}. `document` never loses focus but, for any other element,
  17181. * focus will have to be on, and returned to, this element if the keys are to
  17182. * function.
  17183. * See also {@link ol.interaction.KeyboardZoom}.
  17184. *
  17185. * @constructor
  17186. * @extends {ol.interaction.Interaction}
  17187. * @param {olx.interaction.KeyboardPanOptions=} opt_options Options.
  17188. * @api
  17189. */
  17190. ol.interaction.KeyboardPan = function(opt_options) {
  17191. ol.interaction.Interaction.call(this, {
  17192. handleEvent: ol.interaction.KeyboardPan.handleEvent
  17193. });
  17194. var options = opt_options || {};
  17195. /**
  17196. * @private
  17197. * @param {ol.MapBrowserEvent} mapBrowserEvent Browser event.
  17198. * @return {boolean} Combined condition result.
  17199. */
  17200. this.defaultCondition_ = function(mapBrowserEvent) {
  17201. return ol.events.condition.noModifierKeys(mapBrowserEvent) &&
  17202. ol.events.condition.targetNotEditable(mapBrowserEvent);
  17203. };
  17204. /**
  17205. * @private
  17206. * @type {ol.EventsConditionType}
  17207. */
  17208. this.condition_ = options.condition !== undefined ?
  17209. options.condition : this.defaultCondition_;
  17210. /**
  17211. * @private
  17212. * @type {number}
  17213. */
  17214. this.duration_ = options.duration !== undefined ? options.duration : 100;
  17215. /**
  17216. * @private
  17217. * @type {number}
  17218. */
  17219. this.pixelDelta_ = options.pixelDelta !== undefined ?
  17220. options.pixelDelta : 128;
  17221. };
  17222. ol.inherits(ol.interaction.KeyboardPan, ol.interaction.Interaction);
  17223. /**
  17224. * Handles the {@link ol.MapBrowserEvent map browser event} if it was a
  17225. * `KeyEvent`, and decides the direction to pan to (if an arrow key was
  17226. * pressed).
  17227. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  17228. * @return {boolean} `false` to stop event propagation.
  17229. * @this {ol.interaction.KeyboardPan}
  17230. * @api
  17231. */
  17232. ol.interaction.KeyboardPan.handleEvent = function(mapBrowserEvent) {
  17233. var stopEvent = false;
  17234. if (mapBrowserEvent.type == ol.events.EventType.KEYDOWN) {
  17235. var keyEvent = mapBrowserEvent.originalEvent;
  17236. var keyCode = keyEvent.keyCode;
  17237. if (this.condition_(mapBrowserEvent) &&
  17238. (keyCode == ol.events.KeyCode.DOWN ||
  17239. keyCode == ol.events.KeyCode.LEFT ||
  17240. keyCode == ol.events.KeyCode.RIGHT ||
  17241. keyCode == ol.events.KeyCode.UP)) {
  17242. var map = mapBrowserEvent.map;
  17243. var view = map.getView();
  17244. var mapUnitsDelta = view.getResolution() * this.pixelDelta_;
  17245. var deltaX = 0, deltaY = 0;
  17246. if (keyCode == ol.events.KeyCode.DOWN) {
  17247. deltaY = -mapUnitsDelta;
  17248. } else if (keyCode == ol.events.KeyCode.LEFT) {
  17249. deltaX = -mapUnitsDelta;
  17250. } else if (keyCode == ol.events.KeyCode.RIGHT) {
  17251. deltaX = mapUnitsDelta;
  17252. } else {
  17253. deltaY = mapUnitsDelta;
  17254. }
  17255. var delta = [deltaX, deltaY];
  17256. ol.coordinate.rotate(delta, view.getRotation());
  17257. ol.interaction.Interaction.pan(view, delta, this.duration_);
  17258. mapBrowserEvent.preventDefault();
  17259. stopEvent = true;
  17260. }
  17261. }
  17262. return !stopEvent;
  17263. };
  17264. goog.provide('ol.interaction.KeyboardZoom');
  17265. goog.require('ol');
  17266. goog.require('ol.events.EventType');
  17267. goog.require('ol.events.condition');
  17268. goog.require('ol.interaction.Interaction');
  17269. /**
  17270. * @classdesc
  17271. * Allows the user to zoom the map using keyboard + and -.
  17272. * Note that, although this interaction is by default included in maps,
  17273. * the keys can only be used when browser focus is on the element to which
  17274. * the keyboard events are attached. By default, this is the map div,
  17275. * though you can change this with the `keyboardEventTarget` in
  17276. * {@link ol.Map}. `document` never loses focus but, for any other element,
  17277. * focus will have to be on, and returned to, this element if the keys are to
  17278. * function.
  17279. * See also {@link ol.interaction.KeyboardPan}.
  17280. *
  17281. * @constructor
  17282. * @param {olx.interaction.KeyboardZoomOptions=} opt_options Options.
  17283. * @extends {ol.interaction.Interaction}
  17284. * @api
  17285. */
  17286. ol.interaction.KeyboardZoom = function(opt_options) {
  17287. ol.interaction.Interaction.call(this, {
  17288. handleEvent: ol.interaction.KeyboardZoom.handleEvent
  17289. });
  17290. var options = opt_options ? opt_options : {};
  17291. /**
  17292. * @private
  17293. * @type {ol.EventsConditionType}
  17294. */
  17295. this.condition_ = options.condition ? options.condition :
  17296. ol.events.condition.targetNotEditable;
  17297. /**
  17298. * @private
  17299. * @type {number}
  17300. */
  17301. this.delta_ = options.delta ? options.delta : 1;
  17302. /**
  17303. * @private
  17304. * @type {number}
  17305. */
  17306. this.duration_ = options.duration !== undefined ? options.duration : 100;
  17307. };
  17308. ol.inherits(ol.interaction.KeyboardZoom, ol.interaction.Interaction);
  17309. /**
  17310. * Handles the {@link ol.MapBrowserEvent map browser event} if it was a
  17311. * `KeyEvent`, and decides whether to zoom in or out (depending on whether the
  17312. * key pressed was '+' or '-').
  17313. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  17314. * @return {boolean} `false` to stop event propagation.
  17315. * @this {ol.interaction.KeyboardZoom}
  17316. * @api
  17317. */
  17318. ol.interaction.KeyboardZoom.handleEvent = function(mapBrowserEvent) {
  17319. var stopEvent = false;
  17320. if (mapBrowserEvent.type == ol.events.EventType.KEYDOWN ||
  17321. mapBrowserEvent.type == ol.events.EventType.KEYPRESS) {
  17322. var keyEvent = mapBrowserEvent.originalEvent;
  17323. var charCode = keyEvent.charCode;
  17324. if (this.condition_(mapBrowserEvent) &&
  17325. (charCode == '+'.charCodeAt(0) || charCode == '-'.charCodeAt(0))) {
  17326. var map = mapBrowserEvent.map;
  17327. var delta = (charCode == '+'.charCodeAt(0)) ? this.delta_ : -this.delta_;
  17328. var view = map.getView();
  17329. ol.interaction.Interaction.zoomByDelta(
  17330. view, delta, undefined, this.duration_);
  17331. mapBrowserEvent.preventDefault();
  17332. stopEvent = true;
  17333. }
  17334. }
  17335. return !stopEvent;
  17336. };
  17337. goog.provide('ol.interaction.MouseWheelZoom');
  17338. goog.require('ol');
  17339. goog.require('ol.ViewHint');
  17340. goog.require('ol.easing');
  17341. goog.require('ol.events.EventType');
  17342. goog.require('ol.has');
  17343. goog.require('ol.interaction.Interaction');
  17344. goog.require('ol.math');
  17345. /**
  17346. * @classdesc
  17347. * Allows the user to zoom the map by scrolling the mouse wheel.
  17348. *
  17349. * @constructor
  17350. * @extends {ol.interaction.Interaction}
  17351. * @param {olx.interaction.MouseWheelZoomOptions=} opt_options Options.
  17352. * @api
  17353. */
  17354. ol.interaction.MouseWheelZoom = function(opt_options) {
  17355. ol.interaction.Interaction.call(this, {
  17356. handleEvent: ol.interaction.MouseWheelZoom.handleEvent
  17357. });
  17358. var options = opt_options || {};
  17359. /**
  17360. * @private
  17361. * @type {number}
  17362. */
  17363. this.delta_ = 0;
  17364. /**
  17365. * @private
  17366. * @type {number}
  17367. */
  17368. this.duration_ = options.duration !== undefined ? options.duration : 250;
  17369. /**
  17370. * @private
  17371. * @type {number}
  17372. */
  17373. this.timeout_ = options.timeout !== undefined ? options.timeout : 80;
  17374. /**
  17375. * @private
  17376. * @type {boolean}
  17377. */
  17378. this.useAnchor_ = options.useAnchor !== undefined ? options.useAnchor : true;
  17379. /**
  17380. * @private
  17381. * @type {boolean}
  17382. */
  17383. this.constrainResolution_ = options.constrainResolution || false;
  17384. /**
  17385. * @private
  17386. * @type {?ol.Coordinate}
  17387. */
  17388. this.lastAnchor_ = null;
  17389. /**
  17390. * @private
  17391. * @type {number|undefined}
  17392. */
  17393. this.startTime_ = undefined;
  17394. /**
  17395. * @private
  17396. * @type {number|undefined}
  17397. */
  17398. this.timeoutId_ = undefined;
  17399. /**
  17400. * @private
  17401. * @type {ol.interaction.MouseWheelZoom.Mode_|undefined}
  17402. */
  17403. this.mode_ = undefined;
  17404. /**
  17405. * Trackpad events separated by this delay will be considered separate
  17406. * interactions.
  17407. * @type {number}
  17408. */
  17409. this.trackpadEventGap_ = 400;
  17410. /**
  17411. * @type {number|undefined}
  17412. */
  17413. this.trackpadTimeoutId_ = undefined;
  17414. /**
  17415. * The number of delta values per zoom level
  17416. * @private
  17417. * @type {number}
  17418. */
  17419. this.trackpadDeltaPerZoom_ = 300;
  17420. /**
  17421. * The zoom factor by which scroll zooming is allowed to exceed the limits.
  17422. * @private
  17423. * @type {number}
  17424. */
  17425. this.trackpadZoomBuffer_ = 1.5;
  17426. };
  17427. ol.inherits(ol.interaction.MouseWheelZoom, ol.interaction.Interaction);
  17428. /**
  17429. * Handles the {@link ol.MapBrowserEvent map browser event} (if it was a
  17430. * mousewheel-event) and eventually zooms the map.
  17431. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  17432. * @return {boolean} Allow event propagation.
  17433. * @this {ol.interaction.MouseWheelZoom}
  17434. * @api
  17435. */
  17436. ol.interaction.MouseWheelZoom.handleEvent = function(mapBrowserEvent) {
  17437. var type = mapBrowserEvent.type;
  17438. if (type !== ol.events.EventType.WHEEL && type !== ol.events.EventType.MOUSEWHEEL) {
  17439. return true;
  17440. }
  17441. mapBrowserEvent.preventDefault();
  17442. var map = mapBrowserEvent.map;
  17443. var wheelEvent = /** @type {WheelEvent} */ (mapBrowserEvent.originalEvent);
  17444. if (this.useAnchor_) {
  17445. this.lastAnchor_ = mapBrowserEvent.coordinate;
  17446. }
  17447. // Delta normalisation inspired by
  17448. // https://github.com/mapbox/mapbox-gl-js/blob/001c7b9/js/ui/handler/scroll_zoom.js
  17449. var delta;
  17450. if (mapBrowserEvent.type == ol.events.EventType.WHEEL) {
  17451. delta = wheelEvent.deltaY;
  17452. if (ol.has.FIREFOX &&
  17453. wheelEvent.deltaMode === WheelEvent.DOM_DELTA_PIXEL) {
  17454. delta /= ol.has.DEVICE_PIXEL_RATIO;
  17455. }
  17456. if (wheelEvent.deltaMode === WheelEvent.DOM_DELTA_LINE) {
  17457. delta *= 40;
  17458. }
  17459. } else if (mapBrowserEvent.type == ol.events.EventType.MOUSEWHEEL) {
  17460. delta = -wheelEvent.wheelDeltaY;
  17461. if (ol.has.SAFARI) {
  17462. delta /= 3;
  17463. }
  17464. }
  17465. if (delta === 0) {
  17466. return false;
  17467. }
  17468. var now = Date.now();
  17469. if (this.startTime_ === undefined) {
  17470. this.startTime_ = now;
  17471. }
  17472. if (!this.mode_ || now - this.startTime_ > this.trackpadEventGap_) {
  17473. this.mode_ = Math.abs(delta) < 4 ?
  17474. ol.interaction.MouseWheelZoom.Mode_.TRACKPAD :
  17475. ol.interaction.MouseWheelZoom.Mode_.WHEEL;
  17476. }
  17477. if (this.mode_ === ol.interaction.MouseWheelZoom.Mode_.TRACKPAD) {
  17478. var view = map.getView();
  17479. if (this.trackpadTimeoutId_) {
  17480. clearTimeout(this.trackpadTimeoutId_);
  17481. } else {
  17482. view.setHint(ol.ViewHint.INTERACTING, 1);
  17483. }
  17484. this.trackpadTimeoutId_ = setTimeout(this.decrementInteractingHint_.bind(this), this.trackpadEventGap_);
  17485. var resolution = view.getResolution() * Math.pow(2, delta / this.trackpadDeltaPerZoom_);
  17486. var minResolution = view.getMinResolution();
  17487. var maxResolution = view.getMaxResolution();
  17488. var rebound = 0;
  17489. if (resolution < minResolution) {
  17490. resolution = Math.max(resolution, minResolution / this.trackpadZoomBuffer_);
  17491. rebound = 1;
  17492. } else if (resolution > maxResolution) {
  17493. resolution = Math.min(resolution, maxResolution * this.trackpadZoomBuffer_);
  17494. rebound = -1;
  17495. }
  17496. if (this.lastAnchor_) {
  17497. var center = view.calculateCenterZoom(resolution, this.lastAnchor_);
  17498. view.setCenter(view.constrainCenter(center));
  17499. }
  17500. view.setResolution(resolution);
  17501. if (rebound === 0 && this.constrainResolution_) {
  17502. view.animate({
  17503. resolution: view.constrainResolution(resolution, delta > 0 ? -1 : 1),
  17504. easing: ol.easing.easeOut,
  17505. anchor: this.lastAnchor_,
  17506. duration: this.duration_
  17507. });
  17508. }
  17509. if (rebound > 0) {
  17510. view.animate({
  17511. resolution: minResolution,
  17512. easing: ol.easing.easeOut,
  17513. anchor: this.lastAnchor_,
  17514. duration: 500
  17515. });
  17516. } else if (rebound < 0) {
  17517. view.animate({
  17518. resolution: maxResolution,
  17519. easing: ol.easing.easeOut,
  17520. anchor: this.lastAnchor_,
  17521. duration: 500
  17522. });
  17523. }
  17524. this.startTime_ = now;
  17525. return false;
  17526. }
  17527. this.delta_ += delta;
  17528. var timeLeft = Math.max(this.timeout_ - (now - this.startTime_), 0);
  17529. clearTimeout(this.timeoutId_);
  17530. this.timeoutId_ = setTimeout(this.handleWheelZoom_.bind(this, map), timeLeft);
  17531. return false;
  17532. };
  17533. /**
  17534. * @private
  17535. */
  17536. ol.interaction.MouseWheelZoom.prototype.decrementInteractingHint_ = function() {
  17537. this.trackpadTimeoutId_ = undefined;
  17538. var view = this.getMap().getView();
  17539. view.setHint(ol.ViewHint.INTERACTING, -1);
  17540. };
  17541. /**
  17542. * @private
  17543. * @param {ol.Map} map Map.
  17544. */
  17545. ol.interaction.MouseWheelZoom.prototype.handleWheelZoom_ = function(map) {
  17546. var view = map.getView();
  17547. if (view.getAnimating()) {
  17548. view.cancelAnimations();
  17549. }
  17550. var maxDelta = ol.MOUSEWHEELZOOM_MAXDELTA;
  17551. var delta = ol.math.clamp(this.delta_, -maxDelta, maxDelta);
  17552. ol.interaction.Interaction.zoomByDelta(view, -delta, this.lastAnchor_,
  17553. this.duration_);
  17554. this.mode_ = undefined;
  17555. this.delta_ = 0;
  17556. this.lastAnchor_ = null;
  17557. this.startTime_ = undefined;
  17558. this.timeoutId_ = undefined;
  17559. };
  17560. /**
  17561. * Enable or disable using the mouse's location as an anchor when zooming
  17562. * @param {boolean} useAnchor true to zoom to the mouse's location, false
  17563. * to zoom to the center of the map
  17564. * @api
  17565. */
  17566. ol.interaction.MouseWheelZoom.prototype.setMouseAnchor = function(useAnchor) {
  17567. this.useAnchor_ = useAnchor;
  17568. if (!useAnchor) {
  17569. this.lastAnchor_ = null;
  17570. }
  17571. };
  17572. /**
  17573. * @enum {string}
  17574. * @private
  17575. */
  17576. ol.interaction.MouseWheelZoom.Mode_ = {
  17577. TRACKPAD: 'trackpad',
  17578. WHEEL: 'wheel'
  17579. };
  17580. goog.provide('ol.interaction.PinchRotate');
  17581. goog.require('ol');
  17582. goog.require('ol.ViewHint');
  17583. goog.require('ol.functions');
  17584. goog.require('ol.interaction.Interaction');
  17585. goog.require('ol.interaction.Pointer');
  17586. goog.require('ol.RotationConstraint');
  17587. /**
  17588. * @classdesc
  17589. * Allows the user to rotate the map by twisting with two fingers
  17590. * on a touch screen.
  17591. *
  17592. * @constructor
  17593. * @extends {ol.interaction.Pointer}
  17594. * @param {olx.interaction.PinchRotateOptions=} opt_options Options.
  17595. * @api
  17596. */
  17597. ol.interaction.PinchRotate = function(opt_options) {
  17598. ol.interaction.Pointer.call(this, {
  17599. handleDownEvent: ol.interaction.PinchRotate.handleDownEvent_,
  17600. handleDragEvent: ol.interaction.PinchRotate.handleDragEvent_,
  17601. handleUpEvent: ol.interaction.PinchRotate.handleUpEvent_
  17602. });
  17603. var options = opt_options || {};
  17604. /**
  17605. * @private
  17606. * @type {ol.Coordinate}
  17607. */
  17608. this.anchor_ = null;
  17609. /**
  17610. * @private
  17611. * @type {number|undefined}
  17612. */
  17613. this.lastAngle_ = undefined;
  17614. /**
  17615. * @private
  17616. * @type {boolean}
  17617. */
  17618. this.rotating_ = false;
  17619. /**
  17620. * @private
  17621. * @type {number}
  17622. */
  17623. this.rotationDelta_ = 0.0;
  17624. /**
  17625. * @private
  17626. * @type {number}
  17627. */
  17628. this.threshold_ = options.threshold !== undefined ? options.threshold : 0.3;
  17629. /**
  17630. * @private
  17631. * @type {number}
  17632. */
  17633. this.duration_ = options.duration !== undefined ? options.duration : 250;
  17634. };
  17635. ol.inherits(ol.interaction.PinchRotate, ol.interaction.Pointer);
  17636. /**
  17637. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  17638. * @this {ol.interaction.PinchRotate}
  17639. * @private
  17640. */
  17641. ol.interaction.PinchRotate.handleDragEvent_ = function(mapBrowserEvent) {
  17642. var rotationDelta = 0.0;
  17643. var touch0 = this.targetPointers[0];
  17644. var touch1 = this.targetPointers[1];
  17645. // angle between touches
  17646. var angle = Math.atan2(
  17647. touch1.clientY - touch0.clientY,
  17648. touch1.clientX - touch0.clientX);
  17649. if (this.lastAngle_ !== undefined) {
  17650. var delta = angle - this.lastAngle_;
  17651. this.rotationDelta_ += delta;
  17652. if (!this.rotating_ &&
  17653. Math.abs(this.rotationDelta_) > this.threshold_) {
  17654. this.rotating_ = true;
  17655. }
  17656. rotationDelta = delta;
  17657. }
  17658. this.lastAngle_ = angle;
  17659. var map = mapBrowserEvent.map;
  17660. var view = map.getView();
  17661. if (view.getConstraints().rotation === ol.RotationConstraint.disable) {
  17662. return;
  17663. }
  17664. // rotate anchor point.
  17665. // FIXME: should be the intersection point between the lines:
  17666. // touch0,touch1 and previousTouch0,previousTouch1
  17667. var viewportPosition = map.getViewport().getBoundingClientRect();
  17668. var centroid = ol.interaction.Pointer.centroid(this.targetPointers);
  17669. centroid[0] -= viewportPosition.left;
  17670. centroid[1] -= viewportPosition.top;
  17671. this.anchor_ = map.getCoordinateFromPixel(centroid);
  17672. // rotate
  17673. if (this.rotating_) {
  17674. var rotation = view.getRotation();
  17675. map.render();
  17676. ol.interaction.Interaction.rotateWithoutConstraints(view,
  17677. rotation + rotationDelta, this.anchor_);
  17678. }
  17679. };
  17680. /**
  17681. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  17682. * @return {boolean} Stop drag sequence?
  17683. * @this {ol.interaction.PinchRotate}
  17684. * @private
  17685. */
  17686. ol.interaction.PinchRotate.handleUpEvent_ = function(mapBrowserEvent) {
  17687. if (this.targetPointers.length < 2) {
  17688. var map = mapBrowserEvent.map;
  17689. var view = map.getView();
  17690. view.setHint(ol.ViewHint.INTERACTING, -1);
  17691. if (this.rotating_) {
  17692. var rotation = view.getRotation();
  17693. ol.interaction.Interaction.rotate(
  17694. view, rotation, this.anchor_, this.duration_);
  17695. }
  17696. return false;
  17697. } else {
  17698. return true;
  17699. }
  17700. };
  17701. /**
  17702. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  17703. * @return {boolean} Start drag sequence?
  17704. * @this {ol.interaction.PinchRotate}
  17705. * @private
  17706. */
  17707. ol.interaction.PinchRotate.handleDownEvent_ = function(mapBrowserEvent) {
  17708. if (this.targetPointers.length >= 2) {
  17709. var map = mapBrowserEvent.map;
  17710. this.anchor_ = null;
  17711. this.lastAngle_ = undefined;
  17712. this.rotating_ = false;
  17713. this.rotationDelta_ = 0.0;
  17714. if (!this.handlingDownUpSequence) {
  17715. map.getView().setHint(ol.ViewHint.INTERACTING, 1);
  17716. }
  17717. return true;
  17718. } else {
  17719. return false;
  17720. }
  17721. };
  17722. /**
  17723. * @inheritDoc
  17724. */
  17725. ol.interaction.PinchRotate.prototype.shouldStopEvent = ol.functions.FALSE;
  17726. goog.provide('ol.interaction.PinchZoom');
  17727. goog.require('ol');
  17728. goog.require('ol.ViewHint');
  17729. goog.require('ol.functions');
  17730. goog.require('ol.interaction.Interaction');
  17731. goog.require('ol.interaction.Pointer');
  17732. /**
  17733. * @classdesc
  17734. * Allows the user to zoom the map by pinching with two fingers
  17735. * on a touch screen.
  17736. *
  17737. * @constructor
  17738. * @extends {ol.interaction.Pointer}
  17739. * @param {olx.interaction.PinchZoomOptions=} opt_options Options.
  17740. * @api
  17741. */
  17742. ol.interaction.PinchZoom = function(opt_options) {
  17743. ol.interaction.Pointer.call(this, {
  17744. handleDownEvent: ol.interaction.PinchZoom.handleDownEvent_,
  17745. handleDragEvent: ol.interaction.PinchZoom.handleDragEvent_,
  17746. handleUpEvent: ol.interaction.PinchZoom.handleUpEvent_
  17747. });
  17748. var options = opt_options ? opt_options : {};
  17749. /**
  17750. * @private
  17751. * @type {boolean}
  17752. */
  17753. this.constrainResolution_ = options.constrainResolution || false;
  17754. /**
  17755. * @private
  17756. * @type {ol.Coordinate}
  17757. */
  17758. this.anchor_ = null;
  17759. /**
  17760. * @private
  17761. * @type {number}
  17762. */
  17763. this.duration_ = options.duration !== undefined ? options.duration : 400;
  17764. /**
  17765. * @private
  17766. * @type {number|undefined}
  17767. */
  17768. this.lastDistance_ = undefined;
  17769. /**
  17770. * @private
  17771. * @type {number}
  17772. */
  17773. this.lastScaleDelta_ = 1;
  17774. };
  17775. ol.inherits(ol.interaction.PinchZoom, ol.interaction.Pointer);
  17776. /**
  17777. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  17778. * @this {ol.interaction.PinchZoom}
  17779. * @private
  17780. */
  17781. ol.interaction.PinchZoom.handleDragEvent_ = function(mapBrowserEvent) {
  17782. var scaleDelta = 1.0;
  17783. var touch0 = this.targetPointers[0];
  17784. var touch1 = this.targetPointers[1];
  17785. var dx = touch0.clientX - touch1.clientX;
  17786. var dy = touch0.clientY - touch1.clientY;
  17787. // distance between touches
  17788. var distance = Math.sqrt(dx * dx + dy * dy);
  17789. if (this.lastDistance_ !== undefined) {
  17790. scaleDelta = this.lastDistance_ / distance;
  17791. }
  17792. this.lastDistance_ = distance;
  17793. var map = mapBrowserEvent.map;
  17794. var view = map.getView();
  17795. var resolution = view.getResolution();
  17796. var maxResolution = view.getMaxResolution();
  17797. var minResolution = view.getMinResolution();
  17798. var newResolution = resolution * scaleDelta;
  17799. if (newResolution > maxResolution) {
  17800. scaleDelta = maxResolution / resolution;
  17801. newResolution = maxResolution;
  17802. } else if (newResolution < minResolution) {
  17803. scaleDelta = minResolution / resolution;
  17804. newResolution = minResolution;
  17805. }
  17806. if (scaleDelta != 1.0) {
  17807. this.lastScaleDelta_ = scaleDelta;
  17808. }
  17809. // scale anchor point.
  17810. var viewportPosition = map.getViewport().getBoundingClientRect();
  17811. var centroid = ol.interaction.Pointer.centroid(this.targetPointers);
  17812. centroid[0] -= viewportPosition.left;
  17813. centroid[1] -= viewportPosition.top;
  17814. this.anchor_ = map.getCoordinateFromPixel(centroid);
  17815. // scale, bypass the resolution constraint
  17816. map.render();
  17817. ol.interaction.Interaction.zoomWithoutConstraints(view, newResolution, this.anchor_);
  17818. };
  17819. /**
  17820. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  17821. * @return {boolean} Stop drag sequence?
  17822. * @this {ol.interaction.PinchZoom}
  17823. * @private
  17824. */
  17825. ol.interaction.PinchZoom.handleUpEvent_ = function(mapBrowserEvent) {
  17826. if (this.targetPointers.length < 2) {
  17827. var map = mapBrowserEvent.map;
  17828. var view = map.getView();
  17829. view.setHint(ol.ViewHint.INTERACTING, -1);
  17830. var resolution = view.getResolution();
  17831. if (this.constrainResolution_ ||
  17832. resolution < view.getMinResolution() ||
  17833. resolution > view.getMaxResolution()) {
  17834. // Zoom to final resolution, with an animation, and provide a
  17835. // direction not to zoom out/in if user was pinching in/out.
  17836. // Direction is > 0 if pinching out, and < 0 if pinching in.
  17837. var direction = this.lastScaleDelta_ - 1;
  17838. ol.interaction.Interaction.zoom(view, resolution,
  17839. this.anchor_, this.duration_, direction);
  17840. }
  17841. return false;
  17842. } else {
  17843. return true;
  17844. }
  17845. };
  17846. /**
  17847. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  17848. * @return {boolean} Start drag sequence?
  17849. * @this {ol.interaction.PinchZoom}
  17850. * @private
  17851. */
  17852. ol.interaction.PinchZoom.handleDownEvent_ = function(mapBrowserEvent) {
  17853. if (this.targetPointers.length >= 2) {
  17854. var map = mapBrowserEvent.map;
  17855. this.anchor_ = null;
  17856. this.lastDistance_ = undefined;
  17857. this.lastScaleDelta_ = 1;
  17858. if (!this.handlingDownUpSequence) {
  17859. map.getView().setHint(ol.ViewHint.INTERACTING, 1);
  17860. }
  17861. return true;
  17862. } else {
  17863. return false;
  17864. }
  17865. };
  17866. /**
  17867. * @inheritDoc
  17868. */
  17869. ol.interaction.PinchZoom.prototype.shouldStopEvent = ol.functions.FALSE;
  17870. goog.provide('ol.interaction');
  17871. goog.require('ol.Collection');
  17872. goog.require('ol.Kinetic');
  17873. goog.require('ol.interaction.DoubleClickZoom');
  17874. goog.require('ol.interaction.DragPan');
  17875. goog.require('ol.interaction.DragRotate');
  17876. goog.require('ol.interaction.DragZoom');
  17877. goog.require('ol.interaction.KeyboardPan');
  17878. goog.require('ol.interaction.KeyboardZoom');
  17879. goog.require('ol.interaction.MouseWheelZoom');
  17880. goog.require('ol.interaction.PinchRotate');
  17881. goog.require('ol.interaction.PinchZoom');
  17882. /**
  17883. * Set of interactions included in maps by default. Specific interactions can be
  17884. * excluded by setting the appropriate option to false in the constructor
  17885. * options, but the order of the interactions is fixed. If you want to specify
  17886. * a different order for interactions, you will need to create your own
  17887. * {@link ol.interaction.Interaction} instances and insert them into a
  17888. * {@link ol.Collection} in the order you want before creating your
  17889. * {@link ol.Map} instance. The default set of interactions, in sequence, is:
  17890. * * {@link ol.interaction.DragRotate}
  17891. * * {@link ol.interaction.DoubleClickZoom}
  17892. * * {@link ol.interaction.DragPan}
  17893. * * {@link ol.interaction.PinchRotate}
  17894. * * {@link ol.interaction.PinchZoom}
  17895. * * {@link ol.interaction.KeyboardPan}
  17896. * * {@link ol.interaction.KeyboardZoom}
  17897. * * {@link ol.interaction.MouseWheelZoom}
  17898. * * {@link ol.interaction.DragZoom}
  17899. *
  17900. * @param {olx.interaction.DefaultsOptions=} opt_options Defaults options.
  17901. * @return {ol.Collection.<ol.interaction.Interaction>} A collection of
  17902. * interactions to be used with the ol.Map constructor's interactions option.
  17903. * @api
  17904. */
  17905. ol.interaction.defaults = function(opt_options) {
  17906. var options = opt_options ? opt_options : {};
  17907. var interactions = new ol.Collection();
  17908. var kinetic = new ol.Kinetic(-0.005, 0.05, 100);
  17909. var altShiftDragRotate = options.altShiftDragRotate !== undefined ?
  17910. options.altShiftDragRotate : true;
  17911. if (altShiftDragRotate) {
  17912. interactions.push(new ol.interaction.DragRotate());
  17913. }
  17914. var doubleClickZoom = options.doubleClickZoom !== undefined ?
  17915. options.doubleClickZoom : true;
  17916. if (doubleClickZoom) {
  17917. interactions.push(new ol.interaction.DoubleClickZoom({
  17918. delta: options.zoomDelta,
  17919. duration: options.zoomDuration
  17920. }));
  17921. }
  17922. var dragPan = options.dragPan !== undefined ? options.dragPan : true;
  17923. if (dragPan) {
  17924. interactions.push(new ol.interaction.DragPan({
  17925. kinetic: kinetic
  17926. }));
  17927. }
  17928. var pinchRotate = options.pinchRotate !== undefined ? options.pinchRotate :
  17929. true;
  17930. if (pinchRotate) {
  17931. interactions.push(new ol.interaction.PinchRotate());
  17932. }
  17933. var pinchZoom = options.pinchZoom !== undefined ? options.pinchZoom : true;
  17934. if (pinchZoom) {
  17935. interactions.push(new ol.interaction.PinchZoom({
  17936. constrainResolution: options.constrainResolution,
  17937. duration: options.zoomDuration
  17938. }));
  17939. }
  17940. var keyboard = options.keyboard !== undefined ? options.keyboard : true;
  17941. if (keyboard) {
  17942. interactions.push(new ol.interaction.KeyboardPan());
  17943. interactions.push(new ol.interaction.KeyboardZoom({
  17944. delta: options.zoomDelta,
  17945. duration: options.zoomDuration
  17946. }));
  17947. }
  17948. var mouseWheelZoom = options.mouseWheelZoom !== undefined ?
  17949. options.mouseWheelZoom : true;
  17950. if (mouseWheelZoom) {
  17951. interactions.push(new ol.interaction.MouseWheelZoom({
  17952. constrainResolution: options.constrainResolution,
  17953. duration: options.zoomDuration
  17954. }));
  17955. }
  17956. var shiftDragZoom = options.shiftDragZoom !== undefined ?
  17957. options.shiftDragZoom : true;
  17958. if (shiftDragZoom) {
  17959. interactions.push(new ol.interaction.DragZoom({
  17960. duration: options.zoomDuration
  17961. }));
  17962. }
  17963. return interactions;
  17964. };
  17965. goog.provide('ol.layer.Property');
  17966. /**
  17967. * @enum {string}
  17968. */
  17969. ol.layer.Property = {
  17970. OPACITY: 'opacity',
  17971. VISIBLE: 'visible',
  17972. EXTENT: 'extent',
  17973. Z_INDEX: 'zIndex',
  17974. MAX_RESOLUTION: 'maxResolution',
  17975. MIN_RESOLUTION: 'minResolution',
  17976. SOURCE: 'source'
  17977. };
  17978. goog.provide('ol.layer.Base');
  17979. goog.require('ol');
  17980. goog.require('ol.Object');
  17981. goog.require('ol.layer.Property');
  17982. goog.require('ol.math');
  17983. goog.require('ol.obj');
  17984. /**
  17985. * @classdesc
  17986. * Abstract base class; normally only used for creating subclasses and not
  17987. * instantiated in apps.
  17988. * Note that with `ol.layer.Base` and all its subclasses, any property set in
  17989. * the options is set as a {@link ol.Object} property on the layer object, so
  17990. * is observable, and has get/set accessors.
  17991. *
  17992. * @constructor
  17993. * @abstract
  17994. * @extends {ol.Object}
  17995. * @param {olx.layer.BaseOptions} options Layer options.
  17996. * @api
  17997. */
  17998. ol.layer.Base = function(options) {
  17999. ol.Object.call(this);
  18000. /**
  18001. * @type {Object.<string, *>}
  18002. */
  18003. var properties = ol.obj.assign({}, options);
  18004. properties[ol.layer.Property.OPACITY] =
  18005. options.opacity !== undefined ? options.opacity : 1;
  18006. properties[ol.layer.Property.VISIBLE] =
  18007. options.visible !== undefined ? options.visible : true;
  18008. properties[ol.layer.Property.Z_INDEX] =
  18009. options.zIndex !== undefined ? options.zIndex : 0;
  18010. properties[ol.layer.Property.MAX_RESOLUTION] =
  18011. options.maxResolution !== undefined ? options.maxResolution : Infinity;
  18012. properties[ol.layer.Property.MIN_RESOLUTION] =
  18013. options.minResolution !== undefined ? options.minResolution : 0;
  18014. this.setProperties(properties);
  18015. /**
  18016. * @type {ol.LayerState}
  18017. * @private
  18018. */
  18019. this.state_ = /** @type {ol.LayerState} */ ({
  18020. layer: /** @type {ol.layer.Layer} */ (this),
  18021. managed: true
  18022. });
  18023. };
  18024. ol.inherits(ol.layer.Base, ol.Object);
  18025. /**
  18026. * Create a renderer for this layer.
  18027. * @abstract
  18028. * @param {ol.renderer.Map} mapRenderer The map renderer.
  18029. * @return {ol.renderer.Layer} A layer renderer.
  18030. */
  18031. ol.layer.Base.prototype.createRenderer = function(mapRenderer) {};
  18032. /**
  18033. * @return {ol.LayerState} Layer state.
  18034. */
  18035. ol.layer.Base.prototype.getLayerState = function() {
  18036. this.state_.opacity = ol.math.clamp(this.getOpacity(), 0, 1);
  18037. this.state_.sourceState = this.getSourceState();
  18038. this.state_.visible = this.getVisible();
  18039. this.state_.extent = this.getExtent();
  18040. this.state_.zIndex = this.getZIndex();
  18041. this.state_.maxResolution = this.getMaxResolution();
  18042. this.state_.minResolution = Math.max(this.getMinResolution(), 0);
  18043. return this.state_;
  18044. };
  18045. /**
  18046. * @abstract
  18047. * @param {Array.<ol.layer.Layer>=} opt_array Array of layers (to be
  18048. * modified in place).
  18049. * @return {Array.<ol.layer.Layer>} Array of layers.
  18050. */
  18051. ol.layer.Base.prototype.getLayersArray = function(opt_array) {};
  18052. /**
  18053. * @abstract
  18054. * @param {Array.<ol.LayerState>=} opt_states Optional list of layer
  18055. * states (to be modified in place).
  18056. * @return {Array.<ol.LayerState>} List of layer states.
  18057. */
  18058. ol.layer.Base.prototype.getLayerStatesArray = function(opt_states) {};
  18059. /**
  18060. * Return the {@link ol.Extent extent} of the layer or `undefined` if it
  18061. * will be visible regardless of extent.
  18062. * @return {ol.Extent|undefined} The layer extent.
  18063. * @observable
  18064. * @api
  18065. */
  18066. ol.layer.Base.prototype.getExtent = function() {
  18067. return /** @type {ol.Extent|undefined} */ (
  18068. this.get(ol.layer.Property.EXTENT));
  18069. };
  18070. /**
  18071. * Return the maximum resolution of the layer.
  18072. * @return {number} The maximum resolution of the layer.
  18073. * @observable
  18074. * @api
  18075. */
  18076. ol.layer.Base.prototype.getMaxResolution = function() {
  18077. return /** @type {number} */ (
  18078. this.get(ol.layer.Property.MAX_RESOLUTION));
  18079. };
  18080. /**
  18081. * Return the minimum resolution of the layer.
  18082. * @return {number} The minimum resolution of the layer.
  18083. * @observable
  18084. * @api
  18085. */
  18086. ol.layer.Base.prototype.getMinResolution = function() {
  18087. return /** @type {number} */ (
  18088. this.get(ol.layer.Property.MIN_RESOLUTION));
  18089. };
  18090. /**
  18091. * Return the opacity of the layer (between 0 and 1).
  18092. * @return {number} The opacity of the layer.
  18093. * @observable
  18094. * @api
  18095. */
  18096. ol.layer.Base.prototype.getOpacity = function() {
  18097. return /** @type {number} */ (this.get(ol.layer.Property.OPACITY));
  18098. };
  18099. /**
  18100. * @abstract
  18101. * @return {ol.source.State} Source state.
  18102. */
  18103. ol.layer.Base.prototype.getSourceState = function() {};
  18104. /**
  18105. * Return the visibility of the layer (`true` or `false`).
  18106. * @return {boolean} The visibility of the layer.
  18107. * @observable
  18108. * @api
  18109. */
  18110. ol.layer.Base.prototype.getVisible = function() {
  18111. return /** @type {boolean} */ (this.get(ol.layer.Property.VISIBLE));
  18112. };
  18113. /**
  18114. * Return the Z-index of the layer, which is used to order layers before
  18115. * rendering. The default Z-index is 0.
  18116. * @return {number} The Z-index of the layer.
  18117. * @observable
  18118. * @api
  18119. */
  18120. ol.layer.Base.prototype.getZIndex = function() {
  18121. return /** @type {number} */ (this.get(ol.layer.Property.Z_INDEX));
  18122. };
  18123. /**
  18124. * Set the extent at which the layer is visible. If `undefined`, the layer
  18125. * will be visible at all extents.
  18126. * @param {ol.Extent|undefined} extent The extent of the layer.
  18127. * @observable
  18128. * @api
  18129. */
  18130. ol.layer.Base.prototype.setExtent = function(extent) {
  18131. this.set(ol.layer.Property.EXTENT, extent);
  18132. };
  18133. /**
  18134. * Set the maximum resolution at which the layer is visible.
  18135. * @param {number} maxResolution The maximum resolution of the layer.
  18136. * @observable
  18137. * @api
  18138. */
  18139. ol.layer.Base.prototype.setMaxResolution = function(maxResolution) {
  18140. this.set(ol.layer.Property.MAX_RESOLUTION, maxResolution);
  18141. };
  18142. /**
  18143. * Set the minimum resolution at which the layer is visible.
  18144. * @param {number} minResolution The minimum resolution of the layer.
  18145. * @observable
  18146. * @api
  18147. */
  18148. ol.layer.Base.prototype.setMinResolution = function(minResolution) {
  18149. this.set(ol.layer.Property.MIN_RESOLUTION, minResolution);
  18150. };
  18151. /**
  18152. * Set the opacity of the layer, allowed values range from 0 to 1.
  18153. * @param {number} opacity The opacity of the layer.
  18154. * @observable
  18155. * @api
  18156. */
  18157. ol.layer.Base.prototype.setOpacity = function(opacity) {
  18158. this.set(ol.layer.Property.OPACITY, opacity);
  18159. };
  18160. /**
  18161. * Set the visibility of the layer (`true` or `false`).
  18162. * @param {boolean} visible The visibility of the layer.
  18163. * @observable
  18164. * @api
  18165. */
  18166. ol.layer.Base.prototype.setVisible = function(visible) {
  18167. this.set(ol.layer.Property.VISIBLE, visible);
  18168. };
  18169. /**
  18170. * Set Z-index of the layer, which is used to order layers before rendering.
  18171. * The default Z-index is 0.
  18172. * @param {number} zindex The z-index of the layer.
  18173. * @observable
  18174. * @api
  18175. */
  18176. ol.layer.Base.prototype.setZIndex = function(zindex) {
  18177. this.set(ol.layer.Property.Z_INDEX, zindex);
  18178. };
  18179. goog.provide('ol.source.State');
  18180. /**
  18181. * State of the source, one of 'undefined', 'loading', 'ready' or 'error'.
  18182. * @enum {string}
  18183. */
  18184. ol.source.State = {
  18185. UNDEFINED: 'undefined',
  18186. LOADING: 'loading',
  18187. READY: 'ready',
  18188. ERROR: 'error'
  18189. };
  18190. goog.provide('ol.layer.Group');
  18191. goog.require('ol');
  18192. goog.require('ol.Collection');
  18193. goog.require('ol.CollectionEventType');
  18194. goog.require('ol.Object');
  18195. goog.require('ol.ObjectEventType');
  18196. goog.require('ol.asserts');
  18197. goog.require('ol.events');
  18198. goog.require('ol.events.EventType');
  18199. goog.require('ol.extent');
  18200. goog.require('ol.layer.Base');
  18201. goog.require('ol.obj');
  18202. goog.require('ol.source.State');
  18203. /**
  18204. * @classdesc
  18205. * A {@link ol.Collection} of layers that are handled together.
  18206. *
  18207. * A generic `change` event is triggered when the group/Collection changes.
  18208. *
  18209. * @constructor
  18210. * @extends {ol.layer.Base}
  18211. * @param {olx.layer.GroupOptions=} opt_options Layer options.
  18212. * @api
  18213. */
  18214. ol.layer.Group = function(opt_options) {
  18215. var options = opt_options || {};
  18216. var baseOptions = /** @type {olx.layer.GroupOptions} */
  18217. (ol.obj.assign({}, options));
  18218. delete baseOptions.layers;
  18219. var layers = options.layers;
  18220. ol.layer.Base.call(this, baseOptions);
  18221. /**
  18222. * @private
  18223. * @type {Array.<ol.EventsKey>}
  18224. */
  18225. this.layersListenerKeys_ = [];
  18226. /**
  18227. * @private
  18228. * @type {Object.<string, Array.<ol.EventsKey>>}
  18229. */
  18230. this.listenerKeys_ = {};
  18231. ol.events.listen(this,
  18232. ol.Object.getChangeEventType(ol.layer.Group.Property_.LAYERS),
  18233. this.handleLayersChanged_, this);
  18234. if (layers) {
  18235. if (Array.isArray(layers)) {
  18236. layers = new ol.Collection(layers.slice(), {unique: true});
  18237. } else {
  18238. ol.asserts.assert(layers instanceof ol.Collection,
  18239. 43); // Expected `layers` to be an array or an `ol.Collection`
  18240. layers = layers;
  18241. }
  18242. } else {
  18243. layers = new ol.Collection(undefined, {unique: true});
  18244. }
  18245. this.setLayers(layers);
  18246. };
  18247. ol.inherits(ol.layer.Group, ol.layer.Base);
  18248. /**
  18249. * @inheritDoc
  18250. */
  18251. ol.layer.Group.prototype.createRenderer = function(mapRenderer) {};
  18252. /**
  18253. * @private
  18254. */
  18255. ol.layer.Group.prototype.handleLayerChange_ = function() {
  18256. this.changed();
  18257. };
  18258. /**
  18259. * @param {ol.events.Event} event Event.
  18260. * @private
  18261. */
  18262. ol.layer.Group.prototype.handleLayersChanged_ = function(event) {
  18263. this.layersListenerKeys_.forEach(ol.events.unlistenByKey);
  18264. this.layersListenerKeys_.length = 0;
  18265. var layers = this.getLayers();
  18266. this.layersListenerKeys_.push(
  18267. ol.events.listen(layers, ol.CollectionEventType.ADD,
  18268. this.handleLayersAdd_, this),
  18269. ol.events.listen(layers, ol.CollectionEventType.REMOVE,
  18270. this.handleLayersRemove_, this));
  18271. for (var id in this.listenerKeys_) {
  18272. this.listenerKeys_[id].forEach(ol.events.unlistenByKey);
  18273. }
  18274. ol.obj.clear(this.listenerKeys_);
  18275. var layersArray = layers.getArray();
  18276. var i, ii, layer;
  18277. for (i = 0, ii = layersArray.length; i < ii; i++) {
  18278. layer = layersArray[i];
  18279. this.listenerKeys_[ol.getUid(layer).toString()] = [
  18280. ol.events.listen(layer, ol.ObjectEventType.PROPERTYCHANGE,
  18281. this.handleLayerChange_, this),
  18282. ol.events.listen(layer, ol.events.EventType.CHANGE,
  18283. this.handleLayerChange_, this)
  18284. ];
  18285. }
  18286. this.changed();
  18287. };
  18288. /**
  18289. * @param {ol.Collection.Event} collectionEvent Collection event.
  18290. * @private
  18291. */
  18292. ol.layer.Group.prototype.handleLayersAdd_ = function(collectionEvent) {
  18293. var layer = /** @type {ol.layer.Base} */ (collectionEvent.element);
  18294. var key = ol.getUid(layer).toString();
  18295. this.listenerKeys_[key] = [
  18296. ol.events.listen(layer, ol.ObjectEventType.PROPERTYCHANGE,
  18297. this.handleLayerChange_, this),
  18298. ol.events.listen(layer, ol.events.EventType.CHANGE,
  18299. this.handleLayerChange_, this)
  18300. ];
  18301. this.changed();
  18302. };
  18303. /**
  18304. * @param {ol.Collection.Event} collectionEvent Collection event.
  18305. * @private
  18306. */
  18307. ol.layer.Group.prototype.handleLayersRemove_ = function(collectionEvent) {
  18308. var layer = /** @type {ol.layer.Base} */ (collectionEvent.element);
  18309. var key = ol.getUid(layer).toString();
  18310. this.listenerKeys_[key].forEach(ol.events.unlistenByKey);
  18311. delete this.listenerKeys_[key];
  18312. this.changed();
  18313. };
  18314. /**
  18315. * Returns the {@link ol.Collection collection} of {@link ol.layer.Layer layers}
  18316. * in this group.
  18317. * @return {!ol.Collection.<ol.layer.Base>} Collection of
  18318. * {@link ol.layer.Base layers} that are part of this group.
  18319. * @observable
  18320. * @api
  18321. */
  18322. ol.layer.Group.prototype.getLayers = function() {
  18323. return /** @type {!ol.Collection.<ol.layer.Base>} */ (this.get(
  18324. ol.layer.Group.Property_.LAYERS));
  18325. };
  18326. /**
  18327. * Set the {@link ol.Collection collection} of {@link ol.layer.Layer layers}
  18328. * in this group.
  18329. * @param {!ol.Collection.<ol.layer.Base>} layers Collection of
  18330. * {@link ol.layer.Base layers} that are part of this group.
  18331. * @observable
  18332. * @api
  18333. */
  18334. ol.layer.Group.prototype.setLayers = function(layers) {
  18335. this.set(ol.layer.Group.Property_.LAYERS, layers);
  18336. };
  18337. /**
  18338. * @inheritDoc
  18339. */
  18340. ol.layer.Group.prototype.getLayersArray = function(opt_array) {
  18341. var array = opt_array !== undefined ? opt_array : [];
  18342. this.getLayers().forEach(function(layer) {
  18343. layer.getLayersArray(array);
  18344. });
  18345. return array;
  18346. };
  18347. /**
  18348. * @inheritDoc
  18349. */
  18350. ol.layer.Group.prototype.getLayerStatesArray = function(opt_states) {
  18351. var states = opt_states !== undefined ? opt_states : [];
  18352. var pos = states.length;
  18353. this.getLayers().forEach(function(layer) {
  18354. layer.getLayerStatesArray(states);
  18355. });
  18356. var ownLayerState = this.getLayerState();
  18357. var i, ii, layerState;
  18358. for (i = pos, ii = states.length; i < ii; i++) {
  18359. layerState = states[i];
  18360. layerState.opacity *= ownLayerState.opacity;
  18361. layerState.visible = layerState.visible && ownLayerState.visible;
  18362. layerState.maxResolution = Math.min(
  18363. layerState.maxResolution, ownLayerState.maxResolution);
  18364. layerState.minResolution = Math.max(
  18365. layerState.minResolution, ownLayerState.minResolution);
  18366. if (ownLayerState.extent !== undefined) {
  18367. if (layerState.extent !== undefined) {
  18368. layerState.extent = ol.extent.getIntersection(
  18369. layerState.extent, ownLayerState.extent);
  18370. } else {
  18371. layerState.extent = ownLayerState.extent;
  18372. }
  18373. }
  18374. }
  18375. return states;
  18376. };
  18377. /**
  18378. * @inheritDoc
  18379. */
  18380. ol.layer.Group.prototype.getSourceState = function() {
  18381. return ol.source.State.READY;
  18382. };
  18383. /**
  18384. * @enum {string}
  18385. * @private
  18386. */
  18387. ol.layer.Group.Property_ = {
  18388. LAYERS: 'layers'
  18389. };
  18390. goog.provide('ol.render.EventType');
  18391. /**
  18392. * @enum {string}
  18393. */
  18394. ol.render.EventType = {
  18395. /**
  18396. * @event ol.render.Event#postcompose
  18397. * @api
  18398. */
  18399. POSTCOMPOSE: 'postcompose',
  18400. /**
  18401. * @event ol.render.Event#precompose
  18402. * @api
  18403. */
  18404. PRECOMPOSE: 'precompose',
  18405. /**
  18406. * @event ol.render.Event#render
  18407. * @api
  18408. */
  18409. RENDER: 'render'
  18410. };
  18411. goog.provide('ol.layer.Layer');
  18412. goog.require('ol.events');
  18413. goog.require('ol.events.EventType');
  18414. goog.require('ol');
  18415. goog.require('ol.Object');
  18416. goog.require('ol.layer.Base');
  18417. goog.require('ol.layer.Property');
  18418. goog.require('ol.obj');
  18419. goog.require('ol.render.EventType');
  18420. goog.require('ol.source.State');
  18421. /**
  18422. * @classdesc
  18423. * Abstract base class; normally only used for creating subclasses and not
  18424. * instantiated in apps.
  18425. * A visual representation of raster or vector map data.
  18426. * Layers group together those properties that pertain to how the data is to be
  18427. * displayed, irrespective of the source of that data.
  18428. *
  18429. * Layers are usually added to a map with {@link ol.Map#addLayer}. Components
  18430. * like {@link ol.interaction.Select} use unmanaged layers internally. These
  18431. * unmanaged layers are associated with the map using
  18432. * {@link ol.layer.Layer#setMap} instead.
  18433. *
  18434. * A generic `change` event is fired when the state of the source changes.
  18435. *
  18436. * @constructor
  18437. * @abstract
  18438. * @extends {ol.layer.Base}
  18439. * @fires ol.render.Event
  18440. * @param {olx.layer.LayerOptions} options Layer options.
  18441. * @api
  18442. */
  18443. ol.layer.Layer = function(options) {
  18444. var baseOptions = ol.obj.assign({}, options);
  18445. delete baseOptions.source;
  18446. ol.layer.Base.call(this, /** @type {olx.layer.BaseOptions} */ (baseOptions));
  18447. /**
  18448. * @private
  18449. * @type {?ol.EventsKey}
  18450. */
  18451. this.mapPrecomposeKey_ = null;
  18452. /**
  18453. * @private
  18454. * @type {?ol.EventsKey}
  18455. */
  18456. this.mapRenderKey_ = null;
  18457. /**
  18458. * @private
  18459. * @type {?ol.EventsKey}
  18460. */
  18461. this.sourceChangeKey_ = null;
  18462. if (options.map) {
  18463. this.setMap(options.map);
  18464. }
  18465. ol.events.listen(this,
  18466. ol.Object.getChangeEventType(ol.layer.Property.SOURCE),
  18467. this.handleSourcePropertyChange_, this);
  18468. var source = options.source ? options.source : null;
  18469. this.setSource(source);
  18470. };
  18471. ol.inherits(ol.layer.Layer, ol.layer.Base);
  18472. /**
  18473. * Return `true` if the layer is visible, and if the passed resolution is
  18474. * between the layer's minResolution and maxResolution. The comparison is
  18475. * inclusive for `minResolution` and exclusive for `maxResolution`.
  18476. * @param {ol.LayerState} layerState Layer state.
  18477. * @param {number} resolution Resolution.
  18478. * @return {boolean} The layer is visible at the given resolution.
  18479. */
  18480. ol.layer.Layer.visibleAtResolution = function(layerState, resolution) {
  18481. return layerState.visible && resolution >= layerState.minResolution &&
  18482. resolution < layerState.maxResolution;
  18483. };
  18484. /**
  18485. * @inheritDoc
  18486. */
  18487. ol.layer.Layer.prototype.getLayersArray = function(opt_array) {
  18488. var array = opt_array ? opt_array : [];
  18489. array.push(this);
  18490. return array;
  18491. };
  18492. /**
  18493. * @inheritDoc
  18494. */
  18495. ol.layer.Layer.prototype.getLayerStatesArray = function(opt_states) {
  18496. var states = opt_states ? opt_states : [];
  18497. states.push(this.getLayerState());
  18498. return states;
  18499. };
  18500. /**
  18501. * Get the layer source.
  18502. * @return {ol.source.Source} The layer source (or `null` if not yet set).
  18503. * @observable
  18504. * @api
  18505. */
  18506. ol.layer.Layer.prototype.getSource = function() {
  18507. var source = this.get(ol.layer.Property.SOURCE);
  18508. return /** @type {ol.source.Source} */ (source) || null;
  18509. };
  18510. /**
  18511. * @inheritDoc
  18512. */
  18513. ol.layer.Layer.prototype.getSourceState = function() {
  18514. var source = this.getSource();
  18515. return !source ? ol.source.State.UNDEFINED : source.getState();
  18516. };
  18517. /**
  18518. * @private
  18519. */
  18520. ol.layer.Layer.prototype.handleSourceChange_ = function() {
  18521. this.changed();
  18522. };
  18523. /**
  18524. * @private
  18525. */
  18526. ol.layer.Layer.prototype.handleSourcePropertyChange_ = function() {
  18527. if (this.sourceChangeKey_) {
  18528. ol.events.unlistenByKey(this.sourceChangeKey_);
  18529. this.sourceChangeKey_ = null;
  18530. }
  18531. var source = this.getSource();
  18532. if (source) {
  18533. this.sourceChangeKey_ = ol.events.listen(source,
  18534. ol.events.EventType.CHANGE, this.handleSourceChange_, this);
  18535. }
  18536. this.changed();
  18537. };
  18538. /**
  18539. * Sets the layer to be rendered on top of other layers on a map. The map will
  18540. * not manage this layer in its layers collection, and the callback in
  18541. * {@link ol.Map#forEachLayerAtPixel} will receive `null` as layer. This
  18542. * is useful for temporary layers. To remove an unmanaged layer from the map,
  18543. * use `#setMap(null)`.
  18544. *
  18545. * To add the layer to a map and have it managed by the map, use
  18546. * {@link ol.Map#addLayer} instead.
  18547. * @param {ol.Map} map Map.
  18548. * @api
  18549. */
  18550. ol.layer.Layer.prototype.setMap = function(map) {
  18551. if (this.mapPrecomposeKey_) {
  18552. ol.events.unlistenByKey(this.mapPrecomposeKey_);
  18553. this.mapPrecomposeKey_ = null;
  18554. }
  18555. if (!map) {
  18556. this.changed();
  18557. }
  18558. if (this.mapRenderKey_) {
  18559. ol.events.unlistenByKey(this.mapRenderKey_);
  18560. this.mapRenderKey_ = null;
  18561. }
  18562. if (map) {
  18563. this.mapPrecomposeKey_ = ol.events.listen(
  18564. map, ol.render.EventType.PRECOMPOSE, function(evt) {
  18565. var layerState = this.getLayerState();
  18566. layerState.managed = false;
  18567. layerState.zIndex = Infinity;
  18568. evt.frameState.layerStatesArray.push(layerState);
  18569. evt.frameState.layerStates[ol.getUid(this)] = layerState;
  18570. }, this);
  18571. this.mapRenderKey_ = ol.events.listen(
  18572. this, ol.events.EventType.CHANGE, map.render, map);
  18573. this.changed();
  18574. }
  18575. };
  18576. /**
  18577. * Set the layer source.
  18578. * @param {ol.source.Source} source The layer source.
  18579. * @observable
  18580. * @api
  18581. */
  18582. ol.layer.Layer.prototype.setSource = function(source) {
  18583. this.set(ol.layer.Property.SOURCE, source);
  18584. };
  18585. goog.provide('ol.style.IconImageCache');
  18586. goog.require('ol.color');
  18587. /**
  18588. * @constructor
  18589. */
  18590. ol.style.IconImageCache = function() {
  18591. /**
  18592. * @type {Object.<string, ol.style.IconImage>}
  18593. * @private
  18594. */
  18595. this.cache_ = {};
  18596. /**
  18597. * @type {number}
  18598. * @private
  18599. */
  18600. this.cacheSize_ = 0;
  18601. /**
  18602. * @const
  18603. * @type {number}
  18604. * @private
  18605. */
  18606. this.maxCacheSize_ = 32;
  18607. };
  18608. /**
  18609. * @param {string} src Src.
  18610. * @param {?string} crossOrigin Cross origin.
  18611. * @param {ol.Color} color Color.
  18612. * @return {string} Cache key.
  18613. */
  18614. ol.style.IconImageCache.getKey = function(src, crossOrigin, color) {
  18615. var colorString = color ? ol.color.asString(color) : 'null';
  18616. return crossOrigin + ':' + src + ':' + colorString;
  18617. };
  18618. /**
  18619. * FIXME empty description for jsdoc
  18620. */
  18621. ol.style.IconImageCache.prototype.clear = function() {
  18622. this.cache_ = {};
  18623. this.cacheSize_ = 0;
  18624. };
  18625. /**
  18626. * FIXME empty description for jsdoc
  18627. */
  18628. ol.style.IconImageCache.prototype.expire = function() {
  18629. if (this.cacheSize_ > this.maxCacheSize_) {
  18630. var i = 0;
  18631. var key, iconImage;
  18632. for (key in this.cache_) {
  18633. iconImage = this.cache_[key];
  18634. if ((i++ & 3) === 0 && !iconImage.hasListener()) {
  18635. delete this.cache_[key];
  18636. --this.cacheSize_;
  18637. }
  18638. }
  18639. }
  18640. };
  18641. /**
  18642. * @param {string} src Src.
  18643. * @param {?string} crossOrigin Cross origin.
  18644. * @param {ol.Color} color Color.
  18645. * @return {ol.style.IconImage} Icon image.
  18646. */
  18647. ol.style.IconImageCache.prototype.get = function(src, crossOrigin, color) {
  18648. var key = ol.style.IconImageCache.getKey(src, crossOrigin, color);
  18649. return key in this.cache_ ? this.cache_[key] : null;
  18650. };
  18651. /**
  18652. * @param {string} src Src.
  18653. * @param {?string} crossOrigin Cross origin.
  18654. * @param {ol.Color} color Color.
  18655. * @param {ol.style.IconImage} iconImage Icon image.
  18656. */
  18657. ol.style.IconImageCache.prototype.set = function(src, crossOrigin, color, iconImage) {
  18658. var key = ol.style.IconImageCache.getKey(src, crossOrigin, color);
  18659. this.cache_[key] = iconImage;
  18660. ++this.cacheSize_;
  18661. };
  18662. goog.provide('ol.style');
  18663. goog.require('ol.style.IconImageCache');
  18664. ol.style.iconImageCache = new ol.style.IconImageCache();
  18665. goog.provide('ol.transform');
  18666. goog.require('ol.asserts');
  18667. /**
  18668. * Collection of affine 2d transformation functions. The functions work on an
  18669. * array of 6 elements. The element order is compatible with the [SVGMatrix
  18670. * interface](https://developer.mozilla.org/en-US/docs/Web/API/SVGMatrix) and is
  18671. * a subset (elements a to f) of a 3x3 martrix:
  18672. * ```
  18673. * [ a c e ]
  18674. * [ b d f ]
  18675. * [ 0 0 1 ]
  18676. * ```
  18677. */
  18678. /**
  18679. * @private
  18680. * @type {ol.Transform}
  18681. */
  18682. ol.transform.tmp_ = new Array(6);
  18683. /**
  18684. * Create an identity transform.
  18685. * @return {!ol.Transform} Identity transform.
  18686. */
  18687. ol.transform.create = function() {
  18688. return [1, 0, 0, 1, 0, 0];
  18689. };
  18690. /**
  18691. * Resets the given transform to an identity transform.
  18692. * @param {!ol.Transform} transform Transform.
  18693. * @return {!ol.Transform} Transform.
  18694. */
  18695. ol.transform.reset = function(transform) {
  18696. return ol.transform.set(transform, 1, 0, 0, 1, 0, 0);
  18697. };
  18698. /**
  18699. * Multiply the underlying matrices of two transforms and return the result in
  18700. * the first transform.
  18701. * @param {!ol.Transform} transform1 Transform parameters of matrix 1.
  18702. * @param {!ol.Transform} transform2 Transform parameters of matrix 2.
  18703. * @return {!ol.Transform} transform1 multiplied with transform2.
  18704. */
  18705. ol.transform.multiply = function(transform1, transform2) {
  18706. var a1 = transform1[0];
  18707. var b1 = transform1[1];
  18708. var c1 = transform1[2];
  18709. var d1 = transform1[3];
  18710. var e1 = transform1[4];
  18711. var f1 = transform1[5];
  18712. var a2 = transform2[0];
  18713. var b2 = transform2[1];
  18714. var c2 = transform2[2];
  18715. var d2 = transform2[3];
  18716. var e2 = transform2[4];
  18717. var f2 = transform2[5];
  18718. transform1[0] = a1 * a2 + c1 * b2;
  18719. transform1[1] = b1 * a2 + d1 * b2;
  18720. transform1[2] = a1 * c2 + c1 * d2;
  18721. transform1[3] = b1 * c2 + d1 * d2;
  18722. transform1[4] = a1 * e2 + c1 * f2 + e1;
  18723. transform1[5] = b1 * e2 + d1 * f2 + f1;
  18724. return transform1;
  18725. };
  18726. /**
  18727. * Set the transform components a-f on a given transform.
  18728. * @param {!ol.Transform} transform Transform.
  18729. * @param {number} a The a component of the transform.
  18730. * @param {number} b The b component of the transform.
  18731. * @param {number} c The c component of the transform.
  18732. * @param {number} d The d component of the transform.
  18733. * @param {number} e The e component of the transform.
  18734. * @param {number} f The f component of the transform.
  18735. * @return {!ol.Transform} Matrix with transform applied.
  18736. */
  18737. ol.transform.set = function(transform, a, b, c, d, e, f) {
  18738. transform[0] = a;
  18739. transform[1] = b;
  18740. transform[2] = c;
  18741. transform[3] = d;
  18742. transform[4] = e;
  18743. transform[5] = f;
  18744. return transform;
  18745. };
  18746. /**
  18747. * Set transform on one matrix from another matrix.
  18748. * @param {!ol.Transform} transform1 Matrix to set transform to.
  18749. * @param {!ol.Transform} transform2 Matrix to set transform from.
  18750. * @return {!ol.Transform} transform1 with transform from transform2 applied.
  18751. */
  18752. ol.transform.setFromArray = function(transform1, transform2) {
  18753. transform1[0] = transform2[0];
  18754. transform1[1] = transform2[1];
  18755. transform1[2] = transform2[2];
  18756. transform1[3] = transform2[3];
  18757. transform1[4] = transform2[4];
  18758. transform1[5] = transform2[5];
  18759. return transform1;
  18760. };
  18761. /**
  18762. * Transforms the given coordinate with the given transform returning the
  18763. * resulting, transformed coordinate. The coordinate will be modified in-place.
  18764. *
  18765. * @param {ol.Transform} transform The transformation.
  18766. * @param {ol.Coordinate|ol.Pixel} coordinate The coordinate to transform.
  18767. * @return {ol.Coordinate|ol.Pixel} return coordinate so that operations can be
  18768. * chained together.
  18769. */
  18770. ol.transform.apply = function(transform, coordinate) {
  18771. var x = coordinate[0], y = coordinate[1];
  18772. coordinate[0] = transform[0] * x + transform[2] * y + transform[4];
  18773. coordinate[1] = transform[1] * x + transform[3] * y + transform[5];
  18774. return coordinate;
  18775. };
  18776. /**
  18777. * Applies rotation to the given transform.
  18778. * @param {!ol.Transform} transform Transform.
  18779. * @param {number} angle Angle in radians.
  18780. * @return {!ol.Transform} The rotated transform.
  18781. */
  18782. ol.transform.rotate = function(transform, angle) {
  18783. var cos = Math.cos(angle);
  18784. var sin = Math.sin(angle);
  18785. return ol.transform.multiply(transform,
  18786. ol.transform.set(ol.transform.tmp_, cos, sin, -sin, cos, 0, 0));
  18787. };
  18788. /**
  18789. * Applies scale to a given transform.
  18790. * @param {!ol.Transform} transform Transform.
  18791. * @param {number} x Scale factor x.
  18792. * @param {number} y Scale factor y.
  18793. * @return {!ol.Transform} The scaled transform.
  18794. */
  18795. ol.transform.scale = function(transform, x, y) {
  18796. return ol.transform.multiply(transform,
  18797. ol.transform.set(ol.transform.tmp_, x, 0, 0, y, 0, 0));
  18798. };
  18799. /**
  18800. * Applies translation to the given transform.
  18801. * @param {!ol.Transform} transform Transform.
  18802. * @param {number} dx Translation x.
  18803. * @param {number} dy Translation y.
  18804. * @return {!ol.Transform} The translated transform.
  18805. */
  18806. ol.transform.translate = function(transform, dx, dy) {
  18807. return ol.transform.multiply(transform,
  18808. ol.transform.set(ol.transform.tmp_, 1, 0, 0, 1, dx, dy));
  18809. };
  18810. /**
  18811. * Creates a composite transform given an initial translation, scale, rotation, and
  18812. * final translation (in that order only, not commutative).
  18813. * @param {!ol.Transform} transform The transform (will be modified in place).
  18814. * @param {number} dx1 Initial translation x.
  18815. * @param {number} dy1 Initial translation y.
  18816. * @param {number} sx Scale factor x.
  18817. * @param {number} sy Scale factor y.
  18818. * @param {number} angle Rotation (in counter-clockwise radians).
  18819. * @param {number} dx2 Final translation x.
  18820. * @param {number} dy2 Final translation y.
  18821. * @return {!ol.Transform} The composite transform.
  18822. */
  18823. ol.transform.compose = function(transform, dx1, dy1, sx, sy, angle, dx2, dy2) {
  18824. var sin = Math.sin(angle);
  18825. var cos = Math.cos(angle);
  18826. transform[0] = sx * cos;
  18827. transform[1] = sy * sin;
  18828. transform[2] = -sx * sin;
  18829. transform[3] = sy * cos;
  18830. transform[4] = dx2 * sx * cos - dy2 * sx * sin + dx1;
  18831. transform[5] = dx2 * sy * sin + dy2 * sy * cos + dy1;
  18832. return transform;
  18833. };
  18834. /**
  18835. * Invert the given transform.
  18836. * @param {!ol.Transform} transform Transform.
  18837. * @return {!ol.Transform} Inverse of the transform.
  18838. */
  18839. ol.transform.invert = function(transform) {
  18840. var det = ol.transform.determinant(transform);
  18841. ol.asserts.assert(det !== 0, 32); // Transformation matrix cannot be inverted
  18842. var a = transform[0];
  18843. var b = transform[1];
  18844. var c = transform[2];
  18845. var d = transform[3];
  18846. var e = transform[4];
  18847. var f = transform[5];
  18848. transform[0] = d / det;
  18849. transform[1] = -b / det;
  18850. transform[2] = -c / det;
  18851. transform[3] = a / det;
  18852. transform[4] = (c * f - d * e) / det;
  18853. transform[5] = -(a * f - b * e) / det;
  18854. return transform;
  18855. };
  18856. /**
  18857. * Returns the determinant of the given matrix.
  18858. * @param {!ol.Transform} mat Matrix.
  18859. * @return {number} Determinant.
  18860. */
  18861. ol.transform.determinant = function(mat) {
  18862. return mat[0] * mat[3] - mat[1] * mat[2];
  18863. };
  18864. goog.provide('ol.renderer.Map');
  18865. goog.require('ol');
  18866. goog.require('ol.Disposable');
  18867. goog.require('ol.events');
  18868. goog.require('ol.events.EventType');
  18869. goog.require('ol.extent');
  18870. goog.require('ol.functions');
  18871. goog.require('ol.layer.Layer');
  18872. goog.require('ol.style');
  18873. goog.require('ol.transform');
  18874. /**
  18875. * @constructor
  18876. * @abstract
  18877. * @extends {ol.Disposable}
  18878. * @param {Element} container Container.
  18879. * @param {ol.Map} map Map.
  18880. * @struct
  18881. */
  18882. ol.renderer.Map = function(container, map) {
  18883. ol.Disposable.call(this);
  18884. /**
  18885. * @private
  18886. * @type {ol.Map}
  18887. */
  18888. this.map_ = map;
  18889. /**
  18890. * @private
  18891. * @type {Object.<string, ol.renderer.Layer>}
  18892. */
  18893. this.layerRenderers_ = {};
  18894. /**
  18895. * @private
  18896. * @type {Object.<string, ol.EventsKey>}
  18897. */
  18898. this.layerRendererListeners_ = {};
  18899. };
  18900. ol.inherits(ol.renderer.Map, ol.Disposable);
  18901. /**
  18902. * @param {olx.FrameState} frameState FrameState.
  18903. * @protected
  18904. */
  18905. ol.renderer.Map.prototype.calculateMatrices2D = function(frameState) {
  18906. var viewState = frameState.viewState;
  18907. var coordinateToPixelTransform = frameState.coordinateToPixelTransform;
  18908. var pixelToCoordinateTransform = frameState.pixelToCoordinateTransform;
  18909. ol.transform.compose(coordinateToPixelTransform,
  18910. frameState.size[0] / 2, frameState.size[1] / 2,
  18911. 1 / viewState.resolution, -1 / viewState.resolution,
  18912. -viewState.rotation,
  18913. -viewState.center[0], -viewState.center[1]);
  18914. ol.transform.invert(
  18915. ol.transform.setFromArray(pixelToCoordinateTransform, coordinateToPixelTransform));
  18916. };
  18917. /**
  18918. * @inheritDoc
  18919. */
  18920. ol.renderer.Map.prototype.disposeInternal = function() {
  18921. for (var id in this.layerRenderers_) {
  18922. this.layerRenderers_[id].dispose();
  18923. }
  18924. };
  18925. /**
  18926. * @param {ol.Map} map Map.
  18927. * @param {olx.FrameState} frameState Frame state.
  18928. * @private
  18929. */
  18930. ol.renderer.Map.expireIconCache_ = function(map, frameState) {
  18931. var cache = ol.style.iconImageCache;
  18932. cache.expire();
  18933. };
  18934. /**
  18935. * @param {ol.Coordinate} coordinate Coordinate.
  18936. * @param {olx.FrameState} frameState FrameState.
  18937. * @param {number} hitTolerance Hit tolerance in pixels.
  18938. * @param {function(this: S, (ol.Feature|ol.render.Feature),
  18939. * ol.layer.Layer): T} callback Feature callback.
  18940. * @param {S} thisArg Value to use as `this` when executing `callback`.
  18941. * @param {function(this: U, ol.layer.Layer): boolean} layerFilter Layer filter
  18942. * function, only layers which are visible and for which this function
  18943. * returns `true` will be tested for features. By default, all visible
  18944. * layers will be tested.
  18945. * @param {U} thisArg2 Value to use as `this` when executing `layerFilter`.
  18946. * @return {T|undefined} Callback result.
  18947. * @template S,T,U
  18948. */
  18949. ol.renderer.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg,
  18950. layerFilter, thisArg2) {
  18951. var result;
  18952. var viewState = frameState.viewState;
  18953. var viewResolution = viewState.resolution;
  18954. /**
  18955. * @param {ol.Feature|ol.render.Feature} feature Feature.
  18956. * @param {ol.layer.Layer} layer Layer.
  18957. * @return {?} Callback result.
  18958. */
  18959. function forEachFeatureAtCoordinate(feature, layer) {
  18960. var key = ol.getUid(feature).toString();
  18961. var managed = frameState.layerStates[ol.getUid(layer)].managed;
  18962. if (!(key in frameState.skippedFeatureUids && !managed)) {
  18963. return callback.call(thisArg, feature, managed ? layer : null);
  18964. }
  18965. }
  18966. var projection = viewState.projection;
  18967. var translatedCoordinate = coordinate;
  18968. if (projection.canWrapX()) {
  18969. var projectionExtent = projection.getExtent();
  18970. var worldWidth = ol.extent.getWidth(projectionExtent);
  18971. var x = coordinate[0];
  18972. if (x < projectionExtent[0] || x > projectionExtent[2]) {
  18973. var worldsAway = Math.ceil((projectionExtent[0] - x) / worldWidth);
  18974. translatedCoordinate = [x + worldWidth * worldsAway, coordinate[1]];
  18975. }
  18976. }
  18977. var layerStates = frameState.layerStatesArray;
  18978. var numLayers = layerStates.length;
  18979. var i;
  18980. for (i = numLayers - 1; i >= 0; --i) {
  18981. var layerState = layerStates[i];
  18982. var layer = layerState.layer;
  18983. if (ol.layer.Layer.visibleAtResolution(layerState, viewResolution) &&
  18984. layerFilter.call(thisArg2, layer)) {
  18985. var layerRenderer = this.getLayerRenderer(layer);
  18986. if (layer.getSource()) {
  18987. result = layerRenderer.forEachFeatureAtCoordinate(
  18988. layer.getSource().getWrapX() ? translatedCoordinate : coordinate,
  18989. frameState, hitTolerance, forEachFeatureAtCoordinate, thisArg);
  18990. }
  18991. if (result) {
  18992. return result;
  18993. }
  18994. }
  18995. }
  18996. return undefined;
  18997. };
  18998. /**
  18999. * @abstract
  19000. * @param {ol.Pixel} pixel Pixel.
  19001. * @param {olx.FrameState} frameState FrameState.
  19002. * @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer
  19003. * callback.
  19004. * @param {S} thisArg Value to use as `this` when executing `callback`.
  19005. * @param {function(this: U, ol.layer.Layer): boolean} layerFilter Layer filter
  19006. * function, only layers which are visible and for which this function
  19007. * returns `true` will be tested for features. By default, all visible
  19008. * layers will be tested.
  19009. * @param {U} thisArg2 Value to use as `this` when executing `layerFilter`.
  19010. * @return {T|undefined} Callback result.
  19011. * @template S,T,U
  19012. */
  19013. ol.renderer.Map.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg,
  19014. layerFilter, thisArg2) {};
  19015. /**
  19016. * @param {ol.Coordinate} coordinate Coordinate.
  19017. * @param {olx.FrameState} frameState FrameState.
  19018. * @param {number} hitTolerance Hit tolerance in pixels.
  19019. * @param {function(this: U, ol.layer.Layer): boolean} layerFilter Layer filter
  19020. * function, only layers which are visible and for which this function
  19021. * returns `true` will be tested for features. By default, all visible
  19022. * layers will be tested.
  19023. * @param {U} thisArg Value to use as `this` when executing `layerFilter`.
  19024. * @return {boolean} Is there a feature at the given coordinate?
  19025. * @template U
  19026. */
  19027. ol.renderer.Map.prototype.hasFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, layerFilter, thisArg) {
  19028. var hasFeature = this.forEachFeatureAtCoordinate(
  19029. coordinate, frameState, hitTolerance, ol.functions.TRUE, this, layerFilter, thisArg);
  19030. return hasFeature !== undefined;
  19031. };
  19032. /**
  19033. * @param {ol.layer.Layer} layer Layer.
  19034. * @protected
  19035. * @return {ol.renderer.Layer} Layer renderer.
  19036. */
  19037. ol.renderer.Map.prototype.getLayerRenderer = function(layer) {
  19038. var layerKey = ol.getUid(layer).toString();
  19039. if (layerKey in this.layerRenderers_) {
  19040. return this.layerRenderers_[layerKey];
  19041. } else {
  19042. var layerRenderer = layer.createRenderer(this);
  19043. this.layerRenderers_[layerKey] = layerRenderer;
  19044. this.layerRendererListeners_[layerKey] = ol.events.listen(layerRenderer,
  19045. ol.events.EventType.CHANGE, this.handleLayerRendererChange_, this);
  19046. return layerRenderer;
  19047. }
  19048. };
  19049. /**
  19050. * @param {string} layerKey Layer key.
  19051. * @protected
  19052. * @return {ol.renderer.Layer} Layer renderer.
  19053. */
  19054. ol.renderer.Map.prototype.getLayerRendererByKey = function(layerKey) {
  19055. return this.layerRenderers_[layerKey];
  19056. };
  19057. /**
  19058. * @protected
  19059. * @return {Object.<string, ol.renderer.Layer>} Layer renderers.
  19060. */
  19061. ol.renderer.Map.prototype.getLayerRenderers = function() {
  19062. return this.layerRenderers_;
  19063. };
  19064. /**
  19065. * @return {ol.Map} Map.
  19066. */
  19067. ol.renderer.Map.prototype.getMap = function() {
  19068. return this.map_;
  19069. };
  19070. /**
  19071. * @abstract
  19072. * @return {string} Type
  19073. */
  19074. ol.renderer.Map.prototype.getType = function() {};
  19075. /**
  19076. * Handle changes in a layer renderer.
  19077. * @private
  19078. */
  19079. ol.renderer.Map.prototype.handleLayerRendererChange_ = function() {
  19080. this.map_.render();
  19081. };
  19082. /**
  19083. * @param {string} layerKey Layer key.
  19084. * @return {ol.renderer.Layer} Layer renderer.
  19085. * @private
  19086. */
  19087. ol.renderer.Map.prototype.removeLayerRendererByKey_ = function(layerKey) {
  19088. var layerRenderer = this.layerRenderers_[layerKey];
  19089. delete this.layerRenderers_[layerKey];
  19090. ol.events.unlistenByKey(this.layerRendererListeners_[layerKey]);
  19091. delete this.layerRendererListeners_[layerKey];
  19092. return layerRenderer;
  19093. };
  19094. /**
  19095. * Render.
  19096. * @param {?olx.FrameState} frameState Frame state.
  19097. */
  19098. ol.renderer.Map.prototype.renderFrame = ol.nullFunction;
  19099. /**
  19100. * @param {ol.Map} map Map.
  19101. * @param {olx.FrameState} frameState Frame state.
  19102. * @private
  19103. */
  19104. ol.renderer.Map.prototype.removeUnusedLayerRenderers_ = function(map, frameState) {
  19105. var layerKey;
  19106. for (layerKey in this.layerRenderers_) {
  19107. if (!frameState || !(layerKey in frameState.layerStates)) {
  19108. this.removeLayerRendererByKey_(layerKey).dispose();
  19109. }
  19110. }
  19111. };
  19112. /**
  19113. * @param {olx.FrameState} frameState Frame state.
  19114. * @protected
  19115. */
  19116. ol.renderer.Map.prototype.scheduleExpireIconCache = function(frameState) {
  19117. frameState.postRenderFunctions.push(
  19118. /** @type {ol.PostRenderFunction} */ (ol.renderer.Map.expireIconCache_)
  19119. );
  19120. };
  19121. /**
  19122. * @param {!olx.FrameState} frameState Frame state.
  19123. * @protected
  19124. */
  19125. ol.renderer.Map.prototype.scheduleRemoveUnusedLayerRenderers = function(frameState) {
  19126. var layerKey;
  19127. for (layerKey in this.layerRenderers_) {
  19128. if (!(layerKey in frameState.layerStates)) {
  19129. frameState.postRenderFunctions.push(
  19130. /** @type {ol.PostRenderFunction} */ (this.removeUnusedLayerRenderers_.bind(this))
  19131. );
  19132. return;
  19133. }
  19134. }
  19135. };
  19136. /**
  19137. * @param {ol.LayerState} state1 First layer state.
  19138. * @param {ol.LayerState} state2 Second layer state.
  19139. * @return {number} The zIndex difference.
  19140. */
  19141. ol.renderer.Map.sortByZIndex = function(state1, state2) {
  19142. return state1.zIndex - state2.zIndex;
  19143. };
  19144. goog.provide('ol.renderer.Type');
  19145. /**
  19146. * Available renderers: `'canvas'` or `'webgl'`.
  19147. * @enum {string}
  19148. */
  19149. ol.renderer.Type = {
  19150. CANVAS: 'canvas',
  19151. WEBGL: 'webgl'
  19152. };
  19153. goog.provide('ol.render.Event');
  19154. goog.require('ol');
  19155. goog.require('ol.events.Event');
  19156. /**
  19157. * @constructor
  19158. * @extends {ol.events.Event}
  19159. * @implements {oli.render.Event}
  19160. * @param {ol.render.EventType} type Type.
  19161. * @param {ol.render.VectorContext=} opt_vectorContext Vector context.
  19162. * @param {olx.FrameState=} opt_frameState Frame state.
  19163. * @param {?CanvasRenderingContext2D=} opt_context Context.
  19164. * @param {?ol.webgl.Context=} opt_glContext WebGL Context.
  19165. */
  19166. ol.render.Event = function(
  19167. type, opt_vectorContext, opt_frameState, opt_context,
  19168. opt_glContext) {
  19169. ol.events.Event.call(this, type);
  19170. /**
  19171. * For canvas, this is an instance of {@link ol.render.canvas.Immediate}.
  19172. * @type {ol.render.VectorContext|undefined}
  19173. * @api
  19174. */
  19175. this.vectorContext = opt_vectorContext;
  19176. /**
  19177. * An object representing the current render frame state.
  19178. * @type {olx.FrameState|undefined}
  19179. * @api
  19180. */
  19181. this.frameState = opt_frameState;
  19182. /**
  19183. * Canvas context. Only available when a Canvas renderer is used, null
  19184. * otherwise.
  19185. * @type {CanvasRenderingContext2D|null|undefined}
  19186. * @api
  19187. */
  19188. this.context = opt_context;
  19189. /**
  19190. * WebGL context. Only available when a WebGL renderer is used, null
  19191. * otherwise.
  19192. * @type {ol.webgl.Context|null|undefined}
  19193. * @api
  19194. */
  19195. this.glContext = opt_glContext;
  19196. };
  19197. ol.inherits(ol.render.Event, ol.events.Event);
  19198. goog.provide('ol.render.canvas');
  19199. /**
  19200. * @const
  19201. * @type {string}
  19202. */
  19203. ol.render.canvas.defaultFont = '10px sans-serif';
  19204. /**
  19205. * @const
  19206. * @type {ol.Color}
  19207. */
  19208. ol.render.canvas.defaultFillStyle = [0, 0, 0, 1];
  19209. /**
  19210. * @const
  19211. * @type {string}
  19212. */
  19213. ol.render.canvas.defaultLineCap = 'round';
  19214. /**
  19215. * @const
  19216. * @type {Array.<number>}
  19217. */
  19218. ol.render.canvas.defaultLineDash = [];
  19219. /**
  19220. * @const
  19221. * @type {number}
  19222. */
  19223. ol.render.canvas.defaultLineDashOffset = 0;
  19224. /**
  19225. * @const
  19226. * @type {string}
  19227. */
  19228. ol.render.canvas.defaultLineJoin = 'round';
  19229. /**
  19230. * @const
  19231. * @type {number}
  19232. */
  19233. ol.render.canvas.defaultMiterLimit = 10;
  19234. /**
  19235. * @const
  19236. * @type {ol.Color}
  19237. */
  19238. ol.render.canvas.defaultStrokeStyle = [0, 0, 0, 1];
  19239. /**
  19240. * @const
  19241. * @type {string}
  19242. */
  19243. ol.render.canvas.defaultTextAlign = 'center';
  19244. /**
  19245. * @const
  19246. * @type {string}
  19247. */
  19248. ol.render.canvas.defaultTextBaseline = 'middle';
  19249. /**
  19250. * @const
  19251. * @type {number}
  19252. */
  19253. ol.render.canvas.defaultLineWidth = 1;
  19254. /**
  19255. * @param {CanvasRenderingContext2D} context Context.
  19256. * @param {number} rotation Rotation.
  19257. * @param {number} offsetX X offset.
  19258. * @param {number} offsetY Y offset.
  19259. */
  19260. ol.render.canvas.rotateAtOffset = function(context, rotation, offsetX, offsetY) {
  19261. if (rotation !== 0) {
  19262. context.translate(offsetX, offsetY);
  19263. context.rotate(rotation);
  19264. context.translate(-offsetX, -offsetY);
  19265. }
  19266. };
  19267. goog.provide('ol.render.VectorContext');
  19268. /**
  19269. * Context for drawing geometries. A vector context is available on render
  19270. * events and does not need to be constructed directly.
  19271. * @constructor
  19272. * @abstract
  19273. * @struct
  19274. * @api
  19275. */
  19276. ol.render.VectorContext = function() {
  19277. };
  19278. /**
  19279. * Render a geometry with a custom renderer.
  19280. *
  19281. * @param {ol.geom.SimpleGeometry} geometry Geometry.
  19282. * @param {ol.Feature|ol.render.Feature} feature Feature.
  19283. * @param {Function} renderer Renderer.
  19284. */
  19285. ol.render.VectorContext.prototype.drawCustom = function(geometry, feature, renderer) {};
  19286. /**
  19287. * Render a geometry.
  19288. *
  19289. * @param {ol.geom.Geometry} geometry The geometry to render.
  19290. */
  19291. ol.render.VectorContext.prototype.drawGeometry = function(geometry) {};
  19292. /**
  19293. * Set the rendering style.
  19294. *
  19295. * @param {ol.style.Style} style The rendering style.
  19296. */
  19297. ol.render.VectorContext.prototype.setStyle = function(style) {};
  19298. /**
  19299. * @param {ol.geom.Circle} circleGeometry Circle geometry.
  19300. * @param {ol.Feature} feature Feature.
  19301. */
  19302. ol.render.VectorContext.prototype.drawCircle = function(circleGeometry, feature) {};
  19303. /**
  19304. * @param {ol.Feature} feature Feature.
  19305. * @param {ol.style.Style} style Style.
  19306. */
  19307. ol.render.VectorContext.prototype.drawFeature = function(feature, style) {};
  19308. /**
  19309. * @param {ol.geom.GeometryCollection} geometryCollectionGeometry Geometry
  19310. * collection.
  19311. * @param {ol.Feature} feature Feature.
  19312. */
  19313. ol.render.VectorContext.prototype.drawGeometryCollection = function(geometryCollectionGeometry, feature) {};
  19314. /**
  19315. * @param {ol.geom.LineString|ol.render.Feature} lineStringGeometry Line
  19316. * string geometry.
  19317. * @param {ol.Feature|ol.render.Feature} feature Feature.
  19318. */
  19319. ol.render.VectorContext.prototype.drawLineString = function(lineStringGeometry, feature) {};
  19320. /**
  19321. * @param {ol.geom.MultiLineString|ol.render.Feature} multiLineStringGeometry
  19322. * MultiLineString geometry.
  19323. * @param {ol.Feature|ol.render.Feature} feature Feature.
  19324. */
  19325. ol.render.VectorContext.prototype.drawMultiLineString = function(multiLineStringGeometry, feature) {};
  19326. /**
  19327. * @param {ol.geom.MultiPoint|ol.render.Feature} multiPointGeometry MultiPoint
  19328. * geometry.
  19329. * @param {ol.Feature|ol.render.Feature} feature Feature.
  19330. */
  19331. ol.render.VectorContext.prototype.drawMultiPoint = function(multiPointGeometry, feature) {};
  19332. /**
  19333. * @param {ol.geom.MultiPolygon} multiPolygonGeometry MultiPolygon geometry.
  19334. * @param {ol.Feature|ol.render.Feature} feature Feature.
  19335. */
  19336. ol.render.VectorContext.prototype.drawMultiPolygon = function(multiPolygonGeometry, feature) {};
  19337. /**
  19338. * @param {ol.geom.Point|ol.render.Feature} pointGeometry Point geometry.
  19339. * @param {ol.Feature|ol.render.Feature} feature Feature.
  19340. */
  19341. ol.render.VectorContext.prototype.drawPoint = function(pointGeometry, feature) {};
  19342. /**
  19343. * @param {ol.geom.Polygon|ol.render.Feature} polygonGeometry Polygon
  19344. * geometry.
  19345. * @param {ol.Feature|ol.render.Feature} feature Feature.
  19346. */
  19347. ol.render.VectorContext.prototype.drawPolygon = function(polygonGeometry, feature) {};
  19348. /**
  19349. * @param {Array.<number>} flatCoordinates Flat coordinates.
  19350. * @param {number} offset Offset.
  19351. * @param {number} end End.
  19352. * @param {number} stride Stride.
  19353. * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
  19354. * @param {ol.Feature|ol.render.Feature} feature Feature.
  19355. */
  19356. ol.render.VectorContext.prototype.drawText = function(flatCoordinates, offset, end, stride, geometry, feature) {};
  19357. /**
  19358. * @param {ol.style.Fill} fillStyle Fill style.
  19359. * @param {ol.style.Stroke} strokeStyle Stroke style.
  19360. */
  19361. ol.render.VectorContext.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {};
  19362. /**
  19363. * @param {ol.style.Image} imageStyle Image style.
  19364. */
  19365. ol.render.VectorContext.prototype.setImageStyle = function(imageStyle) {};
  19366. /**
  19367. * @param {ol.style.Text} textStyle Text style.
  19368. */
  19369. ol.render.VectorContext.prototype.setTextStyle = function(textStyle) {};
  19370. // FIXME test, especially polygons with holes and multipolygons
  19371. // FIXME need to handle large thick features (where pixel size matters)
  19372. // FIXME add offset and end to ol.geom.flat.transform.transform2D?
  19373. goog.provide('ol.render.canvas.Immediate');
  19374. goog.require('ol');
  19375. goog.require('ol.array');
  19376. goog.require('ol.colorlike');
  19377. goog.require('ol.extent');
  19378. goog.require('ol.geom.GeometryType');
  19379. goog.require('ol.geom.SimpleGeometry');
  19380. goog.require('ol.geom.flat.transform');
  19381. goog.require('ol.has');
  19382. goog.require('ol.render.VectorContext');
  19383. goog.require('ol.render.canvas');
  19384. goog.require('ol.transform');
  19385. /**
  19386. * @classdesc
  19387. * A concrete subclass of {@link ol.render.VectorContext} that implements
  19388. * direct rendering of features and geometries to an HTML5 Canvas context.
  19389. * Instances of this class are created internally by the library and
  19390. * provided to application code as vectorContext member of the
  19391. * {@link ol.render.Event} object associated with postcompose, precompose and
  19392. * render events emitted by layers and maps.
  19393. *
  19394. * @constructor
  19395. * @extends {ol.render.VectorContext}
  19396. * @param {CanvasRenderingContext2D} context Context.
  19397. * @param {number} pixelRatio Pixel ratio.
  19398. * @param {ol.Extent} extent Extent.
  19399. * @param {ol.Transform} transform Transform.
  19400. * @param {number} viewRotation View rotation.
  19401. * @struct
  19402. */
  19403. ol.render.canvas.Immediate = function(context, pixelRatio, extent, transform, viewRotation) {
  19404. ol.render.VectorContext.call(this);
  19405. /**
  19406. * @private
  19407. * @type {CanvasRenderingContext2D}
  19408. */
  19409. this.context_ = context;
  19410. /**
  19411. * @private
  19412. * @type {number}
  19413. */
  19414. this.pixelRatio_ = pixelRatio;
  19415. /**
  19416. * @private
  19417. * @type {ol.Extent}
  19418. */
  19419. this.extent_ = extent;
  19420. /**
  19421. * @private
  19422. * @type {ol.Transform}
  19423. */
  19424. this.transform_ = transform;
  19425. /**
  19426. * @private
  19427. * @type {number}
  19428. */
  19429. this.viewRotation_ = viewRotation;
  19430. /**
  19431. * @private
  19432. * @type {?ol.CanvasFillState}
  19433. */
  19434. this.contextFillState_ = null;
  19435. /**
  19436. * @private
  19437. * @type {?ol.CanvasStrokeState}
  19438. */
  19439. this.contextStrokeState_ = null;
  19440. /**
  19441. * @private
  19442. * @type {?ol.CanvasTextState}
  19443. */
  19444. this.contextTextState_ = null;
  19445. /**
  19446. * @private
  19447. * @type {?ol.CanvasFillState}
  19448. */
  19449. this.fillState_ = null;
  19450. /**
  19451. * @private
  19452. * @type {?ol.CanvasStrokeState}
  19453. */
  19454. this.strokeState_ = null;
  19455. /**
  19456. * @private
  19457. * @type {HTMLCanvasElement|HTMLVideoElement|Image}
  19458. */
  19459. this.image_ = null;
  19460. /**
  19461. * @private
  19462. * @type {number}
  19463. */
  19464. this.imageAnchorX_ = 0;
  19465. /**
  19466. * @private
  19467. * @type {number}
  19468. */
  19469. this.imageAnchorY_ = 0;
  19470. /**
  19471. * @private
  19472. * @type {number}
  19473. */
  19474. this.imageHeight_ = 0;
  19475. /**
  19476. * @private
  19477. * @type {number}
  19478. */
  19479. this.imageOpacity_ = 0;
  19480. /**
  19481. * @private
  19482. * @type {number}
  19483. */
  19484. this.imageOriginX_ = 0;
  19485. /**
  19486. * @private
  19487. * @type {number}
  19488. */
  19489. this.imageOriginY_ = 0;
  19490. /**
  19491. * @private
  19492. * @type {boolean}
  19493. */
  19494. this.imageRotateWithView_ = false;
  19495. /**
  19496. * @private
  19497. * @type {number}
  19498. */
  19499. this.imageRotation_ = 0;
  19500. /**
  19501. * @private
  19502. * @type {number}
  19503. */
  19504. this.imageScale_ = 0;
  19505. /**
  19506. * @private
  19507. * @type {boolean}
  19508. */
  19509. this.imageSnapToPixel_ = false;
  19510. /**
  19511. * @private
  19512. * @type {number}
  19513. */
  19514. this.imageWidth_ = 0;
  19515. /**
  19516. * @private
  19517. * @type {string}
  19518. */
  19519. this.text_ = '';
  19520. /**
  19521. * @private
  19522. * @type {number}
  19523. */
  19524. this.textOffsetX_ = 0;
  19525. /**
  19526. * @private
  19527. * @type {number}
  19528. */
  19529. this.textOffsetY_ = 0;
  19530. /**
  19531. * @private
  19532. * @type {boolean}
  19533. */
  19534. this.textRotateWithView_ = false;
  19535. /**
  19536. * @private
  19537. * @type {number}
  19538. */
  19539. this.textRotation_ = 0;
  19540. /**
  19541. * @private
  19542. * @type {number}
  19543. */
  19544. this.textScale_ = 0;
  19545. /**
  19546. * @private
  19547. * @type {?ol.CanvasFillState}
  19548. */
  19549. this.textFillState_ = null;
  19550. /**
  19551. * @private
  19552. * @type {?ol.CanvasStrokeState}
  19553. */
  19554. this.textStrokeState_ = null;
  19555. /**
  19556. * @private
  19557. * @type {?ol.CanvasTextState}
  19558. */
  19559. this.textState_ = null;
  19560. /**
  19561. * @private
  19562. * @type {Array.<number>}
  19563. */
  19564. this.pixelCoordinates_ = [];
  19565. /**
  19566. * @private
  19567. * @type {ol.Transform}
  19568. */
  19569. this.tmpLocalTransform_ = ol.transform.create();
  19570. };
  19571. ol.inherits(ol.render.canvas.Immediate, ol.render.VectorContext);
  19572. /**
  19573. * @param {Array.<number>} flatCoordinates Flat coordinates.
  19574. * @param {number} offset Offset.
  19575. * @param {number} end End.
  19576. * @param {number} stride Stride.
  19577. * @private
  19578. */
  19579. ol.render.canvas.Immediate.prototype.drawImages_ = function(flatCoordinates, offset, end, stride) {
  19580. if (!this.image_) {
  19581. return;
  19582. }
  19583. var pixelCoordinates = ol.geom.flat.transform.transform2D(
  19584. flatCoordinates, offset, end, 2, this.transform_,
  19585. this.pixelCoordinates_);
  19586. var context = this.context_;
  19587. var localTransform = this.tmpLocalTransform_;
  19588. var alpha = context.globalAlpha;
  19589. if (this.imageOpacity_ != 1) {
  19590. context.globalAlpha = alpha * this.imageOpacity_;
  19591. }
  19592. var rotation = this.imageRotation_;
  19593. if (this.imageRotateWithView_) {
  19594. rotation += this.viewRotation_;
  19595. }
  19596. var i, ii;
  19597. for (i = 0, ii = pixelCoordinates.length; i < ii; i += 2) {
  19598. var x = pixelCoordinates[i] - this.imageAnchorX_;
  19599. var y = pixelCoordinates[i + 1] - this.imageAnchorY_;
  19600. if (this.imageSnapToPixel_) {
  19601. x = Math.round(x);
  19602. y = Math.round(y);
  19603. }
  19604. if (rotation !== 0 || this.imageScale_ != 1) {
  19605. var centerX = x + this.imageAnchorX_;
  19606. var centerY = y + this.imageAnchorY_;
  19607. ol.transform.compose(localTransform,
  19608. centerX, centerY,
  19609. this.imageScale_, this.imageScale_,
  19610. rotation,
  19611. -centerX, -centerY);
  19612. context.setTransform.apply(context, localTransform);
  19613. }
  19614. context.drawImage(this.image_, this.imageOriginX_, this.imageOriginY_,
  19615. this.imageWidth_, this.imageHeight_, x, y,
  19616. this.imageWidth_, this.imageHeight_);
  19617. }
  19618. if (rotation !== 0 || this.imageScale_ != 1) {
  19619. context.setTransform(1, 0, 0, 1, 0, 0);
  19620. }
  19621. if (this.imageOpacity_ != 1) {
  19622. context.globalAlpha = alpha;
  19623. }
  19624. };
  19625. /**
  19626. * @param {Array.<number>} flatCoordinates Flat coordinates.
  19627. * @param {number} offset Offset.
  19628. * @param {number} end End.
  19629. * @param {number} stride Stride.
  19630. * @private
  19631. */
  19632. ol.render.canvas.Immediate.prototype.drawText_ = function(flatCoordinates, offset, end, stride) {
  19633. if (!this.textState_ || this.text_ === '') {
  19634. return;
  19635. }
  19636. if (this.textFillState_) {
  19637. this.setContextFillState_(this.textFillState_);
  19638. }
  19639. if (this.textStrokeState_) {
  19640. this.setContextStrokeState_(this.textStrokeState_);
  19641. }
  19642. this.setContextTextState_(this.textState_);
  19643. var pixelCoordinates = ol.geom.flat.transform.transform2D(
  19644. flatCoordinates, offset, end, stride, this.transform_,
  19645. this.pixelCoordinates_);
  19646. var context = this.context_;
  19647. var rotation = this.textRotation_;
  19648. if (this.textRotateWithView_) {
  19649. rotation += this.viewRotation_;
  19650. }
  19651. for (; offset < end; offset += stride) {
  19652. var x = pixelCoordinates[offset] + this.textOffsetX_;
  19653. var y = pixelCoordinates[offset + 1] + this.textOffsetY_;
  19654. if (rotation !== 0 || this.textScale_ != 1) {
  19655. var localTransform = ol.transform.compose(this.tmpLocalTransform_,
  19656. x, y,
  19657. this.textScale_, this.textScale_,
  19658. rotation,
  19659. -x, -y);
  19660. context.setTransform.apply(context, localTransform);
  19661. }
  19662. if (this.textStrokeState_) {
  19663. context.strokeText(this.text_, x, y);
  19664. }
  19665. if (this.textFillState_) {
  19666. context.fillText(this.text_, x, y);
  19667. }
  19668. }
  19669. if (rotation !== 0 || this.textScale_ != 1) {
  19670. context.setTransform(1, 0, 0, 1, 0, 0);
  19671. }
  19672. };
  19673. /**
  19674. * @param {Array.<number>} flatCoordinates Flat coordinates.
  19675. * @param {number} offset Offset.
  19676. * @param {number} end End.
  19677. * @param {number} stride Stride.
  19678. * @param {boolean} close Close.
  19679. * @private
  19680. * @return {number} end End.
  19681. */
  19682. ol.render.canvas.Immediate.prototype.moveToLineTo_ = function(flatCoordinates, offset, end, stride, close) {
  19683. var context = this.context_;
  19684. var pixelCoordinates = ol.geom.flat.transform.transform2D(
  19685. flatCoordinates, offset, end, stride, this.transform_,
  19686. this.pixelCoordinates_);
  19687. context.moveTo(pixelCoordinates[0], pixelCoordinates[1]);
  19688. var length = pixelCoordinates.length;
  19689. if (close) {
  19690. length -= 2;
  19691. }
  19692. for (var i = 2; i < length; i += 2) {
  19693. context.lineTo(pixelCoordinates[i], pixelCoordinates[i + 1]);
  19694. }
  19695. if (close) {
  19696. context.closePath();
  19697. }
  19698. return end;
  19699. };
  19700. /**
  19701. * @param {Array.<number>} flatCoordinates Flat coordinates.
  19702. * @param {number} offset Offset.
  19703. * @param {Array.<number>} ends Ends.
  19704. * @param {number} stride Stride.
  19705. * @private
  19706. * @return {number} End.
  19707. */
  19708. ol.render.canvas.Immediate.prototype.drawRings_ = function(flatCoordinates, offset, ends, stride) {
  19709. var i, ii;
  19710. for (i = 0, ii = ends.length; i < ii; ++i) {
  19711. offset = this.moveToLineTo_(
  19712. flatCoordinates, offset, ends[i], stride, true);
  19713. }
  19714. return offset;
  19715. };
  19716. /**
  19717. * Render a circle geometry into the canvas. Rendering is immediate and uses
  19718. * the current fill and stroke styles.
  19719. *
  19720. * @param {ol.geom.Circle} geometry Circle geometry.
  19721. * @override
  19722. * @api
  19723. */
  19724. ol.render.canvas.Immediate.prototype.drawCircle = function(geometry) {
  19725. if (!ol.extent.intersects(this.extent_, geometry.getExtent())) {
  19726. return;
  19727. }
  19728. if (this.fillState_ || this.strokeState_) {
  19729. if (this.fillState_) {
  19730. this.setContextFillState_(this.fillState_);
  19731. }
  19732. if (this.strokeState_) {
  19733. this.setContextStrokeState_(this.strokeState_);
  19734. }
  19735. var pixelCoordinates = ol.geom.SimpleGeometry.transform2D(
  19736. geometry, this.transform_, this.pixelCoordinates_);
  19737. var dx = pixelCoordinates[2] - pixelCoordinates[0];
  19738. var dy = pixelCoordinates[3] - pixelCoordinates[1];
  19739. var radius = Math.sqrt(dx * dx + dy * dy);
  19740. var context = this.context_;
  19741. context.beginPath();
  19742. context.arc(
  19743. pixelCoordinates[0], pixelCoordinates[1], radius, 0, 2 * Math.PI);
  19744. if (this.fillState_) {
  19745. context.fill();
  19746. }
  19747. if (this.strokeState_) {
  19748. context.stroke();
  19749. }
  19750. }
  19751. if (this.text_ !== '') {
  19752. this.drawText_(geometry.getCenter(), 0, 2, 2);
  19753. }
  19754. };
  19755. /**
  19756. * Set the rendering style. Note that since this is an immediate rendering API,
  19757. * any `zIndex` on the provided style will be ignored.
  19758. *
  19759. * @param {ol.style.Style} style The rendering style.
  19760. * @override
  19761. * @api
  19762. */
  19763. ol.render.canvas.Immediate.prototype.setStyle = function(style) {
  19764. this.setFillStrokeStyle(style.getFill(), style.getStroke());
  19765. this.setImageStyle(style.getImage());
  19766. this.setTextStyle(style.getText());
  19767. };
  19768. /**
  19769. * Render a geometry into the canvas. Call
  19770. * {@link ol.render.canvas.Immediate#setStyle} first to set the rendering style.
  19771. *
  19772. * @param {ol.geom.Geometry|ol.render.Feature} geometry The geometry to render.
  19773. * @override
  19774. * @api
  19775. */
  19776. ol.render.canvas.Immediate.prototype.drawGeometry = function(geometry) {
  19777. var type = geometry.getType();
  19778. switch (type) {
  19779. case ol.geom.GeometryType.POINT:
  19780. this.drawPoint(/** @type {ol.geom.Point} */ (geometry));
  19781. break;
  19782. case ol.geom.GeometryType.LINE_STRING:
  19783. this.drawLineString(/** @type {ol.geom.LineString} */ (geometry));
  19784. break;
  19785. case ol.geom.GeometryType.POLYGON:
  19786. this.drawPolygon(/** @type {ol.geom.Polygon} */ (geometry));
  19787. break;
  19788. case ol.geom.GeometryType.MULTI_POINT:
  19789. this.drawMultiPoint(/** @type {ol.geom.MultiPoint} */ (geometry));
  19790. break;
  19791. case ol.geom.GeometryType.MULTI_LINE_STRING:
  19792. this.drawMultiLineString(/** @type {ol.geom.MultiLineString} */ (geometry));
  19793. break;
  19794. case ol.geom.GeometryType.MULTI_POLYGON:
  19795. this.drawMultiPolygon(/** @type {ol.geom.MultiPolygon} */ (geometry));
  19796. break;
  19797. case ol.geom.GeometryType.GEOMETRY_COLLECTION:
  19798. this.drawGeometryCollection(/** @type {ol.geom.GeometryCollection} */ (geometry));
  19799. break;
  19800. case ol.geom.GeometryType.CIRCLE:
  19801. this.drawCircle(/** @type {ol.geom.Circle} */ (geometry));
  19802. break;
  19803. default:
  19804. }
  19805. };
  19806. /**
  19807. * Render a feature into the canvas. Note that any `zIndex` on the provided
  19808. * style will be ignored - features are rendered immediately in the order that
  19809. * this method is called. If you need `zIndex` support, you should be using an
  19810. * {@link ol.layer.Vector} instead.
  19811. *
  19812. * @param {ol.Feature} feature Feature.
  19813. * @param {ol.style.Style} style Style.
  19814. * @override
  19815. * @api
  19816. */
  19817. ol.render.canvas.Immediate.prototype.drawFeature = function(feature, style) {
  19818. var geometry = style.getGeometryFunction()(feature);
  19819. if (!geometry ||
  19820. !ol.extent.intersects(this.extent_, geometry.getExtent())) {
  19821. return;
  19822. }
  19823. this.setStyle(style);
  19824. this.drawGeometry(geometry);
  19825. };
  19826. /**
  19827. * Render a GeometryCollection to the canvas. Rendering is immediate and
  19828. * uses the current styles appropriate for each geometry in the collection.
  19829. *
  19830. * @param {ol.geom.GeometryCollection} geometry Geometry collection.
  19831. * @override
  19832. */
  19833. ol.render.canvas.Immediate.prototype.drawGeometryCollection = function(geometry) {
  19834. var geometries = geometry.getGeometriesArray();
  19835. var i, ii;
  19836. for (i = 0, ii = geometries.length; i < ii; ++i) {
  19837. this.drawGeometry(geometries[i]);
  19838. }
  19839. };
  19840. /**
  19841. * Render a Point geometry into the canvas. Rendering is immediate and uses
  19842. * the current style.
  19843. *
  19844. * @param {ol.geom.Point|ol.render.Feature} geometry Point geometry.
  19845. * @override
  19846. */
  19847. ol.render.canvas.Immediate.prototype.drawPoint = function(geometry) {
  19848. var flatCoordinates = geometry.getFlatCoordinates();
  19849. var stride = geometry.getStride();
  19850. if (this.image_) {
  19851. this.drawImages_(flatCoordinates, 0, flatCoordinates.length, stride);
  19852. }
  19853. if (this.text_ !== '') {
  19854. this.drawText_(flatCoordinates, 0, flatCoordinates.length, stride);
  19855. }
  19856. };
  19857. /**
  19858. * Render a MultiPoint geometry into the canvas. Rendering is immediate and
  19859. * uses the current style.
  19860. *
  19861. * @param {ol.geom.MultiPoint|ol.render.Feature} geometry MultiPoint geometry.
  19862. * @override
  19863. */
  19864. ol.render.canvas.Immediate.prototype.drawMultiPoint = function(geometry) {
  19865. var flatCoordinates = geometry.getFlatCoordinates();
  19866. var stride = geometry.getStride();
  19867. if (this.image_) {
  19868. this.drawImages_(flatCoordinates, 0, flatCoordinates.length, stride);
  19869. }
  19870. if (this.text_ !== '') {
  19871. this.drawText_(flatCoordinates, 0, flatCoordinates.length, stride);
  19872. }
  19873. };
  19874. /**
  19875. * Render a LineString into the canvas. Rendering is immediate and uses
  19876. * the current style.
  19877. *
  19878. * @param {ol.geom.LineString|ol.render.Feature} geometry LineString geometry.
  19879. * @override
  19880. */
  19881. ol.render.canvas.Immediate.prototype.drawLineString = function(geometry) {
  19882. if (!ol.extent.intersects(this.extent_, geometry.getExtent())) {
  19883. return;
  19884. }
  19885. if (this.strokeState_) {
  19886. this.setContextStrokeState_(this.strokeState_);
  19887. var context = this.context_;
  19888. var flatCoordinates = geometry.getFlatCoordinates();
  19889. context.beginPath();
  19890. this.moveToLineTo_(flatCoordinates, 0, flatCoordinates.length,
  19891. geometry.getStride(), false);
  19892. context.stroke();
  19893. }
  19894. if (this.text_ !== '') {
  19895. var flatMidpoint = geometry.getFlatMidpoint();
  19896. this.drawText_(flatMidpoint, 0, 2, 2);
  19897. }
  19898. };
  19899. /**
  19900. * Render a MultiLineString geometry into the canvas. Rendering is immediate
  19901. * and uses the current style.
  19902. *
  19903. * @param {ol.geom.MultiLineString|ol.render.Feature} geometry MultiLineString
  19904. * geometry.
  19905. * @override
  19906. */
  19907. ol.render.canvas.Immediate.prototype.drawMultiLineString = function(geometry) {
  19908. var geometryExtent = geometry.getExtent();
  19909. if (!ol.extent.intersects(this.extent_, geometryExtent)) {
  19910. return;
  19911. }
  19912. if (this.strokeState_) {
  19913. this.setContextStrokeState_(this.strokeState_);
  19914. var context = this.context_;
  19915. var flatCoordinates = geometry.getFlatCoordinates();
  19916. var offset = 0;
  19917. var ends = geometry.getEnds();
  19918. var stride = geometry.getStride();
  19919. context.beginPath();
  19920. var i, ii;
  19921. for (i = 0, ii = ends.length; i < ii; ++i) {
  19922. offset = this.moveToLineTo_(
  19923. flatCoordinates, offset, ends[i], stride, false);
  19924. }
  19925. context.stroke();
  19926. }
  19927. if (this.text_ !== '') {
  19928. var flatMidpoints = geometry.getFlatMidpoints();
  19929. this.drawText_(flatMidpoints, 0, flatMidpoints.length, 2);
  19930. }
  19931. };
  19932. /**
  19933. * Render a Polygon geometry into the canvas. Rendering is immediate and uses
  19934. * the current style.
  19935. *
  19936. * @param {ol.geom.Polygon|ol.render.Feature} geometry Polygon geometry.
  19937. * @override
  19938. */
  19939. ol.render.canvas.Immediate.prototype.drawPolygon = function(geometry) {
  19940. if (!ol.extent.intersects(this.extent_, geometry.getExtent())) {
  19941. return;
  19942. }
  19943. if (this.strokeState_ || this.fillState_) {
  19944. if (this.fillState_) {
  19945. this.setContextFillState_(this.fillState_);
  19946. }
  19947. if (this.strokeState_) {
  19948. this.setContextStrokeState_(this.strokeState_);
  19949. }
  19950. var context = this.context_;
  19951. context.beginPath();
  19952. this.drawRings_(geometry.getOrientedFlatCoordinates(),
  19953. 0, geometry.getEnds(), geometry.getStride());
  19954. if (this.fillState_) {
  19955. context.fill();
  19956. }
  19957. if (this.strokeState_) {
  19958. context.stroke();
  19959. }
  19960. }
  19961. if (this.text_ !== '') {
  19962. var flatInteriorPoint = geometry.getFlatInteriorPoint();
  19963. this.drawText_(flatInteriorPoint, 0, 2, 2);
  19964. }
  19965. };
  19966. /**
  19967. * Render MultiPolygon geometry into the canvas. Rendering is immediate and
  19968. * uses the current style.
  19969. * @param {ol.geom.MultiPolygon} geometry MultiPolygon geometry.
  19970. * @override
  19971. */
  19972. ol.render.canvas.Immediate.prototype.drawMultiPolygon = function(geometry) {
  19973. if (!ol.extent.intersects(this.extent_, geometry.getExtent())) {
  19974. return;
  19975. }
  19976. if (this.strokeState_ || this.fillState_) {
  19977. if (this.fillState_) {
  19978. this.setContextFillState_(this.fillState_);
  19979. }
  19980. if (this.strokeState_) {
  19981. this.setContextStrokeState_(this.strokeState_);
  19982. }
  19983. var context = this.context_;
  19984. var flatCoordinates = geometry.getOrientedFlatCoordinates();
  19985. var offset = 0;
  19986. var endss = geometry.getEndss();
  19987. var stride = geometry.getStride();
  19988. var i, ii;
  19989. context.beginPath();
  19990. for (i = 0, ii = endss.length; i < ii; ++i) {
  19991. var ends = endss[i];
  19992. offset = this.drawRings_(flatCoordinates, offset, ends, stride);
  19993. }
  19994. if (this.fillState_) {
  19995. context.fill();
  19996. }
  19997. if (this.strokeState_) {
  19998. context.stroke();
  19999. }
  20000. }
  20001. if (this.text_ !== '') {
  20002. var flatInteriorPoints = geometry.getFlatInteriorPoints();
  20003. this.drawText_(flatInteriorPoints, 0, flatInteriorPoints.length, 2);
  20004. }
  20005. };
  20006. /**
  20007. * @param {ol.CanvasFillState} fillState Fill state.
  20008. * @private
  20009. */
  20010. ol.render.canvas.Immediate.prototype.setContextFillState_ = function(fillState) {
  20011. var context = this.context_;
  20012. var contextFillState = this.contextFillState_;
  20013. if (!contextFillState) {
  20014. context.fillStyle = fillState.fillStyle;
  20015. this.contextFillState_ = {
  20016. fillStyle: fillState.fillStyle
  20017. };
  20018. } else {
  20019. if (contextFillState.fillStyle != fillState.fillStyle) {
  20020. contextFillState.fillStyle = context.fillStyle = fillState.fillStyle;
  20021. }
  20022. }
  20023. };
  20024. /**
  20025. * @param {ol.CanvasStrokeState} strokeState Stroke state.
  20026. * @private
  20027. */
  20028. ol.render.canvas.Immediate.prototype.setContextStrokeState_ = function(strokeState) {
  20029. var context = this.context_;
  20030. var contextStrokeState = this.contextStrokeState_;
  20031. if (!contextStrokeState) {
  20032. context.lineCap = strokeState.lineCap;
  20033. if (ol.has.CANVAS_LINE_DASH) {
  20034. context.setLineDash(strokeState.lineDash);
  20035. context.lineDashOffset = strokeState.lineDashOffset;
  20036. }
  20037. context.lineJoin = strokeState.lineJoin;
  20038. context.lineWidth = strokeState.lineWidth;
  20039. context.miterLimit = strokeState.miterLimit;
  20040. context.strokeStyle = strokeState.strokeStyle;
  20041. this.contextStrokeState_ = {
  20042. lineCap: strokeState.lineCap,
  20043. lineDash: strokeState.lineDash,
  20044. lineDashOffset: strokeState.lineDashOffset,
  20045. lineJoin: strokeState.lineJoin,
  20046. lineWidth: strokeState.lineWidth,
  20047. miterLimit: strokeState.miterLimit,
  20048. strokeStyle: strokeState.strokeStyle
  20049. };
  20050. } else {
  20051. if (contextStrokeState.lineCap != strokeState.lineCap) {
  20052. contextStrokeState.lineCap = context.lineCap = strokeState.lineCap;
  20053. }
  20054. if (ol.has.CANVAS_LINE_DASH) {
  20055. if (!ol.array.equals(
  20056. contextStrokeState.lineDash, strokeState.lineDash)) {
  20057. context.setLineDash(contextStrokeState.lineDash = strokeState.lineDash);
  20058. }
  20059. if (contextStrokeState.lineDashOffset != strokeState.lineDashOffset) {
  20060. contextStrokeState.lineDashOffset = context.lineDashOffset =
  20061. strokeState.lineDashOffset;
  20062. }
  20063. }
  20064. if (contextStrokeState.lineJoin != strokeState.lineJoin) {
  20065. contextStrokeState.lineJoin = context.lineJoin = strokeState.lineJoin;
  20066. }
  20067. if (contextStrokeState.lineWidth != strokeState.lineWidth) {
  20068. contextStrokeState.lineWidth = context.lineWidth = strokeState.lineWidth;
  20069. }
  20070. if (contextStrokeState.miterLimit != strokeState.miterLimit) {
  20071. contextStrokeState.miterLimit = context.miterLimit =
  20072. strokeState.miterLimit;
  20073. }
  20074. if (contextStrokeState.strokeStyle != strokeState.strokeStyle) {
  20075. contextStrokeState.strokeStyle = context.strokeStyle =
  20076. strokeState.strokeStyle;
  20077. }
  20078. }
  20079. };
  20080. /**
  20081. * @param {ol.CanvasTextState} textState Text state.
  20082. * @private
  20083. */
  20084. ol.render.canvas.Immediate.prototype.setContextTextState_ = function(textState) {
  20085. var context = this.context_;
  20086. var contextTextState = this.contextTextState_;
  20087. if (!contextTextState) {
  20088. context.font = textState.font;
  20089. context.textAlign = textState.textAlign;
  20090. context.textBaseline = textState.textBaseline;
  20091. this.contextTextState_ = {
  20092. font: textState.font,
  20093. textAlign: textState.textAlign,
  20094. textBaseline: textState.textBaseline
  20095. };
  20096. } else {
  20097. if (contextTextState.font != textState.font) {
  20098. contextTextState.font = context.font = textState.font;
  20099. }
  20100. if (contextTextState.textAlign != textState.textAlign) {
  20101. contextTextState.textAlign = context.textAlign = textState.textAlign;
  20102. }
  20103. if (contextTextState.textBaseline != textState.textBaseline) {
  20104. contextTextState.textBaseline = context.textBaseline =
  20105. textState.textBaseline;
  20106. }
  20107. }
  20108. };
  20109. /**
  20110. * Set the fill and stroke style for subsequent draw operations. To clear
  20111. * either fill or stroke styles, pass null for the appropriate parameter.
  20112. *
  20113. * @param {ol.style.Fill} fillStyle Fill style.
  20114. * @param {ol.style.Stroke} strokeStyle Stroke style.
  20115. * @override
  20116. */
  20117. ol.render.canvas.Immediate.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
  20118. if (!fillStyle) {
  20119. this.fillState_ = null;
  20120. } else {
  20121. var fillStyleColor = fillStyle.getColor();
  20122. this.fillState_ = {
  20123. fillStyle: ol.colorlike.asColorLike(fillStyleColor ?
  20124. fillStyleColor : ol.render.canvas.defaultFillStyle)
  20125. };
  20126. }
  20127. if (!strokeStyle) {
  20128. this.strokeState_ = null;
  20129. } else {
  20130. var strokeStyleColor = strokeStyle.getColor();
  20131. var strokeStyleLineCap = strokeStyle.getLineCap();
  20132. var strokeStyleLineDash = strokeStyle.getLineDash();
  20133. var strokeStyleLineDashOffset = strokeStyle.getLineDashOffset();
  20134. var strokeStyleLineJoin = strokeStyle.getLineJoin();
  20135. var strokeStyleWidth = strokeStyle.getWidth();
  20136. var strokeStyleMiterLimit = strokeStyle.getMiterLimit();
  20137. this.strokeState_ = {
  20138. lineCap: strokeStyleLineCap !== undefined ?
  20139. strokeStyleLineCap : ol.render.canvas.defaultLineCap,
  20140. lineDash: strokeStyleLineDash ?
  20141. strokeStyleLineDash : ol.render.canvas.defaultLineDash,
  20142. lineDashOffset: strokeStyleLineDashOffset ?
  20143. strokeStyleLineDashOffset : ol.render.canvas.defaultLineDashOffset,
  20144. lineJoin: strokeStyleLineJoin !== undefined ?
  20145. strokeStyleLineJoin : ol.render.canvas.defaultLineJoin,
  20146. lineWidth: this.pixelRatio_ * (strokeStyleWidth !== undefined ?
  20147. strokeStyleWidth : ol.render.canvas.defaultLineWidth),
  20148. miterLimit: strokeStyleMiterLimit !== undefined ?
  20149. strokeStyleMiterLimit : ol.render.canvas.defaultMiterLimit,
  20150. strokeStyle: ol.colorlike.asColorLike(strokeStyleColor ?
  20151. strokeStyleColor : ol.render.canvas.defaultStrokeStyle)
  20152. };
  20153. }
  20154. };
  20155. /**
  20156. * Set the image style for subsequent draw operations. Pass null to remove
  20157. * the image style.
  20158. *
  20159. * @param {ol.style.Image} imageStyle Image style.
  20160. * @override
  20161. */
  20162. ol.render.canvas.Immediate.prototype.setImageStyle = function(imageStyle) {
  20163. if (!imageStyle) {
  20164. this.image_ = null;
  20165. } else {
  20166. var imageAnchor = imageStyle.getAnchor();
  20167. // FIXME pixel ratio
  20168. var imageImage = imageStyle.getImage(1);
  20169. var imageOrigin = imageStyle.getOrigin();
  20170. var imageSize = imageStyle.getSize();
  20171. this.imageAnchorX_ = imageAnchor[0];
  20172. this.imageAnchorY_ = imageAnchor[1];
  20173. this.imageHeight_ = imageSize[1];
  20174. this.image_ = imageImage;
  20175. this.imageOpacity_ = imageStyle.getOpacity();
  20176. this.imageOriginX_ = imageOrigin[0];
  20177. this.imageOriginY_ = imageOrigin[1];
  20178. this.imageRotateWithView_ = imageStyle.getRotateWithView();
  20179. this.imageRotation_ = imageStyle.getRotation();
  20180. this.imageScale_ = imageStyle.getScale() * this.pixelRatio_;
  20181. this.imageSnapToPixel_ = imageStyle.getSnapToPixel();
  20182. this.imageWidth_ = imageSize[0];
  20183. }
  20184. };
  20185. /**
  20186. * Set the text style for subsequent draw operations. Pass null to
  20187. * remove the text style.
  20188. *
  20189. * @param {ol.style.Text} textStyle Text style.
  20190. * @override
  20191. */
  20192. ol.render.canvas.Immediate.prototype.setTextStyle = function(textStyle) {
  20193. if (!textStyle) {
  20194. this.text_ = '';
  20195. } else {
  20196. var textFillStyle = textStyle.getFill();
  20197. if (!textFillStyle) {
  20198. this.textFillState_ = null;
  20199. } else {
  20200. var textFillStyleColor = textFillStyle.getColor();
  20201. this.textFillState_ = {
  20202. fillStyle: ol.colorlike.asColorLike(textFillStyleColor ?
  20203. textFillStyleColor : ol.render.canvas.defaultFillStyle)
  20204. };
  20205. }
  20206. var textStrokeStyle = textStyle.getStroke();
  20207. if (!textStrokeStyle) {
  20208. this.textStrokeState_ = null;
  20209. } else {
  20210. var textStrokeStyleColor = textStrokeStyle.getColor();
  20211. var textStrokeStyleLineCap = textStrokeStyle.getLineCap();
  20212. var textStrokeStyleLineDash = textStrokeStyle.getLineDash();
  20213. var textStrokeStyleLineDashOffset = textStrokeStyle.getLineDashOffset();
  20214. var textStrokeStyleLineJoin = textStrokeStyle.getLineJoin();
  20215. var textStrokeStyleWidth = textStrokeStyle.getWidth();
  20216. var textStrokeStyleMiterLimit = textStrokeStyle.getMiterLimit();
  20217. this.textStrokeState_ = {
  20218. lineCap: textStrokeStyleLineCap !== undefined ?
  20219. textStrokeStyleLineCap : ol.render.canvas.defaultLineCap,
  20220. lineDash: textStrokeStyleLineDash ?
  20221. textStrokeStyleLineDash : ol.render.canvas.defaultLineDash,
  20222. lineDashOffset: textStrokeStyleLineDashOffset ?
  20223. textStrokeStyleLineDashOffset : ol.render.canvas.defaultLineDashOffset,
  20224. lineJoin: textStrokeStyleLineJoin !== undefined ?
  20225. textStrokeStyleLineJoin : ol.render.canvas.defaultLineJoin,
  20226. lineWidth: textStrokeStyleWidth !== undefined ?
  20227. textStrokeStyleWidth : ol.render.canvas.defaultLineWidth,
  20228. miterLimit: textStrokeStyleMiterLimit !== undefined ?
  20229. textStrokeStyleMiterLimit : ol.render.canvas.defaultMiterLimit,
  20230. strokeStyle: ol.colorlike.asColorLike(textStrokeStyleColor ?
  20231. textStrokeStyleColor : ol.render.canvas.defaultStrokeStyle)
  20232. };
  20233. }
  20234. var textFont = textStyle.getFont();
  20235. var textOffsetX = textStyle.getOffsetX();
  20236. var textOffsetY = textStyle.getOffsetY();
  20237. var textRotateWithView = textStyle.getRotateWithView();
  20238. var textRotation = textStyle.getRotation();
  20239. var textScale = textStyle.getScale();
  20240. var textText = textStyle.getText();
  20241. var textTextAlign = textStyle.getTextAlign();
  20242. var textTextBaseline = textStyle.getTextBaseline();
  20243. this.textState_ = {
  20244. font: textFont !== undefined ?
  20245. textFont : ol.render.canvas.defaultFont,
  20246. textAlign: textTextAlign !== undefined ?
  20247. textTextAlign : ol.render.canvas.defaultTextAlign,
  20248. textBaseline: textTextBaseline !== undefined ?
  20249. textTextBaseline : ol.render.canvas.defaultTextBaseline
  20250. };
  20251. this.text_ = textText !== undefined ? textText : '';
  20252. this.textOffsetX_ =
  20253. textOffsetX !== undefined ? (this.pixelRatio_ * textOffsetX) : 0;
  20254. this.textOffsetY_ =
  20255. textOffsetY !== undefined ? (this.pixelRatio_ * textOffsetY) : 0;
  20256. this.textRotateWithView_ = textRotateWithView !== undefined ? textRotateWithView : false;
  20257. this.textRotation_ = textRotation !== undefined ? textRotation : 0;
  20258. this.textScale_ = this.pixelRatio_ * (textScale !== undefined ?
  20259. textScale : 1);
  20260. }
  20261. };
  20262. // FIXME offset panning
  20263. goog.provide('ol.renderer.canvas.Map');
  20264. goog.require('ol.transform');
  20265. goog.require('ol');
  20266. goog.require('ol.array');
  20267. goog.require('ol.css');
  20268. goog.require('ol.dom');
  20269. goog.require('ol.layer.Layer');
  20270. goog.require('ol.render.Event');
  20271. goog.require('ol.render.EventType');
  20272. goog.require('ol.render.canvas');
  20273. goog.require('ol.render.canvas.Immediate');
  20274. goog.require('ol.renderer.Map');
  20275. goog.require('ol.renderer.Type');
  20276. goog.require('ol.source.State');
  20277. /**
  20278. * @constructor
  20279. * @extends {ol.renderer.Map}
  20280. * @param {Element} container Container.
  20281. * @param {ol.Map} map Map.
  20282. */
  20283. ol.renderer.canvas.Map = function(container, map) {
  20284. ol.renderer.Map.call(this, container, map);
  20285. /**
  20286. * @private
  20287. * @type {CanvasRenderingContext2D}
  20288. */
  20289. this.context_ = ol.dom.createCanvasContext2D();
  20290. /**
  20291. * @private
  20292. * @type {HTMLCanvasElement}
  20293. */
  20294. this.canvas_ = this.context_.canvas;
  20295. this.canvas_.style.width = '100%';
  20296. this.canvas_.style.height = '100%';
  20297. this.canvas_.style.display = 'block';
  20298. this.canvas_.className = ol.css.CLASS_UNSELECTABLE;
  20299. container.insertBefore(this.canvas_, container.childNodes[0] || null);
  20300. /**
  20301. * @private
  20302. * @type {boolean}
  20303. */
  20304. this.renderedVisible_ = true;
  20305. /**
  20306. * @private
  20307. * @type {ol.Transform}
  20308. */
  20309. this.transform_ = ol.transform.create();
  20310. };
  20311. ol.inherits(ol.renderer.canvas.Map, ol.renderer.Map);
  20312. /**
  20313. * @param {ol.render.EventType} type Event type.
  20314. * @param {olx.FrameState} frameState Frame state.
  20315. * @private
  20316. */
  20317. ol.renderer.canvas.Map.prototype.dispatchComposeEvent_ = function(type, frameState) {
  20318. var map = this.getMap();
  20319. var context = this.context_;
  20320. if (map.hasListener(type)) {
  20321. var extent = frameState.extent;
  20322. var pixelRatio = frameState.pixelRatio;
  20323. var viewState = frameState.viewState;
  20324. var rotation = viewState.rotation;
  20325. var transform = this.getTransform(frameState);
  20326. var vectorContext = new ol.render.canvas.Immediate(context, pixelRatio,
  20327. extent, transform, rotation);
  20328. var composeEvent = new ol.render.Event(type, vectorContext,
  20329. frameState, context, null);
  20330. map.dispatchEvent(composeEvent);
  20331. }
  20332. };
  20333. /**
  20334. * @param {olx.FrameState} frameState Frame state.
  20335. * @protected
  20336. * @return {!ol.Transform} Transform.
  20337. */
  20338. ol.renderer.canvas.Map.prototype.getTransform = function(frameState) {
  20339. var viewState = frameState.viewState;
  20340. var dx1 = this.canvas_.width / 2;
  20341. var dy1 = this.canvas_.height / 2;
  20342. var sx = frameState.pixelRatio / viewState.resolution;
  20343. var sy = -sx;
  20344. var angle = -viewState.rotation;
  20345. var dx2 = -viewState.center[0];
  20346. var dy2 = -viewState.center[1];
  20347. return ol.transform.compose(this.transform_, dx1, dy1, sx, sy, angle, dx2, dy2);
  20348. };
  20349. /**
  20350. * @inheritDoc
  20351. */
  20352. ol.renderer.canvas.Map.prototype.getType = function() {
  20353. return ol.renderer.Type.CANVAS;
  20354. };
  20355. /**
  20356. * @inheritDoc
  20357. */
  20358. ol.renderer.canvas.Map.prototype.renderFrame = function(frameState) {
  20359. if (!frameState) {
  20360. if (this.renderedVisible_) {
  20361. this.canvas_.style.display = 'none';
  20362. this.renderedVisible_ = false;
  20363. }
  20364. return;
  20365. }
  20366. var context = this.context_;
  20367. var pixelRatio = frameState.pixelRatio;
  20368. var width = Math.round(frameState.size[0] * pixelRatio);
  20369. var height = Math.round(frameState.size[1] * pixelRatio);
  20370. if (this.canvas_.width != width || this.canvas_.height != height) {
  20371. this.canvas_.width = width;
  20372. this.canvas_.height = height;
  20373. } else {
  20374. context.clearRect(0, 0, width, height);
  20375. }
  20376. var rotation = frameState.viewState.rotation;
  20377. this.calculateMatrices2D(frameState);
  20378. this.dispatchComposeEvent_(ol.render.EventType.PRECOMPOSE, frameState);
  20379. var layerStatesArray = frameState.layerStatesArray;
  20380. ol.array.stableSort(layerStatesArray, ol.renderer.Map.sortByZIndex);
  20381. if (rotation) {
  20382. context.save();
  20383. ol.render.canvas.rotateAtOffset(context, rotation, width / 2, height / 2);
  20384. }
  20385. var viewResolution = frameState.viewState.resolution;
  20386. var i, ii, layer, layerRenderer, layerState;
  20387. for (i = 0, ii = layerStatesArray.length; i < ii; ++i) {
  20388. layerState = layerStatesArray[i];
  20389. layer = layerState.layer;
  20390. layerRenderer = /** @type {ol.renderer.canvas.Layer} */ (this.getLayerRenderer(layer));
  20391. if (!ol.layer.Layer.visibleAtResolution(layerState, viewResolution) ||
  20392. layerState.sourceState != ol.source.State.READY) {
  20393. continue;
  20394. }
  20395. if (layerRenderer.prepareFrame(frameState, layerState)) {
  20396. layerRenderer.composeFrame(frameState, layerState, context);
  20397. }
  20398. }
  20399. if (rotation) {
  20400. context.restore();
  20401. }
  20402. this.dispatchComposeEvent_(
  20403. ol.render.EventType.POSTCOMPOSE, frameState);
  20404. if (!this.renderedVisible_) {
  20405. this.canvas_.style.display = '';
  20406. this.renderedVisible_ = true;
  20407. }
  20408. this.scheduleRemoveUnusedLayerRenderers(frameState);
  20409. this.scheduleExpireIconCache(frameState);
  20410. };
  20411. /**
  20412. * @inheritDoc
  20413. */
  20414. ol.renderer.canvas.Map.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg,
  20415. layerFilter, thisArg2) {
  20416. var result;
  20417. var viewState = frameState.viewState;
  20418. var viewResolution = viewState.resolution;
  20419. var layerStates = frameState.layerStatesArray;
  20420. var numLayers = layerStates.length;
  20421. var coordinate = ol.transform.apply(
  20422. frameState.pixelToCoordinateTransform, pixel.slice());
  20423. var i;
  20424. for (i = numLayers - 1; i >= 0; --i) {
  20425. var layerState = layerStates[i];
  20426. var layer = layerState.layer;
  20427. if (ol.layer.Layer.visibleAtResolution(layerState, viewResolution) &&
  20428. layerFilter.call(thisArg2, layer)) {
  20429. var layerRenderer = /** @type {ol.renderer.canvas.Layer} */ (this.getLayerRenderer(layer));
  20430. result = layerRenderer.forEachLayerAtCoordinate(
  20431. coordinate, frameState, callback, thisArg);
  20432. if (result) {
  20433. return result;
  20434. }
  20435. }
  20436. }
  20437. return undefined;
  20438. };
  20439. goog.provide('ol.render.ReplayType');
  20440. /**
  20441. * @enum {string}
  20442. */
  20443. ol.render.ReplayType = {
  20444. CIRCLE: 'Circle',
  20445. DEFAULT: 'Default',
  20446. IMAGE: 'Image',
  20447. LINE_STRING: 'LineString',
  20448. POLYGON: 'Polygon',
  20449. TEXT: 'Text'
  20450. };
  20451. goog.provide('ol.render.replay');
  20452. goog.require('ol.render.ReplayType');
  20453. /**
  20454. * @const
  20455. * @type {Array.<ol.render.ReplayType>}
  20456. */
  20457. ol.render.replay.ORDER = [
  20458. ol.render.ReplayType.POLYGON,
  20459. ol.render.ReplayType.CIRCLE,
  20460. ol.render.ReplayType.LINE_STRING,
  20461. ol.render.ReplayType.IMAGE,
  20462. ol.render.ReplayType.TEXT,
  20463. ol.render.ReplayType.DEFAULT
  20464. ];
  20465. goog.provide('ol.render.ReplayGroup');
  20466. /**
  20467. * Base class for replay groups.
  20468. * @constructor
  20469. * @abstract
  20470. */
  20471. ol.render.ReplayGroup = function() {};
  20472. /**
  20473. * @abstract
  20474. * @param {number|undefined} zIndex Z index.
  20475. * @param {ol.render.ReplayType} replayType Replay type.
  20476. * @return {ol.render.VectorContext} Replay.
  20477. */
  20478. ol.render.ReplayGroup.prototype.getReplay = function(zIndex, replayType) {};
  20479. /**
  20480. * @abstract
  20481. * @return {boolean} Is empty.
  20482. */
  20483. ol.render.ReplayGroup.prototype.isEmpty = function() {};
  20484. goog.provide('ol.webgl.Shader');
  20485. goog.require('ol');
  20486. goog.require('ol.functions');
  20487. if (ol.ENABLE_WEBGL) {
  20488. /**
  20489. * @constructor
  20490. * @abstract
  20491. * @param {string} source Source.
  20492. * @struct
  20493. */
  20494. ol.webgl.Shader = function(source) {
  20495. /**
  20496. * @private
  20497. * @type {string}
  20498. */
  20499. this.source_ = source;
  20500. };
  20501. /**
  20502. * @abstract
  20503. * @return {number} Type.
  20504. */
  20505. ol.webgl.Shader.prototype.getType = function() {};
  20506. /**
  20507. * @return {string} Source.
  20508. */
  20509. ol.webgl.Shader.prototype.getSource = function() {
  20510. return this.source_;
  20511. };
  20512. /**
  20513. * @return {boolean} Is animated?
  20514. */
  20515. ol.webgl.Shader.prototype.isAnimated = ol.functions.FALSE;
  20516. }
  20517. goog.provide('ol.webgl.Fragment');
  20518. goog.require('ol');
  20519. goog.require('ol.webgl');
  20520. goog.require('ol.webgl.Shader');
  20521. if (ol.ENABLE_WEBGL) {
  20522. /**
  20523. * @constructor
  20524. * @extends {ol.webgl.Shader}
  20525. * @param {string} source Source.
  20526. * @struct
  20527. */
  20528. ol.webgl.Fragment = function(source) {
  20529. ol.webgl.Shader.call(this, source);
  20530. };
  20531. ol.inherits(ol.webgl.Fragment, ol.webgl.Shader);
  20532. /**
  20533. * @inheritDoc
  20534. */
  20535. ol.webgl.Fragment.prototype.getType = function() {
  20536. return ol.webgl.FRAGMENT_SHADER;
  20537. };
  20538. }
  20539. goog.provide('ol.webgl.Vertex');
  20540. goog.require('ol');
  20541. goog.require('ol.webgl');
  20542. goog.require('ol.webgl.Shader');
  20543. if (ol.ENABLE_WEBGL) {
  20544. /**
  20545. * @constructor
  20546. * @extends {ol.webgl.Shader}
  20547. * @param {string} source Source.
  20548. * @struct
  20549. */
  20550. ol.webgl.Vertex = function(source) {
  20551. ol.webgl.Shader.call(this, source);
  20552. };
  20553. ol.inherits(ol.webgl.Vertex, ol.webgl.Shader);
  20554. /**
  20555. * @inheritDoc
  20556. */
  20557. ol.webgl.Vertex.prototype.getType = function() {
  20558. return ol.webgl.VERTEX_SHADER;
  20559. };
  20560. }
  20561. // This file is automatically generated, do not edit
  20562. /* eslint openlayers-internal/no-missing-requires: 0 */
  20563. goog.provide('ol.render.webgl.circlereplay.defaultshader');
  20564. goog.require('ol');
  20565. goog.require('ol.webgl.Fragment');
  20566. goog.require('ol.webgl.Vertex');
  20567. if (ol.ENABLE_WEBGL) {
  20568. /**
  20569. * @constructor
  20570. * @extends {ol.webgl.Fragment}
  20571. * @struct
  20572. */
  20573. ol.render.webgl.circlereplay.defaultshader.Fragment = function() {
  20574. ol.webgl.Fragment.call(this, ol.render.webgl.circlereplay.defaultshader.Fragment.SOURCE);
  20575. };
  20576. ol.inherits(ol.render.webgl.circlereplay.defaultshader.Fragment, ol.webgl.Fragment);
  20577. /**
  20578. * @const
  20579. * @type {string}
  20580. */
  20581. ol.render.webgl.circlereplay.defaultshader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_center;\nvarying vec2 v_offset;\nvarying float v_halfWidth;\nvarying float v_pixelRatio;\n\n\n\nuniform float u_opacity;\nuniform vec4 u_fillColor;\nuniform vec4 u_strokeColor;\nuniform vec2 u_size;\n\nvoid main(void) {\n vec2 windowCenter = vec2((v_center.x + 1.0) / 2.0 * u_size.x * v_pixelRatio,\n (v_center.y + 1.0) / 2.0 * u_size.y * v_pixelRatio);\n vec2 windowOffset = vec2((v_offset.x + 1.0) / 2.0 * u_size.x * v_pixelRatio,\n (v_offset.y + 1.0) / 2.0 * u_size.y * v_pixelRatio);\n float radius = length(windowCenter - windowOffset);\n float dist = length(windowCenter - gl_FragCoord.xy);\n if (dist > radius + v_halfWidth) {\n if (u_strokeColor.a == 0.0) {\n gl_FragColor = u_fillColor;\n } else {\n gl_FragColor = u_strokeColor;\n }\n gl_FragColor.a = gl_FragColor.a - (dist - (radius + v_halfWidth));\n } else if (u_fillColor.a == 0.0) {\n // Hooray, no fill, just stroke. We can use real antialiasing.\n gl_FragColor = u_strokeColor;\n if (dist < radius - v_halfWidth) {\n gl_FragColor.a = gl_FragColor.a - (radius - v_halfWidth - dist);\n }\n } else {\n gl_FragColor = u_fillColor;\n float strokeDist = radius - v_halfWidth;\n float antialias = 2.0 * v_pixelRatio;\n if (dist > strokeDist) {\n gl_FragColor = u_strokeColor;\n } else if (dist >= strokeDist - antialias) {\n float step = smoothstep(strokeDist - antialias, strokeDist, dist);\n gl_FragColor = mix(u_fillColor, u_strokeColor, step);\n }\n }\n gl_FragColor.a = gl_FragColor.a * u_opacity;\n if (gl_FragColor.a <= 0.0) {\n discard;\n }\n}\n';
  20582. /**
  20583. * @const
  20584. * @type {string}
  20585. */
  20586. ol.render.webgl.circlereplay.defaultshader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;varying vec2 b;varying float c;varying float d;uniform float m;uniform vec4 n;uniform vec4 o;uniform vec2 p;void main(void){vec2 windowCenter=vec2((a.x+1.0)/2.0*p.x*d,(a.y+1.0)/2.0*p.y*d);vec2 windowOffset=vec2((b.x+1.0)/2.0*p.x*d,(b.y+1.0)/2.0*p.y*d);float radius=length(windowCenter-windowOffset);float dist=length(windowCenter-gl_FragCoord.xy);if(dist>radius+c){if(o.a==0.0){gl_FragColor=n;}else{gl_FragColor=o;}gl_FragColor.a=gl_FragColor.a-(dist-(radius+c));}else if(n.a==0.0){gl_FragColor=o;if(dist<radius-c){gl_FragColor.a=gl_FragColor.a-(radius-c-dist);}} else{gl_FragColor=n;float strokeDist=radius-c;float antialias=2.0*d;if(dist>strokeDist){gl_FragColor=o;}else if(dist>=strokeDist-antialias){float step=smoothstep(strokeDist-antialias,strokeDist,dist);gl_FragColor=mix(n,o,step);}} gl_FragColor.a=gl_FragColor.a*m;if(gl_FragColor.a<=0.0){discard;}}';
  20587. /**
  20588. * @const
  20589. * @type {string}
  20590. */
  20591. ol.render.webgl.circlereplay.defaultshader.Fragment.SOURCE = ol.DEBUG_WEBGL ?
  20592. ol.render.webgl.circlereplay.defaultshader.Fragment.DEBUG_SOURCE :
  20593. ol.render.webgl.circlereplay.defaultshader.Fragment.OPTIMIZED_SOURCE;
  20594. ol.render.webgl.circlereplay.defaultshader.fragment = new ol.render.webgl.circlereplay.defaultshader.Fragment();
  20595. /**
  20596. * @constructor
  20597. * @extends {ol.webgl.Vertex}
  20598. * @struct
  20599. */
  20600. ol.render.webgl.circlereplay.defaultshader.Vertex = function() {
  20601. ol.webgl.Vertex.call(this, ol.render.webgl.circlereplay.defaultshader.Vertex.SOURCE);
  20602. };
  20603. ol.inherits(ol.render.webgl.circlereplay.defaultshader.Vertex, ol.webgl.Vertex);
  20604. /**
  20605. * @const
  20606. * @type {string}
  20607. */
  20608. ol.render.webgl.circlereplay.defaultshader.Vertex.DEBUG_SOURCE = 'varying vec2 v_center;\nvarying vec2 v_offset;\nvarying float v_halfWidth;\nvarying float v_pixelRatio;\n\n\nattribute vec2 a_position;\nattribute float a_instruction;\nattribute float a_radius;\n\nuniform mat4 u_projectionMatrix;\nuniform mat4 u_offsetScaleMatrix;\nuniform mat4 u_offsetRotateMatrix;\nuniform float u_lineWidth;\nuniform float u_pixelRatio;\n\nvoid main(void) {\n mat4 offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix;\n v_center = vec4(u_projectionMatrix * vec4(a_position, 0.0, 1.0)).xy;\n v_pixelRatio = u_pixelRatio;\n float lineWidth = u_lineWidth * u_pixelRatio;\n v_halfWidth = lineWidth / 2.0;\n if (lineWidth == 0.0) {\n lineWidth = 2.0 * u_pixelRatio;\n }\n vec2 offset;\n // Radius with anitaliasing (roughly).\n float radius = a_radius + 3.0 * u_pixelRatio;\n // Until we get gl_VertexID in WebGL, we store an instruction.\n if (a_instruction == 0.0) {\n // Offsetting the edges of the triangle by lineWidth / 2 is necessary, however\n // we should also leave some space for the antialiasing, thus we offset by lineWidth.\n offset = vec2(-1.0, 1.0);\n } else if (a_instruction == 1.0) {\n offset = vec2(-1.0, -1.0);\n } else if (a_instruction == 2.0) {\n offset = vec2(1.0, -1.0);\n } else {\n offset = vec2(1.0, 1.0);\n }\n\n gl_Position = u_projectionMatrix * vec4(a_position + offset * radius, 0.0, 1.0) +\n offsetMatrix * vec4(offset * lineWidth, 0.0, 0.0);\n v_offset = vec4(u_projectionMatrix * vec4(a_position.x + a_radius, a_position.y,\n 0.0, 1.0)).xy;\n\n if (distance(v_center, v_offset) > 20000.0) {\n gl_Position = vec4(v_center, 0.0, 1.0);\n }\n}\n\n\n';
  20609. /**
  20610. * @const
  20611. * @type {string}
  20612. */
  20613. ol.render.webgl.circlereplay.defaultshader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;varying vec2 b;varying float c;varying float d;attribute vec2 e;attribute float f;attribute float g;uniform mat4 h;uniform mat4 i;uniform mat4 j;uniform float k;uniform float l;void main(void){mat4 offsetMatrix=i*j;a=vec4(h*vec4(e,0.0,1.0)).xy;d=l;float lineWidth=k*l;c=lineWidth/2.0;if(lineWidth==0.0){lineWidth=2.0*l;}vec2 offset;float radius=g+3.0*l;if(f==0.0){offset=vec2(-1.0,1.0);}else if(f==1.0){offset=vec2(-1.0,-1.0);}else if(f==2.0){offset=vec2(1.0,-1.0);}else{offset=vec2(1.0,1.0);}gl_Position=h*vec4(e+offset*radius,0.0,1.0)+offsetMatrix*vec4(offset*lineWidth,0.0,0.0);b=vec4(h*vec4(e.x+g,e.y,0.0,1.0)).xy;if(distance(a,b)>20000.0){gl_Position=vec4(a,0.0,1.0);}}';
  20614. /**
  20615. * @const
  20616. * @type {string}
  20617. */
  20618. ol.render.webgl.circlereplay.defaultshader.Vertex.SOURCE = ol.DEBUG_WEBGL ?
  20619. ol.render.webgl.circlereplay.defaultshader.Vertex.DEBUG_SOURCE :
  20620. ol.render.webgl.circlereplay.defaultshader.Vertex.OPTIMIZED_SOURCE;
  20621. ol.render.webgl.circlereplay.defaultshader.vertex = new ol.render.webgl.circlereplay.defaultshader.Vertex();
  20622. /**
  20623. * @constructor
  20624. * @param {WebGLRenderingContext} gl GL.
  20625. * @param {WebGLProgram} program Program.
  20626. * @struct
  20627. */
  20628. ol.render.webgl.circlereplay.defaultshader.Locations = function(gl, program) {
  20629. /**
  20630. * @type {WebGLUniformLocation}
  20631. */
  20632. this.u_fillColor = gl.getUniformLocation(
  20633. program, ol.DEBUG_WEBGL ? 'u_fillColor' : 'n');
  20634. /**
  20635. * @type {WebGLUniformLocation}
  20636. */
  20637. this.u_lineWidth = gl.getUniformLocation(
  20638. program, ol.DEBUG_WEBGL ? 'u_lineWidth' : 'k');
  20639. /**
  20640. * @type {WebGLUniformLocation}
  20641. */
  20642. this.u_offsetRotateMatrix = gl.getUniformLocation(
  20643. program, ol.DEBUG_WEBGL ? 'u_offsetRotateMatrix' : 'j');
  20644. /**
  20645. * @type {WebGLUniformLocation}
  20646. */
  20647. this.u_offsetScaleMatrix = gl.getUniformLocation(
  20648. program, ol.DEBUG_WEBGL ? 'u_offsetScaleMatrix' : 'i');
  20649. /**
  20650. * @type {WebGLUniformLocation}
  20651. */
  20652. this.u_opacity = gl.getUniformLocation(
  20653. program, ol.DEBUG_WEBGL ? 'u_opacity' : 'm');
  20654. /**
  20655. * @type {WebGLUniformLocation}
  20656. */
  20657. this.u_pixelRatio = gl.getUniformLocation(
  20658. program, ol.DEBUG_WEBGL ? 'u_pixelRatio' : 'l');
  20659. /**
  20660. * @type {WebGLUniformLocation}
  20661. */
  20662. this.u_projectionMatrix = gl.getUniformLocation(
  20663. program, ol.DEBUG_WEBGL ? 'u_projectionMatrix' : 'h');
  20664. /**
  20665. * @type {WebGLUniformLocation}
  20666. */
  20667. this.u_size = gl.getUniformLocation(
  20668. program, ol.DEBUG_WEBGL ? 'u_size' : 'p');
  20669. /**
  20670. * @type {WebGLUniformLocation}
  20671. */
  20672. this.u_strokeColor = gl.getUniformLocation(
  20673. program, ol.DEBUG_WEBGL ? 'u_strokeColor' : 'o');
  20674. /**
  20675. * @type {number}
  20676. */
  20677. this.a_instruction = gl.getAttribLocation(
  20678. program, ol.DEBUG_WEBGL ? 'a_instruction' : 'f');
  20679. /**
  20680. * @type {number}
  20681. */
  20682. this.a_position = gl.getAttribLocation(
  20683. program, ol.DEBUG_WEBGL ? 'a_position' : 'e');
  20684. /**
  20685. * @type {number}
  20686. */
  20687. this.a_radius = gl.getAttribLocation(
  20688. program, ol.DEBUG_WEBGL ? 'a_radius' : 'g');
  20689. };
  20690. }
  20691. goog.provide('ol.vec.Mat4');
  20692. /**
  20693. * @return {Array.<number>} 4x4 matrix representing a 3D identity transform.
  20694. */
  20695. ol.vec.Mat4.create = function() {
  20696. return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
  20697. };
  20698. /**
  20699. * @param {Array.<number>} mat4 Flattened 4x4 matrix receiving the result.
  20700. * @param {ol.Transform} transform Transformation matrix.
  20701. * @return {Array.<number>} 2D transformation matrix as flattened 4x4 matrix.
  20702. */
  20703. ol.vec.Mat4.fromTransform = function(mat4, transform) {
  20704. mat4[0] = transform[0];
  20705. mat4[1] = transform[1];
  20706. mat4[4] = transform[2];
  20707. mat4[5] = transform[3];
  20708. mat4[12] = transform[4];
  20709. mat4[13] = transform[5];
  20710. return mat4;
  20711. };
  20712. goog.provide('ol.render.webgl.Replay');
  20713. goog.require('ol');
  20714. goog.require('ol.extent');
  20715. goog.require('ol.render.VectorContext');
  20716. goog.require('ol.transform');
  20717. goog.require('ol.vec.Mat4');
  20718. goog.require('ol.webgl');
  20719. if (ol.ENABLE_WEBGL) {
  20720. /**
  20721. * @constructor
  20722. * @abstract
  20723. * @extends {ol.render.VectorContext}
  20724. * @param {number} tolerance Tolerance.
  20725. * @param {ol.Extent} maxExtent Max extent.
  20726. * @struct
  20727. */
  20728. ol.render.webgl.Replay = function(tolerance, maxExtent) {
  20729. ol.render.VectorContext.call(this);
  20730. /**
  20731. * @protected
  20732. * @type {number}
  20733. */
  20734. this.tolerance = tolerance;
  20735. /**
  20736. * @protected
  20737. * @const
  20738. * @type {ol.Extent}
  20739. */
  20740. this.maxExtent = maxExtent;
  20741. /**
  20742. * The origin of the coordinate system for the point coordinates sent to
  20743. * the GPU. To eliminate jitter caused by precision problems in the GPU
  20744. * we use the "Rendering Relative to Eye" technique described in the "3D
  20745. * Engine Design for Virtual Globes" book.
  20746. * @protected
  20747. * @type {ol.Coordinate}
  20748. */
  20749. this.origin = ol.extent.getCenter(maxExtent);
  20750. /**
  20751. * @private
  20752. * @type {ol.Transform}
  20753. */
  20754. this.projectionMatrix_ = ol.transform.create();
  20755. /**
  20756. * @private
  20757. * @type {ol.Transform}
  20758. */
  20759. this.offsetRotateMatrix_ = ol.transform.create();
  20760. /**
  20761. * @private
  20762. * @type {ol.Transform}
  20763. */
  20764. this.offsetScaleMatrix_ = ol.transform.create();
  20765. /**
  20766. * @private
  20767. * @type {Array.<number>}
  20768. */
  20769. this.tmpMat4_ = ol.vec.Mat4.create();
  20770. /**
  20771. * @protected
  20772. * @type {Array.<number>}
  20773. */
  20774. this.indices = [];
  20775. /**
  20776. * @protected
  20777. * @type {?ol.webgl.Buffer}
  20778. */
  20779. this.indicesBuffer = null;
  20780. /**
  20781. * Start index per feature (the index).
  20782. * @protected
  20783. * @type {Array.<number>}
  20784. */
  20785. this.startIndices = [];
  20786. /**
  20787. * Start index per feature (the feature).
  20788. * @protected
  20789. * @type {Array.<ol.Feature|ol.render.Feature>}
  20790. */
  20791. this.startIndicesFeature = [];
  20792. /**
  20793. * @protected
  20794. * @type {Array.<number>}
  20795. */
  20796. this.vertices = [];
  20797. /**
  20798. * @protected
  20799. * @type {?ol.webgl.Buffer}
  20800. */
  20801. this.verticesBuffer = null;
  20802. /**
  20803. * Optional parameter for PolygonReplay instances.
  20804. * @protected
  20805. * @type {ol.render.webgl.LineStringReplay|undefined}
  20806. */
  20807. this.lineStringReplay = undefined;
  20808. };
  20809. ol.inherits(ol.render.webgl.Replay, ol.render.VectorContext);
  20810. /**
  20811. * @abstract
  20812. * @param {ol.webgl.Context} context WebGL context.
  20813. * @return {function()} Delete resources function.
  20814. */
  20815. ol.render.webgl.Replay.prototype.getDeleteResourcesFunction = function(context) {};
  20816. /**
  20817. * @abstract
  20818. * @param {ol.webgl.Context} context Context.
  20819. */
  20820. ol.render.webgl.Replay.prototype.finish = function(context) {};
  20821. /**
  20822. * @abstract
  20823. * @protected
  20824. * @param {WebGLRenderingContext} gl gl.
  20825. * @param {ol.webgl.Context} context Context.
  20826. * @param {ol.Size} size Size.
  20827. * @param {number} pixelRatio Pixel ratio.
  20828. * @return {ol.render.webgl.circlereplay.defaultshader.Locations|
  20829. ol.render.webgl.linestringreplay.defaultshader.Locations|
  20830. ol.render.webgl.polygonreplay.defaultshader.Locations|
  20831. ol.render.webgl.texturereplay.defaultshader.Locations} Locations.
  20832. */
  20833. ol.render.webgl.Replay.prototype.setUpProgram = function(gl, context, size, pixelRatio) {};
  20834. /**
  20835. * @abstract
  20836. * @protected
  20837. * @param {WebGLRenderingContext} gl gl.
  20838. * @param {ol.render.webgl.circlereplay.defaultshader.Locations|
  20839. ol.render.webgl.linestringreplay.defaultshader.Locations|
  20840. ol.render.webgl.polygonreplay.defaultshader.Locations|
  20841. ol.render.webgl.texturereplay.defaultshader.Locations} locations Locations.
  20842. */
  20843. ol.render.webgl.Replay.prototype.shutDownProgram = function(gl, locations) {};
  20844. /**
  20845. * @abstract
  20846. * @protected
  20847. * @param {WebGLRenderingContext} gl gl.
  20848. * @param {ol.webgl.Context} context Context.
  20849. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  20850. * to skip.
  20851. * @param {boolean} hitDetection Hit detection mode.
  20852. */
  20853. ol.render.webgl.Replay.prototype.drawReplay = function(gl, context, skippedFeaturesHash, hitDetection) {};
  20854. /**
  20855. * @abstract
  20856. * @protected
  20857. * @param {WebGLRenderingContext} gl gl.
  20858. * @param {ol.webgl.Context} context Context.
  20859. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  20860. * to skip.
  20861. * @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
  20862. * @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
  20863. * this extent are checked.
  20864. * @return {T|undefined} Callback result.
  20865. * @template T
  20866. */
  20867. ol.render.webgl.Replay.prototype.drawHitDetectionReplayOneByOne = function(gl, context, skippedFeaturesHash, featureCallback, opt_hitExtent) {};
  20868. /**
  20869. * @protected
  20870. * @param {WebGLRenderingContext} gl gl.
  20871. * @param {ol.webgl.Context} context Context.
  20872. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  20873. * to skip.
  20874. * @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
  20875. * @param {boolean} oneByOne Draw features one-by-one for the hit-detecion.
  20876. * @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
  20877. * this extent are checked.
  20878. * @return {T|undefined} Callback result.
  20879. * @template T
  20880. */
  20881. ol.render.webgl.Replay.prototype.drawHitDetectionReplay = function(gl, context, skippedFeaturesHash,
  20882. featureCallback, oneByOne, opt_hitExtent) {
  20883. if (!oneByOne) {
  20884. // draw all hit-detection features in "once" (by texture group)
  20885. return this.drawHitDetectionReplayAll(gl, context,
  20886. skippedFeaturesHash, featureCallback);
  20887. } else {
  20888. // draw hit-detection features one by one
  20889. return this.drawHitDetectionReplayOneByOne(gl, context,
  20890. skippedFeaturesHash, featureCallback, opt_hitExtent);
  20891. }
  20892. };
  20893. /**
  20894. * @protected
  20895. * @param {WebGLRenderingContext} gl gl.
  20896. * @param {ol.webgl.Context} context Context.
  20897. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  20898. * to skip.
  20899. * @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
  20900. * @return {T|undefined} Callback result.
  20901. * @template T
  20902. */
  20903. ol.render.webgl.Replay.prototype.drawHitDetectionReplayAll = function(gl, context, skippedFeaturesHash,
  20904. featureCallback) {
  20905. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  20906. this.drawReplay(gl, context, skippedFeaturesHash, true);
  20907. var result = featureCallback(null);
  20908. if (result) {
  20909. return result;
  20910. } else {
  20911. return undefined;
  20912. }
  20913. };
  20914. /**
  20915. * @param {ol.webgl.Context} context Context.
  20916. * @param {ol.Coordinate} center Center.
  20917. * @param {number} resolution Resolution.
  20918. * @param {number} rotation Rotation.
  20919. * @param {ol.Size} size Size.
  20920. * @param {number} pixelRatio Pixel ratio.
  20921. * @param {number} opacity Global opacity.
  20922. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  20923. * to skip.
  20924. * @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
  20925. * @param {boolean} oneByOne Draw features one-by-one for the hit-detecion.
  20926. * @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
  20927. * this extent are checked.
  20928. * @return {T|undefined} Callback result.
  20929. * @template T
  20930. */
  20931. ol.render.webgl.Replay.prototype.replay = function(context,
  20932. center, resolution, rotation, size, pixelRatio,
  20933. opacity, skippedFeaturesHash,
  20934. featureCallback, oneByOne, opt_hitExtent) {
  20935. var gl = context.getGL();
  20936. var tmpStencil, tmpStencilFunc, tmpStencilMaskVal, tmpStencilRef, tmpStencilMask,
  20937. tmpStencilOpFail, tmpStencilOpPass, tmpStencilOpZFail;
  20938. if (this.lineStringReplay) {
  20939. tmpStencil = gl.isEnabled(gl.STENCIL_TEST);
  20940. tmpStencilFunc = gl.getParameter(gl.STENCIL_FUNC);
  20941. tmpStencilMaskVal = gl.getParameter(gl.STENCIL_VALUE_MASK);
  20942. tmpStencilRef = gl.getParameter(gl.STENCIL_REF);
  20943. tmpStencilMask = gl.getParameter(gl.STENCIL_WRITEMASK);
  20944. tmpStencilOpFail = gl.getParameter(gl.STENCIL_FAIL);
  20945. tmpStencilOpPass = gl.getParameter(gl.STENCIL_PASS_DEPTH_PASS);
  20946. tmpStencilOpZFail = gl.getParameter(gl.STENCIL_PASS_DEPTH_FAIL);
  20947. gl.enable(gl.STENCIL_TEST);
  20948. gl.clear(gl.STENCIL_BUFFER_BIT);
  20949. gl.stencilMask(255);
  20950. gl.stencilFunc(gl.ALWAYS, 1, 255);
  20951. gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
  20952. this.lineStringReplay.replay(context,
  20953. center, resolution, rotation, size, pixelRatio,
  20954. opacity, skippedFeaturesHash,
  20955. featureCallback, oneByOne, opt_hitExtent);
  20956. gl.stencilMask(0);
  20957. gl.stencilFunc(gl.NOTEQUAL, 1, 255);
  20958. }
  20959. context.bindBuffer(ol.webgl.ARRAY_BUFFER, this.verticesBuffer);
  20960. context.bindBuffer(ol.webgl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
  20961. var locations = this.setUpProgram(gl, context, size, pixelRatio);
  20962. // set the "uniform" values
  20963. var projectionMatrix = ol.transform.reset(this.projectionMatrix_);
  20964. ol.transform.scale(projectionMatrix, 2 / (resolution * size[0]), 2 / (resolution * size[1]));
  20965. ol.transform.rotate(projectionMatrix, -rotation);
  20966. ol.transform.translate(projectionMatrix, -(center[0] - this.origin[0]), -(center[1] - this.origin[1]));
  20967. var offsetScaleMatrix = ol.transform.reset(this.offsetScaleMatrix_);
  20968. ol.transform.scale(offsetScaleMatrix, 2 / size[0], 2 / size[1]);
  20969. var offsetRotateMatrix = ol.transform.reset(this.offsetRotateMatrix_);
  20970. if (rotation !== 0) {
  20971. ol.transform.rotate(offsetRotateMatrix, -rotation);
  20972. }
  20973. gl.uniformMatrix4fv(locations.u_projectionMatrix, false,
  20974. ol.vec.Mat4.fromTransform(this.tmpMat4_, projectionMatrix));
  20975. gl.uniformMatrix4fv(locations.u_offsetScaleMatrix, false,
  20976. ol.vec.Mat4.fromTransform(this.tmpMat4_, offsetScaleMatrix));
  20977. gl.uniformMatrix4fv(locations.u_offsetRotateMatrix, false,
  20978. ol.vec.Mat4.fromTransform(this.tmpMat4_, offsetRotateMatrix));
  20979. gl.uniform1f(locations.u_opacity, opacity);
  20980. // draw!
  20981. var result;
  20982. if (featureCallback === undefined) {
  20983. this.drawReplay(gl, context, skippedFeaturesHash, false);
  20984. } else {
  20985. // draw feature by feature for the hit-detection
  20986. result = this.drawHitDetectionReplay(gl, context, skippedFeaturesHash,
  20987. featureCallback, oneByOne, opt_hitExtent);
  20988. }
  20989. // disable the vertex attrib arrays
  20990. this.shutDownProgram(gl, locations);
  20991. if (this.lineStringReplay) {
  20992. if (!tmpStencil) {
  20993. gl.disable(gl.STENCIL_TEST);
  20994. }
  20995. gl.clear(gl.STENCIL_BUFFER_BIT);
  20996. gl.stencilFunc(/** @type {number} */ (tmpStencilFunc),
  20997. /** @type {number} */ (tmpStencilRef), /** @type {number} */ (tmpStencilMaskVal));
  20998. gl.stencilMask(/** @type {number} */ (tmpStencilMask));
  20999. gl.stencilOp(/** @type {number} */ (tmpStencilOpFail),
  21000. /** @type {number} */ (tmpStencilOpZFail), /** @type {number} */ (tmpStencilOpPass));
  21001. }
  21002. return result;
  21003. };
  21004. /**
  21005. * @protected
  21006. * @param {WebGLRenderingContext} gl gl.
  21007. * @param {ol.webgl.Context} context Context.
  21008. * @param {number} start Start index.
  21009. * @param {number} end End index.
  21010. */
  21011. ol.render.webgl.Replay.prototype.drawElements = function(
  21012. gl, context, start, end) {
  21013. var elementType = context.hasOESElementIndexUint ?
  21014. ol.webgl.UNSIGNED_INT : ol.webgl.UNSIGNED_SHORT;
  21015. var elementSize = context.hasOESElementIndexUint ? 4 : 2;
  21016. var numItems = end - start;
  21017. var offsetInBytes = start * elementSize;
  21018. gl.drawElements(ol.webgl.TRIANGLES, numItems, elementType, offsetInBytes);
  21019. };
  21020. }
  21021. goog.provide('ol.render.webgl');
  21022. goog.require('ol');
  21023. if (ol.ENABLE_WEBGL) {
  21024. /**
  21025. * @const
  21026. * @type {string}
  21027. */
  21028. ol.render.webgl.defaultFont = '10px sans-serif';
  21029. /**
  21030. * @const
  21031. * @type {ol.Color}
  21032. */
  21033. ol.render.webgl.defaultFillStyle = [0.0, 0.0, 0.0, 1.0];
  21034. /**
  21035. * @const
  21036. * @type {string}
  21037. */
  21038. ol.render.webgl.defaultLineCap = 'round';
  21039. /**
  21040. * @const
  21041. * @type {Array.<number>}
  21042. */
  21043. ol.render.webgl.defaultLineDash = [];
  21044. /**
  21045. * @const
  21046. * @type {number}
  21047. */
  21048. ol.render.webgl.defaultLineDashOffset = 0;
  21049. /**
  21050. * @const
  21051. * @type {string}
  21052. */
  21053. ol.render.webgl.defaultLineJoin = 'round';
  21054. /**
  21055. * @const
  21056. * @type {number}
  21057. */
  21058. ol.render.webgl.defaultMiterLimit = 10;
  21059. /**
  21060. * @const
  21061. * @type {ol.Color}
  21062. */
  21063. ol.render.webgl.defaultStrokeStyle = [0.0, 0.0, 0.0, 1.0];
  21064. /**
  21065. * @const
  21066. * @type {number}
  21067. */
  21068. ol.render.webgl.defaultTextAlign = 0.5;
  21069. /**
  21070. * @const
  21071. * @type {number}
  21072. */
  21073. ol.render.webgl.defaultTextBaseline = 0.5;
  21074. /**
  21075. * @const
  21076. * @type {number}
  21077. */
  21078. ol.render.webgl.defaultLineWidth = 1;
  21079. /**
  21080. * Calculates the orientation of a triangle based on the determinant method.
  21081. * @param {number} x1 First X coordinate.
  21082. * @param {number} y1 First Y coordinate.
  21083. * @param {number} x2 Second X coordinate.
  21084. * @param {number} y2 Second Y coordinate.
  21085. * @param {number} x3 Third X coordinate.
  21086. * @param {number} y3 Third Y coordinate.
  21087. * @return {boolean|undefined} Triangle is clockwise.
  21088. */
  21089. ol.render.webgl.triangleIsCounterClockwise = function(x1, y1, x2, y2, x3, y3) {
  21090. var area = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
  21091. return (area <= ol.render.webgl.EPSILON && area >= -ol.render.webgl.EPSILON) ?
  21092. undefined : area > 0;
  21093. };
  21094. /**
  21095. * @const
  21096. * @type {number}
  21097. */
  21098. ol.render.webgl.EPSILON = Number.EPSILON || 2.220446049250313e-16;
  21099. }
  21100. goog.provide('ol.webgl.Buffer');
  21101. goog.require('ol');
  21102. goog.require('ol.webgl');
  21103. if (ol.ENABLE_WEBGL) {
  21104. /**
  21105. * @constructor
  21106. * @param {Array.<number>=} opt_arr Array.
  21107. * @param {number=} opt_usage Usage.
  21108. * @struct
  21109. */
  21110. ol.webgl.Buffer = function(opt_arr, opt_usage) {
  21111. /**
  21112. * @private
  21113. * @type {Array.<number>}
  21114. */
  21115. this.arr_ = opt_arr !== undefined ? opt_arr : [];
  21116. /**
  21117. * @private
  21118. * @type {number}
  21119. */
  21120. this.usage_ = opt_usage !== undefined ?
  21121. opt_usage : ol.webgl.Buffer.Usage_.STATIC_DRAW;
  21122. };
  21123. /**
  21124. * @return {Array.<number>} Array.
  21125. */
  21126. ol.webgl.Buffer.prototype.getArray = function() {
  21127. return this.arr_;
  21128. };
  21129. /**
  21130. * @return {number} Usage.
  21131. */
  21132. ol.webgl.Buffer.prototype.getUsage = function() {
  21133. return this.usage_;
  21134. };
  21135. /**
  21136. * @enum {number}
  21137. * @private
  21138. */
  21139. ol.webgl.Buffer.Usage_ = {
  21140. STATIC_DRAW: ol.webgl.STATIC_DRAW,
  21141. STREAM_DRAW: ol.webgl.STREAM_DRAW,
  21142. DYNAMIC_DRAW: ol.webgl.DYNAMIC_DRAW
  21143. };
  21144. }
  21145. goog.provide('ol.render.webgl.CircleReplay');
  21146. goog.require('ol');
  21147. goog.require('ol.array');
  21148. goog.require('ol.color');
  21149. goog.require('ol.extent');
  21150. goog.require('ol.obj');
  21151. goog.require('ol.geom.flat.transform');
  21152. goog.require('ol.render.webgl.circlereplay.defaultshader');
  21153. goog.require('ol.render.webgl.Replay');
  21154. goog.require('ol.render.webgl');
  21155. goog.require('ol.webgl');
  21156. goog.require('ol.webgl.Buffer');
  21157. if (ol.ENABLE_WEBGL) {
  21158. /**
  21159. * @constructor
  21160. * @extends {ol.render.webgl.Replay}
  21161. * @param {number} tolerance Tolerance.
  21162. * @param {ol.Extent} maxExtent Max extent.
  21163. * @struct
  21164. */
  21165. ol.render.webgl.CircleReplay = function(tolerance, maxExtent) {
  21166. ol.render.webgl.Replay.call(this, tolerance, maxExtent);
  21167. /**
  21168. * @private
  21169. * @type {ol.render.webgl.circlereplay.defaultshader.Locations}
  21170. */
  21171. this.defaultLocations_ = null;
  21172. /**
  21173. * @private
  21174. * @type {Array.<Array.<Array.<number>|number>>}
  21175. */
  21176. this.styles_ = [];
  21177. /**
  21178. * @private
  21179. * @type {Array.<number>}
  21180. */
  21181. this.styleIndices_ = [];
  21182. /**
  21183. * @private
  21184. * @type {number}
  21185. */
  21186. this.radius_ = 0;
  21187. /**
  21188. * @private
  21189. * @type {{fillColor: (Array.<number>|null),
  21190. * strokeColor: (Array.<number>|null),
  21191. * lineDash: Array.<number>,
  21192. * lineDashOffset: (number|undefined),
  21193. * lineWidth: (number|undefined),
  21194. * changed: boolean}|null}
  21195. */
  21196. this.state_ = {
  21197. fillColor: null,
  21198. strokeColor: null,
  21199. lineDash: null,
  21200. lineDashOffset: undefined,
  21201. lineWidth: undefined,
  21202. changed: false
  21203. };
  21204. };
  21205. ol.inherits(ol.render.webgl.CircleReplay, ol.render.webgl.Replay);
  21206. /**
  21207. * @private
  21208. * @param {Array.<number>} flatCoordinates Flat coordinates.
  21209. * @param {number} offset Offset.
  21210. * @param {number} end End.
  21211. * @param {number} stride Stride.
  21212. */
  21213. ol.render.webgl.CircleReplay.prototype.drawCoordinates_ = function(
  21214. flatCoordinates, offset, end, stride) {
  21215. var numVertices = this.vertices.length;
  21216. var numIndices = this.indices.length;
  21217. var n = numVertices / 4;
  21218. var i, ii;
  21219. for (i = offset, ii = end; i < ii; i += stride) {
  21220. this.vertices[numVertices++] = flatCoordinates[i];
  21221. this.vertices[numVertices++] = flatCoordinates[i + 1];
  21222. this.vertices[numVertices++] = 0;
  21223. this.vertices[numVertices++] = this.radius_;
  21224. this.vertices[numVertices++] = flatCoordinates[i];
  21225. this.vertices[numVertices++] = flatCoordinates[i + 1];
  21226. this.vertices[numVertices++] = 1;
  21227. this.vertices[numVertices++] = this.radius_;
  21228. this.vertices[numVertices++] = flatCoordinates[i];
  21229. this.vertices[numVertices++] = flatCoordinates[i + 1];
  21230. this.vertices[numVertices++] = 2;
  21231. this.vertices[numVertices++] = this.radius_;
  21232. this.vertices[numVertices++] = flatCoordinates[i];
  21233. this.vertices[numVertices++] = flatCoordinates[i + 1];
  21234. this.vertices[numVertices++] = 3;
  21235. this.vertices[numVertices++] = this.radius_;
  21236. this.indices[numIndices++] = n;
  21237. this.indices[numIndices++] = n + 1;
  21238. this.indices[numIndices++] = n + 2;
  21239. this.indices[numIndices++] = n + 2;
  21240. this.indices[numIndices++] = n + 3;
  21241. this.indices[numIndices++] = n;
  21242. n += 4;
  21243. }
  21244. };
  21245. /**
  21246. * @inheritDoc
  21247. */
  21248. ol.render.webgl.CircleReplay.prototype.drawCircle = function(circleGeometry, feature) {
  21249. var radius = circleGeometry.getRadius();
  21250. var stride = circleGeometry.getStride();
  21251. if (radius) {
  21252. this.startIndices.push(this.indices.length);
  21253. this.startIndicesFeature.push(feature);
  21254. if (this.state_.changed) {
  21255. this.styleIndices_.push(this.indices.length);
  21256. this.state_.changed = false;
  21257. }
  21258. this.radius_ = radius;
  21259. var flatCoordinates = circleGeometry.getFlatCoordinates();
  21260. flatCoordinates = ol.geom.flat.transform.translate(flatCoordinates, 0, 2,
  21261. stride, -this.origin[0], -this.origin[1]);
  21262. this.drawCoordinates_(flatCoordinates, 0, 2, stride);
  21263. } else {
  21264. if (this.state_.changed) {
  21265. this.styles_.pop();
  21266. if (this.styles_.length) {
  21267. var lastState = this.styles_[this.styles_.length - 1];
  21268. this.state_.fillColor = /** @type {Array.<number>} */ (lastState[0]);
  21269. this.state_.strokeColor = /** @type {Array.<number>} */ (lastState[1]);
  21270. this.state_.lineWidth = /** @type {number} */ (lastState[2]);
  21271. this.state_.changed = false;
  21272. }
  21273. }
  21274. }
  21275. };
  21276. /**
  21277. * @inheritDoc
  21278. **/
  21279. ol.render.webgl.CircleReplay.prototype.finish = function(context) {
  21280. // create, bind, and populate the vertices buffer
  21281. this.verticesBuffer = new ol.webgl.Buffer(this.vertices);
  21282. // create, bind, and populate the indices buffer
  21283. this.indicesBuffer = new ol.webgl.Buffer(this.indices);
  21284. this.startIndices.push(this.indices.length);
  21285. //Clean up, if there is nothing to draw
  21286. if (this.styleIndices_.length === 0 && this.styles_.length > 0) {
  21287. this.styles_ = [];
  21288. }
  21289. this.vertices = null;
  21290. this.indices = null;
  21291. };
  21292. /**
  21293. * @inheritDoc
  21294. */
  21295. ol.render.webgl.CircleReplay.prototype.getDeleteResourcesFunction = function(context) {
  21296. // We only delete our stuff here. The shaders and the program may
  21297. // be used by other CircleReplay instances (for other layers). And
  21298. // they will be deleted when disposing of the ol.webgl.Context
  21299. // object.
  21300. var verticesBuffer = this.verticesBuffer;
  21301. var indicesBuffer = this.indicesBuffer;
  21302. return function() {
  21303. context.deleteBuffer(verticesBuffer);
  21304. context.deleteBuffer(indicesBuffer);
  21305. };
  21306. };
  21307. /**
  21308. * @inheritDoc
  21309. */
  21310. ol.render.webgl.CircleReplay.prototype.setUpProgram = function(gl, context, size, pixelRatio) {
  21311. // get the program
  21312. var fragmentShader, vertexShader;
  21313. fragmentShader = ol.render.webgl.circlereplay.defaultshader.fragment;
  21314. vertexShader = ol.render.webgl.circlereplay.defaultshader.vertex;
  21315. var program = context.getProgram(fragmentShader, vertexShader);
  21316. // get the locations
  21317. var locations;
  21318. if (!this.defaultLocations_) {
  21319. // eslint-disable-next-line openlayers-internal/no-missing-requires
  21320. locations = new ol.render.webgl.circlereplay.defaultshader.Locations(gl, program);
  21321. this.defaultLocations_ = locations;
  21322. } else {
  21323. locations = this.defaultLocations_;
  21324. }
  21325. context.useProgram(program);
  21326. // enable the vertex attrib arrays
  21327. gl.enableVertexAttribArray(locations.a_position);
  21328. gl.vertexAttribPointer(locations.a_position, 2, ol.webgl.FLOAT,
  21329. false, 16, 0);
  21330. gl.enableVertexAttribArray(locations.a_instruction);
  21331. gl.vertexAttribPointer(locations.a_instruction, 1, ol.webgl.FLOAT,
  21332. false, 16, 8);
  21333. gl.enableVertexAttribArray(locations.a_radius);
  21334. gl.vertexAttribPointer(locations.a_radius, 1, ol.webgl.FLOAT,
  21335. false, 16, 12);
  21336. // Enable renderer specific uniforms.
  21337. gl.uniform2fv(locations.u_size, size);
  21338. gl.uniform1f(locations.u_pixelRatio, pixelRatio);
  21339. return locations;
  21340. };
  21341. /**
  21342. * @inheritDoc
  21343. */
  21344. ol.render.webgl.CircleReplay.prototype.shutDownProgram = function(gl, locations) {
  21345. gl.disableVertexAttribArray(locations.a_position);
  21346. gl.disableVertexAttribArray(locations.a_instruction);
  21347. gl.disableVertexAttribArray(locations.a_radius);
  21348. };
  21349. /**
  21350. * @inheritDoc
  21351. */
  21352. ol.render.webgl.CircleReplay.prototype.drawReplay = function(gl, context, skippedFeaturesHash, hitDetection) {
  21353. if (!ol.obj.isEmpty(skippedFeaturesHash)) {
  21354. this.drawReplaySkipping_(gl, context, skippedFeaturesHash);
  21355. } else {
  21356. //Draw by style groups to minimize drawElements() calls.
  21357. var i, start, end, nextStyle;
  21358. end = this.startIndices[this.startIndices.length - 1];
  21359. for (i = this.styleIndices_.length - 1; i >= 0; --i) {
  21360. start = this.styleIndices_[i];
  21361. nextStyle = this.styles_[i];
  21362. this.setFillStyle_(gl, /** @type {Array.<number>} */ (nextStyle[0]));
  21363. this.setStrokeStyle_(gl, /** @type {Array.<number>} */ (nextStyle[1]),
  21364. /** @type {number} */ (nextStyle[2]));
  21365. this.drawElements(gl, context, start, end);
  21366. end = start;
  21367. }
  21368. }
  21369. };
  21370. /**
  21371. * @inheritDoc
  21372. */
  21373. ol.render.webgl.CircleReplay.prototype.drawHitDetectionReplayOneByOne = function(gl, context, skippedFeaturesHash,
  21374. featureCallback, opt_hitExtent) {
  21375. var i, start, end, nextStyle, groupStart, feature, featureUid, featureIndex;
  21376. featureIndex = this.startIndices.length - 2;
  21377. end = this.startIndices[featureIndex + 1];
  21378. for (i = this.styleIndices_.length - 1; i >= 0; --i) {
  21379. nextStyle = this.styles_[i];
  21380. this.setFillStyle_(gl, /** @type {Array.<number>} */ (nextStyle[0]));
  21381. this.setStrokeStyle_(gl, /** @type {Array.<number>} */ (nextStyle[1]),
  21382. /** @type {number} */ (nextStyle[2]));
  21383. groupStart = this.styleIndices_[i];
  21384. while (featureIndex >= 0 &&
  21385. this.startIndices[featureIndex] >= groupStart) {
  21386. start = this.startIndices[featureIndex];
  21387. feature = this.startIndicesFeature[featureIndex];
  21388. featureUid = ol.getUid(feature).toString();
  21389. if (skippedFeaturesHash[featureUid] === undefined &&
  21390. feature.getGeometry() &&
  21391. (opt_hitExtent === undefined || ol.extent.intersects(
  21392. /** @type {Array<number>} */ (opt_hitExtent),
  21393. feature.getGeometry().getExtent()))) {
  21394. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  21395. this.drawElements(gl, context, start, end);
  21396. var result = featureCallback(feature);
  21397. if (result) {
  21398. return result;
  21399. }
  21400. }
  21401. featureIndex--;
  21402. end = start;
  21403. }
  21404. }
  21405. return undefined;
  21406. };
  21407. /**
  21408. * @private
  21409. * @param {WebGLRenderingContext} gl gl.
  21410. * @param {ol.webgl.Context} context Context.
  21411. * @param {Object} skippedFeaturesHash Ids of features to skip.
  21412. */
  21413. ol.render.webgl.CircleReplay.prototype.drawReplaySkipping_ = function(gl, context, skippedFeaturesHash) {
  21414. var i, start, end, nextStyle, groupStart, feature, featureUid, featureIndex, featureStart;
  21415. featureIndex = this.startIndices.length - 2;
  21416. end = start = this.startIndices[featureIndex + 1];
  21417. for (i = this.styleIndices_.length - 1; i >= 0; --i) {
  21418. nextStyle = this.styles_[i];
  21419. this.setFillStyle_(gl, /** @type {Array.<number>} */ (nextStyle[0]));
  21420. this.setStrokeStyle_(gl, /** @type {Array.<number>} */ (nextStyle[1]),
  21421. /** @type {number} */ (nextStyle[2]));
  21422. groupStart = this.styleIndices_[i];
  21423. while (featureIndex >= 0 &&
  21424. this.startIndices[featureIndex] >= groupStart) {
  21425. featureStart = this.startIndices[featureIndex];
  21426. feature = this.startIndicesFeature[featureIndex];
  21427. featureUid = ol.getUid(feature).toString();
  21428. if (skippedFeaturesHash[featureUid]) {
  21429. if (start !== end) {
  21430. this.drawElements(gl, context, start, end);
  21431. }
  21432. end = featureStart;
  21433. }
  21434. featureIndex--;
  21435. start = featureStart;
  21436. }
  21437. if (start !== end) {
  21438. this.drawElements(gl, context, start, end);
  21439. }
  21440. start = end = groupStart;
  21441. }
  21442. };
  21443. /**
  21444. * @private
  21445. * @param {WebGLRenderingContext} gl gl.
  21446. * @param {Array.<number>} color Color.
  21447. */
  21448. ol.render.webgl.CircleReplay.prototype.setFillStyle_ = function(gl, color) {
  21449. gl.uniform4fv(this.defaultLocations_.u_fillColor, color);
  21450. };
  21451. /**
  21452. * @private
  21453. * @param {WebGLRenderingContext} gl gl.
  21454. * @param {Array.<number>} color Color.
  21455. * @param {number} lineWidth Line width.
  21456. */
  21457. ol.render.webgl.CircleReplay.prototype.setStrokeStyle_ = function(gl, color, lineWidth) {
  21458. gl.uniform4fv(this.defaultLocations_.u_strokeColor, color);
  21459. gl.uniform1f(this.defaultLocations_.u_lineWidth, lineWidth);
  21460. };
  21461. /**
  21462. * @inheritDoc
  21463. */
  21464. ol.render.webgl.CircleReplay.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
  21465. var strokeStyleColor, strokeStyleWidth;
  21466. if (strokeStyle) {
  21467. var strokeStyleLineDash = strokeStyle.getLineDash();
  21468. this.state_.lineDash = strokeStyleLineDash ?
  21469. strokeStyleLineDash : ol.render.webgl.defaultLineDash;
  21470. var strokeStyleLineDashOffset = strokeStyle.getLineDashOffset();
  21471. this.state_.lineDashOffset = strokeStyleLineDashOffset ?
  21472. strokeStyleLineDashOffset : ol.render.webgl.defaultLineDashOffset;
  21473. strokeStyleColor = strokeStyle.getColor();
  21474. if (!(strokeStyleColor instanceof CanvasGradient) &&
  21475. !(strokeStyleColor instanceof CanvasPattern)) {
  21476. strokeStyleColor = ol.color.asArray(strokeStyleColor).map(function(c, i) {
  21477. return i != 3 ? c / 255 : c;
  21478. }) || ol.render.webgl.defaultStrokeStyle;
  21479. } else {
  21480. strokeStyleColor = ol.render.webgl.defaultStrokeStyle;
  21481. }
  21482. strokeStyleWidth = strokeStyle.getWidth();
  21483. strokeStyleWidth = strokeStyleWidth !== undefined ?
  21484. strokeStyleWidth : ol.render.webgl.defaultLineWidth;
  21485. } else {
  21486. strokeStyleColor = [0, 0, 0, 0];
  21487. strokeStyleWidth = 0;
  21488. }
  21489. var fillStyleColor = fillStyle ? fillStyle.getColor() : [0, 0, 0, 0];
  21490. if (!(fillStyleColor instanceof CanvasGradient) &&
  21491. !(fillStyleColor instanceof CanvasPattern)) {
  21492. fillStyleColor = ol.color.asArray(fillStyleColor).map(function(c, i) {
  21493. return i != 3 ? c / 255 : c;
  21494. }) || ol.render.webgl.defaultFillStyle;
  21495. } else {
  21496. fillStyleColor = ol.render.webgl.defaultFillStyle;
  21497. }
  21498. if (!this.state_.strokeColor || !ol.array.equals(this.state_.strokeColor, strokeStyleColor) ||
  21499. !this.state_.fillColor || !ol.array.equals(this.state_.fillColor, fillStyleColor) ||
  21500. this.state_.lineWidth !== strokeStyleWidth) {
  21501. this.state_.changed = true;
  21502. this.state_.fillColor = fillStyleColor;
  21503. this.state_.strokeColor = strokeStyleColor;
  21504. this.state_.lineWidth = strokeStyleWidth;
  21505. this.styles_.push([fillStyleColor, strokeStyleColor, strokeStyleWidth]);
  21506. }
  21507. };
  21508. }
  21509. // This file is automatically generated, do not edit
  21510. /* eslint openlayers-internal/no-missing-requires: 0 */
  21511. goog.provide('ol.render.webgl.texturereplay.defaultshader');
  21512. goog.require('ol');
  21513. goog.require('ol.webgl.Fragment');
  21514. goog.require('ol.webgl.Vertex');
  21515. if (ol.ENABLE_WEBGL) {
  21516. /**
  21517. * @constructor
  21518. * @extends {ol.webgl.Fragment}
  21519. * @struct
  21520. */
  21521. ol.render.webgl.texturereplay.defaultshader.Fragment = function() {
  21522. ol.webgl.Fragment.call(this, ol.render.webgl.texturereplay.defaultshader.Fragment.SOURCE);
  21523. };
  21524. ol.inherits(ol.render.webgl.texturereplay.defaultshader.Fragment, ol.webgl.Fragment);
  21525. /**
  21526. * @const
  21527. * @type {string}
  21528. */
  21529. ol.render.webgl.texturereplay.defaultshader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\nvarying float v_opacity;\n\nuniform float u_opacity;\nuniform sampler2D u_image;\n\nvoid main(void) {\n vec4 texColor = texture2D(u_image, v_texCoord);\n gl_FragColor.rgb = texColor.rgb;\n float alpha = texColor.a * v_opacity * u_opacity;\n if (alpha == 0.0) {\n discard;\n }\n gl_FragColor.a = alpha;\n}\n';
  21530. /**
  21531. * @const
  21532. * @type {string}
  21533. */
  21534. ol.render.webgl.texturereplay.defaultshader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;varying float b;uniform float k;uniform sampler2D l;void main(void){vec4 texColor=texture2D(l,a);gl_FragColor.rgb=texColor.rgb;float alpha=texColor.a*b*k;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}';
  21535. /**
  21536. * @const
  21537. * @type {string}
  21538. */
  21539. ol.render.webgl.texturereplay.defaultshader.Fragment.SOURCE = ol.DEBUG_WEBGL ?
  21540. ol.render.webgl.texturereplay.defaultshader.Fragment.DEBUG_SOURCE :
  21541. ol.render.webgl.texturereplay.defaultshader.Fragment.OPTIMIZED_SOURCE;
  21542. ol.render.webgl.texturereplay.defaultshader.fragment = new ol.render.webgl.texturereplay.defaultshader.Fragment();
  21543. /**
  21544. * @constructor
  21545. * @extends {ol.webgl.Vertex}
  21546. * @struct
  21547. */
  21548. ol.render.webgl.texturereplay.defaultshader.Vertex = function() {
  21549. ol.webgl.Vertex.call(this, ol.render.webgl.texturereplay.defaultshader.Vertex.SOURCE);
  21550. };
  21551. ol.inherits(ol.render.webgl.texturereplay.defaultshader.Vertex, ol.webgl.Vertex);
  21552. /**
  21553. * @const
  21554. * @type {string}
  21555. */
  21556. ol.render.webgl.texturereplay.defaultshader.Vertex.DEBUG_SOURCE = 'varying vec2 v_texCoord;\nvarying float v_opacity;\n\nattribute vec2 a_position;\nattribute vec2 a_texCoord;\nattribute vec2 a_offsets;\nattribute float a_opacity;\nattribute float a_rotateWithView;\n\nuniform mat4 u_projectionMatrix;\nuniform mat4 u_offsetScaleMatrix;\nuniform mat4 u_offsetRotateMatrix;\n\nvoid main(void) {\n mat4 offsetMatrix = u_offsetScaleMatrix;\n if (a_rotateWithView == 1.0) {\n offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix;\n }\n vec4 offsets = offsetMatrix * vec4(a_offsets, 0.0, 0.0);\n gl_Position = u_projectionMatrix * vec4(a_position, 0.0, 1.0) + offsets;\n v_texCoord = a_texCoord;\n v_opacity = a_opacity;\n}\n\n\n';
  21557. /**
  21558. * @const
  21559. * @type {string}
  21560. */
  21561. ol.render.webgl.texturereplay.defaultshader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;varying float b;attribute vec2 c;attribute vec2 d;attribute vec2 e;attribute float f;attribute float g;uniform mat4 h;uniform mat4 i;uniform mat4 j;void main(void){mat4 offsetMatrix=i;if(g==1.0){offsetMatrix=i*j;}vec4 offsets=offsetMatrix*vec4(e,0.0,0.0);gl_Position=h*vec4(c,0.0,1.0)+offsets;a=d;b=f;}';
  21562. /**
  21563. * @const
  21564. * @type {string}
  21565. */
  21566. ol.render.webgl.texturereplay.defaultshader.Vertex.SOURCE = ol.DEBUG_WEBGL ?
  21567. ol.render.webgl.texturereplay.defaultshader.Vertex.DEBUG_SOURCE :
  21568. ol.render.webgl.texturereplay.defaultshader.Vertex.OPTIMIZED_SOURCE;
  21569. ol.render.webgl.texturereplay.defaultshader.vertex = new ol.render.webgl.texturereplay.defaultshader.Vertex();
  21570. /**
  21571. * @constructor
  21572. * @param {WebGLRenderingContext} gl GL.
  21573. * @param {WebGLProgram} program Program.
  21574. * @struct
  21575. */
  21576. ol.render.webgl.texturereplay.defaultshader.Locations = function(gl, program) {
  21577. /**
  21578. * @type {WebGLUniformLocation}
  21579. */
  21580. this.u_image = gl.getUniformLocation(
  21581. program, ol.DEBUG_WEBGL ? 'u_image' : 'l');
  21582. /**
  21583. * @type {WebGLUniformLocation}
  21584. */
  21585. this.u_offsetRotateMatrix = gl.getUniformLocation(
  21586. program, ol.DEBUG_WEBGL ? 'u_offsetRotateMatrix' : 'j');
  21587. /**
  21588. * @type {WebGLUniformLocation}
  21589. */
  21590. this.u_offsetScaleMatrix = gl.getUniformLocation(
  21591. program, ol.DEBUG_WEBGL ? 'u_offsetScaleMatrix' : 'i');
  21592. /**
  21593. * @type {WebGLUniformLocation}
  21594. */
  21595. this.u_opacity = gl.getUniformLocation(
  21596. program, ol.DEBUG_WEBGL ? 'u_opacity' : 'k');
  21597. /**
  21598. * @type {WebGLUniformLocation}
  21599. */
  21600. this.u_projectionMatrix = gl.getUniformLocation(
  21601. program, ol.DEBUG_WEBGL ? 'u_projectionMatrix' : 'h');
  21602. /**
  21603. * @type {number}
  21604. */
  21605. this.a_offsets = gl.getAttribLocation(
  21606. program, ol.DEBUG_WEBGL ? 'a_offsets' : 'e');
  21607. /**
  21608. * @type {number}
  21609. */
  21610. this.a_opacity = gl.getAttribLocation(
  21611. program, ol.DEBUG_WEBGL ? 'a_opacity' : 'f');
  21612. /**
  21613. * @type {number}
  21614. */
  21615. this.a_position = gl.getAttribLocation(
  21616. program, ol.DEBUG_WEBGL ? 'a_position' : 'c');
  21617. /**
  21618. * @type {number}
  21619. */
  21620. this.a_rotateWithView = gl.getAttribLocation(
  21621. program, ol.DEBUG_WEBGL ? 'a_rotateWithView' : 'g');
  21622. /**
  21623. * @type {number}
  21624. */
  21625. this.a_texCoord = gl.getAttribLocation(
  21626. program, ol.DEBUG_WEBGL ? 'a_texCoord' : 'd');
  21627. };
  21628. }
  21629. goog.provide('ol.webgl.ContextEventType');
  21630. /**
  21631. * @enum {string}
  21632. */
  21633. ol.webgl.ContextEventType = {
  21634. LOST: 'webglcontextlost',
  21635. RESTORED: 'webglcontextrestored'
  21636. };
  21637. goog.provide('ol.webgl.Context');
  21638. goog.require('ol');
  21639. goog.require('ol.Disposable');
  21640. goog.require('ol.array');
  21641. goog.require('ol.events');
  21642. goog.require('ol.obj');
  21643. goog.require('ol.webgl');
  21644. goog.require('ol.webgl.ContextEventType');
  21645. if (ol.ENABLE_WEBGL) {
  21646. /**
  21647. * @classdesc
  21648. * A WebGL context for accessing low-level WebGL capabilities.
  21649. *
  21650. * @constructor
  21651. * @extends {ol.Disposable}
  21652. * @param {HTMLCanvasElement} canvas Canvas.
  21653. * @param {WebGLRenderingContext} gl GL.
  21654. */
  21655. ol.webgl.Context = function(canvas, gl) {
  21656. /**
  21657. * @private
  21658. * @type {HTMLCanvasElement}
  21659. */
  21660. this.canvas_ = canvas;
  21661. /**
  21662. * @private
  21663. * @type {WebGLRenderingContext}
  21664. */
  21665. this.gl_ = gl;
  21666. /**
  21667. * @private
  21668. * @type {Object.<string, ol.WebglBufferCacheEntry>}
  21669. */
  21670. this.bufferCache_ = {};
  21671. /**
  21672. * @private
  21673. * @type {Object.<string, WebGLShader>}
  21674. */
  21675. this.shaderCache_ = {};
  21676. /**
  21677. * @private
  21678. * @type {Object.<string, WebGLProgram>}
  21679. */
  21680. this.programCache_ = {};
  21681. /**
  21682. * @private
  21683. * @type {WebGLProgram}
  21684. */
  21685. this.currentProgram_ = null;
  21686. /**
  21687. * @private
  21688. * @type {WebGLFramebuffer}
  21689. */
  21690. this.hitDetectionFramebuffer_ = null;
  21691. /**
  21692. * @private
  21693. * @type {WebGLTexture}
  21694. */
  21695. this.hitDetectionTexture_ = null;
  21696. /**
  21697. * @private
  21698. * @type {WebGLRenderbuffer}
  21699. */
  21700. this.hitDetectionRenderbuffer_ = null;
  21701. /**
  21702. * @type {boolean}
  21703. */
  21704. this.hasOESElementIndexUint = ol.array.includes(
  21705. ol.WEBGL_EXTENSIONS, 'OES_element_index_uint');
  21706. // use the OES_element_index_uint extension if available
  21707. if (this.hasOESElementIndexUint) {
  21708. gl.getExtension('OES_element_index_uint');
  21709. }
  21710. ol.events.listen(this.canvas_, ol.webgl.ContextEventType.LOST,
  21711. this.handleWebGLContextLost, this);
  21712. ol.events.listen(this.canvas_, ol.webgl.ContextEventType.RESTORED,
  21713. this.handleWebGLContextRestored, this);
  21714. };
  21715. ol.inherits(ol.webgl.Context, ol.Disposable);
  21716. /**
  21717. * Just bind the buffer if it's in the cache. Otherwise create
  21718. * the WebGL buffer, bind it, populate it, and add an entry to
  21719. * the cache.
  21720. * @param {number} target Target.
  21721. * @param {ol.webgl.Buffer} buf Buffer.
  21722. */
  21723. ol.webgl.Context.prototype.bindBuffer = function(target, buf) {
  21724. var gl = this.getGL();
  21725. var arr = buf.getArray();
  21726. var bufferKey = String(ol.getUid(buf));
  21727. if (bufferKey in this.bufferCache_) {
  21728. var bufferCacheEntry = this.bufferCache_[bufferKey];
  21729. gl.bindBuffer(target, bufferCacheEntry.buffer);
  21730. } else {
  21731. var buffer = gl.createBuffer();
  21732. gl.bindBuffer(target, buffer);
  21733. var /** @type {ArrayBufferView} */ arrayBuffer;
  21734. if (target == ol.webgl.ARRAY_BUFFER) {
  21735. arrayBuffer = new Float32Array(arr);
  21736. } else if (target == ol.webgl.ELEMENT_ARRAY_BUFFER) {
  21737. arrayBuffer = this.hasOESElementIndexUint ?
  21738. new Uint32Array(arr) : new Uint16Array(arr);
  21739. }
  21740. gl.bufferData(target, arrayBuffer, buf.getUsage());
  21741. this.bufferCache_[bufferKey] = {
  21742. buf: buf,
  21743. buffer: buffer
  21744. };
  21745. }
  21746. };
  21747. /**
  21748. * @param {ol.webgl.Buffer} buf Buffer.
  21749. */
  21750. ol.webgl.Context.prototype.deleteBuffer = function(buf) {
  21751. var gl = this.getGL();
  21752. var bufferKey = String(ol.getUid(buf));
  21753. var bufferCacheEntry = this.bufferCache_[bufferKey];
  21754. if (!gl.isContextLost()) {
  21755. gl.deleteBuffer(bufferCacheEntry.buffer);
  21756. }
  21757. delete this.bufferCache_[bufferKey];
  21758. };
  21759. /**
  21760. * @inheritDoc
  21761. */
  21762. ol.webgl.Context.prototype.disposeInternal = function() {
  21763. ol.events.unlistenAll(this.canvas_);
  21764. var gl = this.getGL();
  21765. if (!gl.isContextLost()) {
  21766. var key;
  21767. for (key in this.bufferCache_) {
  21768. gl.deleteBuffer(this.bufferCache_[key].buffer);
  21769. }
  21770. for (key in this.programCache_) {
  21771. gl.deleteProgram(this.programCache_[key]);
  21772. }
  21773. for (key in this.shaderCache_) {
  21774. gl.deleteShader(this.shaderCache_[key]);
  21775. }
  21776. // delete objects for hit-detection
  21777. gl.deleteFramebuffer(this.hitDetectionFramebuffer_);
  21778. gl.deleteRenderbuffer(this.hitDetectionRenderbuffer_);
  21779. gl.deleteTexture(this.hitDetectionTexture_);
  21780. }
  21781. };
  21782. /**
  21783. * @return {HTMLCanvasElement} Canvas.
  21784. */
  21785. ol.webgl.Context.prototype.getCanvas = function() {
  21786. return this.canvas_;
  21787. };
  21788. /**
  21789. * Get the WebGL rendering context
  21790. * @return {WebGLRenderingContext} The rendering context.
  21791. * @api
  21792. */
  21793. ol.webgl.Context.prototype.getGL = function() {
  21794. return this.gl_;
  21795. };
  21796. /**
  21797. * Get the frame buffer for hit detection.
  21798. * @return {WebGLFramebuffer} The hit detection frame buffer.
  21799. */
  21800. ol.webgl.Context.prototype.getHitDetectionFramebuffer = function() {
  21801. if (!this.hitDetectionFramebuffer_) {
  21802. this.initHitDetectionFramebuffer_();
  21803. }
  21804. return this.hitDetectionFramebuffer_;
  21805. };
  21806. /**
  21807. * Get shader from the cache if it's in the cache. Otherwise, create
  21808. * the WebGL shader, compile it, and add entry to cache.
  21809. * @param {ol.webgl.Shader} shaderObject Shader object.
  21810. * @return {WebGLShader} Shader.
  21811. */
  21812. ol.webgl.Context.prototype.getShader = function(shaderObject) {
  21813. var shaderKey = String(ol.getUid(shaderObject));
  21814. if (shaderKey in this.shaderCache_) {
  21815. return this.shaderCache_[shaderKey];
  21816. } else {
  21817. var gl = this.getGL();
  21818. var shader = gl.createShader(shaderObject.getType());
  21819. gl.shaderSource(shader, shaderObject.getSource());
  21820. gl.compileShader(shader);
  21821. this.shaderCache_[shaderKey] = shader;
  21822. return shader;
  21823. }
  21824. };
  21825. /**
  21826. * Get the program from the cache if it's in the cache. Otherwise create
  21827. * the WebGL program, attach the shaders to it, and add an entry to the
  21828. * cache.
  21829. * @param {ol.webgl.Fragment} fragmentShaderObject Fragment shader.
  21830. * @param {ol.webgl.Vertex} vertexShaderObject Vertex shader.
  21831. * @return {WebGLProgram} Program.
  21832. */
  21833. ol.webgl.Context.prototype.getProgram = function(
  21834. fragmentShaderObject, vertexShaderObject) {
  21835. var programKey =
  21836. ol.getUid(fragmentShaderObject) + '/' + ol.getUid(vertexShaderObject);
  21837. if (programKey in this.programCache_) {
  21838. return this.programCache_[programKey];
  21839. } else {
  21840. var gl = this.getGL();
  21841. var program = gl.createProgram();
  21842. gl.attachShader(program, this.getShader(fragmentShaderObject));
  21843. gl.attachShader(program, this.getShader(vertexShaderObject));
  21844. gl.linkProgram(program);
  21845. this.programCache_[programKey] = program;
  21846. return program;
  21847. }
  21848. };
  21849. /**
  21850. * FIXME empy description for jsdoc
  21851. */
  21852. ol.webgl.Context.prototype.handleWebGLContextLost = function() {
  21853. ol.obj.clear(this.bufferCache_);
  21854. ol.obj.clear(this.shaderCache_);
  21855. ol.obj.clear(this.programCache_);
  21856. this.currentProgram_ = null;
  21857. this.hitDetectionFramebuffer_ = null;
  21858. this.hitDetectionTexture_ = null;
  21859. this.hitDetectionRenderbuffer_ = null;
  21860. };
  21861. /**
  21862. * FIXME empy description for jsdoc
  21863. */
  21864. ol.webgl.Context.prototype.handleWebGLContextRestored = function() {
  21865. };
  21866. /**
  21867. * Creates a 1x1 pixel framebuffer for the hit-detection.
  21868. * @private
  21869. */
  21870. ol.webgl.Context.prototype.initHitDetectionFramebuffer_ = function() {
  21871. var gl = this.gl_;
  21872. var framebuffer = gl.createFramebuffer();
  21873. gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
  21874. var texture = ol.webgl.Context.createEmptyTexture(gl, 1, 1);
  21875. var renderbuffer = gl.createRenderbuffer();
  21876. gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
  21877. gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 1, 1);
  21878. gl.framebufferTexture2D(
  21879. gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
  21880. gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
  21881. gl.RENDERBUFFER, renderbuffer);
  21882. gl.bindTexture(gl.TEXTURE_2D, null);
  21883. gl.bindRenderbuffer(gl.RENDERBUFFER, null);
  21884. gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  21885. this.hitDetectionFramebuffer_ = framebuffer;
  21886. this.hitDetectionTexture_ = texture;
  21887. this.hitDetectionRenderbuffer_ = renderbuffer;
  21888. };
  21889. /**
  21890. * Use a program. If the program is already in use, this will return `false`.
  21891. * @param {WebGLProgram} program Program.
  21892. * @return {boolean} Changed.
  21893. * @api
  21894. */
  21895. ol.webgl.Context.prototype.useProgram = function(program) {
  21896. if (program == this.currentProgram_) {
  21897. return false;
  21898. } else {
  21899. var gl = this.getGL();
  21900. gl.useProgram(program);
  21901. this.currentProgram_ = program;
  21902. return true;
  21903. }
  21904. };
  21905. /**
  21906. * @param {WebGLRenderingContext} gl WebGL rendering context.
  21907. * @param {number=} opt_wrapS wrapS.
  21908. * @param {number=} opt_wrapT wrapT.
  21909. * @return {WebGLTexture} The texture.
  21910. * @private
  21911. */
  21912. ol.webgl.Context.createTexture_ = function(gl, opt_wrapS, opt_wrapT) {
  21913. var texture = gl.createTexture();
  21914. gl.bindTexture(gl.TEXTURE_2D, texture);
  21915. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  21916. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  21917. if (opt_wrapS !== undefined) {
  21918. gl.texParameteri(
  21919. ol.webgl.TEXTURE_2D, ol.webgl.TEXTURE_WRAP_S, opt_wrapS);
  21920. }
  21921. if (opt_wrapT !== undefined) {
  21922. gl.texParameteri(
  21923. ol.webgl.TEXTURE_2D, ol.webgl.TEXTURE_WRAP_T, opt_wrapT);
  21924. }
  21925. return texture;
  21926. };
  21927. /**
  21928. * @param {WebGLRenderingContext} gl WebGL rendering context.
  21929. * @param {number} width Width.
  21930. * @param {number} height Height.
  21931. * @param {number=} opt_wrapS wrapS.
  21932. * @param {number=} opt_wrapT wrapT.
  21933. * @return {WebGLTexture} The texture.
  21934. */
  21935. ol.webgl.Context.createEmptyTexture = function(
  21936. gl, width, height, opt_wrapS, opt_wrapT) {
  21937. var texture = ol.webgl.Context.createTexture_(gl, opt_wrapS, opt_wrapT);
  21938. gl.texImage2D(
  21939. gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE,
  21940. null);
  21941. return texture;
  21942. };
  21943. /**
  21944. * @param {WebGLRenderingContext} gl WebGL rendering context.
  21945. * @param {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} image Image.
  21946. * @param {number=} opt_wrapS wrapS.
  21947. * @param {number=} opt_wrapT wrapT.
  21948. * @return {WebGLTexture} The texture.
  21949. */
  21950. ol.webgl.Context.createTexture = function(gl, image, opt_wrapS, opt_wrapT) {
  21951. var texture = ol.webgl.Context.createTexture_(gl, opt_wrapS, opt_wrapT);
  21952. gl.texImage2D(
  21953. gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
  21954. return texture;
  21955. };
  21956. }
  21957. goog.provide('ol.render.webgl.TextureReplay');
  21958. goog.require('ol');
  21959. goog.require('ol.extent');
  21960. goog.require('ol.obj');
  21961. goog.require('ol.render.webgl.texturereplay.defaultshader');
  21962. goog.require('ol.render.webgl.Replay');
  21963. goog.require('ol.webgl');
  21964. goog.require('ol.webgl.Context');
  21965. if (ol.ENABLE_WEBGL) {
  21966. /**
  21967. * @constructor
  21968. * @abstract
  21969. * @extends {ol.render.webgl.Replay}
  21970. * @param {number} tolerance Tolerance.
  21971. * @param {ol.Extent} maxExtent Max extent.
  21972. * @struct
  21973. */
  21974. ol.render.webgl.TextureReplay = function(tolerance, maxExtent) {
  21975. ol.render.webgl.Replay.call(this, tolerance, maxExtent);
  21976. /**
  21977. * @type {number|undefined}
  21978. * @protected
  21979. */
  21980. this.anchorX = undefined;
  21981. /**
  21982. * @type {number|undefined}
  21983. * @protected
  21984. */
  21985. this.anchorY = undefined;
  21986. /**
  21987. * @type {Array.<number>}
  21988. * @protected
  21989. */
  21990. this.groupIndices = [];
  21991. /**
  21992. * @type {Array.<number>}
  21993. * @protected
  21994. */
  21995. this.hitDetectionGroupIndices = [];
  21996. /**
  21997. * @type {number|undefined}
  21998. * @protected
  21999. */
  22000. this.height = undefined;
  22001. /**
  22002. * @type {number|undefined}
  22003. * @protected
  22004. */
  22005. this.imageHeight = undefined;
  22006. /**
  22007. * @type {number|undefined}
  22008. * @protected
  22009. */
  22010. this.imageWidth = undefined;
  22011. /**
  22012. * @protected
  22013. * @type {ol.render.webgl.texturereplay.defaultshader.Locations}
  22014. */
  22015. this.defaultLocations = null;
  22016. /**
  22017. * @protected
  22018. * @type {number|undefined}
  22019. */
  22020. this.opacity = undefined;
  22021. /**
  22022. * @type {number|undefined}
  22023. * @protected
  22024. */
  22025. this.originX = undefined;
  22026. /**
  22027. * @type {number|undefined}
  22028. * @protected
  22029. */
  22030. this.originY = undefined;
  22031. /**
  22032. * @protected
  22033. * @type {boolean|undefined}
  22034. */
  22035. this.rotateWithView = undefined;
  22036. /**
  22037. * @protected
  22038. * @type {number|undefined}
  22039. */
  22040. this.rotation = undefined;
  22041. /**
  22042. * @protected
  22043. * @type {number|undefined}
  22044. */
  22045. this.scale = undefined;
  22046. /**
  22047. * @type {number|undefined}
  22048. * @protected
  22049. */
  22050. this.width = undefined;
  22051. };
  22052. ol.inherits(ol.render.webgl.TextureReplay, ol.render.webgl.Replay);
  22053. /**
  22054. * @inheritDoc
  22055. */
  22056. ol.render.webgl.TextureReplay.prototype.getDeleteResourcesFunction = function(context) {
  22057. var verticesBuffer = this.verticesBuffer;
  22058. var indicesBuffer = this.indicesBuffer;
  22059. var textures = this.getTextures(true);
  22060. var gl = context.getGL();
  22061. return function() {
  22062. if (!gl.isContextLost()) {
  22063. var i, ii;
  22064. for (i = 0, ii = textures.length; i < ii; ++i) {
  22065. gl.deleteTexture(textures[i]);
  22066. }
  22067. }
  22068. context.deleteBuffer(verticesBuffer);
  22069. context.deleteBuffer(indicesBuffer);
  22070. };
  22071. };
  22072. /**
  22073. * @param {Array.<number>} flatCoordinates Flat coordinates.
  22074. * @param {number} offset Offset.
  22075. * @param {number} end End.
  22076. * @param {number} stride Stride.
  22077. * @return {number} My end.
  22078. * @protected
  22079. */
  22080. ol.render.webgl.TextureReplay.prototype.drawCoordinates = function(flatCoordinates, offset, end, stride) {
  22081. var anchorX = /** @type {number} */ (this.anchorX);
  22082. var anchorY = /** @type {number} */ (this.anchorY);
  22083. var height = /** @type {number} */ (this.height);
  22084. var imageHeight = /** @type {number} */ (this.imageHeight);
  22085. var imageWidth = /** @type {number} */ (this.imageWidth);
  22086. var opacity = /** @type {number} */ (this.opacity);
  22087. var originX = /** @type {number} */ (this.originX);
  22088. var originY = /** @type {number} */ (this.originY);
  22089. var rotateWithView = this.rotateWithView ? 1.0 : 0.0;
  22090. // this.rotation_ is anti-clockwise, but rotation is clockwise
  22091. var rotation = /** @type {number} */ (-this.rotation);
  22092. var scale = /** @type {number} */ (this.scale);
  22093. var width = /** @type {number} */ (this.width);
  22094. var cos = Math.cos(rotation);
  22095. var sin = Math.sin(rotation);
  22096. var numIndices = this.indices.length;
  22097. var numVertices = this.vertices.length;
  22098. var i, n, offsetX, offsetY, x, y;
  22099. for (i = offset; i < end; i += stride) {
  22100. x = flatCoordinates[i] - this.origin[0];
  22101. y = flatCoordinates[i + 1] - this.origin[1];
  22102. // There are 4 vertices per [x, y] point, one for each corner of the
  22103. // rectangle we're going to draw. We'd use 1 vertex per [x, y] point if
  22104. // WebGL supported Geometry Shaders (which can emit new vertices), but that
  22105. // is not currently the case.
  22106. //
  22107. // And each vertex includes 8 values: the x and y coordinates, the x and
  22108. // y offsets used to calculate the position of the corner, the u and
  22109. // v texture coordinates for the corner, the opacity, and whether the
  22110. // the image should be rotated with the view (rotateWithView).
  22111. n = numVertices / 8;
  22112. // bottom-left corner
  22113. offsetX = -scale * anchorX;
  22114. offsetY = -scale * (height - anchorY);
  22115. this.vertices[numVertices++] = x;
  22116. this.vertices[numVertices++] = y;
  22117. this.vertices[numVertices++] = offsetX * cos - offsetY * sin;
  22118. this.vertices[numVertices++] = offsetX * sin + offsetY * cos;
  22119. this.vertices[numVertices++] = originX / imageWidth;
  22120. this.vertices[numVertices++] = (originY + height) / imageHeight;
  22121. this.vertices[numVertices++] = opacity;
  22122. this.vertices[numVertices++] = rotateWithView;
  22123. // bottom-right corner
  22124. offsetX = scale * (width - anchorX);
  22125. offsetY = -scale * (height - anchorY);
  22126. this.vertices[numVertices++] = x;
  22127. this.vertices[numVertices++] = y;
  22128. this.vertices[numVertices++] = offsetX * cos - offsetY * sin;
  22129. this.vertices[numVertices++] = offsetX * sin + offsetY * cos;
  22130. this.vertices[numVertices++] = (originX + width) / imageWidth;
  22131. this.vertices[numVertices++] = (originY + height) / imageHeight;
  22132. this.vertices[numVertices++] = opacity;
  22133. this.vertices[numVertices++] = rotateWithView;
  22134. // top-right corner
  22135. offsetX = scale * (width - anchorX);
  22136. offsetY = scale * anchorY;
  22137. this.vertices[numVertices++] = x;
  22138. this.vertices[numVertices++] = y;
  22139. this.vertices[numVertices++] = offsetX * cos - offsetY * sin;
  22140. this.vertices[numVertices++] = offsetX * sin + offsetY * cos;
  22141. this.vertices[numVertices++] = (originX + width) / imageWidth;
  22142. this.vertices[numVertices++] = originY / imageHeight;
  22143. this.vertices[numVertices++] = opacity;
  22144. this.vertices[numVertices++] = rotateWithView;
  22145. // top-left corner
  22146. offsetX = -scale * anchorX;
  22147. offsetY = scale * anchorY;
  22148. this.vertices[numVertices++] = x;
  22149. this.vertices[numVertices++] = y;
  22150. this.vertices[numVertices++] = offsetX * cos - offsetY * sin;
  22151. this.vertices[numVertices++] = offsetX * sin + offsetY * cos;
  22152. this.vertices[numVertices++] = originX / imageWidth;
  22153. this.vertices[numVertices++] = originY / imageHeight;
  22154. this.vertices[numVertices++] = opacity;
  22155. this.vertices[numVertices++] = rotateWithView;
  22156. this.indices[numIndices++] = n;
  22157. this.indices[numIndices++] = n + 1;
  22158. this.indices[numIndices++] = n + 2;
  22159. this.indices[numIndices++] = n;
  22160. this.indices[numIndices++] = n + 2;
  22161. this.indices[numIndices++] = n + 3;
  22162. }
  22163. return numVertices;
  22164. };
  22165. /**
  22166. * @protected
  22167. * @param {Array.<WebGLTexture>} textures Textures.
  22168. * @param {Array.<HTMLCanvasElement|HTMLImageElement|HTMLVideoElement>} images
  22169. * Images.
  22170. * @param {Object.<string, WebGLTexture>} texturePerImage Texture cache.
  22171. * @param {WebGLRenderingContext} gl Gl.
  22172. */
  22173. ol.render.webgl.TextureReplay.prototype.createTextures = function(textures, images, texturePerImage, gl) {
  22174. var texture, image, uid, i;
  22175. var ii = images.length;
  22176. for (i = 0; i < ii; ++i) {
  22177. image = images[i];
  22178. uid = ol.getUid(image).toString();
  22179. if (uid in texturePerImage) {
  22180. texture = texturePerImage[uid];
  22181. } else {
  22182. texture = ol.webgl.Context.createTexture(
  22183. gl, image, ol.webgl.CLAMP_TO_EDGE, ol.webgl.CLAMP_TO_EDGE);
  22184. texturePerImage[uid] = texture;
  22185. }
  22186. textures[i] = texture;
  22187. }
  22188. };
  22189. /**
  22190. * @inheritDoc
  22191. */
  22192. ol.render.webgl.TextureReplay.prototype.setUpProgram = function(gl, context, size, pixelRatio) {
  22193. // get the program
  22194. var fragmentShader = ol.render.webgl.texturereplay.defaultshader.fragment;
  22195. var vertexShader = ol.render.webgl.texturereplay.defaultshader.vertex;
  22196. var program = context.getProgram(fragmentShader, vertexShader);
  22197. // get the locations
  22198. var locations;
  22199. if (!this.defaultLocations) {
  22200. // eslint-disable-next-line openlayers-internal/no-missing-requires
  22201. locations = new ol.render.webgl.texturereplay.defaultshader.Locations(gl, program);
  22202. this.defaultLocations = locations;
  22203. } else {
  22204. locations = this.defaultLocations;
  22205. }
  22206. // use the program (FIXME: use the return value)
  22207. context.useProgram(program);
  22208. // enable the vertex attrib arrays
  22209. gl.enableVertexAttribArray(locations.a_position);
  22210. gl.vertexAttribPointer(locations.a_position, 2, ol.webgl.FLOAT,
  22211. false, 32, 0);
  22212. gl.enableVertexAttribArray(locations.a_offsets);
  22213. gl.vertexAttribPointer(locations.a_offsets, 2, ol.webgl.FLOAT,
  22214. false, 32, 8);
  22215. gl.enableVertexAttribArray(locations.a_texCoord);
  22216. gl.vertexAttribPointer(locations.a_texCoord, 2, ol.webgl.FLOAT,
  22217. false, 32, 16);
  22218. gl.enableVertexAttribArray(locations.a_opacity);
  22219. gl.vertexAttribPointer(locations.a_opacity, 1, ol.webgl.FLOAT,
  22220. false, 32, 24);
  22221. gl.enableVertexAttribArray(locations.a_rotateWithView);
  22222. gl.vertexAttribPointer(locations.a_rotateWithView, 1, ol.webgl.FLOAT,
  22223. false, 32, 28);
  22224. return locations;
  22225. };
  22226. /**
  22227. * @inheritDoc
  22228. */
  22229. ol.render.webgl.TextureReplay.prototype.shutDownProgram = function(gl, locations) {
  22230. gl.disableVertexAttribArray(locations.a_position);
  22231. gl.disableVertexAttribArray(locations.a_offsets);
  22232. gl.disableVertexAttribArray(locations.a_texCoord);
  22233. gl.disableVertexAttribArray(locations.a_opacity);
  22234. gl.disableVertexAttribArray(locations.a_rotateWithView);
  22235. };
  22236. /**
  22237. * @inheritDoc
  22238. */
  22239. ol.render.webgl.TextureReplay.prototype.drawReplay = function(gl, context, skippedFeaturesHash, hitDetection) {
  22240. var textures = hitDetection ? this.getHitDetectionTextures() : this.getTextures();
  22241. var groupIndices = hitDetection ? this.hitDetectionGroupIndices : this.groupIndices;
  22242. if (!ol.obj.isEmpty(skippedFeaturesHash)) {
  22243. this.drawReplaySkipping(
  22244. gl, context, skippedFeaturesHash, textures, groupIndices);
  22245. } else {
  22246. var i, ii, start;
  22247. for (i = 0, ii = textures.length, start = 0; i < ii; ++i) {
  22248. gl.bindTexture(ol.webgl.TEXTURE_2D, textures[i]);
  22249. var end = groupIndices[i];
  22250. this.drawElements(gl, context, start, end);
  22251. start = end;
  22252. }
  22253. }
  22254. };
  22255. /**
  22256. * Draw the replay while paying attention to skipped features.
  22257. *
  22258. * This functions creates groups of features that can be drawn to together,
  22259. * so that the number of `drawElements` calls is minimized.
  22260. *
  22261. * For example given the following texture groups:
  22262. *
  22263. * Group 1: A B C
  22264. * Group 2: D [E] F G
  22265. *
  22266. * If feature E should be skipped, the following `drawElements` calls will be
  22267. * made:
  22268. *
  22269. * drawElements with feature A, B and C
  22270. * drawElements with feature D
  22271. * drawElements with feature F and G
  22272. *
  22273. * @protected
  22274. * @param {WebGLRenderingContext} gl gl.
  22275. * @param {ol.webgl.Context} context Context.
  22276. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  22277. * to skip.
  22278. * @param {Array.<WebGLTexture>} textures Textures.
  22279. * @param {Array.<number>} groupIndices Texture group indices.
  22280. */
  22281. ol.render.webgl.TextureReplay.prototype.drawReplaySkipping = function(gl, context, skippedFeaturesHash, textures,
  22282. groupIndices) {
  22283. var featureIndex = 0;
  22284. var i, ii;
  22285. for (i = 0, ii = textures.length; i < ii; ++i) {
  22286. gl.bindTexture(ol.webgl.TEXTURE_2D, textures[i]);
  22287. var groupStart = (i > 0) ? groupIndices[i - 1] : 0;
  22288. var groupEnd = groupIndices[i];
  22289. var start = groupStart;
  22290. var end = groupStart;
  22291. while (featureIndex < this.startIndices.length &&
  22292. this.startIndices[featureIndex] <= groupEnd) {
  22293. var feature = this.startIndicesFeature[featureIndex];
  22294. var featureUid = ol.getUid(feature).toString();
  22295. if (skippedFeaturesHash[featureUid] !== undefined) {
  22296. // feature should be skipped
  22297. if (start !== end) {
  22298. // draw the features so far
  22299. this.drawElements(gl, context, start, end);
  22300. }
  22301. // continue with the next feature
  22302. start = (featureIndex === this.startIndices.length - 1) ?
  22303. groupEnd : this.startIndices[featureIndex + 1];
  22304. end = start;
  22305. } else {
  22306. // the feature is not skipped, augment the end index
  22307. end = (featureIndex === this.startIndices.length - 1) ?
  22308. groupEnd : this.startIndices[featureIndex + 1];
  22309. }
  22310. featureIndex++;
  22311. }
  22312. if (start !== end) {
  22313. // draw the remaining features (in case there was no skipped feature
  22314. // in this texture group, all features of a group are drawn together)
  22315. this.drawElements(gl, context, start, end);
  22316. }
  22317. }
  22318. };
  22319. /**
  22320. * @inheritDoc
  22321. */
  22322. ol.render.webgl.TextureReplay.prototype.drawHitDetectionReplayOneByOne = function(gl, context, skippedFeaturesHash,
  22323. featureCallback, opt_hitExtent) {
  22324. var i, groupStart, start, end, feature, featureUid;
  22325. var featureIndex = this.startIndices.length - 1;
  22326. var hitDetectionTextures = this.getHitDetectionTextures();
  22327. for (i = hitDetectionTextures.length - 1; i >= 0; --i) {
  22328. gl.bindTexture(ol.webgl.TEXTURE_2D, hitDetectionTextures[i]);
  22329. groupStart = (i > 0) ? this.hitDetectionGroupIndices[i - 1] : 0;
  22330. end = this.hitDetectionGroupIndices[i];
  22331. // draw all features for this texture group
  22332. while (featureIndex >= 0 &&
  22333. this.startIndices[featureIndex] >= groupStart) {
  22334. start = this.startIndices[featureIndex];
  22335. feature = this.startIndicesFeature[featureIndex];
  22336. featureUid = ol.getUid(feature).toString();
  22337. if (skippedFeaturesHash[featureUid] === undefined &&
  22338. feature.getGeometry() &&
  22339. (opt_hitExtent === undefined || ol.extent.intersects(
  22340. /** @type {Array<number>} */ (opt_hitExtent),
  22341. feature.getGeometry().getExtent()))) {
  22342. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  22343. this.drawElements(gl, context, start, end);
  22344. var result = featureCallback(feature);
  22345. if (result) {
  22346. return result;
  22347. }
  22348. }
  22349. end = start;
  22350. featureIndex--;
  22351. }
  22352. }
  22353. return undefined;
  22354. };
  22355. /**
  22356. * @inheritDoc
  22357. */
  22358. ol.render.webgl.TextureReplay.prototype.finish = function(context) {
  22359. this.anchorX = undefined;
  22360. this.anchorY = undefined;
  22361. this.height = undefined;
  22362. this.imageHeight = undefined;
  22363. this.imageWidth = undefined;
  22364. this.indices = null;
  22365. this.opacity = undefined;
  22366. this.originX = undefined;
  22367. this.originY = undefined;
  22368. this.rotateWithView = undefined;
  22369. this.rotation = undefined;
  22370. this.scale = undefined;
  22371. this.vertices = null;
  22372. this.width = undefined;
  22373. };
  22374. /**
  22375. * @abstract
  22376. * @protected
  22377. * @param {boolean=} opt_all Return hit detection textures with regular ones.
  22378. * @returns {Array.<WebGLTexture>} Textures.
  22379. */
  22380. ol.render.webgl.TextureReplay.prototype.getTextures = function(opt_all) {};
  22381. /**
  22382. * @abstract
  22383. * @protected
  22384. * @returns {Array.<WebGLTexture>} Textures.
  22385. */
  22386. ol.render.webgl.TextureReplay.prototype.getHitDetectionTextures = function() {};
  22387. }
  22388. goog.provide('ol.render.webgl.ImageReplay');
  22389. goog.require('ol');
  22390. goog.require('ol.render.webgl.TextureReplay');
  22391. goog.require('ol.webgl.Buffer');
  22392. if (ol.ENABLE_WEBGL) {
  22393. /**
  22394. * @constructor
  22395. * @extends {ol.render.webgl.TextureReplay}
  22396. * @param {number} tolerance Tolerance.
  22397. * @param {ol.Extent} maxExtent Max extent.
  22398. * @struct
  22399. */
  22400. ol.render.webgl.ImageReplay = function(tolerance, maxExtent) {
  22401. ol.render.webgl.TextureReplay.call(this, tolerance, maxExtent);
  22402. /**
  22403. * @type {Array.<HTMLCanvasElement|HTMLImageElement|HTMLVideoElement>}
  22404. * @protected
  22405. */
  22406. this.images_ = [];
  22407. /**
  22408. * @type {Array.<HTMLCanvasElement|HTMLImageElement|HTMLVideoElement>}
  22409. * @protected
  22410. */
  22411. this.hitDetectionImages_ = [];
  22412. /**
  22413. * @type {Array.<WebGLTexture>}
  22414. * @private
  22415. */
  22416. this.textures_ = [];
  22417. /**
  22418. * @type {Array.<WebGLTexture>}
  22419. * @private
  22420. */
  22421. this.hitDetectionTextures_ = [];
  22422. };
  22423. ol.inherits(ol.render.webgl.ImageReplay, ol.render.webgl.TextureReplay);
  22424. /**
  22425. * @inheritDoc
  22426. */
  22427. ol.render.webgl.ImageReplay.prototype.drawMultiPoint = function(multiPointGeometry, feature) {
  22428. this.startIndices.push(this.indices.length);
  22429. this.startIndicesFeature.push(feature);
  22430. var flatCoordinates = multiPointGeometry.getFlatCoordinates();
  22431. var stride = multiPointGeometry.getStride();
  22432. this.drawCoordinates(
  22433. flatCoordinates, 0, flatCoordinates.length, stride);
  22434. };
  22435. /**
  22436. * @inheritDoc
  22437. */
  22438. ol.render.webgl.ImageReplay.prototype.drawPoint = function(pointGeometry, feature) {
  22439. this.startIndices.push(this.indices.length);
  22440. this.startIndicesFeature.push(feature);
  22441. var flatCoordinates = pointGeometry.getFlatCoordinates();
  22442. var stride = pointGeometry.getStride();
  22443. this.drawCoordinates(
  22444. flatCoordinates, 0, flatCoordinates.length, stride);
  22445. };
  22446. /**
  22447. * @inheritDoc
  22448. */
  22449. ol.render.webgl.ImageReplay.prototype.finish = function(context) {
  22450. var gl = context.getGL();
  22451. this.groupIndices.push(this.indices.length);
  22452. this.hitDetectionGroupIndices.push(this.indices.length);
  22453. // create, bind, and populate the vertices buffer
  22454. this.verticesBuffer = new ol.webgl.Buffer(this.vertices);
  22455. var indices = this.indices;
  22456. // create, bind, and populate the indices buffer
  22457. this.indicesBuffer = new ol.webgl.Buffer(indices);
  22458. // create textures
  22459. /** @type {Object.<string, WebGLTexture>} */
  22460. var texturePerImage = {};
  22461. this.createTextures(this.textures_, this.images_, texturePerImage, gl);
  22462. this.createTextures(this.hitDetectionTextures_, this.hitDetectionImages_,
  22463. texturePerImage, gl);
  22464. this.images_ = null;
  22465. this.hitDetectionImages_ = null;
  22466. ol.render.webgl.TextureReplay.prototype.finish.call(this, context);
  22467. };
  22468. /**
  22469. * @inheritDoc
  22470. */
  22471. ol.render.webgl.ImageReplay.prototype.setImageStyle = function(imageStyle) {
  22472. var anchor = imageStyle.getAnchor();
  22473. var image = imageStyle.getImage(1);
  22474. var imageSize = imageStyle.getImageSize();
  22475. var hitDetectionImage = imageStyle.getHitDetectionImage(1);
  22476. var opacity = imageStyle.getOpacity();
  22477. var origin = imageStyle.getOrigin();
  22478. var rotateWithView = imageStyle.getRotateWithView();
  22479. var rotation = imageStyle.getRotation();
  22480. var size = imageStyle.getSize();
  22481. var scale = imageStyle.getScale();
  22482. var currentImage;
  22483. if (this.images_.length === 0) {
  22484. this.images_.push(image);
  22485. } else {
  22486. currentImage = this.images_[this.images_.length - 1];
  22487. if (ol.getUid(currentImage) != ol.getUid(image)) {
  22488. this.groupIndices.push(this.indices.length);
  22489. this.images_.push(image);
  22490. }
  22491. }
  22492. if (this.hitDetectionImages_.length === 0) {
  22493. this.hitDetectionImages_.push(hitDetectionImage);
  22494. } else {
  22495. currentImage =
  22496. this.hitDetectionImages_[this.hitDetectionImages_.length - 1];
  22497. if (ol.getUid(currentImage) != ol.getUid(hitDetectionImage)) {
  22498. this.hitDetectionGroupIndices.push(this.indices.length);
  22499. this.hitDetectionImages_.push(hitDetectionImage);
  22500. }
  22501. }
  22502. this.anchorX = anchor[0];
  22503. this.anchorY = anchor[1];
  22504. this.height = size[1];
  22505. this.imageHeight = imageSize[1];
  22506. this.imageWidth = imageSize[0];
  22507. this.opacity = opacity;
  22508. this.originX = origin[0];
  22509. this.originY = origin[1];
  22510. this.rotation = rotation;
  22511. this.rotateWithView = rotateWithView;
  22512. this.scale = scale;
  22513. this.width = size[0];
  22514. };
  22515. /**
  22516. * @inheritDoc
  22517. */
  22518. ol.render.webgl.ImageReplay.prototype.getTextures = function(opt_all) {
  22519. return opt_all ? this.textures_.concat(this.hitDetectionTextures_) : this.textures_;
  22520. };
  22521. /**
  22522. * @inheritDoc
  22523. */
  22524. ol.render.webgl.ImageReplay.prototype.getHitDetectionTextures = function() {
  22525. return this.hitDetectionTextures_;
  22526. };
  22527. }
  22528. goog.provide('ol.geom.flat.topology');
  22529. goog.require('ol.geom.flat.area');
  22530. /**
  22531. * Check if the linestring is a boundary.
  22532. * @param {Array.<number>} flatCoordinates Flat coordinates.
  22533. * @param {number} offset Offset.
  22534. * @param {number} end End.
  22535. * @param {number} stride Stride.
  22536. * @return {boolean} The linestring is a boundary.
  22537. */
  22538. ol.geom.flat.topology.lineStringIsClosed = function(flatCoordinates, offset, end, stride) {
  22539. var lastCoord = end - stride;
  22540. if (flatCoordinates[offset] === flatCoordinates[lastCoord] &&
  22541. flatCoordinates[offset + 1] === flatCoordinates[lastCoord + 1] && (end - offset) / stride > 3) {
  22542. return !!ol.geom.flat.area.linearRing(flatCoordinates, offset, end, stride);
  22543. }
  22544. return false;
  22545. };
  22546. // This file is automatically generated, do not edit
  22547. /* eslint openlayers-internal/no-missing-requires: 0 */
  22548. goog.provide('ol.render.webgl.linestringreplay.defaultshader');
  22549. goog.require('ol');
  22550. goog.require('ol.webgl.Fragment');
  22551. goog.require('ol.webgl.Vertex');
  22552. if (ol.ENABLE_WEBGL) {
  22553. /**
  22554. * @constructor
  22555. * @extends {ol.webgl.Fragment}
  22556. * @struct
  22557. */
  22558. ol.render.webgl.linestringreplay.defaultshader.Fragment = function() {
  22559. ol.webgl.Fragment.call(this, ol.render.webgl.linestringreplay.defaultshader.Fragment.SOURCE);
  22560. };
  22561. ol.inherits(ol.render.webgl.linestringreplay.defaultshader.Fragment, ol.webgl.Fragment);
  22562. /**
  22563. * @const
  22564. * @type {string}
  22565. */
  22566. ol.render.webgl.linestringreplay.defaultshader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying float v_round;\nvarying vec2 v_roundVertex;\nvarying float v_halfWidth;\n\n\n\nuniform float u_opacity;\nuniform vec4 u_color;\nuniform vec2 u_size;\nuniform float u_pixelRatio;\n\nvoid main(void) {\n if (v_round > 0.0) {\n vec2 windowCoords = vec2((v_roundVertex.x + 1.0) / 2.0 * u_size.x * u_pixelRatio,\n (v_roundVertex.y + 1.0) / 2.0 * u_size.y * u_pixelRatio);\n if (length(windowCoords - gl_FragCoord.xy) > v_halfWidth * u_pixelRatio) {\n discard;\n }\n }\n gl_FragColor = u_color;\n float alpha = u_color.a * u_opacity;\n if (alpha == 0.0) {\n discard;\n }\n gl_FragColor.a = alpha;\n}\n';
  22567. /**
  22568. * @const
  22569. * @type {string}
  22570. */
  22571. ol.render.webgl.linestringreplay.defaultshader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying float a;varying vec2 b;varying float c;uniform float m;uniform vec4 n;uniform vec2 o;uniform float p;void main(void){if(a>0.0){vec2 windowCoords=vec2((b.x+1.0)/2.0*o.x*p,(b.y+1.0)/2.0*o.y*p);if(length(windowCoords-gl_FragCoord.xy)>c*p){discard;}} gl_FragColor=n;float alpha=n.a*m;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}';
  22572. /**
  22573. * @const
  22574. * @type {string}
  22575. */
  22576. ol.render.webgl.linestringreplay.defaultshader.Fragment.SOURCE = ol.DEBUG_WEBGL ?
  22577. ol.render.webgl.linestringreplay.defaultshader.Fragment.DEBUG_SOURCE :
  22578. ol.render.webgl.linestringreplay.defaultshader.Fragment.OPTIMIZED_SOURCE;
  22579. ol.render.webgl.linestringreplay.defaultshader.fragment = new ol.render.webgl.linestringreplay.defaultshader.Fragment();
  22580. /**
  22581. * @constructor
  22582. * @extends {ol.webgl.Vertex}
  22583. * @struct
  22584. */
  22585. ol.render.webgl.linestringreplay.defaultshader.Vertex = function() {
  22586. ol.webgl.Vertex.call(this, ol.render.webgl.linestringreplay.defaultshader.Vertex.SOURCE);
  22587. };
  22588. ol.inherits(ol.render.webgl.linestringreplay.defaultshader.Vertex, ol.webgl.Vertex);
  22589. /**
  22590. * @const
  22591. * @type {string}
  22592. */
  22593. ol.render.webgl.linestringreplay.defaultshader.Vertex.DEBUG_SOURCE = 'varying float v_round;\nvarying vec2 v_roundVertex;\nvarying float v_halfWidth;\n\n\nattribute vec2 a_lastPos;\nattribute vec2 a_position;\nattribute vec2 a_nextPos;\nattribute float a_direction;\n\nuniform mat4 u_projectionMatrix;\nuniform mat4 u_offsetScaleMatrix;\nuniform mat4 u_offsetRotateMatrix;\nuniform float u_lineWidth;\nuniform float u_miterLimit;\n\nbool nearlyEquals(in float value, in float ref) {\n float epsilon = 0.000000000001;\n return value >= ref - epsilon && value <= ref + epsilon;\n}\n\nvoid alongNormal(out vec2 offset, in vec2 nextP, in float turnDir, in float direction) {\n vec2 dirVect = nextP - a_position;\n vec2 normal = normalize(vec2(-turnDir * dirVect.y, turnDir * dirVect.x));\n offset = u_lineWidth / 2.0 * normal * direction;\n}\n\nvoid miterUp(out vec2 offset, out float round, in bool isRound, in float direction) {\n float halfWidth = u_lineWidth / 2.0;\n vec2 tangent = normalize(normalize(a_nextPos - a_position) + normalize(a_position - a_lastPos));\n vec2 normal = vec2(-tangent.y, tangent.x);\n vec2 dirVect = a_nextPos - a_position;\n vec2 tmpNormal = normalize(vec2(-dirVect.y, dirVect.x));\n float miterLength = abs(halfWidth / dot(normal, tmpNormal));\n offset = normal * direction * miterLength;\n round = 0.0;\n if (isRound) {\n round = 1.0;\n } else if (miterLength > u_miterLimit + u_lineWidth) {\n offset = halfWidth * tmpNormal * direction;\n }\n}\n\nbool miterDown(out vec2 offset, in vec4 projPos, in mat4 offsetMatrix, in float direction) {\n bool degenerate = false;\n vec2 tangent = normalize(normalize(a_nextPos - a_position) + normalize(a_position - a_lastPos));\n vec2 normal = vec2(-tangent.y, tangent.x);\n vec2 dirVect = a_lastPos - a_position;\n vec2 tmpNormal = normalize(vec2(-dirVect.y, dirVect.x));\n vec2 longOffset, shortOffset, longVertex;\n vec4 shortProjVertex;\n float halfWidth = u_lineWidth / 2.0;\n if (length(a_nextPos - a_position) > length(a_lastPos - a_position)) {\n longOffset = tmpNormal * direction * halfWidth;\n shortOffset = normalize(vec2(dirVect.y, -dirVect.x)) * direction * halfWidth;\n longVertex = a_nextPos;\n shortProjVertex = u_projectionMatrix * vec4(a_lastPos, 0.0, 1.0);\n } else {\n shortOffset = tmpNormal * direction * halfWidth;\n longOffset = normalize(vec2(dirVect.y, -dirVect.x)) * direction * halfWidth;\n longVertex = a_lastPos;\n shortProjVertex = u_projectionMatrix * vec4(a_nextPos, 0.0, 1.0);\n }\n //Intersection algorithm based on theory by Paul Bourke (http://paulbourke.net/geometry/pointlineplane/).\n vec4 p1 = u_projectionMatrix * vec4(longVertex, 0.0, 1.0) + offsetMatrix * vec4(longOffset, 0.0, 0.0);\n vec4 p2 = projPos + offsetMatrix * vec4(longOffset, 0.0, 0.0);\n vec4 p3 = shortProjVertex + offsetMatrix * vec4(-shortOffset, 0.0, 0.0);\n vec4 p4 = shortProjVertex + offsetMatrix * vec4(shortOffset, 0.0, 0.0);\n float denom = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y);\n float firstU = ((p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x)) / denom;\n float secondU = ((p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x)) / denom;\n float epsilon = 0.000000000001;\n if (firstU > epsilon && firstU < 1.0 - epsilon && secondU > epsilon && secondU < 1.0 - epsilon) {\n shortProjVertex.x = p1.x + firstU * (p2.x - p1.x);\n shortProjVertex.y = p1.y + firstU * (p2.y - p1.y);\n offset = shortProjVertex.xy;\n degenerate = true;\n } else {\n float miterLength = abs(halfWidth / dot(normal, tmpNormal));\n offset = normal * direction * miterLength;\n }\n return degenerate;\n}\n\nvoid squareCap(out vec2 offset, out float round, in bool isRound, in vec2 nextP,\n in float turnDir, in float direction) {\n round = 0.0;\n vec2 dirVect = a_position - nextP;\n vec2 firstNormal = normalize(dirVect);\n vec2 secondNormal = vec2(turnDir * firstNormal.y * direction, -turnDir * firstNormal.x * direction);\n vec2 hypotenuse = normalize(firstNormal - secondNormal);\n vec2 normal = vec2(turnDir * hypotenuse.y * direction, -turnDir * hypotenuse.x * direction);\n float length = sqrt(v_halfWidth * v_halfWidth * 2.0);\n offset = normal * length;\n if (isRound) {\n round = 1.0;\n }\n}\n\nvoid main(void) {\n bool degenerate = false;\n float direction = float(sign(a_direction));\n mat4 offsetMatrix = u_offsetScaleMatrix * u_offsetRotateMatrix;\n vec2 offset;\n vec4 projPos = u_projectionMatrix * vec4(a_position, 0.0, 1.0);\n bool round = nearlyEquals(mod(a_direction, 2.0), 0.0);\n\n v_round = 0.0;\n v_halfWidth = u_lineWidth / 2.0;\n v_roundVertex = projPos.xy;\n\n if (nearlyEquals(mod(a_direction, 3.0), 0.0) || nearlyEquals(mod(a_direction, 17.0), 0.0)) {\n alongNormal(offset, a_nextPos, 1.0, direction);\n } else if (nearlyEquals(mod(a_direction, 5.0), 0.0) || nearlyEquals(mod(a_direction, 13.0), 0.0)) {\n alongNormal(offset, a_lastPos, -1.0, direction);\n } else if (nearlyEquals(mod(a_direction, 23.0), 0.0)) {\n miterUp(offset, v_round, round, direction);\n } else if (nearlyEquals(mod(a_direction, 19.0), 0.0)) {\n degenerate = miterDown(offset, projPos, offsetMatrix, direction);\n } else if (nearlyEquals(mod(a_direction, 7.0), 0.0)) {\n squareCap(offset, v_round, round, a_nextPos, 1.0, direction);\n } else if (nearlyEquals(mod(a_direction, 11.0), 0.0)) {\n squareCap(offset, v_round, round, a_lastPos, -1.0, direction);\n }\n if (!degenerate) {\n vec4 offsets = offsetMatrix * vec4(offset, 0.0, 0.0);\n gl_Position = projPos + offsets;\n } else {\n gl_Position = vec4(offset, 0.0, 1.0);\n }\n}\n\n\n';
  22594. /**
  22595. * @const
  22596. * @type {string}
  22597. */
  22598. ol.render.webgl.linestringreplay.defaultshader.Vertex.OPTIMIZED_SOURCE = 'varying float a;varying vec2 b;varying float c;attribute vec2 d;attribute vec2 e;attribute vec2 f;attribute float g;uniform mat4 h;uniform mat4 i;uniform mat4 j;uniform float k;uniform float l;bool nearlyEquals(in float value,in float ref){float epsilon=0.000000000001;return value>=ref-epsilon&&value<=ref+epsilon;}void alongNormal(out vec2 offset,in vec2 nextP,in float turnDir,in float direction){vec2 dirVect=nextP-e;vec2 normal=normalize(vec2(-turnDir*dirVect.y,turnDir*dirVect.x));offset=k/2.0*normal*direction;}void miterUp(out vec2 offset,out float round,in bool isRound,in float direction){float halfWidth=k/2.0;vec2 tangent=normalize(normalize(f-e)+normalize(e-d));vec2 normal=vec2(-tangent.y,tangent.x);vec2 dirVect=f-e;vec2 tmpNormal=normalize(vec2(-dirVect.y,dirVect.x));float miterLength=abs(halfWidth/dot(normal,tmpNormal));offset=normal*direction*miterLength;round=0.0;if(isRound){round=1.0;}else if(miterLength>l+k){offset=halfWidth*tmpNormal*direction;}} bool miterDown(out vec2 offset,in vec4 projPos,in mat4 offsetMatrix,in float direction){bool degenerate=false;vec2 tangent=normalize(normalize(f-e)+normalize(e-d));vec2 normal=vec2(-tangent.y,tangent.x);vec2 dirVect=d-e;vec2 tmpNormal=normalize(vec2(-dirVect.y,dirVect.x));vec2 longOffset,shortOffset,longVertex;vec4 shortProjVertex;float halfWidth=k/2.0;if(length(f-e)>length(d-e)){longOffset=tmpNormal*direction*halfWidth;shortOffset=normalize(vec2(dirVect.y,-dirVect.x))*direction*halfWidth;longVertex=f;shortProjVertex=h*vec4(d,0.0,1.0);}else{shortOffset=tmpNormal*direction*halfWidth;longOffset=normalize(vec2(dirVect.y,-dirVect.x))*direction*halfWidth;longVertex=d;shortProjVertex=h*vec4(f,0.0,1.0);}vec4 p1=h*vec4(longVertex,0.0,1.0)+offsetMatrix*vec4(longOffset,0.0,0.0);vec4 p2=projPos+offsetMatrix*vec4(longOffset,0.0,0.0);vec4 p3=shortProjVertex+offsetMatrix*vec4(-shortOffset,0.0,0.0);vec4 p4=shortProjVertex+offsetMatrix*vec4(shortOffset,0.0,0.0);float denom=(p4.y-p3.y)*(p2.x-p1.x)-(p4.x-p3.x)*(p2.y-p1.y);float firstU=((p4.x-p3.x)*(p1.y-p3.y)-(p4.y-p3.y)*(p1.x-p3.x))/denom;float secondU=((p2.x-p1.x)*(p1.y-p3.y)-(p2.y-p1.y)*(p1.x-p3.x))/denom;float epsilon=0.000000000001;if(firstU>epsilon&&firstU<1.0-epsilon&&secondU>epsilon&&secondU<1.0-epsilon){shortProjVertex.x=p1.x+firstU*(p2.x-p1.x);shortProjVertex.y=p1.y+firstU*(p2.y-p1.y);offset=shortProjVertex.xy;degenerate=true;}else{float miterLength=abs(halfWidth/dot(normal,tmpNormal));offset=normal*direction*miterLength;}return degenerate;}void squareCap(out vec2 offset,out float round,in bool isRound,in vec2 nextP,in float turnDir,in float direction){round=0.0;vec2 dirVect=e-nextP;vec2 firstNormal=normalize(dirVect);vec2 secondNormal=vec2(turnDir*firstNormal.y*direction,-turnDir*firstNormal.x*direction);vec2 hypotenuse=normalize(firstNormal-secondNormal);vec2 normal=vec2(turnDir*hypotenuse.y*direction,-turnDir*hypotenuse.x*direction);float length=sqrt(c*c*2.0);offset=normal*length;if(isRound){round=1.0;}} void main(void){bool degenerate=false;float direction=float(sign(g));mat4 offsetMatrix=i*j;vec2 offset;vec4 projPos=h*vec4(e,0.0,1.0);bool round=nearlyEquals(mod(g,2.0),0.0);a=0.0;c=k/2.0;b=projPos.xy;if(nearlyEquals(mod(g,3.0),0.0)||nearlyEquals(mod(g,17.0),0.0)){alongNormal(offset,f,1.0,direction);}else if(nearlyEquals(mod(g,5.0),0.0)||nearlyEquals(mod(g,13.0),0.0)){alongNormal(offset,d,-1.0,direction);}else if(nearlyEquals(mod(g,23.0),0.0)){miterUp(offset,a,round,direction);}else if(nearlyEquals(mod(g,19.0),0.0)){degenerate=miterDown(offset,projPos,offsetMatrix,direction);}else if(nearlyEquals(mod(g,7.0),0.0)){squareCap(offset,a,round,f,1.0,direction);}else if(nearlyEquals(mod(g,11.0),0.0)){squareCap(offset,a,round,d,-1.0,direction);}if(!degenerate){vec4 offsets=offsetMatrix*vec4(offset,0.0,0.0);gl_Position=projPos+offsets;}else{gl_Position=vec4(offset,0.0,1.0);}}';
  22599. /**
  22600. * @const
  22601. * @type {string}
  22602. */
  22603. ol.render.webgl.linestringreplay.defaultshader.Vertex.SOURCE = ol.DEBUG_WEBGL ?
  22604. ol.render.webgl.linestringreplay.defaultshader.Vertex.DEBUG_SOURCE :
  22605. ol.render.webgl.linestringreplay.defaultshader.Vertex.OPTIMIZED_SOURCE;
  22606. ol.render.webgl.linestringreplay.defaultshader.vertex = new ol.render.webgl.linestringreplay.defaultshader.Vertex();
  22607. /**
  22608. * @constructor
  22609. * @param {WebGLRenderingContext} gl GL.
  22610. * @param {WebGLProgram} program Program.
  22611. * @struct
  22612. */
  22613. ol.render.webgl.linestringreplay.defaultshader.Locations = function(gl, program) {
  22614. /**
  22615. * @type {WebGLUniformLocation}
  22616. */
  22617. this.u_color = gl.getUniformLocation(
  22618. program, ol.DEBUG_WEBGL ? 'u_color' : 'n');
  22619. /**
  22620. * @type {WebGLUniformLocation}
  22621. */
  22622. this.u_lineWidth = gl.getUniformLocation(
  22623. program, ol.DEBUG_WEBGL ? 'u_lineWidth' : 'k');
  22624. /**
  22625. * @type {WebGLUniformLocation}
  22626. */
  22627. this.u_miterLimit = gl.getUniformLocation(
  22628. program, ol.DEBUG_WEBGL ? 'u_miterLimit' : 'l');
  22629. /**
  22630. * @type {WebGLUniformLocation}
  22631. */
  22632. this.u_offsetRotateMatrix = gl.getUniformLocation(
  22633. program, ol.DEBUG_WEBGL ? 'u_offsetRotateMatrix' : 'j');
  22634. /**
  22635. * @type {WebGLUniformLocation}
  22636. */
  22637. this.u_offsetScaleMatrix = gl.getUniformLocation(
  22638. program, ol.DEBUG_WEBGL ? 'u_offsetScaleMatrix' : 'i');
  22639. /**
  22640. * @type {WebGLUniformLocation}
  22641. */
  22642. this.u_opacity = gl.getUniformLocation(
  22643. program, ol.DEBUG_WEBGL ? 'u_opacity' : 'm');
  22644. /**
  22645. * @type {WebGLUniformLocation}
  22646. */
  22647. this.u_pixelRatio = gl.getUniformLocation(
  22648. program, ol.DEBUG_WEBGL ? 'u_pixelRatio' : 'p');
  22649. /**
  22650. * @type {WebGLUniformLocation}
  22651. */
  22652. this.u_projectionMatrix = gl.getUniformLocation(
  22653. program, ol.DEBUG_WEBGL ? 'u_projectionMatrix' : 'h');
  22654. /**
  22655. * @type {WebGLUniformLocation}
  22656. */
  22657. this.u_size = gl.getUniformLocation(
  22658. program, ol.DEBUG_WEBGL ? 'u_size' : 'o');
  22659. /**
  22660. * @type {number}
  22661. */
  22662. this.a_direction = gl.getAttribLocation(
  22663. program, ol.DEBUG_WEBGL ? 'a_direction' : 'g');
  22664. /**
  22665. * @type {number}
  22666. */
  22667. this.a_lastPos = gl.getAttribLocation(
  22668. program, ol.DEBUG_WEBGL ? 'a_lastPos' : 'd');
  22669. /**
  22670. * @type {number}
  22671. */
  22672. this.a_nextPos = gl.getAttribLocation(
  22673. program, ol.DEBUG_WEBGL ? 'a_nextPos' : 'f');
  22674. /**
  22675. * @type {number}
  22676. */
  22677. this.a_position = gl.getAttribLocation(
  22678. program, ol.DEBUG_WEBGL ? 'a_position' : 'e');
  22679. };
  22680. }
  22681. goog.provide('ol.render.webgl.LineStringReplay');
  22682. goog.require('ol');
  22683. goog.require('ol.array');
  22684. goog.require('ol.color');
  22685. goog.require('ol.extent');
  22686. goog.require('ol.geom.flat.orient');
  22687. goog.require('ol.geom.flat.transform');
  22688. goog.require('ol.geom.flat.topology');
  22689. goog.require('ol.obj');
  22690. goog.require('ol.render.webgl');
  22691. goog.require('ol.render.webgl.Replay');
  22692. goog.require('ol.render.webgl.linestringreplay.defaultshader');
  22693. goog.require('ol.webgl');
  22694. goog.require('ol.webgl.Buffer');
  22695. if (ol.ENABLE_WEBGL) {
  22696. /**
  22697. * @constructor
  22698. * @extends {ol.render.webgl.Replay}
  22699. * @param {number} tolerance Tolerance.
  22700. * @param {ol.Extent} maxExtent Max extent.
  22701. * @struct
  22702. */
  22703. ol.render.webgl.LineStringReplay = function(tolerance, maxExtent) {
  22704. ol.render.webgl.Replay.call(this, tolerance, maxExtent);
  22705. /**
  22706. * @private
  22707. * @type {ol.render.webgl.linestringreplay.defaultshader.Locations}
  22708. */
  22709. this.defaultLocations_ = null;
  22710. /**
  22711. * @private
  22712. * @type {Array.<Array.<?>>}
  22713. */
  22714. this.styles_ = [];
  22715. /**
  22716. * @private
  22717. * @type {Array.<number>}
  22718. */
  22719. this.styleIndices_ = [];
  22720. /**
  22721. * @private
  22722. * @type {{strokeColor: (Array.<number>|null),
  22723. * lineCap: (string|undefined),
  22724. * lineDash: Array.<number>,
  22725. * lineDashOffset: (number|undefined),
  22726. * lineJoin: (string|undefined),
  22727. * lineWidth: (number|undefined),
  22728. * miterLimit: (number|undefined),
  22729. * changed: boolean}|null}
  22730. */
  22731. this.state_ = {
  22732. strokeColor: null,
  22733. lineCap: undefined,
  22734. lineDash: null,
  22735. lineDashOffset: undefined,
  22736. lineJoin: undefined,
  22737. lineWidth: undefined,
  22738. miterLimit: undefined,
  22739. changed: false
  22740. };
  22741. };
  22742. ol.inherits(ol.render.webgl.LineStringReplay, ol.render.webgl.Replay);
  22743. /**
  22744. * Draw one segment.
  22745. * @private
  22746. * @param {Array.<number>} flatCoordinates Flat coordinates.
  22747. * @param {number} offset Offset.
  22748. * @param {number} end End.
  22749. * @param {number} stride Stride.
  22750. */
  22751. ol.render.webgl.LineStringReplay.prototype.drawCoordinates_ = function(flatCoordinates, offset, end, stride) {
  22752. var i, ii;
  22753. var numVertices = this.vertices.length;
  22754. var numIndices = this.indices.length;
  22755. //To save a vertex, the direction of a point is a product of the sign (1 or -1), a prime from
  22756. //ol.render.webgl.LineStringReplay.Instruction_, and a rounding factor (1 or 2). If the product is even,
  22757. //we round it. If it is odd, we don't.
  22758. var lineJoin = this.state_.lineJoin === 'bevel' ? 0 :
  22759. this.state_.lineJoin === 'miter' ? 1 : 2;
  22760. var lineCap = this.state_.lineCap === 'butt' ? 0 :
  22761. this.state_.lineCap === 'square' ? 1 : 2;
  22762. var closed = ol.geom.flat.topology.lineStringIsClosed(flatCoordinates, offset, end, stride);
  22763. var startCoords, sign, n;
  22764. var lastIndex = numIndices;
  22765. var lastSign = 1;
  22766. //We need the adjacent vertices to define normals in joins. p0 = last, p1 = current, p2 = next.
  22767. var p0, p1, p2;
  22768. for (i = offset, ii = end; i < ii; i += stride) {
  22769. n = numVertices / 7;
  22770. p0 = p1;
  22771. p1 = p2 || [flatCoordinates[i], flatCoordinates[i + 1]];
  22772. //First vertex.
  22773. if (i === offset) {
  22774. p2 = [flatCoordinates[i + stride], flatCoordinates[i + stride + 1]];
  22775. if (end - offset === stride * 2 && ol.array.equals(p1, p2)) {
  22776. break;
  22777. }
  22778. if (closed) {
  22779. //A closed line! Complete the circle.
  22780. p0 = [flatCoordinates[end - stride * 2],
  22781. flatCoordinates[end - stride * 2 + 1]];
  22782. startCoords = p2;
  22783. } else {
  22784. //Add the first two/four vertices.
  22785. if (lineCap) {
  22786. numVertices = this.addVertices_([0, 0], p1, p2,
  22787. lastSign * ol.render.webgl.LineStringReplay.Instruction_.BEGIN_LINE_CAP * lineCap, numVertices);
  22788. numVertices = this.addVertices_([0, 0], p1, p2,
  22789. -lastSign * ol.render.webgl.LineStringReplay.Instruction_.BEGIN_LINE_CAP * lineCap, numVertices);
  22790. this.indices[numIndices++] = n + 2;
  22791. this.indices[numIndices++] = n;
  22792. this.indices[numIndices++] = n + 1;
  22793. this.indices[numIndices++] = n + 1;
  22794. this.indices[numIndices++] = n + 3;
  22795. this.indices[numIndices++] = n + 2;
  22796. }
  22797. numVertices = this.addVertices_([0, 0], p1, p2,
  22798. lastSign * ol.render.webgl.LineStringReplay.Instruction_.BEGIN_LINE * (lineCap || 1), numVertices);
  22799. numVertices = this.addVertices_([0, 0], p1, p2,
  22800. -lastSign * ol.render.webgl.LineStringReplay.Instruction_.BEGIN_LINE * (lineCap || 1), numVertices);
  22801. lastIndex = numVertices / 7 - 1;
  22802. continue;
  22803. }
  22804. } else if (i === end - stride) {
  22805. //Last vertex.
  22806. if (closed) {
  22807. //Same as the first vertex.
  22808. p2 = startCoords;
  22809. break;
  22810. } else {
  22811. p0 = p0 || [0, 0];
  22812. numVertices = this.addVertices_(p0, p1, [0, 0],
  22813. lastSign * ol.render.webgl.LineStringReplay.Instruction_.END_LINE * (lineCap || 1), numVertices);
  22814. numVertices = this.addVertices_(p0, p1, [0, 0],
  22815. -lastSign * ol.render.webgl.LineStringReplay.Instruction_.END_LINE * (lineCap || 1), numVertices);
  22816. this.indices[numIndices++] = n;
  22817. this.indices[numIndices++] = lastIndex - 1;
  22818. this.indices[numIndices++] = lastIndex;
  22819. this.indices[numIndices++] = lastIndex;
  22820. this.indices[numIndices++] = n + 1;
  22821. this.indices[numIndices++] = n;
  22822. if (lineCap) {
  22823. numVertices = this.addVertices_(p0, p1, [0, 0],
  22824. lastSign * ol.render.webgl.LineStringReplay.Instruction_.END_LINE_CAP * lineCap, numVertices);
  22825. numVertices = this.addVertices_(p0, p1, [0, 0],
  22826. -lastSign * ol.render.webgl.LineStringReplay.Instruction_.END_LINE_CAP * lineCap, numVertices);
  22827. this.indices[numIndices++] = n + 2;
  22828. this.indices[numIndices++] = n;
  22829. this.indices[numIndices++] = n + 1;
  22830. this.indices[numIndices++] = n + 1;
  22831. this.indices[numIndices++] = n + 3;
  22832. this.indices[numIndices++] = n + 2;
  22833. }
  22834. break;
  22835. }
  22836. } else {
  22837. p2 = [flatCoordinates[i + stride], flatCoordinates[i + stride + 1]];
  22838. }
  22839. // We group CW and straight lines, thus the not so inituitive CCW checking function.
  22840. sign = ol.render.webgl.triangleIsCounterClockwise(p0[0], p0[1], p1[0], p1[1], p2[0], p2[1])
  22841. ? -1 : 1;
  22842. numVertices = this.addVertices_(p0, p1, p2,
  22843. sign * ol.render.webgl.LineStringReplay.Instruction_.BEVEL_FIRST * (lineJoin || 1), numVertices);
  22844. numVertices = this.addVertices_(p0, p1, p2,
  22845. sign * ol.render.webgl.LineStringReplay.Instruction_.BEVEL_SECOND * (lineJoin || 1), numVertices);
  22846. numVertices = this.addVertices_(p0, p1, p2,
  22847. -sign * ol.render.webgl.LineStringReplay.Instruction_.MITER_BOTTOM * (lineJoin || 1), numVertices);
  22848. if (i > offset) {
  22849. this.indices[numIndices++] = n;
  22850. this.indices[numIndices++] = lastIndex - 1;
  22851. this.indices[numIndices++] = lastIndex;
  22852. this.indices[numIndices++] = n + 2;
  22853. this.indices[numIndices++] = n;
  22854. this.indices[numIndices++] = lastSign * sign > 0 ? lastIndex : lastIndex - 1;
  22855. }
  22856. this.indices[numIndices++] = n;
  22857. this.indices[numIndices++] = n + 2;
  22858. this.indices[numIndices++] = n + 1;
  22859. lastIndex = n + 2;
  22860. lastSign = sign;
  22861. //Add miter
  22862. if (lineJoin) {
  22863. numVertices = this.addVertices_(p0, p1, p2,
  22864. sign * ol.render.webgl.LineStringReplay.Instruction_.MITER_TOP * lineJoin, numVertices);
  22865. this.indices[numIndices++] = n + 1;
  22866. this.indices[numIndices++] = n + 3;
  22867. this.indices[numIndices++] = n;
  22868. }
  22869. }
  22870. if (closed) {
  22871. n = n || numVertices / 7;
  22872. sign = ol.geom.flat.orient.linearRingIsClockwise([p0[0], p0[1], p1[0], p1[1], p2[0], p2[1]], 0, 6, 2)
  22873. ? 1 : -1;
  22874. numVertices = this.addVertices_(p0, p1, p2,
  22875. sign * ol.render.webgl.LineStringReplay.Instruction_.BEVEL_FIRST * (lineJoin || 1), numVertices);
  22876. numVertices = this.addVertices_(p0, p1, p2,
  22877. -sign * ol.render.webgl.LineStringReplay.Instruction_.MITER_BOTTOM * (lineJoin || 1), numVertices);
  22878. this.indices[numIndices++] = n;
  22879. this.indices[numIndices++] = lastIndex - 1;
  22880. this.indices[numIndices++] = lastIndex;
  22881. this.indices[numIndices++] = n + 1;
  22882. this.indices[numIndices++] = n;
  22883. this.indices[numIndices++] = lastSign * sign > 0 ? lastIndex : lastIndex - 1;
  22884. }
  22885. };
  22886. /**
  22887. * @param {Array.<number>} p0 Last coordinates.
  22888. * @param {Array.<number>} p1 Current coordinates.
  22889. * @param {Array.<number>} p2 Next coordinates.
  22890. * @param {number} product Sign, instruction, and rounding product.
  22891. * @param {number} numVertices Vertex counter.
  22892. * @return {number} Vertex counter.
  22893. * @private
  22894. */
  22895. ol.render.webgl.LineStringReplay.prototype.addVertices_ = function(p0, p1, p2, product, numVertices) {
  22896. this.vertices[numVertices++] = p0[0];
  22897. this.vertices[numVertices++] = p0[1];
  22898. this.vertices[numVertices++] = p1[0];
  22899. this.vertices[numVertices++] = p1[1];
  22900. this.vertices[numVertices++] = p2[0];
  22901. this.vertices[numVertices++] = p2[1];
  22902. this.vertices[numVertices++] = product;
  22903. return numVertices;
  22904. };
  22905. /**
  22906. * Check if the linestring can be drawn (i. e. valid).
  22907. * @param {Array.<number>} flatCoordinates Flat coordinates.
  22908. * @param {number} offset Offset.
  22909. * @param {number} end End.
  22910. * @param {number} stride Stride.
  22911. * @return {boolean} The linestring can be drawn.
  22912. * @private
  22913. */
  22914. ol.render.webgl.LineStringReplay.prototype.isValid_ = function(flatCoordinates, offset, end, stride) {
  22915. var range = end - offset;
  22916. if (range < stride * 2) {
  22917. return false;
  22918. } else if (range === stride * 2) {
  22919. var firstP = [flatCoordinates[offset], flatCoordinates[offset + 1]];
  22920. var lastP = [flatCoordinates[offset + stride], flatCoordinates[offset + stride + 1]];
  22921. return !ol.array.equals(firstP, lastP);
  22922. }
  22923. return true;
  22924. };
  22925. /**
  22926. * @inheritDoc
  22927. */
  22928. ol.render.webgl.LineStringReplay.prototype.drawLineString = function(lineStringGeometry, feature) {
  22929. var flatCoordinates = lineStringGeometry.getFlatCoordinates();
  22930. var stride = lineStringGeometry.getStride();
  22931. if (this.isValid_(flatCoordinates, 0, flatCoordinates.length, stride)) {
  22932. flatCoordinates = ol.geom.flat.transform.translate(flatCoordinates, 0, flatCoordinates.length,
  22933. stride, -this.origin[0], -this.origin[1]);
  22934. if (this.state_.changed) {
  22935. this.styleIndices_.push(this.indices.length);
  22936. this.state_.changed = false;
  22937. }
  22938. this.startIndices.push(this.indices.length);
  22939. this.startIndicesFeature.push(feature);
  22940. this.drawCoordinates_(
  22941. flatCoordinates, 0, flatCoordinates.length, stride);
  22942. }
  22943. };
  22944. /**
  22945. * @inheritDoc
  22946. */
  22947. ol.render.webgl.LineStringReplay.prototype.drawMultiLineString = function(multiLineStringGeometry, feature) {
  22948. var indexCount = this.indices.length;
  22949. var ends = multiLineStringGeometry.getEnds();
  22950. ends.unshift(0);
  22951. var flatCoordinates = multiLineStringGeometry.getFlatCoordinates();
  22952. var stride = multiLineStringGeometry.getStride();
  22953. var i, ii;
  22954. if (ends.length > 1) {
  22955. for (i = 1, ii = ends.length; i < ii; ++i) {
  22956. if (this.isValid_(flatCoordinates, ends[i - 1], ends[i], stride)) {
  22957. var lineString = ol.geom.flat.transform.translate(flatCoordinates, ends[i - 1], ends[i],
  22958. stride, -this.origin[0], -this.origin[1]);
  22959. this.drawCoordinates_(
  22960. lineString, 0, lineString.length, stride);
  22961. }
  22962. }
  22963. }
  22964. if (this.indices.length > indexCount) {
  22965. this.startIndices.push(indexCount);
  22966. this.startIndicesFeature.push(feature);
  22967. if (this.state_.changed) {
  22968. this.styleIndices_.push(indexCount);
  22969. this.state_.changed = false;
  22970. }
  22971. }
  22972. };
  22973. /**
  22974. * @param {Array.<number>} flatCoordinates Flat coordinates.
  22975. * @param {Array.<Array.<number>>} holeFlatCoordinates Hole flat coordinates.
  22976. * @param {number} stride Stride.
  22977. */
  22978. ol.render.webgl.LineStringReplay.prototype.drawPolygonCoordinates = function(
  22979. flatCoordinates, holeFlatCoordinates, stride) {
  22980. if (!ol.geom.flat.topology.lineStringIsClosed(flatCoordinates, 0,
  22981. flatCoordinates.length, stride)) {
  22982. flatCoordinates.push(flatCoordinates[0]);
  22983. flatCoordinates.push(flatCoordinates[1]);
  22984. }
  22985. this.drawCoordinates_(flatCoordinates, 0, flatCoordinates.length, stride);
  22986. if (holeFlatCoordinates.length) {
  22987. var i, ii;
  22988. for (i = 0, ii = holeFlatCoordinates.length; i < ii; ++i) {
  22989. if (!ol.geom.flat.topology.lineStringIsClosed(holeFlatCoordinates[i], 0,
  22990. holeFlatCoordinates[i].length, stride)) {
  22991. holeFlatCoordinates[i].push(holeFlatCoordinates[i][0]);
  22992. holeFlatCoordinates[i].push(holeFlatCoordinates[i][1]);
  22993. }
  22994. this.drawCoordinates_(holeFlatCoordinates[i], 0,
  22995. holeFlatCoordinates[i].length, stride);
  22996. }
  22997. }
  22998. };
  22999. /**
  23000. * @param {ol.Feature|ol.render.Feature} feature Feature.
  23001. * @param {number=} opt_index Index count.
  23002. */
  23003. ol.render.webgl.LineStringReplay.prototype.setPolygonStyle = function(feature, opt_index) {
  23004. var index = opt_index === undefined ? this.indices.length : opt_index;
  23005. this.startIndices.push(index);
  23006. this.startIndicesFeature.push(feature);
  23007. if (this.state_.changed) {
  23008. this.styleIndices_.push(index);
  23009. this.state_.changed = false;
  23010. }
  23011. };
  23012. /**
  23013. * @return {number} Current index.
  23014. */
  23015. ol.render.webgl.LineStringReplay.prototype.getCurrentIndex = function() {
  23016. return this.indices.length;
  23017. };
  23018. /**
  23019. * @inheritDoc
  23020. **/
  23021. ol.render.webgl.LineStringReplay.prototype.finish = function(context) {
  23022. // create, bind, and populate the vertices buffer
  23023. this.verticesBuffer = new ol.webgl.Buffer(this.vertices);
  23024. // create, bind, and populate the indices buffer
  23025. this.indicesBuffer = new ol.webgl.Buffer(this.indices);
  23026. this.startIndices.push(this.indices.length);
  23027. //Clean up, if there is nothing to draw
  23028. if (this.styleIndices_.length === 0 && this.styles_.length > 0) {
  23029. this.styles_ = [];
  23030. }
  23031. this.vertices = null;
  23032. this.indices = null;
  23033. };
  23034. /**
  23035. * @inheritDoc
  23036. */
  23037. ol.render.webgl.LineStringReplay.prototype.getDeleteResourcesFunction = function(context) {
  23038. var verticesBuffer = this.verticesBuffer;
  23039. var indicesBuffer = this.indicesBuffer;
  23040. return function() {
  23041. context.deleteBuffer(verticesBuffer);
  23042. context.deleteBuffer(indicesBuffer);
  23043. };
  23044. };
  23045. /**
  23046. * @inheritDoc
  23047. */
  23048. ol.render.webgl.LineStringReplay.prototype.setUpProgram = function(gl, context, size, pixelRatio) {
  23049. // get the program
  23050. var fragmentShader, vertexShader;
  23051. fragmentShader = ol.render.webgl.linestringreplay.defaultshader.fragment;
  23052. vertexShader = ol.render.webgl.linestringreplay.defaultshader.vertex;
  23053. var program = context.getProgram(fragmentShader, vertexShader);
  23054. // get the locations
  23055. var locations;
  23056. if (!this.defaultLocations_) {
  23057. // eslint-disable-next-line openlayers-internal/no-missing-requires
  23058. locations = new ol.render.webgl.linestringreplay.defaultshader.Locations(gl, program);
  23059. this.defaultLocations_ = locations;
  23060. } else {
  23061. locations = this.defaultLocations_;
  23062. }
  23063. context.useProgram(program);
  23064. // enable the vertex attrib arrays
  23065. gl.enableVertexAttribArray(locations.a_lastPos);
  23066. gl.vertexAttribPointer(locations.a_lastPos, 2, ol.webgl.FLOAT,
  23067. false, 28, 0);
  23068. gl.enableVertexAttribArray(locations.a_position);
  23069. gl.vertexAttribPointer(locations.a_position, 2, ol.webgl.FLOAT,
  23070. false, 28, 8);
  23071. gl.enableVertexAttribArray(locations.a_nextPos);
  23072. gl.vertexAttribPointer(locations.a_nextPos, 2, ol.webgl.FLOAT,
  23073. false, 28, 16);
  23074. gl.enableVertexAttribArray(locations.a_direction);
  23075. gl.vertexAttribPointer(locations.a_direction, 1, ol.webgl.FLOAT,
  23076. false, 28, 24);
  23077. // Enable renderer specific uniforms.
  23078. gl.uniform2fv(locations.u_size, size);
  23079. gl.uniform1f(locations.u_pixelRatio, pixelRatio);
  23080. return locations;
  23081. };
  23082. /**
  23083. * @inheritDoc
  23084. */
  23085. ol.render.webgl.LineStringReplay.prototype.shutDownProgram = function(gl, locations) {
  23086. gl.disableVertexAttribArray(locations.a_lastPos);
  23087. gl.disableVertexAttribArray(locations.a_position);
  23088. gl.disableVertexAttribArray(locations.a_nextPos);
  23089. gl.disableVertexAttribArray(locations.a_direction);
  23090. };
  23091. /**
  23092. * @inheritDoc
  23093. */
  23094. ol.render.webgl.LineStringReplay.prototype.drawReplay = function(gl, context, skippedFeaturesHash, hitDetection) {
  23095. //Save GL parameters.
  23096. var tmpDepthFunc = /** @type {number} */ (gl.getParameter(gl.DEPTH_FUNC));
  23097. var tmpDepthMask = /** @type {boolean} */ (gl.getParameter(gl.DEPTH_WRITEMASK));
  23098. if (!hitDetection) {
  23099. gl.enable(gl.DEPTH_TEST);
  23100. gl.depthMask(true);
  23101. gl.depthFunc(gl.NOTEQUAL);
  23102. }
  23103. if (!ol.obj.isEmpty(skippedFeaturesHash)) {
  23104. this.drawReplaySkipping_(gl, context, skippedFeaturesHash);
  23105. } else {
  23106. //Draw by style groups to minimize drawElements() calls.
  23107. var i, start, end, nextStyle;
  23108. end = this.startIndices[this.startIndices.length - 1];
  23109. for (i = this.styleIndices_.length - 1; i >= 0; --i) {
  23110. start = this.styleIndices_[i];
  23111. nextStyle = this.styles_[i];
  23112. this.setStrokeStyle_(gl, nextStyle[0], nextStyle[1], nextStyle[2]);
  23113. this.drawElements(gl, context, start, end);
  23114. gl.clear(gl.DEPTH_BUFFER_BIT);
  23115. end = start;
  23116. }
  23117. }
  23118. if (!hitDetection) {
  23119. gl.disable(gl.DEPTH_TEST);
  23120. gl.clear(gl.DEPTH_BUFFER_BIT);
  23121. //Restore GL parameters.
  23122. gl.depthMask(tmpDepthMask);
  23123. gl.depthFunc(tmpDepthFunc);
  23124. }
  23125. };
  23126. /**
  23127. * @private
  23128. * @param {WebGLRenderingContext} gl gl.
  23129. * @param {ol.webgl.Context} context Context.
  23130. * @param {Object} skippedFeaturesHash Ids of features to skip.
  23131. */
  23132. ol.render.webgl.LineStringReplay.prototype.drawReplaySkipping_ = function(gl, context, skippedFeaturesHash) {
  23133. var i, start, end, nextStyle, groupStart, feature, featureUid, featureIndex, featureStart;
  23134. featureIndex = this.startIndices.length - 2;
  23135. end = start = this.startIndices[featureIndex + 1];
  23136. for (i = this.styleIndices_.length - 1; i >= 0; --i) {
  23137. nextStyle = this.styles_[i];
  23138. this.setStrokeStyle_(gl, nextStyle[0], nextStyle[1], nextStyle[2]);
  23139. groupStart = this.styleIndices_[i];
  23140. while (featureIndex >= 0 &&
  23141. this.startIndices[featureIndex] >= groupStart) {
  23142. featureStart = this.startIndices[featureIndex];
  23143. feature = this.startIndicesFeature[featureIndex];
  23144. featureUid = ol.getUid(feature).toString();
  23145. if (skippedFeaturesHash[featureUid]) {
  23146. if (start !== end) {
  23147. this.drawElements(gl, context, start, end);
  23148. gl.clear(gl.DEPTH_BUFFER_BIT);
  23149. }
  23150. end = featureStart;
  23151. }
  23152. featureIndex--;
  23153. start = featureStart;
  23154. }
  23155. if (start !== end) {
  23156. this.drawElements(gl, context, start, end);
  23157. gl.clear(gl.DEPTH_BUFFER_BIT);
  23158. }
  23159. start = end = groupStart;
  23160. }
  23161. };
  23162. /**
  23163. * @inheritDoc
  23164. */
  23165. ol.render.webgl.LineStringReplay.prototype.drawHitDetectionReplayOneByOne = function(gl, context, skippedFeaturesHash,
  23166. featureCallback, opt_hitExtent) {
  23167. var i, start, end, nextStyle, groupStart, feature, featureUid, featureIndex;
  23168. featureIndex = this.startIndices.length - 2;
  23169. end = this.startIndices[featureIndex + 1];
  23170. for (i = this.styleIndices_.length - 1; i >= 0; --i) {
  23171. nextStyle = this.styles_[i];
  23172. this.setStrokeStyle_(gl, nextStyle[0], nextStyle[1], nextStyle[2]);
  23173. groupStart = this.styleIndices_[i];
  23174. while (featureIndex >= 0 &&
  23175. this.startIndices[featureIndex] >= groupStart) {
  23176. start = this.startIndices[featureIndex];
  23177. feature = this.startIndicesFeature[featureIndex];
  23178. featureUid = ol.getUid(feature).toString();
  23179. if (skippedFeaturesHash[featureUid] === undefined &&
  23180. feature.getGeometry() &&
  23181. (opt_hitExtent === undefined || ol.extent.intersects(
  23182. /** @type {Array<number>} */ (opt_hitExtent),
  23183. feature.getGeometry().getExtent()))) {
  23184. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  23185. this.drawElements(gl, context, start, end);
  23186. var result = featureCallback(feature);
  23187. if (result) {
  23188. return result;
  23189. }
  23190. }
  23191. featureIndex--;
  23192. end = start;
  23193. }
  23194. }
  23195. return undefined;
  23196. };
  23197. /**
  23198. * @private
  23199. * @param {WebGLRenderingContext} gl gl.
  23200. * @param {Array.<number>} color Color.
  23201. * @param {number} lineWidth Line width.
  23202. * @param {number} miterLimit Miter limit.
  23203. */
  23204. ol.render.webgl.LineStringReplay.prototype.setStrokeStyle_ = function(gl, color, lineWidth, miterLimit) {
  23205. gl.uniform4fv(this.defaultLocations_.u_color, color);
  23206. gl.uniform1f(this.defaultLocations_.u_lineWidth, lineWidth);
  23207. gl.uniform1f(this.defaultLocations_.u_miterLimit, miterLimit);
  23208. };
  23209. /**
  23210. * @inheritDoc
  23211. */
  23212. ol.render.webgl.LineStringReplay.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
  23213. var strokeStyleLineCap = strokeStyle.getLineCap();
  23214. this.state_.lineCap = strokeStyleLineCap !== undefined ?
  23215. strokeStyleLineCap : ol.render.webgl.defaultLineCap;
  23216. var strokeStyleLineDash = strokeStyle.getLineDash();
  23217. this.state_.lineDash = strokeStyleLineDash ?
  23218. strokeStyleLineDash : ol.render.webgl.defaultLineDash;
  23219. var strokeStyleLineDashOffset = strokeStyle.getLineDashOffset();
  23220. this.state_.lineDashOffset = strokeStyleLineDashOffset ?
  23221. strokeStyleLineDashOffset : ol.render.webgl.defaultLineDashOffset;
  23222. var strokeStyleLineJoin = strokeStyle.getLineJoin();
  23223. this.state_.lineJoin = strokeStyleLineJoin !== undefined ?
  23224. strokeStyleLineJoin : ol.render.webgl.defaultLineJoin;
  23225. var strokeStyleColor = strokeStyle.getColor();
  23226. if (!(strokeStyleColor instanceof CanvasGradient) &&
  23227. !(strokeStyleColor instanceof CanvasPattern)) {
  23228. strokeStyleColor = ol.color.asArray(strokeStyleColor).map(function(c, i) {
  23229. return i != 3 ? c / 255 : c;
  23230. }) || ol.render.webgl.defaultStrokeStyle;
  23231. } else {
  23232. strokeStyleColor = ol.render.webgl.defaultStrokeStyle;
  23233. }
  23234. var strokeStyleWidth = strokeStyle.getWidth();
  23235. strokeStyleWidth = strokeStyleWidth !== undefined ?
  23236. strokeStyleWidth : ol.render.webgl.defaultLineWidth;
  23237. var strokeStyleMiterLimit = strokeStyle.getMiterLimit();
  23238. strokeStyleMiterLimit = strokeStyleMiterLimit !== undefined ?
  23239. strokeStyleMiterLimit : ol.render.webgl.defaultMiterLimit;
  23240. if (!this.state_.strokeColor || !ol.array.equals(this.state_.strokeColor, strokeStyleColor) ||
  23241. this.state_.lineWidth !== strokeStyleWidth || this.state_.miterLimit !== strokeStyleMiterLimit) {
  23242. this.state_.changed = true;
  23243. this.state_.strokeColor = strokeStyleColor;
  23244. this.state_.lineWidth = strokeStyleWidth;
  23245. this.state_.miterLimit = strokeStyleMiterLimit;
  23246. this.styles_.push([strokeStyleColor, strokeStyleWidth, strokeStyleMiterLimit]);
  23247. }
  23248. };
  23249. /**
  23250. * @enum {number}
  23251. * @private
  23252. */
  23253. ol.render.webgl.LineStringReplay.Instruction_ = {
  23254. ROUND: 2,
  23255. BEGIN_LINE: 3,
  23256. END_LINE: 5,
  23257. BEGIN_LINE_CAP: 7,
  23258. END_LINE_CAP: 11,
  23259. BEVEL_FIRST: 13,
  23260. BEVEL_SECOND: 17,
  23261. MITER_BOTTOM: 19,
  23262. MITER_TOP: 23
  23263. };
  23264. }
  23265. // This file is automatically generated, do not edit
  23266. /* eslint openlayers-internal/no-missing-requires: 0 */
  23267. goog.provide('ol.render.webgl.polygonreplay.defaultshader');
  23268. goog.require('ol');
  23269. goog.require('ol.webgl.Fragment');
  23270. goog.require('ol.webgl.Vertex');
  23271. if (ol.ENABLE_WEBGL) {
  23272. /**
  23273. * @constructor
  23274. * @extends {ol.webgl.Fragment}
  23275. * @struct
  23276. */
  23277. ol.render.webgl.polygonreplay.defaultshader.Fragment = function() {
  23278. ol.webgl.Fragment.call(this, ol.render.webgl.polygonreplay.defaultshader.Fragment.SOURCE);
  23279. };
  23280. ol.inherits(ol.render.webgl.polygonreplay.defaultshader.Fragment, ol.webgl.Fragment);
  23281. /**
  23282. * @const
  23283. * @type {string}
  23284. */
  23285. ol.render.webgl.polygonreplay.defaultshader.Fragment.DEBUG_SOURCE = 'precision mediump float;\n\n\n\nuniform vec4 u_color;\nuniform float u_opacity;\n\nvoid main(void) {\n gl_FragColor = u_color;\n float alpha = u_color.a * u_opacity;\n if (alpha == 0.0) {\n discard;\n }\n gl_FragColor.a = alpha;\n}\n';
  23286. /**
  23287. * @const
  23288. * @type {string}
  23289. */
  23290. ol.render.webgl.polygonreplay.defaultshader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;uniform vec4 e;uniform float f;void main(void){gl_FragColor=e;float alpha=e.a*f;if(alpha==0.0){discard;}gl_FragColor.a=alpha;}';
  23291. /**
  23292. * @const
  23293. * @type {string}
  23294. */
  23295. ol.render.webgl.polygonreplay.defaultshader.Fragment.SOURCE = ol.DEBUG_WEBGL ?
  23296. ol.render.webgl.polygonreplay.defaultshader.Fragment.DEBUG_SOURCE :
  23297. ol.render.webgl.polygonreplay.defaultshader.Fragment.OPTIMIZED_SOURCE;
  23298. ol.render.webgl.polygonreplay.defaultshader.fragment = new ol.render.webgl.polygonreplay.defaultshader.Fragment();
  23299. /**
  23300. * @constructor
  23301. * @extends {ol.webgl.Vertex}
  23302. * @struct
  23303. */
  23304. ol.render.webgl.polygonreplay.defaultshader.Vertex = function() {
  23305. ol.webgl.Vertex.call(this, ol.render.webgl.polygonreplay.defaultshader.Vertex.SOURCE);
  23306. };
  23307. ol.inherits(ol.render.webgl.polygonreplay.defaultshader.Vertex, ol.webgl.Vertex);
  23308. /**
  23309. * @const
  23310. * @type {string}
  23311. */
  23312. ol.render.webgl.polygonreplay.defaultshader.Vertex.DEBUG_SOURCE = '\n\nattribute vec2 a_position;\n\nuniform mat4 u_projectionMatrix;\nuniform mat4 u_offsetScaleMatrix;\nuniform mat4 u_offsetRotateMatrix;\n\nvoid main(void) {\n gl_Position = u_projectionMatrix * vec4(a_position, 0.0, 1.0);\n}\n\n\n';
  23313. /**
  23314. * @const
  23315. * @type {string}
  23316. */
  23317. ol.render.webgl.polygonreplay.defaultshader.Vertex.OPTIMIZED_SOURCE = 'attribute vec2 a;uniform mat4 b;uniform mat4 c;uniform mat4 d;void main(void){gl_Position=b*vec4(a,0.0,1.0);}';
  23318. /**
  23319. * @const
  23320. * @type {string}
  23321. */
  23322. ol.render.webgl.polygonreplay.defaultshader.Vertex.SOURCE = ol.DEBUG_WEBGL ?
  23323. ol.render.webgl.polygonreplay.defaultshader.Vertex.DEBUG_SOURCE :
  23324. ol.render.webgl.polygonreplay.defaultshader.Vertex.OPTIMIZED_SOURCE;
  23325. ol.render.webgl.polygonreplay.defaultshader.vertex = new ol.render.webgl.polygonreplay.defaultshader.Vertex();
  23326. /**
  23327. * @constructor
  23328. * @param {WebGLRenderingContext} gl GL.
  23329. * @param {WebGLProgram} program Program.
  23330. * @struct
  23331. */
  23332. ol.render.webgl.polygonreplay.defaultshader.Locations = function(gl, program) {
  23333. /**
  23334. * @type {WebGLUniformLocation}
  23335. */
  23336. this.u_color = gl.getUniformLocation(
  23337. program, ol.DEBUG_WEBGL ? 'u_color' : 'e');
  23338. /**
  23339. * @type {WebGLUniformLocation}
  23340. */
  23341. this.u_offsetRotateMatrix = gl.getUniformLocation(
  23342. program, ol.DEBUG_WEBGL ? 'u_offsetRotateMatrix' : 'd');
  23343. /**
  23344. * @type {WebGLUniformLocation}
  23345. */
  23346. this.u_offsetScaleMatrix = gl.getUniformLocation(
  23347. program, ol.DEBUG_WEBGL ? 'u_offsetScaleMatrix' : 'c');
  23348. /**
  23349. * @type {WebGLUniformLocation}
  23350. */
  23351. this.u_opacity = gl.getUniformLocation(
  23352. program, ol.DEBUG_WEBGL ? 'u_opacity' : 'f');
  23353. /**
  23354. * @type {WebGLUniformLocation}
  23355. */
  23356. this.u_projectionMatrix = gl.getUniformLocation(
  23357. program, ol.DEBUG_WEBGL ? 'u_projectionMatrix' : 'b');
  23358. /**
  23359. * @type {number}
  23360. */
  23361. this.a_position = gl.getAttribLocation(
  23362. program, ol.DEBUG_WEBGL ? 'a_position' : 'a');
  23363. };
  23364. }
  23365. goog.provide('ol.style.Stroke');
  23366. goog.require('ol');
  23367. /**
  23368. * @classdesc
  23369. * Set stroke style for vector features.
  23370. * Note that the defaults given are the Canvas defaults, which will be used if
  23371. * option is not defined. The `get` functions return whatever was entered in
  23372. * the options; they will not return the default.
  23373. *
  23374. * @constructor
  23375. * @param {olx.style.StrokeOptions=} opt_options Options.
  23376. * @api
  23377. */
  23378. ol.style.Stroke = function(opt_options) {
  23379. var options = opt_options || {};
  23380. /**
  23381. * @private
  23382. * @type {ol.Color|ol.ColorLike}
  23383. */
  23384. this.color_ = options.color !== undefined ? options.color : null;
  23385. /**
  23386. * @private
  23387. * @type {string|undefined}
  23388. */
  23389. this.lineCap_ = options.lineCap;
  23390. /**
  23391. * @private
  23392. * @type {Array.<number>}
  23393. */
  23394. this.lineDash_ = options.lineDash !== undefined ? options.lineDash : null;
  23395. /**
  23396. * @private
  23397. * @type {number|undefined}
  23398. */
  23399. this.lineDashOffset_ = options.lineDashOffset;
  23400. /**
  23401. * @private
  23402. * @type {string|undefined}
  23403. */
  23404. this.lineJoin_ = options.lineJoin;
  23405. /**
  23406. * @private
  23407. * @type {number|undefined}
  23408. */
  23409. this.miterLimit_ = options.miterLimit;
  23410. /**
  23411. * @private
  23412. * @type {number|undefined}
  23413. */
  23414. this.width_ = options.width;
  23415. /**
  23416. * @private
  23417. * @type {string|undefined}
  23418. */
  23419. this.checksum_ = undefined;
  23420. };
  23421. /**
  23422. * Clones the style.
  23423. * @return {ol.style.Stroke} The cloned style.
  23424. * @api
  23425. */
  23426. ol.style.Stroke.prototype.clone = function() {
  23427. var color = this.getColor();
  23428. return new ol.style.Stroke({
  23429. color: (color && color.slice) ? color.slice() : color || undefined,
  23430. lineCap: this.getLineCap(),
  23431. lineDash: this.getLineDash() ? this.getLineDash().slice() : undefined,
  23432. lineDashOffset: this.getLineDashOffset(),
  23433. lineJoin: this.getLineJoin(),
  23434. miterLimit: this.getMiterLimit(),
  23435. width: this.getWidth()
  23436. });
  23437. };
  23438. /**
  23439. * Get the stroke color.
  23440. * @return {ol.Color|ol.ColorLike} Color.
  23441. * @api
  23442. */
  23443. ol.style.Stroke.prototype.getColor = function() {
  23444. return this.color_;
  23445. };
  23446. /**
  23447. * Get the line cap type for the stroke.
  23448. * @return {string|undefined} Line cap.
  23449. * @api
  23450. */
  23451. ol.style.Stroke.prototype.getLineCap = function() {
  23452. return this.lineCap_;
  23453. };
  23454. /**
  23455. * Get the line dash style for the stroke.
  23456. * @return {Array.<number>} Line dash.
  23457. * @api
  23458. */
  23459. ol.style.Stroke.prototype.getLineDash = function() {
  23460. return this.lineDash_;
  23461. };
  23462. /**
  23463. * Get the line dash offset for the stroke.
  23464. * @return {number|undefined} Line dash offset.
  23465. * @api
  23466. */
  23467. ol.style.Stroke.prototype.getLineDashOffset = function() {
  23468. return this.lineDashOffset_;
  23469. };
  23470. /**
  23471. * Get the line join type for the stroke.
  23472. * @return {string|undefined} Line join.
  23473. * @api
  23474. */
  23475. ol.style.Stroke.prototype.getLineJoin = function() {
  23476. return this.lineJoin_;
  23477. };
  23478. /**
  23479. * Get the miter limit for the stroke.
  23480. * @return {number|undefined} Miter limit.
  23481. * @api
  23482. */
  23483. ol.style.Stroke.prototype.getMiterLimit = function() {
  23484. return this.miterLimit_;
  23485. };
  23486. /**
  23487. * Get the stroke width.
  23488. * @return {number|undefined} Width.
  23489. * @api
  23490. */
  23491. ol.style.Stroke.prototype.getWidth = function() {
  23492. return this.width_;
  23493. };
  23494. /**
  23495. * Set the color.
  23496. *
  23497. * @param {ol.Color|ol.ColorLike} color Color.
  23498. * @api
  23499. */
  23500. ol.style.Stroke.prototype.setColor = function(color) {
  23501. this.color_ = color;
  23502. this.checksum_ = undefined;
  23503. };
  23504. /**
  23505. * Set the line cap.
  23506. *
  23507. * @param {string|undefined} lineCap Line cap.
  23508. * @api
  23509. */
  23510. ol.style.Stroke.prototype.setLineCap = function(lineCap) {
  23511. this.lineCap_ = lineCap;
  23512. this.checksum_ = undefined;
  23513. };
  23514. /**
  23515. * Set the line dash.
  23516. *
  23517. * Please note that Internet Explorer 10 and lower [do not support][mdn] the
  23518. * `setLineDash` method on the `CanvasRenderingContext2D` and therefore this
  23519. * property will have no visual effect in these browsers.
  23520. *
  23521. * [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility
  23522. *
  23523. * @param {Array.<number>} lineDash Line dash.
  23524. * @api
  23525. */
  23526. ol.style.Stroke.prototype.setLineDash = function(lineDash) {
  23527. this.lineDash_ = lineDash;
  23528. this.checksum_ = undefined;
  23529. };
  23530. /**
  23531. * Set the line dash offset.
  23532. *
  23533. * @param {number|undefined} lineDashOffset Line dash offset.
  23534. * @api
  23535. */
  23536. ol.style.Stroke.prototype.setLineDashOffset = function(lineDashOffset) {
  23537. this.lineDashOffset_ = lineDashOffset;
  23538. this.checksum_ = undefined;
  23539. };
  23540. /**
  23541. * Set the line join.
  23542. *
  23543. * @param {string|undefined} lineJoin Line join.
  23544. * @api
  23545. */
  23546. ol.style.Stroke.prototype.setLineJoin = function(lineJoin) {
  23547. this.lineJoin_ = lineJoin;
  23548. this.checksum_ = undefined;
  23549. };
  23550. /**
  23551. * Set the miter limit.
  23552. *
  23553. * @param {number|undefined} miterLimit Miter limit.
  23554. * @api
  23555. */
  23556. ol.style.Stroke.prototype.setMiterLimit = function(miterLimit) {
  23557. this.miterLimit_ = miterLimit;
  23558. this.checksum_ = undefined;
  23559. };
  23560. /**
  23561. * Set the width.
  23562. *
  23563. * @param {number|undefined} width Width.
  23564. * @api
  23565. */
  23566. ol.style.Stroke.prototype.setWidth = function(width) {
  23567. this.width_ = width;
  23568. this.checksum_ = undefined;
  23569. };
  23570. /**
  23571. * @return {string} The checksum.
  23572. */
  23573. ol.style.Stroke.prototype.getChecksum = function() {
  23574. if (this.checksum_ === undefined) {
  23575. this.checksum_ = 's';
  23576. if (this.color_) {
  23577. if (typeof this.color_ === 'string') {
  23578. this.checksum_ += this.color_;
  23579. } else {
  23580. this.checksum_ += ol.getUid(this.color_).toString();
  23581. }
  23582. } else {
  23583. this.checksum_ += '-';
  23584. }
  23585. this.checksum_ += ',' +
  23586. (this.lineCap_ !== undefined ?
  23587. this.lineCap_.toString() : '-') + ',' +
  23588. (this.lineDash_ ?
  23589. this.lineDash_.toString() : '-') + ',' +
  23590. (this.lineDashOffset_ !== undefined ?
  23591. this.lineDashOffset_ : '-') + ',' +
  23592. (this.lineJoin_ !== undefined ?
  23593. this.lineJoin_ : '-') + ',' +
  23594. (this.miterLimit_ !== undefined ?
  23595. this.miterLimit_.toString() : '-') + ',' +
  23596. (this.width_ !== undefined ?
  23597. this.width_.toString() : '-');
  23598. }
  23599. return this.checksum_;
  23600. };
  23601. goog.provide('ol.structs.LinkedList');
  23602. /**
  23603. * Creates an empty linked list structure.
  23604. *
  23605. * @constructor
  23606. * @struct
  23607. * @param {boolean=} opt_circular The last item is connected to the first one,
  23608. * and the first item to the last one. Default is true.
  23609. */
  23610. ol.structs.LinkedList = function(opt_circular) {
  23611. /**
  23612. * @private
  23613. * @type {ol.LinkedListItem|undefined}
  23614. */
  23615. this.first_ = undefined;
  23616. /**
  23617. * @private
  23618. * @type {ol.LinkedListItem|undefined}
  23619. */
  23620. this.last_ = undefined;
  23621. /**
  23622. * @private
  23623. * @type {ol.LinkedListItem|undefined}
  23624. */
  23625. this.head_ = undefined;
  23626. /**
  23627. * @private
  23628. * @type {boolean}
  23629. */
  23630. this.circular_ = opt_circular === undefined ? true : opt_circular;
  23631. /**
  23632. * @private
  23633. * @type {number}
  23634. */
  23635. this.length_ = 0;
  23636. };
  23637. /**
  23638. * Inserts an item into the linked list right after the current one.
  23639. *
  23640. * @param {?} data Item data.
  23641. */
  23642. ol.structs.LinkedList.prototype.insertItem = function(data) {
  23643. /** @type {ol.LinkedListItem} */
  23644. var item = {
  23645. prev: undefined,
  23646. next: undefined,
  23647. data: data
  23648. };
  23649. var head = this.head_;
  23650. //Initialize the list.
  23651. if (!head) {
  23652. this.first_ = item;
  23653. this.last_ = item;
  23654. if (this.circular_) {
  23655. item.next = item;
  23656. item.prev = item;
  23657. }
  23658. } else {
  23659. //Link the new item to the adjacent ones.
  23660. var next = head.next;
  23661. item.prev = head;
  23662. item.next = next;
  23663. head.next = item;
  23664. if (next) {
  23665. next.prev = item;
  23666. }
  23667. if (head === this.last_) {
  23668. this.last_ = item;
  23669. }
  23670. }
  23671. this.head_ = item;
  23672. this.length_++;
  23673. };
  23674. /**
  23675. * Removes the current item from the list. Sets the cursor to the next item,
  23676. * if possible.
  23677. */
  23678. ol.structs.LinkedList.prototype.removeItem = function() {
  23679. var head = this.head_;
  23680. if (head) {
  23681. var next = head.next;
  23682. var prev = head.prev;
  23683. if (next) {
  23684. next.prev = prev;
  23685. }
  23686. if (prev) {
  23687. prev.next = next;
  23688. }
  23689. this.head_ = next || prev;
  23690. if (this.first_ === this.last_) {
  23691. this.head_ = undefined;
  23692. this.first_ = undefined;
  23693. this.last_ = undefined;
  23694. } else if (this.first_ === head) {
  23695. this.first_ = this.head_;
  23696. } else if (this.last_ === head) {
  23697. this.last_ = prev ? this.head_.prev : this.head_;
  23698. }
  23699. this.length_--;
  23700. }
  23701. };
  23702. /**
  23703. * Sets the cursor to the first item, and returns the associated data.
  23704. *
  23705. * @return {?} Item data.
  23706. */
  23707. ol.structs.LinkedList.prototype.firstItem = function() {
  23708. this.head_ = this.first_;
  23709. if (this.head_) {
  23710. return this.head_.data;
  23711. }
  23712. return undefined;
  23713. };
  23714. /**
  23715. * Sets the cursor to the last item, and returns the associated data.
  23716. *
  23717. * @return {?} Item data.
  23718. */
  23719. ol.structs.LinkedList.prototype.lastItem = function() {
  23720. this.head_ = this.last_;
  23721. if (this.head_) {
  23722. return this.head_.data;
  23723. }
  23724. return undefined;
  23725. };
  23726. /**
  23727. * Sets the cursor to the next item, and returns the associated data.
  23728. *
  23729. * @return {?} Item data.
  23730. */
  23731. ol.structs.LinkedList.prototype.nextItem = function() {
  23732. if (this.head_ && this.head_.next) {
  23733. this.head_ = this.head_.next;
  23734. return this.head_.data;
  23735. }
  23736. return undefined;
  23737. };
  23738. /**
  23739. * Returns the next item's data without moving the cursor.
  23740. *
  23741. * @return {?} Item data.
  23742. */
  23743. ol.structs.LinkedList.prototype.getNextItem = function() {
  23744. if (this.head_ && this.head_.next) {
  23745. return this.head_.next.data;
  23746. }
  23747. return undefined;
  23748. };
  23749. /**
  23750. * Sets the cursor to the previous item, and returns the associated data.
  23751. *
  23752. * @return {?} Item data.
  23753. */
  23754. ol.structs.LinkedList.prototype.prevItem = function() {
  23755. if (this.head_ && this.head_.prev) {
  23756. this.head_ = this.head_.prev;
  23757. return this.head_.data;
  23758. }
  23759. return undefined;
  23760. };
  23761. /**
  23762. * Returns the previous item's data without moving the cursor.
  23763. *
  23764. * @return {?} Item data.
  23765. */
  23766. ol.structs.LinkedList.prototype.getPrevItem = function() {
  23767. if (this.head_ && this.head_.prev) {
  23768. return this.head_.prev.data;
  23769. }
  23770. return undefined;
  23771. };
  23772. /**
  23773. * Returns the current item's data.
  23774. *
  23775. * @return {?} Item data.
  23776. */
  23777. ol.structs.LinkedList.prototype.getCurrItem = function() {
  23778. if (this.head_) {
  23779. return this.head_.data;
  23780. }
  23781. return undefined;
  23782. };
  23783. /**
  23784. * Sets the first item of the list. This only works for circular lists, and sets
  23785. * the last item accordingly.
  23786. */
  23787. ol.structs.LinkedList.prototype.setFirstItem = function() {
  23788. if (this.circular_ && this.head_) {
  23789. this.first_ = this.head_;
  23790. this.last_ = this.head_.prev;
  23791. }
  23792. };
  23793. /**
  23794. * Concatenates two lists.
  23795. * @param {ol.structs.LinkedList} list List to merge into the current list.
  23796. */
  23797. ol.structs.LinkedList.prototype.concat = function(list) {
  23798. if (list.head_) {
  23799. if (this.head_) {
  23800. var end = this.head_.next;
  23801. this.head_.next = list.first_;
  23802. list.first_.prev = this.head_;
  23803. end.prev = list.last_;
  23804. list.last_.next = end;
  23805. this.length_ += list.length_;
  23806. } else {
  23807. this.head_ = list.head_;
  23808. this.first_ = list.first_;
  23809. this.last_ = list.last_;
  23810. this.length_ = list.length_;
  23811. }
  23812. list.head_ = undefined;
  23813. list.first_ = undefined;
  23814. list.last_ = undefined;
  23815. list.length_ = 0;
  23816. }
  23817. };
  23818. /**
  23819. * Returns the current length of the list.
  23820. *
  23821. * @return {number} Length.
  23822. */
  23823. ol.structs.LinkedList.prototype.getLength = function() {
  23824. return this.length_;
  23825. };
  23826. /**
  23827. * @fileoverview
  23828. * @suppress {accessControls, ambiguousFunctionDecl, checkDebuggerStatement, checkRegExp, checkTypes, checkVars, const, constantProperty, deprecated, duplicate, es5Strict, fileoverviewTags, missingProperties, nonStandardJsDocs, strictModuleDepCheck, suspiciousCode, undefinedNames, undefinedVars, unknownDefines, unusedLocalVariables, uselessCode, visibility}
  23829. */
  23830. goog.provide('ol.ext.rbush');
  23831. /** @typedef {function(*)} */
  23832. ol.ext.rbush = function() {};
  23833. (function() {(function (exports) {
  23834. 'use strict';
  23835. var quickselect = partialSort;
  23836. function partialSort(arr, k, left, right, compare) {
  23837. left = left || 0;
  23838. right = right || (arr.length - 1);
  23839. compare = compare || defaultCompare;
  23840. while (right > left) {
  23841. if (right - left > 600) {
  23842. var n = right - left + 1;
  23843. var m = k - left + 1;
  23844. var z = Math.log(n);
  23845. var s = 0.5 * Math.exp(2 * z / 3);
  23846. var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
  23847. var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
  23848. var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
  23849. partialSort(arr, k, newLeft, newRight, compare);
  23850. }
  23851. var t = arr[k];
  23852. var i = left;
  23853. var j = right;
  23854. swap(arr, left, k);
  23855. if (compare(arr[right], t) > 0) swap(arr, left, right);
  23856. while (i < j) {
  23857. swap(arr, i, j);
  23858. i++;
  23859. j--;
  23860. while (compare(arr[i], t) < 0) i++;
  23861. while (compare(arr[j], t) > 0) j--;
  23862. }
  23863. if (compare(arr[left], t) === 0) swap(arr, left, j);
  23864. else {
  23865. j++;
  23866. swap(arr, j, right);
  23867. }
  23868. if (j <= k) left = j + 1;
  23869. if (k <= j) right = j - 1;
  23870. }
  23871. }
  23872. function swap(arr, i, j) {
  23873. var tmp = arr[i];
  23874. arr[i] = arr[j];
  23875. arr[j] = tmp;
  23876. }
  23877. function defaultCompare(a, b) {
  23878. return a < b ? -1 : a > b ? 1 : 0;
  23879. }
  23880. var rbush_1 = rbush;
  23881. function rbush(maxEntries, format) {
  23882. if (!(this instanceof rbush)) return new rbush(maxEntries, format);
  23883. this._maxEntries = Math.max(4, maxEntries || 9);
  23884. this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
  23885. if (format) {
  23886. this._initFormat(format);
  23887. }
  23888. this.clear();
  23889. }
  23890. rbush.prototype = {
  23891. all: function () {
  23892. return this._all(this.data, []);
  23893. },
  23894. search: function (bbox) {
  23895. var node = this.data,
  23896. result = [],
  23897. toBBox = this.toBBox;
  23898. if (!intersects(bbox, node)) return result;
  23899. var nodesToSearch = [],
  23900. i, len, child, childBBox;
  23901. while (node) {
  23902. for (i = 0, len = node.children.length; i < len; i++) {
  23903. child = node.children[i];
  23904. childBBox = node.leaf ? toBBox(child) : child;
  23905. if (intersects(bbox, childBBox)) {
  23906. if (node.leaf) result.push(child);
  23907. else if (contains(bbox, childBBox)) this._all(child, result);
  23908. else nodesToSearch.push(child);
  23909. }
  23910. }
  23911. node = nodesToSearch.pop();
  23912. }
  23913. return result;
  23914. },
  23915. collides: function (bbox) {
  23916. var node = this.data,
  23917. toBBox = this.toBBox;
  23918. if (!intersects(bbox, node)) return false;
  23919. var nodesToSearch = [],
  23920. i, len, child, childBBox;
  23921. while (node) {
  23922. for (i = 0, len = node.children.length; i < len; i++) {
  23923. child = node.children[i];
  23924. childBBox = node.leaf ? toBBox(child) : child;
  23925. if (intersects(bbox, childBBox)) {
  23926. if (node.leaf || contains(bbox, childBBox)) return true;
  23927. nodesToSearch.push(child);
  23928. }
  23929. }
  23930. node = nodesToSearch.pop();
  23931. }
  23932. return false;
  23933. },
  23934. load: function (data) {
  23935. if (!(data && data.length)) return this;
  23936. if (data.length < this._minEntries) {
  23937. for (var i = 0, len = data.length; i < len; i++) {
  23938. this.insert(data[i]);
  23939. }
  23940. return this;
  23941. }
  23942. var node = this._build(data.slice(), 0, data.length - 1, 0);
  23943. if (!this.data.children.length) {
  23944. this.data = node;
  23945. } else if (this.data.height === node.height) {
  23946. this._splitRoot(this.data, node);
  23947. } else {
  23948. if (this.data.height < node.height) {
  23949. var tmpNode = this.data;
  23950. this.data = node;
  23951. node = tmpNode;
  23952. }
  23953. this._insert(node, this.data.height - node.height - 1, true);
  23954. }
  23955. return this;
  23956. },
  23957. insert: function (item) {
  23958. if (item) this._insert(item, this.data.height - 1);
  23959. return this;
  23960. },
  23961. clear: function () {
  23962. this.data = createNode([]);
  23963. return this;
  23964. },
  23965. remove: function (item, equalsFn) {
  23966. if (!item) return this;
  23967. var node = this.data,
  23968. bbox = this.toBBox(item),
  23969. path = [],
  23970. indexes = [],
  23971. i, parent, index, goingUp;
  23972. while (node || path.length) {
  23973. if (!node) {
  23974. node = path.pop();
  23975. parent = path[path.length - 1];
  23976. i = indexes.pop();
  23977. goingUp = true;
  23978. }
  23979. if (node.leaf) {
  23980. index = findItem(item, node.children, equalsFn);
  23981. if (index !== -1) {
  23982. node.children.splice(index, 1);
  23983. path.push(node);
  23984. this._condense(path);
  23985. return this;
  23986. }
  23987. }
  23988. if (!goingUp && !node.leaf && contains(node, bbox)) {
  23989. path.push(node);
  23990. indexes.push(i);
  23991. i = 0;
  23992. parent = node;
  23993. node = node.children[0];
  23994. } else if (parent) {
  23995. i++;
  23996. node = parent.children[i];
  23997. goingUp = false;
  23998. } else node = null;
  23999. }
  24000. return this;
  24001. },
  24002. toBBox: function (item) { return item; },
  24003. compareMinX: compareNodeMinX,
  24004. compareMinY: compareNodeMinY,
  24005. toJSON: function () { return this.data; },
  24006. fromJSON: function (data) {
  24007. this.data = data;
  24008. return this;
  24009. },
  24010. _all: function (node, result) {
  24011. var nodesToSearch = [];
  24012. while (node) {
  24013. if (node.leaf) result.push.apply(result, node.children);
  24014. else nodesToSearch.push.apply(nodesToSearch, node.children);
  24015. node = nodesToSearch.pop();
  24016. }
  24017. return result;
  24018. },
  24019. _build: function (items, left, right, height) {
  24020. var N = right - left + 1,
  24021. M = this._maxEntries,
  24022. node;
  24023. if (N <= M) {
  24024. node = createNode(items.slice(left, right + 1));
  24025. calcBBox(node, this.toBBox);
  24026. return node;
  24027. }
  24028. if (!height) {
  24029. height = Math.ceil(Math.log(N) / Math.log(M));
  24030. M = Math.ceil(N / Math.pow(M, height - 1));
  24031. }
  24032. node = createNode([]);
  24033. node.leaf = false;
  24034. node.height = height;
  24035. var N2 = Math.ceil(N / M),
  24036. N1 = N2 * Math.ceil(Math.sqrt(M)),
  24037. i, j, right2, right3;
  24038. multiSelect(items, left, right, N1, this.compareMinX);
  24039. for (i = left; i <= right; i += N1) {
  24040. right2 = Math.min(i + N1 - 1, right);
  24041. multiSelect(items, i, right2, N2, this.compareMinY);
  24042. for (j = i; j <= right2; j += N2) {
  24043. right3 = Math.min(j + N2 - 1, right2);
  24044. node.children.push(this._build(items, j, right3, height - 1));
  24045. }
  24046. }
  24047. calcBBox(node, this.toBBox);
  24048. return node;
  24049. },
  24050. _chooseSubtree: function (bbox, node, level, path) {
  24051. var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
  24052. while (true) {
  24053. path.push(node);
  24054. if (node.leaf || path.length - 1 === level) break;
  24055. minArea = minEnlargement = Infinity;
  24056. for (i = 0, len = node.children.length; i < len; i++) {
  24057. child = node.children[i];
  24058. area = bboxArea(child);
  24059. enlargement = enlargedArea(bbox, child) - area;
  24060. if (enlargement < minEnlargement) {
  24061. minEnlargement = enlargement;
  24062. minArea = area < minArea ? area : minArea;
  24063. targetNode = child;
  24064. } else if (enlargement === minEnlargement) {
  24065. if (area < minArea) {
  24066. minArea = area;
  24067. targetNode = child;
  24068. }
  24069. }
  24070. }
  24071. node = targetNode || node.children[0];
  24072. }
  24073. return node;
  24074. },
  24075. _insert: function (item, level, isNode) {
  24076. var toBBox = this.toBBox,
  24077. bbox = isNode ? item : toBBox(item),
  24078. insertPath = [];
  24079. var node = this._chooseSubtree(bbox, this.data, level, insertPath);
  24080. node.children.push(item);
  24081. extend(node, bbox);
  24082. while (level >= 0) {
  24083. if (insertPath[level].children.length > this._maxEntries) {
  24084. this._split(insertPath, level);
  24085. level--;
  24086. } else break;
  24087. }
  24088. this._adjustParentBBoxes(bbox, insertPath, level);
  24089. },
  24090. _split: function (insertPath, level) {
  24091. var node = insertPath[level],
  24092. M = node.children.length,
  24093. m = this._minEntries;
  24094. this._chooseSplitAxis(node, m, M);
  24095. var splitIndex = this._chooseSplitIndex(node, m, M);
  24096. var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
  24097. newNode.height = node.height;
  24098. newNode.leaf = node.leaf;
  24099. calcBBox(node, this.toBBox);
  24100. calcBBox(newNode, this.toBBox);
  24101. if (level) insertPath[level - 1].children.push(newNode);
  24102. else this._splitRoot(node, newNode);
  24103. },
  24104. _splitRoot: function (node, newNode) {
  24105. this.data = createNode([node, newNode]);
  24106. this.data.height = node.height + 1;
  24107. this.data.leaf = false;
  24108. calcBBox(this.data, this.toBBox);
  24109. },
  24110. _chooseSplitIndex: function (node, m, M) {
  24111. var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
  24112. minOverlap = minArea = Infinity;
  24113. for (i = m; i <= M - m; i++) {
  24114. bbox1 = distBBox(node, 0, i, this.toBBox);
  24115. bbox2 = distBBox(node, i, M, this.toBBox);
  24116. overlap = intersectionArea(bbox1, bbox2);
  24117. area = bboxArea(bbox1) + bboxArea(bbox2);
  24118. if (overlap < minOverlap) {
  24119. minOverlap = overlap;
  24120. index = i;
  24121. minArea = area < minArea ? area : minArea;
  24122. } else if (overlap === minOverlap) {
  24123. if (area < minArea) {
  24124. minArea = area;
  24125. index = i;
  24126. }
  24127. }
  24128. }
  24129. return index;
  24130. },
  24131. _chooseSplitAxis: function (node, m, M) {
  24132. var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
  24133. compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
  24134. xMargin = this._allDistMargin(node, m, M, compareMinX),
  24135. yMargin = this._allDistMargin(node, m, M, compareMinY);
  24136. if (xMargin < yMargin) node.children.sort(compareMinX);
  24137. },
  24138. _allDistMargin: function (node, m, M, compare) {
  24139. node.children.sort(compare);
  24140. var toBBox = this.toBBox,
  24141. leftBBox = distBBox(node, 0, m, toBBox),
  24142. rightBBox = distBBox(node, M - m, M, toBBox),
  24143. margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
  24144. i, child;
  24145. for (i = m; i < M - m; i++) {
  24146. child = node.children[i];
  24147. extend(leftBBox, node.leaf ? toBBox(child) : child);
  24148. margin += bboxMargin(leftBBox);
  24149. }
  24150. for (i = M - m - 1; i >= m; i--) {
  24151. child = node.children[i];
  24152. extend(rightBBox, node.leaf ? toBBox(child) : child);
  24153. margin += bboxMargin(rightBBox);
  24154. }
  24155. return margin;
  24156. },
  24157. _adjustParentBBoxes: function (bbox, path, level) {
  24158. for (var i = level; i >= 0; i--) {
  24159. extend(path[i], bbox);
  24160. }
  24161. },
  24162. _condense: function (path) {
  24163. for (var i = path.length - 1, siblings; i >= 0; i--) {
  24164. if (path[i].children.length === 0) {
  24165. if (i > 0) {
  24166. siblings = path[i - 1].children;
  24167. siblings.splice(siblings.indexOf(path[i]), 1);
  24168. } else this.clear();
  24169. } else calcBBox(path[i], this.toBBox);
  24170. }
  24171. },
  24172. _initFormat: function (format) {
  24173. var compareArr = ['return a', ' - b', ';'];
  24174. this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
  24175. this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
  24176. this.toBBox = new Function('a',
  24177. 'return {minX: a' + format[0] +
  24178. ', minY: a' + format[1] +
  24179. ', maxX: a' + format[2] +
  24180. ', maxY: a' + format[3] + '};');
  24181. }
  24182. };
  24183. function findItem(item, items, equalsFn) {
  24184. if (!equalsFn) return items.indexOf(item);
  24185. for (var i = 0; i < items.length; i++) {
  24186. if (equalsFn(item, items[i])) return i;
  24187. }
  24188. return -1;
  24189. }
  24190. function calcBBox(node, toBBox) {
  24191. distBBox(node, 0, node.children.length, toBBox, node);
  24192. }
  24193. function distBBox(node, k, p, toBBox, destNode) {
  24194. if (!destNode) destNode = createNode(null);
  24195. destNode.minX = Infinity;
  24196. destNode.minY = Infinity;
  24197. destNode.maxX = -Infinity;
  24198. destNode.maxY = -Infinity;
  24199. for (var i = k, child; i < p; i++) {
  24200. child = node.children[i];
  24201. extend(destNode, node.leaf ? toBBox(child) : child);
  24202. }
  24203. return destNode;
  24204. }
  24205. function extend(a, b) {
  24206. a.minX = Math.min(a.minX, b.minX);
  24207. a.minY = Math.min(a.minY, b.minY);
  24208. a.maxX = Math.max(a.maxX, b.maxX);
  24209. a.maxY = Math.max(a.maxY, b.maxY);
  24210. return a;
  24211. }
  24212. function compareNodeMinX(a, b) { return a.minX - b.minX; }
  24213. function compareNodeMinY(a, b) { return a.minY - b.minY; }
  24214. function bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }
  24215. function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
  24216. function enlargedArea(a, b) {
  24217. return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
  24218. (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
  24219. }
  24220. function intersectionArea(a, b) {
  24221. var minX = Math.max(a.minX, b.minX),
  24222. minY = Math.max(a.minY, b.minY),
  24223. maxX = Math.min(a.maxX, b.maxX),
  24224. maxY = Math.min(a.maxY, b.maxY);
  24225. return Math.max(0, maxX - minX) *
  24226. Math.max(0, maxY - minY);
  24227. }
  24228. function contains(a, b) {
  24229. return a.minX <= b.minX &&
  24230. a.minY <= b.minY &&
  24231. b.maxX <= a.maxX &&
  24232. b.maxY <= a.maxY;
  24233. }
  24234. function intersects(a, b) {
  24235. return b.minX <= a.maxX &&
  24236. b.minY <= a.maxY &&
  24237. b.maxX >= a.minX &&
  24238. b.maxY >= a.minY;
  24239. }
  24240. function createNode(children) {
  24241. return {
  24242. children: children,
  24243. height: 1,
  24244. leaf: true,
  24245. minX: Infinity,
  24246. minY: Infinity,
  24247. maxX: -Infinity,
  24248. maxY: -Infinity
  24249. };
  24250. }
  24251. function multiSelect(arr, left, right, n, compare) {
  24252. var stack = [left, right],
  24253. mid;
  24254. while (stack.length) {
  24255. right = stack.pop();
  24256. left = stack.pop();
  24257. if (right - left <= n) continue;
  24258. mid = left + Math.ceil((right - left) / n / 2) * n;
  24259. quickselect(arr, mid, left, right, compare);
  24260. stack.push(left, mid, mid, right);
  24261. }
  24262. }
  24263. exports['default'] = rbush_1;
  24264. }((this.rbush = this.rbush || {})));}).call(ol.ext);
  24265. ol.ext.rbush = ol.ext.rbush.default;
  24266. goog.provide('ol.structs.RBush');
  24267. goog.require('ol');
  24268. goog.require('ol.ext.rbush');
  24269. goog.require('ol.extent');
  24270. goog.require('ol.obj');
  24271. /**
  24272. * Wrapper around the RBush by Vladimir Agafonkin.
  24273. *
  24274. * @constructor
  24275. * @param {number=} opt_maxEntries Max entries.
  24276. * @see https://github.com/mourner/rbush
  24277. * @struct
  24278. * @template T
  24279. */
  24280. ol.structs.RBush = function(opt_maxEntries) {
  24281. /**
  24282. * @private
  24283. */
  24284. this.rbush_ = ol.ext.rbush(opt_maxEntries);
  24285. /**
  24286. * A mapping between the objects added to this rbush wrapper
  24287. * and the objects that are actually added to the internal rbush.
  24288. * @private
  24289. * @type {Object.<number, ol.RBushEntry>}
  24290. */
  24291. this.items_ = {};
  24292. };
  24293. /**
  24294. * Insert a value into the RBush.
  24295. * @param {ol.Extent} extent Extent.
  24296. * @param {T} value Value.
  24297. */
  24298. ol.structs.RBush.prototype.insert = function(extent, value) {
  24299. /** @type {ol.RBushEntry} */
  24300. var item = {
  24301. minX: extent[0],
  24302. minY: extent[1],
  24303. maxX: extent[2],
  24304. maxY: extent[3],
  24305. value: value
  24306. };
  24307. this.rbush_.insert(item);
  24308. this.items_[ol.getUid(value)] = item;
  24309. };
  24310. /**
  24311. * Bulk-insert values into the RBush.
  24312. * @param {Array.<ol.Extent>} extents Extents.
  24313. * @param {Array.<T>} values Values.
  24314. */
  24315. ol.structs.RBush.prototype.load = function(extents, values) {
  24316. var items = new Array(values.length);
  24317. for (var i = 0, l = values.length; i < l; i++) {
  24318. var extent = extents[i];
  24319. var value = values[i];
  24320. /** @type {ol.RBushEntry} */
  24321. var item = {
  24322. minX: extent[0],
  24323. minY: extent[1],
  24324. maxX: extent[2],
  24325. maxY: extent[3],
  24326. value: value
  24327. };
  24328. items[i] = item;
  24329. this.items_[ol.getUid(value)] = item;
  24330. }
  24331. this.rbush_.load(items);
  24332. };
  24333. /**
  24334. * Remove a value from the RBush.
  24335. * @param {T} value Value.
  24336. * @return {boolean} Removed.
  24337. */
  24338. ol.structs.RBush.prototype.remove = function(value) {
  24339. var uid = ol.getUid(value);
  24340. // get the object in which the value was wrapped when adding to the
  24341. // internal rbush. then use that object to do the removal.
  24342. var item = this.items_[uid];
  24343. delete this.items_[uid];
  24344. return this.rbush_.remove(item) !== null;
  24345. };
  24346. /**
  24347. * Update the extent of a value in the RBush.
  24348. * @param {ol.Extent} extent Extent.
  24349. * @param {T} value Value.
  24350. */
  24351. ol.structs.RBush.prototype.update = function(extent, value) {
  24352. var item = this.items_[ol.getUid(value)];
  24353. var bbox = [item.minX, item.minY, item.maxX, item.maxY];
  24354. if (!ol.extent.equals(bbox, extent)) {
  24355. this.remove(value);
  24356. this.insert(extent, value);
  24357. }
  24358. };
  24359. /**
  24360. * Return all values in the RBush.
  24361. * @return {Array.<T>} All.
  24362. */
  24363. ol.structs.RBush.prototype.getAll = function() {
  24364. var items = this.rbush_.all();
  24365. return items.map(function(item) {
  24366. return item.value;
  24367. });
  24368. };
  24369. /**
  24370. * Return all values in the given extent.
  24371. * @param {ol.Extent} extent Extent.
  24372. * @return {Array.<T>} All in extent.
  24373. */
  24374. ol.structs.RBush.prototype.getInExtent = function(extent) {
  24375. /** @type {ol.RBushEntry} */
  24376. var bbox = {
  24377. minX: extent[0],
  24378. minY: extent[1],
  24379. maxX: extent[2],
  24380. maxY: extent[3]
  24381. };
  24382. var items = this.rbush_.search(bbox);
  24383. return items.map(function(item) {
  24384. return item.value;
  24385. });
  24386. };
  24387. /**
  24388. * Calls a callback function with each value in the tree.
  24389. * If the callback returns a truthy value, this value is returned without
  24390. * checking the rest of the tree.
  24391. * @param {function(this: S, T): *} callback Callback.
  24392. * @param {S=} opt_this The object to use as `this` in `callback`.
  24393. * @return {*} Callback return value.
  24394. * @template S
  24395. */
  24396. ol.structs.RBush.prototype.forEach = function(callback, opt_this) {
  24397. return this.forEach_(this.getAll(), callback, opt_this);
  24398. };
  24399. /**
  24400. * Calls a callback function with each value in the provided extent.
  24401. * @param {ol.Extent} extent Extent.
  24402. * @param {function(this: S, T): *} callback Callback.
  24403. * @param {S=} opt_this The object to use as `this` in `callback`.
  24404. * @return {*} Callback return value.
  24405. * @template S
  24406. */
  24407. ol.structs.RBush.prototype.forEachInExtent = function(extent, callback, opt_this) {
  24408. return this.forEach_(this.getInExtent(extent), callback, opt_this);
  24409. };
  24410. /**
  24411. * @param {Array.<T>} values Values.
  24412. * @param {function(this: S, T): *} callback Callback.
  24413. * @param {S=} opt_this The object to use as `this` in `callback`.
  24414. * @private
  24415. * @return {*} Callback return value.
  24416. * @template S
  24417. */
  24418. ol.structs.RBush.prototype.forEach_ = function(values, callback, opt_this) {
  24419. var result;
  24420. for (var i = 0, l = values.length; i < l; i++) {
  24421. result = callback.call(opt_this, values[i]);
  24422. if (result) {
  24423. return result;
  24424. }
  24425. }
  24426. return result;
  24427. };
  24428. /**
  24429. * @return {boolean} Is empty.
  24430. */
  24431. ol.structs.RBush.prototype.isEmpty = function() {
  24432. return ol.obj.isEmpty(this.items_);
  24433. };
  24434. /**
  24435. * Remove all values from the RBush.
  24436. */
  24437. ol.structs.RBush.prototype.clear = function() {
  24438. this.rbush_.clear();
  24439. this.items_ = {};
  24440. };
  24441. /**
  24442. * @param {ol.Extent=} opt_extent Extent.
  24443. * @return {ol.Extent} Extent.
  24444. */
  24445. ol.structs.RBush.prototype.getExtent = function(opt_extent) {
  24446. // FIXME add getExtent() to rbush
  24447. var data = this.rbush_.data;
  24448. return ol.extent.createOrUpdate(data.minX, data.minY, data.maxX, data.maxY, opt_extent);
  24449. };
  24450. /**
  24451. * @param {ol.structs.RBush} rbush R-Tree.
  24452. */
  24453. ol.structs.RBush.prototype.concat = function(rbush) {
  24454. this.rbush_.load(rbush.rbush_.all());
  24455. for (var i in rbush.items_) {
  24456. this.items_[i | 0] = rbush.items_[i | 0];
  24457. }
  24458. };
  24459. goog.provide('ol.render.webgl.PolygonReplay');
  24460. goog.require('ol');
  24461. goog.require('ol.array');
  24462. goog.require('ol.color');
  24463. goog.require('ol.extent');
  24464. goog.require('ol.obj');
  24465. goog.require('ol.geom.flat.contains');
  24466. goog.require('ol.geom.flat.orient');
  24467. goog.require('ol.geom.flat.transform');
  24468. goog.require('ol.render.webgl.polygonreplay.defaultshader');
  24469. goog.require('ol.render.webgl.LineStringReplay');
  24470. goog.require('ol.render.webgl.Replay');
  24471. goog.require('ol.render.webgl');
  24472. goog.require('ol.style.Stroke');
  24473. goog.require('ol.structs.LinkedList');
  24474. goog.require('ol.structs.RBush');
  24475. goog.require('ol.webgl');
  24476. goog.require('ol.webgl.Buffer');
  24477. if (ol.ENABLE_WEBGL) {
  24478. /**
  24479. * @constructor
  24480. * @extends {ol.render.webgl.Replay}
  24481. * @param {number} tolerance Tolerance.
  24482. * @param {ol.Extent} maxExtent Max extent.
  24483. * @struct
  24484. */
  24485. ol.render.webgl.PolygonReplay = function(tolerance, maxExtent) {
  24486. ol.render.webgl.Replay.call(this, tolerance, maxExtent);
  24487. this.lineStringReplay = new ol.render.webgl.LineStringReplay(
  24488. tolerance, maxExtent);
  24489. /**
  24490. * @private
  24491. * @type {ol.render.webgl.polygonreplay.defaultshader.Locations}
  24492. */
  24493. this.defaultLocations_ = null;
  24494. /**
  24495. * @private
  24496. * @type {Array.<Array.<number>>}
  24497. */
  24498. this.styles_ = [];
  24499. /**
  24500. * @private
  24501. * @type {Array.<number>}
  24502. */
  24503. this.styleIndices_ = [];
  24504. /**
  24505. * @private
  24506. * @type {{fillColor: (Array.<number>|null),
  24507. * changed: boolean}|null}
  24508. */
  24509. this.state_ = {
  24510. fillColor: null,
  24511. changed: false
  24512. };
  24513. };
  24514. ol.inherits(ol.render.webgl.PolygonReplay, ol.render.webgl.Replay);
  24515. /**
  24516. * Draw one polygon.
  24517. * @param {Array.<number>} flatCoordinates Flat coordinates.
  24518. * @param {Array.<Array.<number>>} holeFlatCoordinates Hole flat coordinates.
  24519. * @param {number} stride Stride.
  24520. * @private
  24521. */
  24522. ol.render.webgl.PolygonReplay.prototype.drawCoordinates_ = function(
  24523. flatCoordinates, holeFlatCoordinates, stride) {
  24524. // Triangulate the polygon
  24525. var outerRing = new ol.structs.LinkedList();
  24526. var rtree = new ol.structs.RBush();
  24527. // Initialize the outer ring
  24528. this.processFlatCoordinates_(flatCoordinates, stride, outerRing, rtree, true);
  24529. var maxCoords = this.getMaxCoords_(outerRing);
  24530. // Eliminate holes, if there are any
  24531. if (holeFlatCoordinates.length) {
  24532. var i, ii;
  24533. var holeLists = [];
  24534. for (i = 0, ii = holeFlatCoordinates.length; i < ii; ++i) {
  24535. var holeList = {
  24536. list: new ol.structs.LinkedList(),
  24537. maxCoords: undefined,
  24538. rtree: new ol.structs.RBush()
  24539. };
  24540. holeLists.push(holeList);
  24541. this.processFlatCoordinates_(holeFlatCoordinates[i],
  24542. stride, holeList.list, holeList.rtree, false);
  24543. this.classifyPoints_(holeList.list, holeList.rtree, true);
  24544. holeList.maxCoords = this.getMaxCoords_(holeList.list);
  24545. }
  24546. holeLists.sort(function(a, b) {
  24547. return b.maxCoords[0] === a.maxCoords[0] ?
  24548. a.maxCoords[1] - b.maxCoords[1] : b.maxCoords[0] - a.maxCoords[0];
  24549. });
  24550. for (i = 0; i < holeLists.length; ++i) {
  24551. var currList = holeLists[i].list;
  24552. var start = currList.firstItem();
  24553. var currItem = start;
  24554. var intersection;
  24555. do {
  24556. //TODO: Triangulate holes when they intersect the outer ring.
  24557. if (this.getIntersections_(currItem, rtree).length) {
  24558. intersection = true;
  24559. break;
  24560. }
  24561. currItem = currList.nextItem();
  24562. } while (start !== currItem);
  24563. if (!intersection) {
  24564. if (this.bridgeHole_(currList, holeLists[i].maxCoords[0], outerRing, maxCoords[0], rtree)) {
  24565. rtree.concat(holeLists[i].rtree);
  24566. this.classifyPoints_(outerRing, rtree, false);
  24567. }
  24568. }
  24569. }
  24570. } else {
  24571. this.classifyPoints_(outerRing, rtree, false);
  24572. }
  24573. this.triangulate_(outerRing, rtree);
  24574. };
  24575. /**
  24576. * Inserts flat coordinates in a linked list and adds them to the vertex buffer.
  24577. * @private
  24578. * @param {Array.<number>} flatCoordinates Flat coordinates.
  24579. * @param {number} stride Stride.
  24580. * @param {ol.structs.LinkedList} list Linked list.
  24581. * @param {ol.structs.RBush} rtree R-Tree of the polygon.
  24582. * @param {boolean} clockwise Coordinate order should be clockwise.
  24583. */
  24584. ol.render.webgl.PolygonReplay.prototype.processFlatCoordinates_ = function(
  24585. flatCoordinates, stride, list, rtree, clockwise) {
  24586. var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(flatCoordinates,
  24587. 0, flatCoordinates.length, stride);
  24588. var i, ii;
  24589. var n = this.vertices.length / 2;
  24590. /** @type {ol.WebglPolygonVertex} */
  24591. var start;
  24592. /** @type {ol.WebglPolygonVertex} */
  24593. var p0;
  24594. /** @type {ol.WebglPolygonVertex} */
  24595. var p1;
  24596. var extents = [];
  24597. var segments = [];
  24598. if (clockwise === isClockwise) {
  24599. start = this.createPoint_(flatCoordinates[0], flatCoordinates[1], n++);
  24600. p0 = start;
  24601. for (i = stride, ii = flatCoordinates.length; i < ii; i += stride) {
  24602. p1 = this.createPoint_(flatCoordinates[i], flatCoordinates[i + 1], n++);
  24603. segments.push(this.insertItem_(p0, p1, list));
  24604. extents.push([Math.min(p0.x, p1.x), Math.min(p0.y, p1.y), Math.max(p0.x, p1.x),
  24605. Math.max(p0.y, p1.y)]);
  24606. p0 = p1;
  24607. }
  24608. segments.push(this.insertItem_(p1, start, list));
  24609. extents.push([Math.min(p0.x, p1.x), Math.min(p0.y, p1.y), Math.max(p0.x, p1.x),
  24610. Math.max(p0.y, p1.y)]);
  24611. } else {
  24612. var end = flatCoordinates.length - stride;
  24613. start = this.createPoint_(flatCoordinates[end], flatCoordinates[end + 1], n++);
  24614. p0 = start;
  24615. for (i = end - stride, ii = 0; i >= ii; i -= stride) {
  24616. p1 = this.createPoint_(flatCoordinates[i], flatCoordinates[i + 1], n++);
  24617. segments.push(this.insertItem_(p0, p1, list));
  24618. extents.push([Math.min(p0.x, p1.x), Math.min(p0.y, p1.y), Math.max(p0.x, p1.x),
  24619. Math.max(p0.y, p1.y)]);
  24620. p0 = p1;
  24621. }
  24622. segments.push(this.insertItem_(p1, start, list));
  24623. extents.push([Math.min(p0.x, p1.x), Math.min(p0.y, p1.y), Math.max(p0.x, p1.x),
  24624. Math.max(p0.y, p1.y)]);
  24625. }
  24626. rtree.load(extents, segments);
  24627. };
  24628. /**
  24629. * Returns the rightmost coordinates of a polygon on the X axis.
  24630. * @private
  24631. * @param {ol.structs.LinkedList} list Polygons ring.
  24632. * @return {Array.<number>} Max X coordinates.
  24633. */
  24634. ol.render.webgl.PolygonReplay.prototype.getMaxCoords_ = function(list) {
  24635. var start = list.firstItem();
  24636. var seg = start;
  24637. var maxCoords = [seg.p0.x, seg.p0.y];
  24638. do {
  24639. seg = list.nextItem();
  24640. if (seg.p0.x > maxCoords[0]) {
  24641. maxCoords = [seg.p0.x, seg.p0.y];
  24642. }
  24643. } while (seg !== start);
  24644. return maxCoords;
  24645. };
  24646. /**
  24647. * Classifies the points of a polygon list as convex, reflex. Removes collinear vertices.
  24648. * @private
  24649. * @param {ol.structs.LinkedList} list Polygon ring.
  24650. * @param {ol.structs.RBush} rtree R-Tree of the polygon.
  24651. * @param {boolean} ccw The orientation of the polygon is counter-clockwise.
  24652. * @return {boolean} There were reclassified points.
  24653. */
  24654. ol.render.webgl.PolygonReplay.prototype.classifyPoints_ = function(list, rtree, ccw) {
  24655. var start = list.firstItem();
  24656. var s0 = start;
  24657. var s1 = list.nextItem();
  24658. var pointsReclassified = false;
  24659. do {
  24660. var reflex = ccw ? ol.render.webgl.triangleIsCounterClockwise(s1.p1.x,
  24661. s1.p1.y, s0.p1.x, s0.p1.y, s0.p0.x, s0.p0.y) :
  24662. ol.render.webgl.triangleIsCounterClockwise(s0.p0.x, s0.p0.y, s0.p1.x,
  24663. s0.p1.y, s1.p1.x, s1.p1.y);
  24664. if (reflex === undefined) {
  24665. this.removeItem_(s0, s1, list, rtree);
  24666. pointsReclassified = true;
  24667. if (s1 === start) {
  24668. start = list.getNextItem();
  24669. }
  24670. s1 = s0;
  24671. list.prevItem();
  24672. } else if (s0.p1.reflex !== reflex) {
  24673. s0.p1.reflex = reflex;
  24674. pointsReclassified = true;
  24675. }
  24676. s0 = s1;
  24677. s1 = list.nextItem();
  24678. } while (s0 !== start);
  24679. return pointsReclassified;
  24680. };
  24681. /**
  24682. * @private
  24683. * @param {ol.structs.LinkedList} hole Linked list of the hole.
  24684. * @param {number} holeMaxX Maximum X value of the hole.
  24685. * @param {ol.structs.LinkedList} list Linked list of the polygon.
  24686. * @param {number} listMaxX Maximum X value of the polygon.
  24687. * @param {ol.structs.RBush} rtree R-Tree of the polygon.
  24688. * @return {boolean} Bridging was successful.
  24689. */
  24690. ol.render.webgl.PolygonReplay.prototype.bridgeHole_ = function(hole, holeMaxX,
  24691. list, listMaxX, rtree) {
  24692. var seg = hole.firstItem();
  24693. while (seg.p1.x !== holeMaxX) {
  24694. seg = hole.nextItem();
  24695. }
  24696. var p1 = seg.p1;
  24697. /** @type {ol.WebglPolygonVertex} */
  24698. var p2 = {x: listMaxX, y: p1.y, i: -1};
  24699. var minDist = Infinity;
  24700. var i, ii, bestPoint;
  24701. /** @type {ol.WebglPolygonVertex} */
  24702. var p5;
  24703. var intersectingSegments = this.getIntersections_({p0: p1, p1: p2}, rtree, true);
  24704. for (i = 0, ii = intersectingSegments.length; i < ii; ++i) {
  24705. var currSeg = intersectingSegments[i];
  24706. var intersection = this.calculateIntersection_(p1, p2, currSeg.p0,
  24707. currSeg.p1, true);
  24708. var dist = Math.abs(p1.x - intersection[0]);
  24709. if (dist < minDist && ol.render.webgl.triangleIsCounterClockwise(p1.x, p1.y,
  24710. currSeg.p0.x, currSeg.p0.y, currSeg.p1.x, currSeg.p1.y) !== undefined) {
  24711. minDist = dist;
  24712. p5 = {x: intersection[0], y: intersection[1], i: -1};
  24713. seg = currSeg;
  24714. }
  24715. }
  24716. if (minDist === Infinity) {
  24717. return false;
  24718. }
  24719. bestPoint = seg.p1;
  24720. if (minDist > 0) {
  24721. var pointsInTriangle = this.getPointsInTriangle_(p1, p5, seg.p1, rtree);
  24722. if (pointsInTriangle.length) {
  24723. var theta = Infinity;
  24724. for (i = 0, ii = pointsInTriangle.length; i < ii; ++i) {
  24725. var currPoint = pointsInTriangle[i];
  24726. var currTheta = Math.atan2(p1.y - currPoint.y, p2.x - currPoint.x);
  24727. if (currTheta < theta || (currTheta === theta && currPoint.x < bestPoint.x)) {
  24728. theta = currTheta;
  24729. bestPoint = currPoint;
  24730. }
  24731. }
  24732. }
  24733. }
  24734. seg = list.firstItem();
  24735. while (seg.p1.x !== bestPoint.x || seg.p1.y !== bestPoint.y) {
  24736. seg = list.nextItem();
  24737. }
  24738. //We clone the bridge points as they can have different convexity.
  24739. var p0Bridge = {x: p1.x, y: p1.y, i: p1.i, reflex: undefined};
  24740. var p1Bridge = {x: seg.p1.x, y: seg.p1.y, i: seg.p1.i, reflex: undefined};
  24741. hole.getNextItem().p0 = p0Bridge;
  24742. this.insertItem_(p1, seg.p1, hole, rtree);
  24743. this.insertItem_(p1Bridge, p0Bridge, hole, rtree);
  24744. seg.p1 = p1Bridge;
  24745. hole.setFirstItem();
  24746. list.concat(hole);
  24747. return true;
  24748. };
  24749. /**
  24750. * @private
  24751. * @param {ol.structs.LinkedList} list Linked list of the polygon.
  24752. * @param {ol.structs.RBush} rtree R-Tree of the polygon.
  24753. */
  24754. ol.render.webgl.PolygonReplay.prototype.triangulate_ = function(list, rtree) {
  24755. var ccw = false;
  24756. var simple = this.isSimple_(list, rtree);
  24757. // Start clipping ears
  24758. while (list.getLength() > 3) {
  24759. if (simple) {
  24760. if (!this.clipEars_(list, rtree, simple, ccw)) {
  24761. if (!this.classifyPoints_(list, rtree, ccw)) {
  24762. // Due to the behavior of OL's PIP algorithm, the ear clipping cannot
  24763. // introduce touching segments. However, the original data may have some.
  24764. if (!this.resolveSelfIntersections_(list, rtree, true)) {
  24765. break;
  24766. }
  24767. }
  24768. }
  24769. } else {
  24770. if (!this.clipEars_(list, rtree, simple, ccw)) {
  24771. // We ran out of ears, try to reclassify.
  24772. if (!this.classifyPoints_(list, rtree, ccw)) {
  24773. // We have a bad polygon, try to resolve local self-intersections.
  24774. if (!this.resolveSelfIntersections_(list, rtree)) {
  24775. simple = this.isSimple_(list, rtree);
  24776. if (!simple) {
  24777. // We have a really bad polygon, try more time consuming methods.
  24778. this.splitPolygon_(list, rtree);
  24779. break;
  24780. } else {
  24781. ccw = !this.isClockwise_(list);
  24782. this.classifyPoints_(list, rtree, ccw);
  24783. }
  24784. }
  24785. }
  24786. }
  24787. }
  24788. }
  24789. if (list.getLength() === 3) {
  24790. var numIndices = this.indices.length;
  24791. this.indices[numIndices++] = list.getPrevItem().p0.i;
  24792. this.indices[numIndices++] = list.getCurrItem().p0.i;
  24793. this.indices[numIndices++] = list.getNextItem().p0.i;
  24794. }
  24795. };
  24796. /**
  24797. * @private
  24798. * @param {ol.structs.LinkedList} list Linked list of the polygon.
  24799. * @param {ol.structs.RBush} rtree R-Tree of the polygon.
  24800. * @param {boolean} simple The polygon is simple.
  24801. * @param {boolean} ccw Orientation of the polygon is counter-clockwise.
  24802. * @return {boolean} There were processed ears.
  24803. */
  24804. ol.render.webgl.PolygonReplay.prototype.clipEars_ = function(list, rtree, simple, ccw) {
  24805. var numIndices = this.indices.length;
  24806. var start = list.firstItem();
  24807. var s0 = list.getPrevItem();
  24808. var s1 = start;
  24809. var s2 = list.nextItem();
  24810. var s3 = list.getNextItem();
  24811. var p0, p1, p2;
  24812. var processedEars = false;
  24813. do {
  24814. p0 = s1.p0;
  24815. p1 = s1.p1;
  24816. p2 = s2.p1;
  24817. if (p1.reflex === false) {
  24818. // We might have a valid ear
  24819. var variableCriterion;
  24820. if (simple) {
  24821. variableCriterion = this.getPointsInTriangle_(p0, p1, p2, rtree, true).length === 0;
  24822. } else {
  24823. variableCriterion = ccw ? this.diagonalIsInside_(s3.p1, p2, p1, p0,
  24824. s0.p0) : this.diagonalIsInside_(s0.p0, p0, p1, p2, s3.p1);
  24825. }
  24826. if ((simple || this.getIntersections_({p0: p0, p1: p2}, rtree).length === 0) &&
  24827. variableCriterion) {
  24828. //The diagonal is completely inside the polygon
  24829. if (simple || p0.reflex === false || p2.reflex === false ||
  24830. ol.geom.flat.orient.linearRingIsClockwise([s0.p0.x, s0.p0.y, p0.x,
  24831. p0.y, p1.x, p1.y, p2.x, p2.y, s3.p1.x, s3.p1.y], 0, 10, 2) === !ccw) {
  24832. //The diagonal is persumably valid, we have an ear
  24833. this.indices[numIndices++] = p0.i;
  24834. this.indices[numIndices++] = p1.i;
  24835. this.indices[numIndices++] = p2.i;
  24836. this.removeItem_(s1, s2, list, rtree);
  24837. if (s2 === start) {
  24838. start = s3;
  24839. }
  24840. processedEars = true;
  24841. }
  24842. }
  24843. }
  24844. // Else we have a reflex point.
  24845. s0 = list.getPrevItem();
  24846. s1 = list.getCurrItem();
  24847. s2 = list.nextItem();
  24848. s3 = list.getNextItem();
  24849. } while (s1 !== start && list.getLength() > 3);
  24850. return processedEars;
  24851. };
  24852. /**
  24853. * @private
  24854. * @param {ol.structs.LinkedList} list Linked list of the polygon.
  24855. * @param {ol.structs.RBush} rtree R-Tree of the polygon.
  24856. * @param {boolean=} opt_touch Resolve touching segments.
  24857. * @return {boolean} There were resolved intersections.
  24858. */
  24859. ol.render.webgl.PolygonReplay.prototype.resolveSelfIntersections_ = function(
  24860. list, rtree, opt_touch) {
  24861. var start = list.firstItem();
  24862. list.nextItem();
  24863. var s0 = start;
  24864. var s1 = list.nextItem();
  24865. var resolvedIntersections = false;
  24866. do {
  24867. var intersection = this.calculateIntersection_(s0.p0, s0.p1, s1.p0, s1.p1,
  24868. opt_touch);
  24869. if (intersection) {
  24870. var breakCond = false;
  24871. var numVertices = this.vertices.length;
  24872. var numIndices = this.indices.length;
  24873. var n = numVertices / 2;
  24874. var seg = list.prevItem();
  24875. list.removeItem();
  24876. rtree.remove(seg);
  24877. breakCond = (seg === start);
  24878. var p;
  24879. if (opt_touch) {
  24880. if (intersection[0] === s0.p0.x && intersection[1] === s0.p0.y) {
  24881. list.prevItem();
  24882. p = s0.p0;
  24883. s1.p0 = p;
  24884. rtree.remove(s0);
  24885. breakCond = breakCond || (s0 === start);
  24886. } else {
  24887. p = s1.p1;
  24888. s0.p1 = p;
  24889. rtree.remove(s1);
  24890. breakCond = breakCond || (s1 === start);
  24891. }
  24892. list.removeItem();
  24893. } else {
  24894. p = this.createPoint_(intersection[0], intersection[1], n);
  24895. s0.p1 = p;
  24896. s1.p0 = p;
  24897. rtree.update([Math.min(s0.p0.x, s0.p1.x), Math.min(s0.p0.y, s0.p1.y),
  24898. Math.max(s0.p0.x, s0.p1.x), Math.max(s0.p0.y, s0.p1.y)], s0);
  24899. rtree.update([Math.min(s1.p0.x, s1.p1.x), Math.min(s1.p0.y, s1.p1.y),
  24900. Math.max(s1.p0.x, s1.p1.x), Math.max(s1.p0.y, s1.p1.y)], s1);
  24901. }
  24902. this.indices[numIndices++] = seg.p0.i;
  24903. this.indices[numIndices++] = seg.p1.i;
  24904. this.indices[numIndices++] = p.i;
  24905. resolvedIntersections = true;
  24906. if (breakCond) {
  24907. break;
  24908. }
  24909. }
  24910. s0 = list.getPrevItem();
  24911. s1 = list.nextItem();
  24912. } while (s0 !== start);
  24913. return resolvedIntersections;
  24914. };
  24915. /**
  24916. * @private
  24917. * @param {ol.structs.LinkedList} list Linked list of the polygon.
  24918. * @param {ol.structs.RBush} rtree R-Tree of the polygon.
  24919. * @return {boolean} The polygon is simple.
  24920. */
  24921. ol.render.webgl.PolygonReplay.prototype.isSimple_ = function(list, rtree) {
  24922. var start = list.firstItem();
  24923. var seg = start;
  24924. do {
  24925. if (this.getIntersections_(seg, rtree).length) {
  24926. return false;
  24927. }
  24928. seg = list.nextItem();
  24929. } while (seg !== start);
  24930. return true;
  24931. };
  24932. /**
  24933. * @private
  24934. * @param {ol.structs.LinkedList} list Linked list of the polygon.
  24935. * @return {boolean} Orientation is clockwise.
  24936. */
  24937. ol.render.webgl.PolygonReplay.prototype.isClockwise_ = function(list) {
  24938. var length = list.getLength() * 2;
  24939. var flatCoordinates = new Array(length);
  24940. var start = list.firstItem();
  24941. var seg = start;
  24942. var i = 0;
  24943. do {
  24944. flatCoordinates[i++] = seg.p0.x;
  24945. flatCoordinates[i++] = seg.p0.y;
  24946. seg = list.nextItem();
  24947. } while (seg !== start);
  24948. return ol.geom.flat.orient.linearRingIsClockwise(flatCoordinates, 0, length, 2);
  24949. };
  24950. /**
  24951. * @private
  24952. * @param {ol.structs.LinkedList} list Linked list of the polygon.
  24953. * @param {ol.structs.RBush} rtree R-Tree of the polygon.
  24954. */
  24955. ol.render.webgl.PolygonReplay.prototype.splitPolygon_ = function(list, rtree) {
  24956. var start = list.firstItem();
  24957. var s0 = start;
  24958. do {
  24959. var intersections = this.getIntersections_(s0, rtree);
  24960. if (intersections.length) {
  24961. var s1 = intersections[0];
  24962. var n = this.vertices.length / 2;
  24963. var intersection = this.calculateIntersection_(s0.p0,
  24964. s0.p1, s1.p0, s1.p1);
  24965. var p = this.createPoint_(intersection[0], intersection[1], n);
  24966. var newPolygon = new ol.structs.LinkedList();
  24967. var newRtree = new ol.structs.RBush();
  24968. this.insertItem_(p, s0.p1, newPolygon, newRtree);
  24969. s0.p1 = p;
  24970. rtree.update([Math.min(s0.p0.x, p.x), Math.min(s0.p0.y, p.y),
  24971. Math.max(s0.p0.x, p.x), Math.max(s0.p0.y, p.y)], s0);
  24972. var currItem = list.nextItem();
  24973. while (currItem !== s1) {
  24974. this.insertItem_(currItem.p0, currItem.p1, newPolygon, newRtree);
  24975. rtree.remove(currItem);
  24976. list.removeItem();
  24977. currItem = list.getCurrItem();
  24978. }
  24979. this.insertItem_(s1.p0, p, newPolygon, newRtree);
  24980. s1.p0 = p;
  24981. rtree.update([Math.min(s1.p1.x, p.x), Math.min(s1.p1.y, p.y),
  24982. Math.max(s1.p1.x, p.x), Math.max(s1.p1.y, p.y)], s1);
  24983. this.classifyPoints_(list, rtree, false);
  24984. this.triangulate_(list, rtree);
  24985. this.classifyPoints_(newPolygon, newRtree, false);
  24986. this.triangulate_(newPolygon, newRtree);
  24987. break;
  24988. }
  24989. s0 = list.nextItem();
  24990. } while (s0 !== start);
  24991. };
  24992. /**
  24993. * @private
  24994. * @param {number} x X coordinate.
  24995. * @param {number} y Y coordinate.
  24996. * @param {number} i Index.
  24997. * @return {ol.WebglPolygonVertex} List item.
  24998. */
  24999. ol.render.webgl.PolygonReplay.prototype.createPoint_ = function(x, y, i) {
  25000. var numVertices = this.vertices.length;
  25001. this.vertices[numVertices++] = x;
  25002. this.vertices[numVertices++] = y;
  25003. /** @type {ol.WebglPolygonVertex} */
  25004. var p = {
  25005. x: x,
  25006. y: y,
  25007. i: i,
  25008. reflex: undefined
  25009. };
  25010. return p;
  25011. };
  25012. /**
  25013. * @private
  25014. * @param {ol.WebglPolygonVertex} p0 First point of segment.
  25015. * @param {ol.WebglPolygonVertex} p1 Second point of segment.
  25016. * @param {ol.structs.LinkedList} list Polygon ring.
  25017. * @param {ol.structs.RBush=} opt_rtree Insert the segment into the R-Tree.
  25018. * @return {ol.WebglPolygonSegment} segment.
  25019. */
  25020. ol.render.webgl.PolygonReplay.prototype.insertItem_ = function(p0, p1, list, opt_rtree) {
  25021. var seg = {
  25022. p0: p0,
  25023. p1: p1
  25024. };
  25025. list.insertItem(seg);
  25026. if (opt_rtree) {
  25027. opt_rtree.insert([Math.min(p0.x, p1.x), Math.min(p0.y, p1.y),
  25028. Math.max(p0.x, p1.x), Math.max(p0.y, p1.y)], seg);
  25029. }
  25030. return seg;
  25031. };
  25032. /**
  25033. * @private
  25034. * @param {ol.WebglPolygonSegment} s0 Segment before the remove candidate.
  25035. * @param {ol.WebglPolygonSegment} s1 Remove candidate segment.
  25036. * @param {ol.structs.LinkedList} list Polygon ring.
  25037. * @param {ol.structs.RBush} rtree R-Tree of the polygon.
  25038. */
  25039. ol.render.webgl.PolygonReplay.prototype.removeItem_ = function(s0, s1, list, rtree) {
  25040. if (list.getCurrItem() === s1) {
  25041. list.removeItem();
  25042. s0.p1 = s1.p1;
  25043. rtree.remove(s1);
  25044. rtree.update([Math.min(s0.p0.x, s0.p1.x), Math.min(s0.p0.y, s0.p1.y),
  25045. Math.max(s0.p0.x, s0.p1.x), Math.max(s0.p0.y, s0.p1.y)], s0);
  25046. }
  25047. };
  25048. /**
  25049. * @private
  25050. * @param {ol.WebglPolygonVertex} p0 First point.
  25051. * @param {ol.WebglPolygonVertex} p1 Second point.
  25052. * @param {ol.WebglPolygonVertex} p2 Third point.
  25053. * @param {ol.structs.RBush} rtree R-Tree of the polygon.
  25054. * @param {boolean=} opt_reflex Only include reflex points.
  25055. * @return {Array.<ol.WebglPolygonVertex>} Points in the triangle.
  25056. */
  25057. ol.render.webgl.PolygonReplay.prototype.getPointsInTriangle_ = function(p0, p1,
  25058. p2, rtree, opt_reflex) {
  25059. var i, ii, j, p;
  25060. var result = [];
  25061. var segmentsInExtent = rtree.getInExtent([Math.min(p0.x, p1.x, p2.x),
  25062. Math.min(p0.y, p1.y, p2.y), Math.max(p0.x, p1.x, p2.x), Math.max(p0.y,
  25063. p1.y, p2.y)]);
  25064. for (i = 0, ii = segmentsInExtent.length; i < ii; ++i) {
  25065. for (j in segmentsInExtent[i]) {
  25066. p = segmentsInExtent[i][j];
  25067. if (typeof p === 'object' && (!opt_reflex || p.reflex)) {
  25068. if ((p.x !== p0.x || p.y !== p0.y) && (p.x !== p1.x || p.y !== p1.y) &&
  25069. (p.x !== p2.x || p.y !== p2.y) && result.indexOf(p) === -1 &&
  25070. ol.geom.flat.contains.linearRingContainsXY([p0.x, p0.y, p1.x, p1.y,
  25071. p2.x, p2.y], 0, 6, 2, p.x, p.y)) {
  25072. result.push(p);
  25073. }
  25074. }
  25075. }
  25076. }
  25077. return result;
  25078. };
  25079. /**
  25080. * @private
  25081. * @param {ol.WebglPolygonSegment} segment Segment.
  25082. * @param {ol.structs.RBush} rtree R-Tree of the polygon.
  25083. * @param {boolean=} opt_touch Touching segments should be considered an intersection.
  25084. * @return {Array.<ol.WebglPolygonSegment>} Intersecting segments.
  25085. */
  25086. ol.render.webgl.PolygonReplay.prototype.getIntersections_ = function(segment, rtree, opt_touch) {
  25087. var p0 = segment.p0;
  25088. var p1 = segment.p1;
  25089. var segmentsInExtent = rtree.getInExtent([Math.min(p0.x, p1.x),
  25090. Math.min(p0.y, p1.y), Math.max(p0.x, p1.x), Math.max(p0.y, p1.y)]);
  25091. var result = [];
  25092. var i, ii;
  25093. for (i = 0, ii = segmentsInExtent.length; i < ii; ++i) {
  25094. var currSeg = segmentsInExtent[i];
  25095. if (segment !== currSeg && (opt_touch || currSeg.p0 !== p1 || currSeg.p1 !== p0) &&
  25096. this.calculateIntersection_(p0, p1, currSeg.p0, currSeg.p1, opt_touch)) {
  25097. result.push(currSeg);
  25098. }
  25099. }
  25100. return result;
  25101. };
  25102. /**
  25103. * Line intersection algorithm by Paul Bourke.
  25104. * @see http://paulbourke.net/geometry/pointlineplane/
  25105. *
  25106. * @private
  25107. * @param {ol.WebglPolygonVertex} p0 First point.
  25108. * @param {ol.WebglPolygonVertex} p1 Second point.
  25109. * @param {ol.WebglPolygonVertex} p2 Third point.
  25110. * @param {ol.WebglPolygonVertex} p3 Fourth point.
  25111. * @param {boolean=} opt_touch Touching segments should be considered an intersection.
  25112. * @return {Array.<number>|undefined} Intersection coordinates.
  25113. */
  25114. ol.render.webgl.PolygonReplay.prototype.calculateIntersection_ = function(p0,
  25115. p1, p2, p3, opt_touch) {
  25116. var denom = (p3.y - p2.y) * (p1.x - p0.x) - (p3.x - p2.x) * (p1.y - p0.y);
  25117. if (denom !== 0) {
  25118. var ua = ((p3.x - p2.x) * (p0.y - p2.y) - (p3.y - p2.y) * (p0.x - p2.x)) / denom;
  25119. var ub = ((p1.x - p0.x) * (p0.y - p2.y) - (p1.y - p0.y) * (p0.x - p2.x)) / denom;
  25120. if ((!opt_touch && ua > ol.render.webgl.EPSILON && ua < 1 - ol.render.webgl.EPSILON &&
  25121. ub > ol.render.webgl.EPSILON && ub < 1 - ol.render.webgl.EPSILON) || (opt_touch &&
  25122. ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1)) {
  25123. return [p0.x + ua * (p1.x - p0.x), p0.y + ua * (p1.y - p0.y)];
  25124. }
  25125. }
  25126. return undefined;
  25127. };
  25128. /**
  25129. * @private
  25130. * @param {ol.WebglPolygonVertex} p0 Point before the start of the diagonal.
  25131. * @param {ol.WebglPolygonVertex} p1 Start point of the diagonal.
  25132. * @param {ol.WebglPolygonVertex} p2 Ear candidate.
  25133. * @param {ol.WebglPolygonVertex} p3 End point of the diagonal.
  25134. * @param {ol.WebglPolygonVertex} p4 Point after the end of the diagonal.
  25135. * @return {boolean} Diagonal is inside the polygon.
  25136. */
  25137. ol.render.webgl.PolygonReplay.prototype.diagonalIsInside_ = function(p0, p1, p2, p3, p4) {
  25138. if (p1.reflex === undefined || p3.reflex === undefined) {
  25139. return false;
  25140. }
  25141. var p1IsLeftOf = (p2.x - p3.x) * (p1.y - p3.y) > (p2.y - p3.y) * (p1.x - p3.x);
  25142. var p1IsRightOf = (p4.x - p3.x) * (p1.y - p3.y) < (p4.y - p3.y) * (p1.x - p3.x);
  25143. var p3IsLeftOf = (p0.x - p1.x) * (p3.y - p1.y) > (p0.y - p1.y) * (p3.x - p1.x);
  25144. var p3IsRightOf = (p2.x - p1.x) * (p3.y - p1.y) < (p2.y - p1.y) * (p3.x - p1.x);
  25145. var p1InCone = p3.reflex ? p1IsRightOf || p1IsLeftOf : p1IsRightOf && p1IsLeftOf;
  25146. var p3InCone = p1.reflex ? p3IsRightOf || p3IsLeftOf : p3IsRightOf && p3IsLeftOf;
  25147. return p1InCone && p3InCone;
  25148. };
  25149. /**
  25150. * @inheritDoc
  25151. */
  25152. ol.render.webgl.PolygonReplay.prototype.drawMultiPolygon = function(multiPolygonGeometry, feature) {
  25153. var endss = multiPolygonGeometry.getEndss();
  25154. var stride = multiPolygonGeometry.getStride();
  25155. var currIndex = this.indices.length;
  25156. var currLineIndex = this.lineStringReplay.getCurrentIndex();
  25157. var flatCoordinates = multiPolygonGeometry.getFlatCoordinates();
  25158. var i, ii, j, jj;
  25159. var start = 0;
  25160. for (i = 0, ii = endss.length; i < ii; ++i) {
  25161. var ends = endss[i];
  25162. if (ends.length > 0) {
  25163. var outerRing = ol.geom.flat.transform.translate(flatCoordinates, start, ends[0],
  25164. stride, -this.origin[0], -this.origin[1]);
  25165. if (outerRing.length) {
  25166. var holes = [];
  25167. var holeFlatCoords;
  25168. for (j = 1, jj = ends.length; j < jj; ++j) {
  25169. if (ends[j] !== ends[j - 1]) {
  25170. holeFlatCoords = ol.geom.flat.transform.translate(flatCoordinates, ends[j - 1],
  25171. ends[j], stride, -this.origin[0], -this.origin[1]);
  25172. holes.push(holeFlatCoords);
  25173. }
  25174. }
  25175. this.lineStringReplay.drawPolygonCoordinates(outerRing, holes, stride);
  25176. this.drawCoordinates_(outerRing, holes, stride);
  25177. }
  25178. }
  25179. start = ends[ends.length - 1];
  25180. }
  25181. if (this.indices.length > currIndex) {
  25182. this.startIndices.push(currIndex);
  25183. this.startIndicesFeature.push(feature);
  25184. if (this.state_.changed) {
  25185. this.styleIndices_.push(currIndex);
  25186. this.state_.changed = false;
  25187. }
  25188. }
  25189. if (this.lineStringReplay.getCurrentIndex() > currLineIndex) {
  25190. this.lineStringReplay.setPolygonStyle(feature, currLineIndex);
  25191. }
  25192. };
  25193. /**
  25194. * @inheritDoc
  25195. */
  25196. ol.render.webgl.PolygonReplay.prototype.drawPolygon = function(polygonGeometry, feature) {
  25197. var ends = polygonGeometry.getEnds();
  25198. var stride = polygonGeometry.getStride();
  25199. if (ends.length > 0) {
  25200. var flatCoordinates = polygonGeometry.getFlatCoordinates().map(Number);
  25201. var outerRing = ol.geom.flat.transform.translate(flatCoordinates, 0, ends[0],
  25202. stride, -this.origin[0], -this.origin[1]);
  25203. if (outerRing.length) {
  25204. var holes = [];
  25205. var i, ii, holeFlatCoords;
  25206. for (i = 1, ii = ends.length; i < ii; ++i) {
  25207. if (ends[i] !== ends[i - 1]) {
  25208. holeFlatCoords = ol.geom.flat.transform.translate(flatCoordinates, ends[i - 1],
  25209. ends[i], stride, -this.origin[0], -this.origin[1]);
  25210. holes.push(holeFlatCoords);
  25211. }
  25212. }
  25213. this.startIndices.push(this.indices.length);
  25214. this.startIndicesFeature.push(feature);
  25215. if (this.state_.changed) {
  25216. this.styleIndices_.push(this.indices.length);
  25217. this.state_.changed = false;
  25218. }
  25219. this.lineStringReplay.setPolygonStyle(feature);
  25220. this.lineStringReplay.drawPolygonCoordinates(outerRing, holes, stride);
  25221. this.drawCoordinates_(outerRing, holes, stride);
  25222. }
  25223. }
  25224. };
  25225. /**
  25226. * @inheritDoc
  25227. **/
  25228. ol.render.webgl.PolygonReplay.prototype.finish = function(context) {
  25229. // create, bind, and populate the vertices buffer
  25230. this.verticesBuffer = new ol.webgl.Buffer(this.vertices);
  25231. // create, bind, and populate the indices buffer
  25232. this.indicesBuffer = new ol.webgl.Buffer(this.indices);
  25233. this.startIndices.push(this.indices.length);
  25234. this.lineStringReplay.finish(context);
  25235. //Clean up, if there is nothing to draw
  25236. if (this.styleIndices_.length === 0 && this.styles_.length > 0) {
  25237. this.styles_ = [];
  25238. }
  25239. this.vertices = null;
  25240. this.indices = null;
  25241. };
  25242. /**
  25243. * @inheritDoc
  25244. */
  25245. ol.render.webgl.PolygonReplay.prototype.getDeleteResourcesFunction = function(context) {
  25246. var verticesBuffer = this.verticesBuffer;
  25247. var indicesBuffer = this.indicesBuffer;
  25248. var lineDeleter = this.lineStringReplay.getDeleteResourcesFunction(context);
  25249. return function() {
  25250. context.deleteBuffer(verticesBuffer);
  25251. context.deleteBuffer(indicesBuffer);
  25252. lineDeleter();
  25253. };
  25254. };
  25255. /**
  25256. * @inheritDoc
  25257. */
  25258. ol.render.webgl.PolygonReplay.prototype.setUpProgram = function(gl, context, size, pixelRatio) {
  25259. // get the program
  25260. var fragmentShader, vertexShader;
  25261. fragmentShader = ol.render.webgl.polygonreplay.defaultshader.fragment;
  25262. vertexShader = ol.render.webgl.polygonreplay.defaultshader.vertex;
  25263. var program = context.getProgram(fragmentShader, vertexShader);
  25264. // get the locations
  25265. var locations;
  25266. if (!this.defaultLocations_) {
  25267. // eslint-disable-next-line openlayers-internal/no-missing-requires
  25268. locations = new ol.render.webgl.polygonreplay.defaultshader.Locations(gl, program);
  25269. this.defaultLocations_ = locations;
  25270. } else {
  25271. locations = this.defaultLocations_;
  25272. }
  25273. context.useProgram(program);
  25274. // enable the vertex attrib arrays
  25275. gl.enableVertexAttribArray(locations.a_position);
  25276. gl.vertexAttribPointer(locations.a_position, 2, ol.webgl.FLOAT,
  25277. false, 8, 0);
  25278. return locations;
  25279. };
  25280. /**
  25281. * @inheritDoc
  25282. */
  25283. ol.render.webgl.PolygonReplay.prototype.shutDownProgram = function(gl, locations) {
  25284. gl.disableVertexAttribArray(locations.a_position);
  25285. };
  25286. /**
  25287. * @inheritDoc
  25288. */
  25289. ol.render.webgl.PolygonReplay.prototype.drawReplay = function(gl, context, skippedFeaturesHash, hitDetection) {
  25290. //Save GL parameters.
  25291. var tmpDepthFunc = /** @type {number} */ (gl.getParameter(gl.DEPTH_FUNC));
  25292. var tmpDepthMask = /** @type {boolean} */ (gl.getParameter(gl.DEPTH_WRITEMASK));
  25293. if (!hitDetection) {
  25294. gl.enable(gl.DEPTH_TEST);
  25295. gl.depthMask(true);
  25296. gl.depthFunc(gl.NOTEQUAL);
  25297. }
  25298. if (!ol.obj.isEmpty(skippedFeaturesHash)) {
  25299. this.drawReplaySkipping_(gl, context, skippedFeaturesHash);
  25300. } else {
  25301. //Draw by style groups to minimize drawElements() calls.
  25302. var i, start, end, nextStyle;
  25303. end = this.startIndices[this.startIndices.length - 1];
  25304. for (i = this.styleIndices_.length - 1; i >= 0; --i) {
  25305. start = this.styleIndices_[i];
  25306. nextStyle = this.styles_[i];
  25307. this.setFillStyle_(gl, nextStyle);
  25308. this.drawElements(gl, context, start, end);
  25309. end = start;
  25310. }
  25311. }
  25312. if (!hitDetection) {
  25313. gl.disable(gl.DEPTH_TEST);
  25314. gl.clear(gl.DEPTH_BUFFER_BIT);
  25315. //Restore GL parameters.
  25316. gl.depthMask(tmpDepthMask);
  25317. gl.depthFunc(tmpDepthFunc);
  25318. }
  25319. };
  25320. /**
  25321. * @inheritDoc
  25322. */
  25323. ol.render.webgl.PolygonReplay.prototype.drawHitDetectionReplayOneByOne = function(gl, context, skippedFeaturesHash,
  25324. featureCallback, opt_hitExtent) {
  25325. var i, start, end, nextStyle, groupStart, feature, featureUid, featureIndex;
  25326. featureIndex = this.startIndices.length - 2;
  25327. end = this.startIndices[featureIndex + 1];
  25328. for (i = this.styleIndices_.length - 1; i >= 0; --i) {
  25329. nextStyle = this.styles_[i];
  25330. this.setFillStyle_(gl, nextStyle);
  25331. groupStart = this.styleIndices_[i];
  25332. while (featureIndex >= 0 &&
  25333. this.startIndices[featureIndex] >= groupStart) {
  25334. start = this.startIndices[featureIndex];
  25335. feature = this.startIndicesFeature[featureIndex];
  25336. featureUid = ol.getUid(feature).toString();
  25337. if (skippedFeaturesHash[featureUid] === undefined &&
  25338. feature.getGeometry() &&
  25339. (opt_hitExtent === undefined || ol.extent.intersects(
  25340. /** @type {Array<number>} */ (opt_hitExtent),
  25341. feature.getGeometry().getExtent()))) {
  25342. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  25343. this.drawElements(gl, context, start, end);
  25344. var result = featureCallback(feature);
  25345. if (result) {
  25346. return result;
  25347. }
  25348. }
  25349. featureIndex--;
  25350. end = start;
  25351. }
  25352. }
  25353. return undefined;
  25354. };
  25355. /**
  25356. * @private
  25357. * @param {WebGLRenderingContext} gl gl.
  25358. * @param {ol.webgl.Context} context Context.
  25359. * @param {Object} skippedFeaturesHash Ids of features to skip.
  25360. */
  25361. ol.render.webgl.PolygonReplay.prototype.drawReplaySkipping_ = function(gl, context, skippedFeaturesHash) {
  25362. var i, start, end, nextStyle, groupStart, feature, featureUid, featureIndex, featureStart;
  25363. featureIndex = this.startIndices.length - 2;
  25364. end = start = this.startIndices[featureIndex + 1];
  25365. for (i = this.styleIndices_.length - 1; i >= 0; --i) {
  25366. nextStyle = this.styles_[i];
  25367. this.setFillStyle_(gl, nextStyle);
  25368. groupStart = this.styleIndices_[i];
  25369. while (featureIndex >= 0 &&
  25370. this.startIndices[featureIndex] >= groupStart) {
  25371. featureStart = this.startIndices[featureIndex];
  25372. feature = this.startIndicesFeature[featureIndex];
  25373. featureUid = ol.getUid(feature).toString();
  25374. if (skippedFeaturesHash[featureUid]) {
  25375. if (start !== end) {
  25376. this.drawElements(gl, context, start, end);
  25377. gl.clear(gl.DEPTH_BUFFER_BIT);
  25378. }
  25379. end = featureStart;
  25380. }
  25381. featureIndex--;
  25382. start = featureStart;
  25383. }
  25384. if (start !== end) {
  25385. this.drawElements(gl, context, start, end);
  25386. gl.clear(gl.DEPTH_BUFFER_BIT);
  25387. }
  25388. start = end = groupStart;
  25389. }
  25390. };
  25391. /**
  25392. * @private
  25393. * @param {WebGLRenderingContext} gl gl.
  25394. * @param {Array.<number>} color Color.
  25395. */
  25396. ol.render.webgl.PolygonReplay.prototype.setFillStyle_ = function(gl, color) {
  25397. gl.uniform4fv(this.defaultLocations_.u_color, color);
  25398. };
  25399. /**
  25400. * @inheritDoc
  25401. */
  25402. ol.render.webgl.PolygonReplay.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
  25403. var fillStyleColor = fillStyle ? fillStyle.getColor() : [0, 0, 0, 0];
  25404. if (!(fillStyleColor instanceof CanvasGradient) &&
  25405. !(fillStyleColor instanceof CanvasPattern)) {
  25406. fillStyleColor = ol.color.asArray(fillStyleColor).map(function(c, i) {
  25407. return i != 3 ? c / 255 : c;
  25408. }) || ol.render.webgl.defaultFillStyle;
  25409. } else {
  25410. fillStyleColor = ol.render.webgl.defaultFillStyle;
  25411. }
  25412. if (!this.state_.fillColor || !ol.array.equals(fillStyleColor, this.state_.fillColor)) {
  25413. this.state_.fillColor = fillStyleColor;
  25414. this.state_.changed = true;
  25415. this.styles_.push(fillStyleColor);
  25416. }
  25417. //Provide a null stroke style, if no strokeStyle is provided. Required for the draw interaction to work.
  25418. if (strokeStyle) {
  25419. this.lineStringReplay.setFillStrokeStyle(null, strokeStyle);
  25420. } else {
  25421. var nullStrokeStyle = new ol.style.Stroke({
  25422. color: [0, 0, 0, 0],
  25423. lineWidth: 0
  25424. });
  25425. this.lineStringReplay.setFillStrokeStyle(null, nullStrokeStyle);
  25426. }
  25427. };
  25428. }
  25429. goog.provide('ol.style.Atlas');
  25430. goog.require('ol.dom');
  25431. /**
  25432. * This class facilitates the creation of image atlases.
  25433. *
  25434. * Images added to an atlas will be rendered onto a single
  25435. * atlas canvas. The distribution of images on the canvas is
  25436. * managed with the bin packing algorithm described in:
  25437. * http://www.blackpawn.com/texts/lightmaps/
  25438. *
  25439. * @constructor
  25440. * @struct
  25441. * @param {number} size The size in pixels of the sprite image.
  25442. * @param {number} space The space in pixels between images.
  25443. * Because texture coordinates are float values, the edges of
  25444. * images might not be completely correct (in a way that the
  25445. * edges overlap when being rendered). To avoid this we add a
  25446. * padding around each image.
  25447. */
  25448. ol.style.Atlas = function(size, space) {
  25449. /**
  25450. * @private
  25451. * @type {number}
  25452. */
  25453. this.space_ = space;
  25454. /**
  25455. * @private
  25456. * @type {Array.<ol.AtlasBlock>}
  25457. */
  25458. this.emptyBlocks_ = [{x: 0, y: 0, width: size, height: size}];
  25459. /**
  25460. * @private
  25461. * @type {Object.<string, ol.AtlasInfo>}
  25462. */
  25463. this.entries_ = {};
  25464. /**
  25465. * @private
  25466. * @type {CanvasRenderingContext2D}
  25467. */
  25468. this.context_ = ol.dom.createCanvasContext2D(size, size);
  25469. /**
  25470. * @private
  25471. * @type {HTMLCanvasElement}
  25472. */
  25473. this.canvas_ = this.context_.canvas;
  25474. };
  25475. /**
  25476. * @param {string} id The identifier of the entry to check.
  25477. * @return {?ol.AtlasInfo} The atlas info.
  25478. */
  25479. ol.style.Atlas.prototype.get = function(id) {
  25480. return this.entries_[id] || null;
  25481. };
  25482. /**
  25483. * @param {string} id The identifier of the entry to add.
  25484. * @param {number} width The width.
  25485. * @param {number} height The height.
  25486. * @param {function(CanvasRenderingContext2D, number, number)} renderCallback
  25487. * Called to render the new image onto an atlas image.
  25488. * @param {Object=} opt_this Value to use as `this` when executing
  25489. * `renderCallback`.
  25490. * @return {?ol.AtlasInfo} The position and atlas image for the entry.
  25491. */
  25492. ol.style.Atlas.prototype.add = function(id, width, height, renderCallback, opt_this) {
  25493. var block, i, ii;
  25494. for (i = 0, ii = this.emptyBlocks_.length; i < ii; ++i) {
  25495. block = this.emptyBlocks_[i];
  25496. if (block.width >= width + this.space_ &&
  25497. block.height >= height + this.space_) {
  25498. // we found a block that is big enough for our entry
  25499. var entry = {
  25500. offsetX: block.x + this.space_,
  25501. offsetY: block.y + this.space_,
  25502. image: this.canvas_
  25503. };
  25504. this.entries_[id] = entry;
  25505. // render the image on the atlas image
  25506. renderCallback.call(opt_this, this.context_,
  25507. block.x + this.space_, block.y + this.space_);
  25508. // split the block after the insertion, either horizontally or vertically
  25509. this.split_(i, block, width + this.space_, height + this.space_);
  25510. return entry;
  25511. }
  25512. }
  25513. // there is no space for the new entry in this atlas
  25514. return null;
  25515. };
  25516. /**
  25517. * @private
  25518. * @param {number} index The index of the block.
  25519. * @param {ol.AtlasBlock} block The block to split.
  25520. * @param {number} width The width of the entry to insert.
  25521. * @param {number} height The height of the entry to insert.
  25522. */
  25523. ol.style.Atlas.prototype.split_ = function(index, block, width, height) {
  25524. var deltaWidth = block.width - width;
  25525. var deltaHeight = block.height - height;
  25526. /** @type {ol.AtlasBlock} */
  25527. var newBlock1;
  25528. /** @type {ol.AtlasBlock} */
  25529. var newBlock2;
  25530. if (deltaWidth > deltaHeight) {
  25531. // split vertically
  25532. // block right of the inserted entry
  25533. newBlock1 = {
  25534. x: block.x + width,
  25535. y: block.y,
  25536. width: block.width - width,
  25537. height: block.height
  25538. };
  25539. // block below the inserted entry
  25540. newBlock2 = {
  25541. x: block.x,
  25542. y: block.y + height,
  25543. width: width,
  25544. height: block.height - height
  25545. };
  25546. this.updateBlocks_(index, newBlock1, newBlock2);
  25547. } else {
  25548. // split horizontally
  25549. // block right of the inserted entry
  25550. newBlock1 = {
  25551. x: block.x + width,
  25552. y: block.y,
  25553. width: block.width - width,
  25554. height: height
  25555. };
  25556. // block below the inserted entry
  25557. newBlock2 = {
  25558. x: block.x,
  25559. y: block.y + height,
  25560. width: block.width,
  25561. height: block.height - height
  25562. };
  25563. this.updateBlocks_(index, newBlock1, newBlock2);
  25564. }
  25565. };
  25566. /**
  25567. * Remove the old block and insert new blocks at the same array position.
  25568. * The new blocks are inserted at the same position, so that splitted
  25569. * blocks (that are potentially smaller) are filled first.
  25570. * @private
  25571. * @param {number} index The index of the block to remove.
  25572. * @param {ol.AtlasBlock} newBlock1 The 1st block to add.
  25573. * @param {ol.AtlasBlock} newBlock2 The 2nd block to add.
  25574. */
  25575. ol.style.Atlas.prototype.updateBlocks_ = function(index, newBlock1, newBlock2) {
  25576. var args = [index, 1];
  25577. if (newBlock1.width > 0 && newBlock1.height > 0) {
  25578. args.push(newBlock1);
  25579. }
  25580. if (newBlock2.width > 0 && newBlock2.height > 0) {
  25581. args.push(newBlock2);
  25582. }
  25583. this.emptyBlocks_.splice.apply(this.emptyBlocks_, args);
  25584. };
  25585. goog.provide('ol.style.AtlasManager');
  25586. goog.require('ol');
  25587. goog.require('ol.style.Atlas');
  25588. /**
  25589. * Manages the creation of image atlases.
  25590. *
  25591. * Images added to this manager will be inserted into an atlas, which
  25592. * will be used for rendering.
  25593. * The `size` given in the constructor is the size for the first
  25594. * atlas. After that, when new atlases are created, they will have
  25595. * twice the size as the latest atlas (until `maxSize` is reached).
  25596. *
  25597. * If an application uses many images or very large images, it is recommended
  25598. * to set a higher `size` value to avoid the creation of too many atlases.
  25599. *
  25600. * @constructor
  25601. * @struct
  25602. * @api
  25603. * @param {olx.style.AtlasManagerOptions=} opt_options Options.
  25604. */
  25605. ol.style.AtlasManager = function(opt_options) {
  25606. var options = opt_options || {};
  25607. /**
  25608. * The size in pixels of the latest atlas image.
  25609. * @private
  25610. * @type {number}
  25611. */
  25612. this.currentSize_ = options.initialSize !== undefined ?
  25613. options.initialSize : ol.INITIAL_ATLAS_SIZE;
  25614. /**
  25615. * The maximum size in pixels of atlas images.
  25616. * @private
  25617. * @type {number}
  25618. */
  25619. this.maxSize_ = options.maxSize !== undefined ?
  25620. options.maxSize : ol.MAX_ATLAS_SIZE != -1 ?
  25621. ol.MAX_ATLAS_SIZE : ol.WEBGL_MAX_TEXTURE_SIZE !== undefined ?
  25622. ol.WEBGL_MAX_TEXTURE_SIZE : 2048;
  25623. /**
  25624. * The size in pixels between images.
  25625. * @private
  25626. * @type {number}
  25627. */
  25628. this.space_ = options.space !== undefined ? options.space : 1;
  25629. /**
  25630. * @private
  25631. * @type {Array.<ol.style.Atlas>}
  25632. */
  25633. this.atlases_ = [new ol.style.Atlas(this.currentSize_, this.space_)];
  25634. /**
  25635. * The size in pixels of the latest atlas image for hit-detection images.
  25636. * @private
  25637. * @type {number}
  25638. */
  25639. this.currentHitSize_ = this.currentSize_;
  25640. /**
  25641. * @private
  25642. * @type {Array.<ol.style.Atlas>}
  25643. */
  25644. this.hitAtlases_ = [new ol.style.Atlas(this.currentHitSize_, this.space_)];
  25645. };
  25646. /**
  25647. * @param {string} id The identifier of the entry to check.
  25648. * @return {?ol.AtlasManagerInfo} The position and atlas image for the
  25649. * entry, or `null` if the entry is not part of the atlas manager.
  25650. */
  25651. ol.style.AtlasManager.prototype.getInfo = function(id) {
  25652. /** @type {?ol.AtlasInfo} */
  25653. var info = this.getInfo_(this.atlases_, id);
  25654. if (!info) {
  25655. return null;
  25656. }
  25657. var hitInfo = /** @type {ol.AtlasInfo} */ (this.getInfo_(this.hitAtlases_, id));
  25658. return this.mergeInfos_(info, hitInfo);
  25659. };
  25660. /**
  25661. * @private
  25662. * @param {Array.<ol.style.Atlas>} atlases The atlases to search.
  25663. * @param {string} id The identifier of the entry to check.
  25664. * @return {?ol.AtlasInfo} The position and atlas image for the entry,
  25665. * or `null` if the entry is not part of the atlases.
  25666. */
  25667. ol.style.AtlasManager.prototype.getInfo_ = function(atlases, id) {
  25668. var atlas, info, i, ii;
  25669. for (i = 0, ii = atlases.length; i < ii; ++i) {
  25670. atlas = atlases[i];
  25671. info = atlas.get(id);
  25672. if (info) {
  25673. return info;
  25674. }
  25675. }
  25676. return null;
  25677. };
  25678. /**
  25679. * @private
  25680. * @param {ol.AtlasInfo} info The info for the real image.
  25681. * @param {ol.AtlasInfo} hitInfo The info for the hit-detection
  25682. * image.
  25683. * @return {?ol.AtlasManagerInfo} The position and atlas image for the
  25684. * entry, or `null` if the entry is not part of the atlases.
  25685. */
  25686. ol.style.AtlasManager.prototype.mergeInfos_ = function(info, hitInfo) {
  25687. return /** @type {ol.AtlasManagerInfo} */ ({
  25688. offsetX: info.offsetX,
  25689. offsetY: info.offsetY,
  25690. image: info.image,
  25691. hitImage: hitInfo.image
  25692. });
  25693. };
  25694. /**
  25695. * Add an image to the atlas manager.
  25696. *
  25697. * If an entry for the given id already exists, the entry will
  25698. * be overridden (but the space on the atlas graphic will not be freed).
  25699. *
  25700. * If `renderHitCallback` is provided, the image (or the hit-detection version
  25701. * of the image) will be rendered into a separate hit-detection atlas image.
  25702. *
  25703. * @param {string} id The identifier of the entry to add.
  25704. * @param {number} width The width.
  25705. * @param {number} height The height.
  25706. * @param {function(CanvasRenderingContext2D, number, number)} renderCallback
  25707. * Called to render the new image onto an atlas image.
  25708. * @param {function(CanvasRenderingContext2D, number, number)=}
  25709. * opt_renderHitCallback Called to render a hit-detection image onto a hit
  25710. * detection atlas image.
  25711. * @param {Object=} opt_this Value to use as `this` when executing
  25712. * `renderCallback` and `renderHitCallback`.
  25713. * @return {?ol.AtlasManagerInfo} The position and atlas image for the
  25714. * entry, or `null` if the image is too big.
  25715. */
  25716. ol.style.AtlasManager.prototype.add = function(id, width, height,
  25717. renderCallback, opt_renderHitCallback, opt_this) {
  25718. if (width + this.space_ > this.maxSize_ ||
  25719. height + this.space_ > this.maxSize_) {
  25720. return null;
  25721. }
  25722. /** @type {?ol.AtlasInfo} */
  25723. var info = this.add_(false,
  25724. id, width, height, renderCallback, opt_this);
  25725. if (!info) {
  25726. return null;
  25727. }
  25728. // even if no hit-detection entry is requested, we insert a fake entry into
  25729. // the hit-detection atlas, to make sure that the offset is the same for
  25730. // the original image and the hit-detection image.
  25731. var renderHitCallback = opt_renderHitCallback !== undefined ?
  25732. opt_renderHitCallback : ol.nullFunction;
  25733. var hitInfo = /** @type {ol.AtlasInfo} */ (this.add_(true,
  25734. id, width, height, renderHitCallback, opt_this));
  25735. return this.mergeInfos_(info, hitInfo);
  25736. };
  25737. /**
  25738. * @private
  25739. * @param {boolean} isHitAtlas If the hit-detection atlases are used.
  25740. * @param {string} id The identifier of the entry to add.
  25741. * @param {number} width The width.
  25742. * @param {number} height The height.
  25743. * @param {function(CanvasRenderingContext2D, number, number)} renderCallback
  25744. * Called to render the new image onto an atlas image.
  25745. * @param {Object=} opt_this Value to use as `this` when executing
  25746. * `renderCallback` and `renderHitCallback`.
  25747. * @return {?ol.AtlasInfo} The position and atlas image for the entry,
  25748. * or `null` if the image is too big.
  25749. */
  25750. ol.style.AtlasManager.prototype.add_ = function(isHitAtlas, id, width, height,
  25751. renderCallback, opt_this) {
  25752. var atlases = (isHitAtlas) ? this.hitAtlases_ : this.atlases_;
  25753. var atlas, info, i, ii;
  25754. for (i = 0, ii = atlases.length; i < ii; ++i) {
  25755. atlas = atlases[i];
  25756. info = atlas.add(id, width, height, renderCallback, opt_this);
  25757. if (info) {
  25758. return info;
  25759. } else if (!info && i === ii - 1) {
  25760. // the entry could not be added to one of the existing atlases,
  25761. // create a new atlas that is twice as big and try to add to this one.
  25762. var size;
  25763. if (isHitAtlas) {
  25764. size = Math.min(this.currentHitSize_ * 2, this.maxSize_);
  25765. this.currentHitSize_ = size;
  25766. } else {
  25767. size = Math.min(this.currentSize_ * 2, this.maxSize_);
  25768. this.currentSize_ = size;
  25769. }
  25770. atlas = new ol.style.Atlas(size, this.space_);
  25771. atlases.push(atlas);
  25772. // run the loop another time
  25773. ++ii;
  25774. }
  25775. }
  25776. return null;
  25777. };
  25778. goog.provide('ol.render.webgl.TextReplay');
  25779. goog.require('ol');
  25780. goog.require('ol.colorlike');
  25781. goog.require('ol.dom');
  25782. goog.require('ol.has');
  25783. goog.require('ol.render.webgl');
  25784. goog.require('ol.render.webgl.TextureReplay');
  25785. goog.require('ol.style.AtlasManager');
  25786. goog.require('ol.webgl.Buffer');
  25787. if (ol.ENABLE_WEBGL) {
  25788. /**
  25789. * @constructor
  25790. * @extends {ol.render.webgl.TextureReplay}
  25791. * @param {number} tolerance Tolerance.
  25792. * @param {ol.Extent} maxExtent Max extent.
  25793. * @struct
  25794. */
  25795. ol.render.webgl.TextReplay = function(tolerance, maxExtent) {
  25796. ol.render.webgl.TextureReplay.call(this, tolerance, maxExtent);
  25797. /**
  25798. * @private
  25799. * @type {Array.<HTMLCanvasElement>}
  25800. */
  25801. this.images_ = [];
  25802. /**
  25803. * @private
  25804. * @type {Array.<WebGLTexture>}
  25805. */
  25806. this.textures_ = [];
  25807. /**
  25808. * @private
  25809. * @type {HTMLCanvasElement}
  25810. */
  25811. this.measureCanvas_ = ol.dom.createCanvasContext2D(0, 0).canvas;
  25812. /**
  25813. * @private
  25814. * @type {{strokeColor: (ol.ColorLike|null),
  25815. * lineCap: (string|undefined),
  25816. * lineDash: Array.<number>,
  25817. * lineDashOffset: (number|undefined),
  25818. * lineJoin: (string|undefined),
  25819. * lineWidth: number,
  25820. * miterLimit: (number|undefined),
  25821. * fillColor: (ol.ColorLike|null),
  25822. * font: (string|undefined),
  25823. * scale: (number|undefined)}}
  25824. */
  25825. this.state_ = {
  25826. strokeColor: null,
  25827. lineCap: undefined,
  25828. lineDash: null,
  25829. lineDashOffset: undefined,
  25830. lineJoin: undefined,
  25831. lineWidth: 0,
  25832. miterLimit: undefined,
  25833. fillColor: null,
  25834. font: undefined,
  25835. scale: undefined
  25836. };
  25837. /**
  25838. * @private
  25839. * @type {string}
  25840. */
  25841. this.text_ = '';
  25842. /**
  25843. * @private
  25844. * @type {number|undefined}
  25845. */
  25846. this.textAlign_ = undefined;
  25847. /**
  25848. * @private
  25849. * @type {number|undefined}
  25850. */
  25851. this.textBaseline_ = undefined;
  25852. /**
  25853. * @private
  25854. * @type {number|undefined}
  25855. */
  25856. this.offsetX_ = undefined;
  25857. /**
  25858. * @private
  25859. * @type {number|undefined}
  25860. */
  25861. this.offsetY_ = undefined;
  25862. /**
  25863. * @private
  25864. * @type {Object.<string, ol.WebglGlyphAtlas>}
  25865. */
  25866. this.atlases_ = {};
  25867. /**
  25868. * @private
  25869. * @type {ol.WebglGlyphAtlas|undefined}
  25870. */
  25871. this.currAtlas_ = undefined;
  25872. this.scale = 1;
  25873. this.opacity = 1;
  25874. };
  25875. ol.inherits(ol.render.webgl.TextReplay, ol.render.webgl.TextureReplay);
  25876. /**
  25877. * @inheritDoc
  25878. */
  25879. ol.render.webgl.TextReplay.prototype.drawText = function(flatCoordinates, offset,
  25880. end, stride, geometry, feature) {
  25881. if (this.text_) {
  25882. this.startIndices.push(this.indices.length);
  25883. this.startIndicesFeature.push(feature);
  25884. var glyphAtlas = this.currAtlas_;
  25885. var lines = this.text_.split('\n');
  25886. var textSize = this.getTextSize_(lines);
  25887. var i, ii, j, jj, currX, currY, charArr, charInfo;
  25888. var anchorX = Math.round(textSize[0] * this.textAlign_ - this.offsetX_);
  25889. var anchorY = Math.round(textSize[1] * this.textBaseline_ - this.offsetY_);
  25890. var lineWidth = (this.state_.lineWidth / 2) * this.state_.scale;
  25891. for (i = 0, ii = lines.length; i < ii; ++i) {
  25892. currX = 0;
  25893. currY = glyphAtlas.height * i;
  25894. charArr = lines[i].split('');
  25895. for (j = 0, jj = charArr.length; j < jj; ++j) {
  25896. charInfo = glyphAtlas.atlas.getInfo(charArr[j]);
  25897. if (charInfo) {
  25898. var image = charInfo.image;
  25899. this.anchorX = anchorX - currX;
  25900. this.anchorY = anchorY - currY;
  25901. this.originX = j === 0 ? charInfo.offsetX - lineWidth : charInfo.offsetX;
  25902. this.originY = charInfo.offsetY;
  25903. this.height = glyphAtlas.height;
  25904. this.width = j === 0 || j === charArr.length - 1 ?
  25905. glyphAtlas.width[charArr[j]] + lineWidth : glyphAtlas.width[charArr[j]];
  25906. this.imageHeight = image.height;
  25907. this.imageWidth = image.width;
  25908. var currentImage;
  25909. if (this.images_.length === 0) {
  25910. this.images_.push(image);
  25911. } else {
  25912. currentImage = this.images_[this.images_.length - 1];
  25913. if (ol.getUid(currentImage) != ol.getUid(image)) {
  25914. this.groupIndices.push(this.indices.length);
  25915. this.images_.push(image);
  25916. }
  25917. }
  25918. this.drawText_(flatCoordinates, offset, end, stride);
  25919. }
  25920. currX += this.width;
  25921. }
  25922. }
  25923. }
  25924. };
  25925. /**
  25926. * @private
  25927. * @param {Array.<string>} lines Label to draw split to lines.
  25928. * @return {Array.<number>} Size of the label in pixels.
  25929. */
  25930. ol.render.webgl.TextReplay.prototype.getTextSize_ = function(lines) {
  25931. var self = this;
  25932. var glyphAtlas = this.currAtlas_;
  25933. var textHeight = lines.length * glyphAtlas.height;
  25934. //Split every line to an array of chars, sum up their width, and select the longest.
  25935. var textWidth = lines.map(function(str) {
  25936. var sum = 0;
  25937. var i, ii;
  25938. for (i = 0, ii = str.length; i < ii; ++i) {
  25939. var curr = str[i];
  25940. if (!glyphAtlas.width[curr]) {
  25941. self.addCharToAtlas_(curr);
  25942. }
  25943. sum += glyphAtlas.width[curr] ? glyphAtlas.width[curr] : 0;
  25944. }
  25945. return sum;
  25946. }).reduce(function(max, curr) {
  25947. return Math.max(max, curr);
  25948. });
  25949. return [textWidth, textHeight];
  25950. };
  25951. /**
  25952. * @private
  25953. * @param {Array.<number>} flatCoordinates Flat coordinates.
  25954. * @param {number} offset Offset.
  25955. * @param {number} end End.
  25956. * @param {number} stride Stride.
  25957. */
  25958. ol.render.webgl.TextReplay.prototype.drawText_ = function(flatCoordinates, offset,
  25959. end, stride) {
  25960. var i, ii;
  25961. for (i = offset, ii = end; i < ii; i += stride) {
  25962. this.drawCoordinates(flatCoordinates, offset, end, stride);
  25963. }
  25964. };
  25965. /**
  25966. * @private
  25967. * @param {string} char Character.
  25968. */
  25969. ol.render.webgl.TextReplay.prototype.addCharToAtlas_ = function(char) {
  25970. if (char.length === 1) {
  25971. var glyphAtlas = this.currAtlas_;
  25972. var state = this.state_;
  25973. var mCtx = this.measureCanvas_.getContext('2d');
  25974. mCtx.font = state.font;
  25975. var width = Math.ceil(mCtx.measureText(char).width * state.scale);
  25976. var info = glyphAtlas.atlas.add(char, width, glyphAtlas.height,
  25977. function(ctx, x, y) {
  25978. //Parameterize the canvas
  25979. ctx.font = /** @type {string} */ (state.font);
  25980. ctx.fillStyle = state.fillColor;
  25981. ctx.strokeStyle = state.strokeColor;
  25982. ctx.lineWidth = state.lineWidth;
  25983. ctx.lineCap = /*** @type {string} */ (state.lineCap);
  25984. ctx.lineJoin = /** @type {string} */ (state.lineJoin);
  25985. ctx.miterLimit = /** @type {number} */ (state.miterLimit);
  25986. ctx.textAlign = 'left';
  25987. ctx.textBaseline = 'top';
  25988. if (ol.has.CANVAS_LINE_DASH && state.lineDash) {
  25989. //FIXME: use pixelRatio
  25990. ctx.setLineDash(state.lineDash);
  25991. ctx.lineDashOffset = /** @type {number} */ (state.lineDashOffset);
  25992. }
  25993. if (state.scale !== 1) {
  25994. //FIXME: use pixelRatio
  25995. ctx.setTransform(/** @type {number} */ (state.scale), 0, 0,
  25996. /** @type {number} */ (state.scale), 0, 0);
  25997. }
  25998. //Draw the character on the canvas
  25999. if (state.strokeColor) {
  26000. ctx.strokeText(char, x, y);
  26001. }
  26002. if (state.fillColor) {
  26003. ctx.fillText(char, x, y);
  26004. }
  26005. });
  26006. if (info) {
  26007. glyphAtlas.width[char] = width;
  26008. }
  26009. }
  26010. };
  26011. /**
  26012. * @inheritDoc
  26013. */
  26014. ol.render.webgl.TextReplay.prototype.finish = function(context) {
  26015. var gl = context.getGL();
  26016. this.groupIndices.push(this.indices.length);
  26017. this.hitDetectionGroupIndices = this.groupIndices;
  26018. // create, bind, and populate the vertices buffer
  26019. this.verticesBuffer = new ol.webgl.Buffer(this.vertices);
  26020. // create, bind, and populate the indices buffer
  26021. this.indicesBuffer = new ol.webgl.Buffer(this.indices);
  26022. // create textures
  26023. /** @type {Object.<string, WebGLTexture>} */
  26024. var texturePerImage = {};
  26025. this.createTextures(this.textures_, this.images_, texturePerImage, gl);
  26026. this.state_ = {
  26027. strokeColor: null,
  26028. lineCap: undefined,
  26029. lineDash: null,
  26030. lineDashOffset: undefined,
  26031. lineJoin: undefined,
  26032. lineWidth: 0,
  26033. miterLimit: undefined,
  26034. fillColor: null,
  26035. font: undefined,
  26036. scale: undefined
  26037. };
  26038. this.text_ = '';
  26039. this.textAlign_ = undefined;
  26040. this.textBaseline_ = undefined;
  26041. this.offsetX_ = undefined;
  26042. this.offsetY_ = undefined;
  26043. this.images_ = null;
  26044. this.atlases_ = {};
  26045. this.currAtlas_ = undefined;
  26046. ol.render.webgl.TextureReplay.prototype.finish.call(this, context);
  26047. };
  26048. /**
  26049. * @inheritDoc
  26050. */
  26051. ol.render.webgl.TextReplay.prototype.setTextStyle = function(textStyle) {
  26052. var state = this.state_;
  26053. var textFillStyle = textStyle.getFill();
  26054. var textStrokeStyle = textStyle.getStroke();
  26055. if (!textStyle || !textStyle.getText() || (!textFillStyle && !textStrokeStyle)) {
  26056. this.text_ = '';
  26057. } else {
  26058. if (!textFillStyle) {
  26059. state.fillColor = null;
  26060. } else {
  26061. var textFillStyleColor = textFillStyle.getColor();
  26062. state.fillColor = ol.colorlike.asColorLike(textFillStyleColor ?
  26063. textFillStyleColor : ol.render.webgl.defaultFillStyle);
  26064. }
  26065. if (!textStrokeStyle) {
  26066. state.strokeColor = null;
  26067. state.lineWidth = 0;
  26068. } else {
  26069. var textStrokeStyleColor = textStrokeStyle.getColor();
  26070. state.strokeColor = ol.colorlike.asColorLike(textStrokeStyleColor ?
  26071. textStrokeStyleColor : ol.render.webgl.defaultStrokeStyle);
  26072. state.lineWidth = textStrokeStyle.getWidth() || ol.render.webgl.defaultLineWidth;
  26073. state.lineCap = textStrokeStyle.getLineCap() || ol.render.webgl.defaultLineCap;
  26074. state.lineDashOffset = textStrokeStyle.getLineDashOffset() || ol.render.webgl.defaultLineDashOffset;
  26075. state.lineJoin = textStrokeStyle.getLineJoin() || ol.render.webgl.defaultLineJoin;
  26076. state.miterLimit = textStrokeStyle.getMiterLimit() || ol.render.webgl.defaultMiterLimit;
  26077. var lineDash = textStrokeStyle.getLineDash();
  26078. state.lineDash = lineDash ? lineDash.slice() : ol.render.webgl.defaultLineDash;
  26079. }
  26080. state.font = textStyle.getFont() || ol.render.webgl.defaultFont;
  26081. state.scale = textStyle.getScale() || 1;
  26082. this.text_ = /** @type {string} */ (textStyle.getText());
  26083. var textAlign = ol.render.webgl.TextReplay.Align_[textStyle.getTextAlign()];
  26084. var textBaseline = ol.render.webgl.TextReplay.Align_[textStyle.getTextBaseline()];
  26085. this.textAlign_ = textAlign === undefined ?
  26086. ol.render.webgl.defaultTextAlign : textAlign;
  26087. this.textBaseline_ = textBaseline === undefined ?
  26088. ol.render.webgl.defaultTextBaseline : textBaseline;
  26089. this.offsetX_ = textStyle.getOffsetX() || 0;
  26090. this.offsetY_ = textStyle.getOffsetY() || 0;
  26091. this.rotateWithView = !!textStyle.getRotateWithView();
  26092. this.rotation = textStyle.getRotation() || 0;
  26093. this.currAtlas_ = this.getAtlas_(state);
  26094. }
  26095. };
  26096. /**
  26097. * @private
  26098. * @param {Object} state Font attributes.
  26099. * @return {ol.WebglGlyphAtlas} Glyph atlas.
  26100. */
  26101. ol.render.webgl.TextReplay.prototype.getAtlas_ = function(state) {
  26102. var params = [];
  26103. var i;
  26104. for (i in state) {
  26105. if (state[i] || state[i] === 0) {
  26106. if (Array.isArray(state[i])) {
  26107. params = params.concat(state[i]);
  26108. } else {
  26109. params.push(state[i]);
  26110. }
  26111. }
  26112. }
  26113. var hash = this.calculateHash_(params);
  26114. if (!this.atlases_[hash]) {
  26115. var mCtx = this.measureCanvas_.getContext('2d');
  26116. mCtx.font = state.font;
  26117. var height = Math.ceil((mCtx.measureText('M').width * 1.5 +
  26118. state.lineWidth / 2) * state.scale);
  26119. this.atlases_[hash] = {
  26120. atlas: new ol.style.AtlasManager({
  26121. space: state.lineWidth + 1
  26122. }),
  26123. width: {},
  26124. height: height
  26125. };
  26126. }
  26127. return this.atlases_[hash];
  26128. };
  26129. /**
  26130. * @private
  26131. * @param {Array.<string|number>} params Array of parameters.
  26132. * @return {string} Hash string.
  26133. */
  26134. ol.render.webgl.TextReplay.prototype.calculateHash_ = function(params) {
  26135. //TODO: Create a more performant, reliable, general hash function.
  26136. var i, ii;
  26137. var hash = '';
  26138. for (i = 0, ii = params.length; i < ii; ++i) {
  26139. hash += params[i];
  26140. }
  26141. return hash;
  26142. };
  26143. /**
  26144. * @inheritDoc
  26145. */
  26146. ol.render.webgl.TextReplay.prototype.getTextures = function(opt_all) {
  26147. return this.textures_;
  26148. };
  26149. /**
  26150. * @inheritDoc
  26151. */
  26152. ol.render.webgl.TextReplay.prototype.getHitDetectionTextures = function() {
  26153. return this.textures_;
  26154. };
  26155. /**
  26156. * @enum {number}
  26157. * @private
  26158. */
  26159. ol.render.webgl.TextReplay.Align_ = {
  26160. left: 0,
  26161. end: 0,
  26162. center: 0.5,
  26163. right: 1,
  26164. start: 1,
  26165. top: 0,
  26166. middle: 0.5,
  26167. hanging: 0.2,
  26168. alphabetic: 0.8,
  26169. ideographic: 0.8,
  26170. bottom: 1
  26171. };
  26172. }
  26173. goog.provide('ol.render.webgl.ReplayGroup');
  26174. goog.require('ol');
  26175. goog.require('ol.array');
  26176. goog.require('ol.extent');
  26177. goog.require('ol.obj');
  26178. goog.require('ol.render.replay');
  26179. goog.require('ol.render.ReplayGroup');
  26180. goog.require('ol.render.webgl.CircleReplay');
  26181. goog.require('ol.render.webgl.ImageReplay');
  26182. goog.require('ol.render.webgl.LineStringReplay');
  26183. goog.require('ol.render.webgl.PolygonReplay');
  26184. goog.require('ol.render.webgl.TextReplay');
  26185. if (ol.ENABLE_WEBGL) {
  26186. /**
  26187. * @constructor
  26188. * @extends {ol.render.ReplayGroup}
  26189. * @param {number} tolerance Tolerance.
  26190. * @param {ol.Extent} maxExtent Max extent.
  26191. * @param {number=} opt_renderBuffer Render buffer.
  26192. * @struct
  26193. */
  26194. ol.render.webgl.ReplayGroup = function(tolerance, maxExtent, opt_renderBuffer) {
  26195. ol.render.ReplayGroup.call(this);
  26196. /**
  26197. * @type {ol.Extent}
  26198. * @private
  26199. */
  26200. this.maxExtent_ = maxExtent;
  26201. /**
  26202. * @type {number}
  26203. * @private
  26204. */
  26205. this.tolerance_ = tolerance;
  26206. /**
  26207. * @type {number|undefined}
  26208. * @private
  26209. */
  26210. this.renderBuffer_ = opt_renderBuffer;
  26211. /**
  26212. * @private
  26213. * @type {!Object.<string,
  26214. * Object.<ol.render.ReplayType, ol.render.webgl.Replay>>}
  26215. */
  26216. this.replaysByZIndex_ = {};
  26217. };
  26218. ol.inherits(ol.render.webgl.ReplayGroup, ol.render.ReplayGroup);
  26219. /**
  26220. * @param {ol.webgl.Context} context WebGL context.
  26221. * @return {function()} Delete resources function.
  26222. */
  26223. ol.render.webgl.ReplayGroup.prototype.getDeleteResourcesFunction = function(context) {
  26224. var functions = [];
  26225. var zKey;
  26226. for (zKey in this.replaysByZIndex_) {
  26227. var replays = this.replaysByZIndex_[zKey];
  26228. var replayKey;
  26229. for (replayKey in replays) {
  26230. functions.push(
  26231. replays[replayKey].getDeleteResourcesFunction(context));
  26232. }
  26233. }
  26234. return function() {
  26235. var length = functions.length;
  26236. var result;
  26237. for (var i = 0; i < length; i++) {
  26238. result = functions[i].apply(this, arguments);
  26239. }
  26240. return result;
  26241. };
  26242. };
  26243. /**
  26244. * @param {ol.webgl.Context} context Context.
  26245. */
  26246. ol.render.webgl.ReplayGroup.prototype.finish = function(context) {
  26247. var zKey;
  26248. for (zKey in this.replaysByZIndex_) {
  26249. var replays = this.replaysByZIndex_[zKey];
  26250. var replayKey;
  26251. for (replayKey in replays) {
  26252. replays[replayKey].finish(context);
  26253. }
  26254. }
  26255. };
  26256. /**
  26257. * @inheritDoc
  26258. */
  26259. ol.render.webgl.ReplayGroup.prototype.getReplay = function(zIndex, replayType) {
  26260. var zIndexKey = zIndex !== undefined ? zIndex.toString() : '0';
  26261. var replays = this.replaysByZIndex_[zIndexKey];
  26262. if (replays === undefined) {
  26263. replays = {};
  26264. this.replaysByZIndex_[zIndexKey] = replays;
  26265. }
  26266. var replay = replays[replayType];
  26267. if (replay === undefined) {
  26268. /**
  26269. * @type {Function}
  26270. */
  26271. var Constructor = ol.render.webgl.ReplayGroup.BATCH_CONSTRUCTORS_[replayType];
  26272. replay = new Constructor(this.tolerance_, this.maxExtent_);
  26273. replays[replayType] = replay;
  26274. }
  26275. return replay;
  26276. };
  26277. /**
  26278. * @inheritDoc
  26279. */
  26280. ol.render.webgl.ReplayGroup.prototype.isEmpty = function() {
  26281. return ol.obj.isEmpty(this.replaysByZIndex_);
  26282. };
  26283. /**
  26284. * @param {ol.webgl.Context} context Context.
  26285. * @param {ol.Coordinate} center Center.
  26286. * @param {number} resolution Resolution.
  26287. * @param {number} rotation Rotation.
  26288. * @param {ol.Size} size Size.
  26289. * @param {number} pixelRatio Pixel ratio.
  26290. * @param {number} opacity Global opacity.
  26291. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  26292. * to skip.
  26293. */
  26294. ol.render.webgl.ReplayGroup.prototype.replay = function(context,
  26295. center, resolution, rotation, size, pixelRatio,
  26296. opacity, skippedFeaturesHash) {
  26297. /** @type {Array.<number>} */
  26298. var zs = Object.keys(this.replaysByZIndex_).map(Number);
  26299. zs.sort(ol.array.numberSafeCompareFunction);
  26300. var i, ii, j, jj, replays, replay;
  26301. for (i = 0, ii = zs.length; i < ii; ++i) {
  26302. replays = this.replaysByZIndex_[zs[i].toString()];
  26303. for (j = 0, jj = ol.render.replay.ORDER.length; j < jj; ++j) {
  26304. replay = replays[ol.render.replay.ORDER[j]];
  26305. if (replay !== undefined) {
  26306. replay.replay(context,
  26307. center, resolution, rotation, size, pixelRatio,
  26308. opacity, skippedFeaturesHash,
  26309. undefined, false);
  26310. }
  26311. }
  26312. }
  26313. };
  26314. /**
  26315. * @private
  26316. * @param {ol.webgl.Context} context Context.
  26317. * @param {ol.Coordinate} center Center.
  26318. * @param {number} resolution Resolution.
  26319. * @param {number} rotation Rotation.
  26320. * @param {ol.Size} size Size.
  26321. * @param {number} pixelRatio Pixel ratio.
  26322. * @param {number} opacity Global opacity.
  26323. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  26324. * to skip.
  26325. * @param {function((ol.Feature|ol.render.Feature)): T|undefined} featureCallback Feature callback.
  26326. * @param {boolean} oneByOne Draw features one-by-one for the hit-detecion.
  26327. * @param {ol.Extent=} opt_hitExtent Hit extent: Only features intersecting
  26328. * this extent are checked.
  26329. * @return {T|undefined} Callback result.
  26330. * @template T
  26331. */
  26332. ol.render.webgl.ReplayGroup.prototype.replayHitDetection_ = function(context,
  26333. center, resolution, rotation, size, pixelRatio, opacity,
  26334. skippedFeaturesHash, featureCallback, oneByOne, opt_hitExtent) {
  26335. /** @type {Array.<number>} */
  26336. var zs = Object.keys(this.replaysByZIndex_).map(Number);
  26337. zs.sort(function(a, b) {
  26338. return b - a;
  26339. });
  26340. var i, ii, j, replays, replay, result;
  26341. for (i = 0, ii = zs.length; i < ii; ++i) {
  26342. replays = this.replaysByZIndex_[zs[i].toString()];
  26343. for (j = ol.render.replay.ORDER.length - 1; j >= 0; --j) {
  26344. replay = replays[ol.render.replay.ORDER[j]];
  26345. if (replay !== undefined) {
  26346. result = replay.replay(context,
  26347. center, resolution, rotation, size, pixelRatio, opacity,
  26348. skippedFeaturesHash, featureCallback, oneByOne, opt_hitExtent);
  26349. if (result) {
  26350. return result;
  26351. }
  26352. }
  26353. }
  26354. }
  26355. return undefined;
  26356. };
  26357. /**
  26358. * @param {ol.Coordinate} coordinate Coordinate.
  26359. * @param {ol.webgl.Context} context Context.
  26360. * @param {ol.Coordinate} center Center.
  26361. * @param {number} resolution Resolution.
  26362. * @param {number} rotation Rotation.
  26363. * @param {ol.Size} size Size.
  26364. * @param {number} pixelRatio Pixel ratio.
  26365. * @param {number} opacity Global opacity.
  26366. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  26367. * to skip.
  26368. * @param {function((ol.Feature|ol.render.Feature)): T|undefined} callback Feature callback.
  26369. * @return {T|undefined} Callback result.
  26370. * @template T
  26371. */
  26372. ol.render.webgl.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
  26373. coordinate, context, center, resolution, rotation, size, pixelRatio,
  26374. opacity, skippedFeaturesHash,
  26375. callback) {
  26376. var gl = context.getGL();
  26377. gl.bindFramebuffer(
  26378. gl.FRAMEBUFFER, context.getHitDetectionFramebuffer());
  26379. /**
  26380. * @type {ol.Extent}
  26381. */
  26382. var hitExtent;
  26383. if (this.renderBuffer_ !== undefined) {
  26384. // build an extent around the coordinate, so that only features that
  26385. // intersect this extent are checked
  26386. hitExtent = ol.extent.buffer(
  26387. ol.extent.createOrUpdateFromCoordinate(coordinate),
  26388. resolution * this.renderBuffer_);
  26389. }
  26390. return this.replayHitDetection_(context,
  26391. coordinate, resolution, rotation, ol.render.webgl.ReplayGroup.HIT_DETECTION_SIZE_,
  26392. pixelRatio, opacity, skippedFeaturesHash,
  26393. /**
  26394. * @param {ol.Feature|ol.render.Feature} feature Feature.
  26395. * @return {?} Callback result.
  26396. */
  26397. function(feature) {
  26398. var imageData = new Uint8Array(4);
  26399. gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, imageData);
  26400. if (imageData[3] > 0) {
  26401. var result = callback(feature);
  26402. if (result) {
  26403. return result;
  26404. }
  26405. }
  26406. }, true, hitExtent);
  26407. };
  26408. /**
  26409. * @param {ol.Coordinate} coordinate Coordinate.
  26410. * @param {ol.webgl.Context} context Context.
  26411. * @param {ol.Coordinate} center Center.
  26412. * @param {number} resolution Resolution.
  26413. * @param {number} rotation Rotation.
  26414. * @param {ol.Size} size Size.
  26415. * @param {number} pixelRatio Pixel ratio.
  26416. * @param {number} opacity Global opacity.
  26417. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  26418. * to skip.
  26419. * @return {boolean} Is there a feature at the given coordinate?
  26420. */
  26421. ol.render.webgl.ReplayGroup.prototype.hasFeatureAtCoordinate = function(
  26422. coordinate, context, center, resolution, rotation, size, pixelRatio,
  26423. opacity, skippedFeaturesHash) {
  26424. var gl = context.getGL();
  26425. gl.bindFramebuffer(
  26426. gl.FRAMEBUFFER, context.getHitDetectionFramebuffer());
  26427. var hasFeature = this.replayHitDetection_(context,
  26428. coordinate, resolution, rotation, ol.render.webgl.ReplayGroup.HIT_DETECTION_SIZE_,
  26429. pixelRatio, opacity, skippedFeaturesHash,
  26430. /**
  26431. * @param {ol.Feature|ol.render.Feature} feature Feature.
  26432. * @return {boolean} Is there a feature?
  26433. */
  26434. function(feature) {
  26435. var imageData = new Uint8Array(4);
  26436. gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, imageData);
  26437. return imageData[3] > 0;
  26438. }, false);
  26439. return hasFeature !== undefined;
  26440. };
  26441. /**
  26442. * @const
  26443. * @private
  26444. * @type {Array.<number>}
  26445. */
  26446. ol.render.webgl.ReplayGroup.HIT_DETECTION_SIZE_ = [1, 1];
  26447. /**
  26448. * @const
  26449. * @private
  26450. * @type {Object.<ol.render.ReplayType,
  26451. * function(new: ol.render.webgl.Replay, number,
  26452. * ol.Extent)>}
  26453. */
  26454. ol.render.webgl.ReplayGroup.BATCH_CONSTRUCTORS_ = {
  26455. 'Circle': ol.render.webgl.CircleReplay,
  26456. 'Image': ol.render.webgl.ImageReplay,
  26457. 'LineString': ol.render.webgl.LineStringReplay,
  26458. 'Polygon': ol.render.webgl.PolygonReplay,
  26459. 'Text': ol.render.webgl.TextReplay
  26460. };
  26461. }
  26462. goog.provide('ol.render.webgl.Immediate');
  26463. goog.require('ol');
  26464. goog.require('ol.extent');
  26465. goog.require('ol.geom.GeometryType');
  26466. goog.require('ol.render.ReplayType');
  26467. goog.require('ol.render.VectorContext');
  26468. goog.require('ol.render.webgl.ReplayGroup');
  26469. if (ol.ENABLE_WEBGL) {
  26470. /**
  26471. * @constructor
  26472. * @extends {ol.render.VectorContext}
  26473. * @param {ol.webgl.Context} context Context.
  26474. * @param {ol.Coordinate} center Center.
  26475. * @param {number} resolution Resolution.
  26476. * @param {number} rotation Rotation.
  26477. * @param {ol.Size} size Size.
  26478. * @param {ol.Extent} extent Extent.
  26479. * @param {number} pixelRatio Pixel ratio.
  26480. * @struct
  26481. */
  26482. ol.render.webgl.Immediate = function(context, center, resolution, rotation, size, extent, pixelRatio) {
  26483. ol.render.VectorContext.call(this);
  26484. /**
  26485. * @private
  26486. */
  26487. this.context_ = context;
  26488. /**
  26489. * @private
  26490. */
  26491. this.center_ = center;
  26492. /**
  26493. * @private
  26494. */
  26495. this.extent_ = extent;
  26496. /**
  26497. * @private
  26498. */
  26499. this.pixelRatio_ = pixelRatio;
  26500. /**
  26501. * @private
  26502. */
  26503. this.size_ = size;
  26504. /**
  26505. * @private
  26506. */
  26507. this.rotation_ = rotation;
  26508. /**
  26509. * @private
  26510. */
  26511. this.resolution_ = resolution;
  26512. /**
  26513. * @private
  26514. * @type {ol.style.Image}
  26515. */
  26516. this.imageStyle_ = null;
  26517. /**
  26518. * @private
  26519. * @type {ol.style.Fill}
  26520. */
  26521. this.fillStyle_ = null;
  26522. /**
  26523. * @private
  26524. * @type {ol.style.Stroke}
  26525. */
  26526. this.strokeStyle_ = null;
  26527. /**
  26528. * @private
  26529. * @type {ol.style.Text}
  26530. */
  26531. this.textStyle_ = null;
  26532. };
  26533. ol.inherits(ol.render.webgl.Immediate, ol.render.VectorContext);
  26534. /**
  26535. * @param {ol.render.webgl.ReplayGroup} replayGroup Replay group.
  26536. * @param {Array.<number>} flatCoordinates Flat coordinates.
  26537. * @param {number} offset Offset.
  26538. * @param {number} end End.
  26539. * @param {number} stride Stride.
  26540. * @private
  26541. */
  26542. ol.render.webgl.Immediate.prototype.drawText_ = function(replayGroup,
  26543. flatCoordinates, offset, end, stride) {
  26544. var context = this.context_;
  26545. var replay = /** @type {ol.render.webgl.TextReplay} */ (
  26546. replayGroup.getReplay(0, ol.render.ReplayType.TEXT));
  26547. replay.setTextStyle(this.textStyle_);
  26548. replay.drawText(flatCoordinates, offset, end, stride, null, null);
  26549. replay.finish(context);
  26550. // default colors
  26551. var opacity = 1;
  26552. var skippedFeatures = {};
  26553. var featureCallback;
  26554. var oneByOne = false;
  26555. replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
  26556. this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
  26557. oneByOne);
  26558. replay.getDeleteResourcesFunction(context)();
  26559. };
  26560. /**
  26561. * Set the rendering style. Note that since this is an immediate rendering API,
  26562. * any `zIndex` on the provided style will be ignored.
  26563. *
  26564. * @param {ol.style.Style} style The rendering style.
  26565. * @override
  26566. * @api
  26567. */
  26568. ol.render.webgl.Immediate.prototype.setStyle = function(style) {
  26569. this.setFillStrokeStyle(style.getFill(), style.getStroke());
  26570. this.setImageStyle(style.getImage());
  26571. this.setTextStyle(style.getText());
  26572. };
  26573. /**
  26574. * Render a geometry into the canvas. Call
  26575. * {@link ol.render.webgl.Immediate#setStyle} first to set the rendering style.
  26576. *
  26577. * @param {ol.geom.Geometry|ol.render.Feature} geometry The geometry to render.
  26578. * @override
  26579. * @api
  26580. */
  26581. ol.render.webgl.Immediate.prototype.drawGeometry = function(geometry) {
  26582. var type = geometry.getType();
  26583. switch (type) {
  26584. case ol.geom.GeometryType.POINT:
  26585. this.drawPoint(/** @type {ol.geom.Point} */ (geometry), null);
  26586. break;
  26587. case ol.geom.GeometryType.LINE_STRING:
  26588. this.drawLineString(/** @type {ol.geom.LineString} */ (geometry), null);
  26589. break;
  26590. case ol.geom.GeometryType.POLYGON:
  26591. this.drawPolygon(/** @type {ol.geom.Polygon} */ (geometry), null);
  26592. break;
  26593. case ol.geom.GeometryType.MULTI_POINT:
  26594. this.drawMultiPoint(/** @type {ol.geom.MultiPoint} */ (geometry), null);
  26595. break;
  26596. case ol.geom.GeometryType.MULTI_LINE_STRING:
  26597. this.drawMultiLineString(/** @type {ol.geom.MultiLineString} */ (geometry), null);
  26598. break;
  26599. case ol.geom.GeometryType.MULTI_POLYGON:
  26600. this.drawMultiPolygon(/** @type {ol.geom.MultiPolygon} */ (geometry), null);
  26601. break;
  26602. case ol.geom.GeometryType.GEOMETRY_COLLECTION:
  26603. this.drawGeometryCollection(/** @type {ol.geom.GeometryCollection} */ (geometry), null);
  26604. break;
  26605. case ol.geom.GeometryType.CIRCLE:
  26606. this.drawCircle(/** @type {ol.geom.Circle} */ (geometry), null);
  26607. break;
  26608. default:
  26609. // pass
  26610. }
  26611. };
  26612. /**
  26613. * @inheritDoc
  26614. * @api
  26615. */
  26616. ol.render.webgl.Immediate.prototype.drawFeature = function(feature, style) {
  26617. var geometry = style.getGeometryFunction()(feature);
  26618. if (!geometry ||
  26619. !ol.extent.intersects(this.extent_, geometry.getExtent())) {
  26620. return;
  26621. }
  26622. this.setStyle(style);
  26623. this.drawGeometry(geometry);
  26624. };
  26625. /**
  26626. * @inheritDoc
  26627. */
  26628. ol.render.webgl.Immediate.prototype.drawGeometryCollection = function(geometry, data) {
  26629. var geometries = geometry.getGeometriesArray();
  26630. var i, ii;
  26631. for (i = 0, ii = geometries.length; i < ii; ++i) {
  26632. this.drawGeometry(geometries[i]);
  26633. }
  26634. };
  26635. /**
  26636. * @inheritDoc
  26637. */
  26638. ol.render.webgl.Immediate.prototype.drawPoint = function(geometry, data) {
  26639. var context = this.context_;
  26640. var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
  26641. var replay = /** @type {ol.render.webgl.ImageReplay} */ (
  26642. replayGroup.getReplay(0, ol.render.ReplayType.IMAGE));
  26643. replay.setImageStyle(this.imageStyle_);
  26644. replay.drawPoint(geometry, data);
  26645. replay.finish(context);
  26646. // default colors
  26647. var opacity = 1;
  26648. var skippedFeatures = {};
  26649. var featureCallback;
  26650. var oneByOne = false;
  26651. replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
  26652. this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
  26653. oneByOne);
  26654. replay.getDeleteResourcesFunction(context)();
  26655. if (this.textStyle_) {
  26656. var flatCoordinates = geometry.getFlatCoordinates();
  26657. var stride = geometry.getStride();
  26658. this.drawText_(replayGroup, flatCoordinates, 0, flatCoordinates.length, stride);
  26659. }
  26660. };
  26661. /**
  26662. * @inheritDoc
  26663. */
  26664. ol.render.webgl.Immediate.prototype.drawMultiPoint = function(geometry, data) {
  26665. var context = this.context_;
  26666. var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
  26667. var replay = /** @type {ol.render.webgl.ImageReplay} */ (
  26668. replayGroup.getReplay(0, ol.render.ReplayType.IMAGE));
  26669. replay.setImageStyle(this.imageStyle_);
  26670. replay.drawMultiPoint(geometry, data);
  26671. replay.finish(context);
  26672. var opacity = 1;
  26673. var skippedFeatures = {};
  26674. var featureCallback;
  26675. var oneByOne = false;
  26676. replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
  26677. this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
  26678. oneByOne);
  26679. replay.getDeleteResourcesFunction(context)();
  26680. if (this.textStyle_) {
  26681. var flatCoordinates = geometry.getFlatCoordinates();
  26682. var stride = geometry.getStride();
  26683. this.drawText_(replayGroup, flatCoordinates, 0, flatCoordinates.length, stride);
  26684. }
  26685. };
  26686. /**
  26687. * @inheritDoc
  26688. */
  26689. ol.render.webgl.Immediate.prototype.drawLineString = function(geometry, data) {
  26690. var context = this.context_;
  26691. var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
  26692. var replay = /** @type {ol.render.webgl.LineStringReplay} */ (
  26693. replayGroup.getReplay(0, ol.render.ReplayType.LINE_STRING));
  26694. replay.setFillStrokeStyle(null, this.strokeStyle_);
  26695. replay.drawLineString(geometry, data);
  26696. replay.finish(context);
  26697. var opacity = 1;
  26698. var skippedFeatures = {};
  26699. var featureCallback;
  26700. var oneByOne = false;
  26701. replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
  26702. this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
  26703. oneByOne);
  26704. replay.getDeleteResourcesFunction(context)();
  26705. if (this.textStyle_) {
  26706. var flatMidpoint = geometry.getFlatMidpoint();
  26707. this.drawText_(replayGroup, flatMidpoint, 0, 2, 2);
  26708. }
  26709. };
  26710. /**
  26711. * @inheritDoc
  26712. */
  26713. ol.render.webgl.Immediate.prototype.drawMultiLineString = function(geometry, data) {
  26714. var context = this.context_;
  26715. var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
  26716. var replay = /** @type {ol.render.webgl.LineStringReplay} */ (
  26717. replayGroup.getReplay(0, ol.render.ReplayType.LINE_STRING));
  26718. replay.setFillStrokeStyle(null, this.strokeStyle_);
  26719. replay.drawMultiLineString(geometry, data);
  26720. replay.finish(context);
  26721. var opacity = 1;
  26722. var skippedFeatures = {};
  26723. var featureCallback;
  26724. var oneByOne = false;
  26725. replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
  26726. this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
  26727. oneByOne);
  26728. replay.getDeleteResourcesFunction(context)();
  26729. if (this.textStyle_) {
  26730. var flatMidpoints = geometry.getFlatMidpoints();
  26731. this.drawText_(replayGroup, flatMidpoints, 0, flatMidpoints.length, 2);
  26732. }
  26733. };
  26734. /**
  26735. * @inheritDoc
  26736. */
  26737. ol.render.webgl.Immediate.prototype.drawPolygon = function(geometry, data) {
  26738. var context = this.context_;
  26739. var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
  26740. var replay = /** @type {ol.render.webgl.PolygonReplay} */ (
  26741. replayGroup.getReplay(0, ol.render.ReplayType.POLYGON));
  26742. replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
  26743. replay.drawPolygon(geometry, data);
  26744. replay.finish(context);
  26745. var opacity = 1;
  26746. var skippedFeatures = {};
  26747. var featureCallback;
  26748. var oneByOne = false;
  26749. replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
  26750. this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
  26751. oneByOne);
  26752. replay.getDeleteResourcesFunction(context)();
  26753. if (this.textStyle_) {
  26754. var flatInteriorPoint = geometry.getFlatInteriorPoint();
  26755. this.drawText_(replayGroup, flatInteriorPoint, 0, 2, 2);
  26756. }
  26757. };
  26758. /**
  26759. * @inheritDoc
  26760. */
  26761. ol.render.webgl.Immediate.prototype.drawMultiPolygon = function(geometry, data) {
  26762. var context = this.context_;
  26763. var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
  26764. var replay = /** @type {ol.render.webgl.PolygonReplay} */ (
  26765. replayGroup.getReplay(0, ol.render.ReplayType.POLYGON));
  26766. replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
  26767. replay.drawMultiPolygon(geometry, data);
  26768. replay.finish(context);
  26769. var opacity = 1;
  26770. var skippedFeatures = {};
  26771. var featureCallback;
  26772. var oneByOne = false;
  26773. replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
  26774. this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
  26775. oneByOne);
  26776. replay.getDeleteResourcesFunction(context)();
  26777. if (this.textStyle_) {
  26778. var flatInteriorPoints = geometry.getFlatInteriorPoints();
  26779. this.drawText_(replayGroup, flatInteriorPoints, 0, flatInteriorPoints.length, 2);
  26780. }
  26781. };
  26782. /**
  26783. * @inheritDoc
  26784. */
  26785. ol.render.webgl.Immediate.prototype.drawCircle = function(geometry, data) {
  26786. var context = this.context_;
  26787. var replayGroup = new ol.render.webgl.ReplayGroup(1, this.extent_);
  26788. var replay = /** @type {ol.render.webgl.CircleReplay} */ (
  26789. replayGroup.getReplay(0, ol.render.ReplayType.CIRCLE));
  26790. replay.setFillStrokeStyle(this.fillStyle_, this.strokeStyle_);
  26791. replay.drawCircle(geometry, data);
  26792. replay.finish(context);
  26793. var opacity = 1;
  26794. var skippedFeatures = {};
  26795. var featureCallback;
  26796. var oneByOne = false;
  26797. replay.replay(this.context_, this.center_, this.resolution_, this.rotation_,
  26798. this.size_, this.pixelRatio_, opacity, skippedFeatures, featureCallback,
  26799. oneByOne);
  26800. replay.getDeleteResourcesFunction(context)();
  26801. if (this.textStyle_) {
  26802. this.drawText_(replayGroup, geometry.getCenter(), 0, 2, 2);
  26803. }
  26804. };
  26805. /**
  26806. * @inheritDoc
  26807. */
  26808. ol.render.webgl.Immediate.prototype.setImageStyle = function(imageStyle) {
  26809. this.imageStyle_ = imageStyle;
  26810. };
  26811. /**
  26812. * @inheritDoc
  26813. */
  26814. ol.render.webgl.Immediate.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
  26815. this.fillStyle_ = fillStyle;
  26816. this.strokeStyle_ = strokeStyle;
  26817. };
  26818. /**
  26819. * @inheritDoc
  26820. */
  26821. ol.render.webgl.Immediate.prototype.setTextStyle = function(textStyle) {
  26822. this.textStyle_ = textStyle;
  26823. };
  26824. }
  26825. goog.provide('ol.structs.LRUCache');
  26826. goog.require('ol.asserts');
  26827. /**
  26828. * Implements a Least-Recently-Used cache where the keys do not conflict with
  26829. * Object's properties (e.g. 'hasOwnProperty' is not allowed as a key). Expiring
  26830. * items from the cache is the responsibility of the user.
  26831. * @constructor
  26832. * @struct
  26833. * @template T
  26834. */
  26835. ol.structs.LRUCache = function() {
  26836. /**
  26837. * @private
  26838. * @type {number}
  26839. */
  26840. this.count_ = 0;
  26841. /**
  26842. * @private
  26843. * @type {!Object.<string, ol.LRUCacheEntry>}
  26844. */
  26845. this.entries_ = {};
  26846. /**
  26847. * @private
  26848. * @type {?ol.LRUCacheEntry}
  26849. */
  26850. this.oldest_ = null;
  26851. /**
  26852. * @private
  26853. * @type {?ol.LRUCacheEntry}
  26854. */
  26855. this.newest_ = null;
  26856. };
  26857. /**
  26858. * FIXME empty description for jsdoc
  26859. */
  26860. ol.structs.LRUCache.prototype.clear = function() {
  26861. this.count_ = 0;
  26862. this.entries_ = {};
  26863. this.oldest_ = null;
  26864. this.newest_ = null;
  26865. };
  26866. /**
  26867. * @param {string} key Key.
  26868. * @return {boolean} Contains key.
  26869. */
  26870. ol.structs.LRUCache.prototype.containsKey = function(key) {
  26871. return this.entries_.hasOwnProperty(key);
  26872. };
  26873. /**
  26874. * @param {function(this: S, T, string, ol.structs.LRUCache): ?} f The function
  26875. * to call for every entry from the oldest to the newer. This function takes
  26876. * 3 arguments (the entry value, the entry key and the LRUCache object).
  26877. * The return value is ignored.
  26878. * @param {S=} opt_this The object to use as `this` in `f`.
  26879. * @template S
  26880. */
  26881. ol.structs.LRUCache.prototype.forEach = function(f, opt_this) {
  26882. var entry = this.oldest_;
  26883. while (entry) {
  26884. f.call(opt_this, entry.value_, entry.key_, this);
  26885. entry = entry.newer;
  26886. }
  26887. };
  26888. /**
  26889. * @param {string} key Key.
  26890. * @return {T} Value.
  26891. */
  26892. ol.structs.LRUCache.prototype.get = function(key) {
  26893. var entry = this.entries_[key];
  26894. ol.asserts.assert(entry !== undefined,
  26895. 15); // Tried to get a value for a key that does not exist in the cache
  26896. if (entry === this.newest_) {
  26897. return entry.value_;
  26898. } else if (entry === this.oldest_) {
  26899. this.oldest_ = /** @type {ol.LRUCacheEntry} */ (this.oldest_.newer);
  26900. this.oldest_.older = null;
  26901. } else {
  26902. entry.newer.older = entry.older;
  26903. entry.older.newer = entry.newer;
  26904. }
  26905. entry.newer = null;
  26906. entry.older = this.newest_;
  26907. this.newest_.newer = entry;
  26908. this.newest_ = entry;
  26909. return entry.value_;
  26910. };
  26911. /**
  26912. * @return {number} Count.
  26913. */
  26914. ol.structs.LRUCache.prototype.getCount = function() {
  26915. return this.count_;
  26916. };
  26917. /**
  26918. * @return {Array.<string>} Keys.
  26919. */
  26920. ol.structs.LRUCache.prototype.getKeys = function() {
  26921. var keys = new Array(this.count_);
  26922. var i = 0;
  26923. var entry;
  26924. for (entry = this.newest_; entry; entry = entry.older) {
  26925. keys[i++] = entry.key_;
  26926. }
  26927. return keys;
  26928. };
  26929. /**
  26930. * @return {Array.<T>} Values.
  26931. */
  26932. ol.structs.LRUCache.prototype.getValues = function() {
  26933. var values = new Array(this.count_);
  26934. var i = 0;
  26935. var entry;
  26936. for (entry = this.newest_; entry; entry = entry.older) {
  26937. values[i++] = entry.value_;
  26938. }
  26939. return values;
  26940. };
  26941. /**
  26942. * @return {T} Last value.
  26943. */
  26944. ol.structs.LRUCache.prototype.peekLast = function() {
  26945. return this.oldest_.value_;
  26946. };
  26947. /**
  26948. * @return {string} Last key.
  26949. */
  26950. ol.structs.LRUCache.prototype.peekLastKey = function() {
  26951. return this.oldest_.key_;
  26952. };
  26953. /**
  26954. * @return {T} value Value.
  26955. */
  26956. ol.structs.LRUCache.prototype.pop = function() {
  26957. var entry = this.oldest_;
  26958. delete this.entries_[entry.key_];
  26959. if (entry.newer) {
  26960. entry.newer.older = null;
  26961. }
  26962. this.oldest_ = /** @type {ol.LRUCacheEntry} */ (entry.newer);
  26963. if (!this.oldest_) {
  26964. this.newest_ = null;
  26965. }
  26966. --this.count_;
  26967. return entry.value_;
  26968. };
  26969. /**
  26970. * @param {string} key Key.
  26971. * @param {T} value Value.
  26972. */
  26973. ol.structs.LRUCache.prototype.replace = function(key, value) {
  26974. this.get(key); // update `newest_`
  26975. this.entries_[key].value_ = value;
  26976. };
  26977. /**
  26978. * @param {string} key Key.
  26979. * @param {T} value Value.
  26980. */
  26981. ol.structs.LRUCache.prototype.set = function(key, value) {
  26982. ol.asserts.assert(!(key in this.entries_),
  26983. 16); // Tried to set a value for a key that is used already
  26984. var entry = /** @type {ol.LRUCacheEntry} */ ({
  26985. key_: key,
  26986. newer: null,
  26987. older: this.newest_,
  26988. value_: value
  26989. });
  26990. if (!this.newest_) {
  26991. this.oldest_ = entry;
  26992. } else {
  26993. this.newest_.newer = entry;
  26994. }
  26995. this.newest_ = entry;
  26996. this.entries_[key] = entry;
  26997. ++this.count_;
  26998. };
  26999. // FIXME check against gl.getParameter(webgl.MAX_TEXTURE_SIZE)
  27000. goog.provide('ol.renderer.webgl.Map');
  27001. goog.require('ol');
  27002. goog.require('ol.array');
  27003. goog.require('ol.css');
  27004. goog.require('ol.dom');
  27005. goog.require('ol.events');
  27006. goog.require('ol.layer.Layer');
  27007. goog.require('ol.render.Event');
  27008. goog.require('ol.render.EventType');
  27009. goog.require('ol.render.webgl.Immediate');
  27010. goog.require('ol.renderer.Map');
  27011. goog.require('ol.renderer.Type');
  27012. goog.require('ol.source.State');
  27013. goog.require('ol.structs.LRUCache');
  27014. goog.require('ol.structs.PriorityQueue');
  27015. goog.require('ol.webgl');
  27016. goog.require('ol.webgl.Context');
  27017. goog.require('ol.webgl.ContextEventType');
  27018. if (ol.ENABLE_WEBGL) {
  27019. /**
  27020. * @constructor
  27021. * @extends {ol.renderer.Map}
  27022. * @param {Element} container Container.
  27023. * @param {ol.Map} map Map.
  27024. */
  27025. ol.renderer.webgl.Map = function(container, map) {
  27026. ol.renderer.Map.call(this, container, map);
  27027. /**
  27028. * @private
  27029. * @type {HTMLCanvasElement}
  27030. */
  27031. this.canvas_ = /** @type {HTMLCanvasElement} */
  27032. (document.createElement('CANVAS'));
  27033. this.canvas_.style.width = '100%';
  27034. this.canvas_.style.height = '100%';
  27035. this.canvas_.style.display = 'block';
  27036. this.canvas_.className = ol.css.CLASS_UNSELECTABLE;
  27037. container.insertBefore(this.canvas_, container.childNodes[0] || null);
  27038. /**
  27039. * @private
  27040. * @type {number}
  27041. */
  27042. this.clipTileCanvasWidth_ = 0;
  27043. /**
  27044. * @private
  27045. * @type {number}
  27046. */
  27047. this.clipTileCanvasHeight_ = 0;
  27048. /**
  27049. * @private
  27050. * @type {CanvasRenderingContext2D}
  27051. */
  27052. this.clipTileContext_ = ol.dom.createCanvasContext2D();
  27053. /**
  27054. * @private
  27055. * @type {boolean}
  27056. */
  27057. this.renderedVisible_ = true;
  27058. /**
  27059. * @private
  27060. * @type {WebGLRenderingContext}
  27061. */
  27062. this.gl_ = ol.webgl.getContext(this.canvas_, {
  27063. antialias: true,
  27064. depth: true,
  27065. failIfMajorPerformanceCaveat: true,
  27066. preserveDrawingBuffer: false,
  27067. stencil: true
  27068. });
  27069. /**
  27070. * @private
  27071. * @type {ol.webgl.Context}
  27072. */
  27073. this.context_ = new ol.webgl.Context(this.canvas_, this.gl_);
  27074. ol.events.listen(this.canvas_, ol.webgl.ContextEventType.LOST,
  27075. this.handleWebGLContextLost, this);
  27076. ol.events.listen(this.canvas_, ol.webgl.ContextEventType.RESTORED,
  27077. this.handleWebGLContextRestored, this);
  27078. /**
  27079. * @private
  27080. * @type {ol.structs.LRUCache.<ol.WebglTextureCacheEntry|null>}
  27081. */
  27082. this.textureCache_ = new ol.structs.LRUCache();
  27083. /**
  27084. * @private
  27085. * @type {ol.Coordinate}
  27086. */
  27087. this.focus_ = null;
  27088. /**
  27089. * @private
  27090. * @type {ol.structs.PriorityQueue.<Array>}
  27091. */
  27092. this.tileTextureQueue_ = new ol.structs.PriorityQueue(
  27093. /**
  27094. * @param {Array.<*>} element Element.
  27095. * @return {number} Priority.
  27096. * @this {ol.renderer.webgl.Map}
  27097. */
  27098. (function(element) {
  27099. var tileCenter = /** @type {ol.Coordinate} */ (element[1]);
  27100. var tileResolution = /** @type {number} */ (element[2]);
  27101. var deltaX = tileCenter[0] - this.focus_[0];
  27102. var deltaY = tileCenter[1] - this.focus_[1];
  27103. return 65536 * Math.log(tileResolution) +
  27104. Math.sqrt(deltaX * deltaX + deltaY * deltaY) / tileResolution;
  27105. }).bind(this),
  27106. /**
  27107. * @param {Array.<*>} element Element.
  27108. * @return {string} Key.
  27109. */
  27110. function(element) {
  27111. return /** @type {ol.Tile} */ (element[0]).getKey();
  27112. });
  27113. /**
  27114. * @param {ol.Map} map Map.
  27115. * @param {?olx.FrameState} frameState Frame state.
  27116. * @return {boolean} false.
  27117. * @this {ol.renderer.webgl.Map}
  27118. */
  27119. this.loadNextTileTexture_ =
  27120. function(map, frameState) {
  27121. if (!this.tileTextureQueue_.isEmpty()) {
  27122. this.tileTextureQueue_.reprioritize();
  27123. var element = this.tileTextureQueue_.dequeue();
  27124. var tile = /** @type {ol.Tile} */ (element[0]);
  27125. var tileSize = /** @type {ol.Size} */ (element[3]);
  27126. var tileGutter = /** @type {number} */ (element[4]);
  27127. this.bindTileTexture(
  27128. tile, tileSize, tileGutter, ol.webgl.LINEAR, ol.webgl.LINEAR);
  27129. }
  27130. return false;
  27131. }.bind(this);
  27132. /**
  27133. * @private
  27134. * @type {number}
  27135. */
  27136. this.textureCacheFrameMarkerCount_ = 0;
  27137. this.initializeGL_();
  27138. };
  27139. ol.inherits(ol.renderer.webgl.Map, ol.renderer.Map);
  27140. /**
  27141. * @param {ol.Tile} tile Tile.
  27142. * @param {ol.Size} tileSize Tile size.
  27143. * @param {number} tileGutter Tile gutter.
  27144. * @param {number} magFilter Mag filter.
  27145. * @param {number} minFilter Min filter.
  27146. */
  27147. ol.renderer.webgl.Map.prototype.bindTileTexture = function(tile, tileSize, tileGutter, magFilter, minFilter) {
  27148. var gl = this.getGL();
  27149. var tileKey = tile.getKey();
  27150. if (this.textureCache_.containsKey(tileKey)) {
  27151. var textureCacheEntry = this.textureCache_.get(tileKey);
  27152. gl.bindTexture(ol.webgl.TEXTURE_2D, textureCacheEntry.texture);
  27153. if (textureCacheEntry.magFilter != magFilter) {
  27154. gl.texParameteri(
  27155. ol.webgl.TEXTURE_2D, ol.webgl.TEXTURE_MAG_FILTER, magFilter);
  27156. textureCacheEntry.magFilter = magFilter;
  27157. }
  27158. if (textureCacheEntry.minFilter != minFilter) {
  27159. gl.texParameteri(
  27160. ol.webgl.TEXTURE_2D, ol.webgl.TEXTURE_MIN_FILTER, minFilter);
  27161. textureCacheEntry.minFilter = minFilter;
  27162. }
  27163. } else {
  27164. var texture = gl.createTexture();
  27165. gl.bindTexture(ol.webgl.TEXTURE_2D, texture);
  27166. if (tileGutter > 0) {
  27167. var clipTileCanvas = this.clipTileContext_.canvas;
  27168. var clipTileContext = this.clipTileContext_;
  27169. if (this.clipTileCanvasWidth_ !== tileSize[0] ||
  27170. this.clipTileCanvasHeight_ !== tileSize[1]) {
  27171. clipTileCanvas.width = tileSize[0];
  27172. clipTileCanvas.height = tileSize[1];
  27173. this.clipTileCanvasWidth_ = tileSize[0];
  27174. this.clipTileCanvasHeight_ = tileSize[1];
  27175. } else {
  27176. clipTileContext.clearRect(0, 0, tileSize[0], tileSize[1]);
  27177. }
  27178. clipTileContext.drawImage(tile.getImage(), tileGutter, tileGutter,
  27179. tileSize[0], tileSize[1], 0, 0, tileSize[0], tileSize[1]);
  27180. gl.texImage2D(ol.webgl.TEXTURE_2D, 0,
  27181. ol.webgl.RGBA, ol.webgl.RGBA,
  27182. ol.webgl.UNSIGNED_BYTE, clipTileCanvas);
  27183. } else {
  27184. gl.texImage2D(ol.webgl.TEXTURE_2D, 0,
  27185. ol.webgl.RGBA, ol.webgl.RGBA,
  27186. ol.webgl.UNSIGNED_BYTE, tile.getImage());
  27187. }
  27188. gl.texParameteri(
  27189. ol.webgl.TEXTURE_2D, ol.webgl.TEXTURE_MAG_FILTER, magFilter);
  27190. gl.texParameteri(
  27191. ol.webgl.TEXTURE_2D, ol.webgl.TEXTURE_MIN_FILTER, minFilter);
  27192. gl.texParameteri(ol.webgl.TEXTURE_2D, ol.webgl.TEXTURE_WRAP_S,
  27193. ol.webgl.CLAMP_TO_EDGE);
  27194. gl.texParameteri(ol.webgl.TEXTURE_2D, ol.webgl.TEXTURE_WRAP_T,
  27195. ol.webgl.CLAMP_TO_EDGE);
  27196. this.textureCache_.set(tileKey, {
  27197. texture: texture,
  27198. magFilter: magFilter,
  27199. minFilter: minFilter
  27200. });
  27201. }
  27202. };
  27203. /**
  27204. * @param {ol.render.EventType} type Event type.
  27205. * @param {olx.FrameState} frameState Frame state.
  27206. * @private
  27207. */
  27208. ol.renderer.webgl.Map.prototype.dispatchComposeEvent_ = function(type, frameState) {
  27209. var map = this.getMap();
  27210. if (map.hasListener(type)) {
  27211. var context = this.context_;
  27212. var extent = frameState.extent;
  27213. var size = frameState.size;
  27214. var viewState = frameState.viewState;
  27215. var pixelRatio = frameState.pixelRatio;
  27216. var resolution = viewState.resolution;
  27217. var center = viewState.center;
  27218. var rotation = viewState.rotation;
  27219. var vectorContext = new ol.render.webgl.Immediate(context,
  27220. center, resolution, rotation, size, extent, pixelRatio);
  27221. var composeEvent = new ol.render.Event(type, vectorContext,
  27222. frameState, null, context);
  27223. map.dispatchEvent(composeEvent);
  27224. }
  27225. };
  27226. /**
  27227. * @inheritDoc
  27228. */
  27229. ol.renderer.webgl.Map.prototype.disposeInternal = function() {
  27230. var gl = this.getGL();
  27231. if (!gl.isContextLost()) {
  27232. this.textureCache_.forEach(
  27233. /**
  27234. * @param {?ol.WebglTextureCacheEntry} textureCacheEntry
  27235. * Texture cache entry.
  27236. */
  27237. function(textureCacheEntry) {
  27238. if (textureCacheEntry) {
  27239. gl.deleteTexture(textureCacheEntry.texture);
  27240. }
  27241. });
  27242. }
  27243. this.context_.dispose();
  27244. ol.renderer.Map.prototype.disposeInternal.call(this);
  27245. };
  27246. /**
  27247. * @param {ol.Map} map Map.
  27248. * @param {olx.FrameState} frameState Frame state.
  27249. * @private
  27250. */
  27251. ol.renderer.webgl.Map.prototype.expireCache_ = function(map, frameState) {
  27252. var gl = this.getGL();
  27253. var textureCacheEntry;
  27254. while (this.textureCache_.getCount() - this.textureCacheFrameMarkerCount_ >
  27255. ol.WEBGL_TEXTURE_CACHE_HIGH_WATER_MARK) {
  27256. textureCacheEntry = this.textureCache_.peekLast();
  27257. if (!textureCacheEntry) {
  27258. if (+this.textureCache_.peekLastKey() == frameState.index) {
  27259. break;
  27260. } else {
  27261. --this.textureCacheFrameMarkerCount_;
  27262. }
  27263. } else {
  27264. gl.deleteTexture(textureCacheEntry.texture);
  27265. }
  27266. this.textureCache_.pop();
  27267. }
  27268. };
  27269. /**
  27270. * @return {ol.webgl.Context} The context.
  27271. */
  27272. ol.renderer.webgl.Map.prototype.getContext = function() {
  27273. return this.context_;
  27274. };
  27275. /**
  27276. * @return {WebGLRenderingContext} GL.
  27277. */
  27278. ol.renderer.webgl.Map.prototype.getGL = function() {
  27279. return this.gl_;
  27280. };
  27281. /**
  27282. * @return {ol.structs.PriorityQueue.<Array>} Tile texture queue.
  27283. */
  27284. ol.renderer.webgl.Map.prototype.getTileTextureQueue = function() {
  27285. return this.tileTextureQueue_;
  27286. };
  27287. /**
  27288. * @inheritDoc
  27289. */
  27290. ol.renderer.webgl.Map.prototype.getType = function() {
  27291. return ol.renderer.Type.WEBGL;
  27292. };
  27293. /**
  27294. * @param {ol.events.Event} event Event.
  27295. * @protected
  27296. */
  27297. ol.renderer.webgl.Map.prototype.handleWebGLContextLost = function(event) {
  27298. event.preventDefault();
  27299. this.textureCache_.clear();
  27300. this.textureCacheFrameMarkerCount_ = 0;
  27301. var renderers = this.getLayerRenderers();
  27302. for (var id in renderers) {
  27303. var renderer = /** @type {ol.renderer.webgl.Layer} */ (renderers[id]);
  27304. renderer.handleWebGLContextLost();
  27305. }
  27306. };
  27307. /**
  27308. * @protected
  27309. */
  27310. ol.renderer.webgl.Map.prototype.handleWebGLContextRestored = function() {
  27311. this.initializeGL_();
  27312. this.getMap().render();
  27313. };
  27314. /**
  27315. * @private
  27316. */
  27317. ol.renderer.webgl.Map.prototype.initializeGL_ = function() {
  27318. var gl = this.gl_;
  27319. gl.activeTexture(ol.webgl.TEXTURE0);
  27320. gl.blendFuncSeparate(
  27321. ol.webgl.SRC_ALPHA, ol.webgl.ONE_MINUS_SRC_ALPHA,
  27322. ol.webgl.ONE, ol.webgl.ONE_MINUS_SRC_ALPHA);
  27323. gl.disable(ol.webgl.CULL_FACE);
  27324. gl.disable(ol.webgl.DEPTH_TEST);
  27325. gl.disable(ol.webgl.SCISSOR_TEST);
  27326. gl.disable(ol.webgl.STENCIL_TEST);
  27327. };
  27328. /**
  27329. * @param {ol.Tile} tile Tile.
  27330. * @return {boolean} Is tile texture loaded.
  27331. */
  27332. ol.renderer.webgl.Map.prototype.isTileTextureLoaded = function(tile) {
  27333. return this.textureCache_.containsKey(tile.getKey());
  27334. };
  27335. /**
  27336. * @inheritDoc
  27337. */
  27338. ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
  27339. var context = this.getContext();
  27340. var gl = this.getGL();
  27341. if (gl.isContextLost()) {
  27342. return false;
  27343. }
  27344. if (!frameState) {
  27345. if (this.renderedVisible_) {
  27346. this.canvas_.style.display = 'none';
  27347. this.renderedVisible_ = false;
  27348. }
  27349. return false;
  27350. }
  27351. this.focus_ = frameState.focus;
  27352. this.textureCache_.set((-frameState.index).toString(), null);
  27353. ++this.textureCacheFrameMarkerCount_;
  27354. this.dispatchComposeEvent_(ol.render.EventType.PRECOMPOSE, frameState);
  27355. /** @type {Array.<ol.LayerState>} */
  27356. var layerStatesToDraw = [];
  27357. var layerStatesArray = frameState.layerStatesArray;
  27358. ol.array.stableSort(layerStatesArray, ol.renderer.Map.sortByZIndex);
  27359. var viewResolution = frameState.viewState.resolution;
  27360. var i, ii, layerRenderer, layerState;
  27361. for (i = 0, ii = layerStatesArray.length; i < ii; ++i) {
  27362. layerState = layerStatesArray[i];
  27363. if (ol.layer.Layer.visibleAtResolution(layerState, viewResolution) &&
  27364. layerState.sourceState == ol.source.State.READY) {
  27365. layerRenderer = /** @type {ol.renderer.webgl.Layer} */ (this.getLayerRenderer(layerState.layer));
  27366. if (layerRenderer.prepareFrame(frameState, layerState, context)) {
  27367. layerStatesToDraw.push(layerState);
  27368. }
  27369. }
  27370. }
  27371. var width = frameState.size[0] * frameState.pixelRatio;
  27372. var height = frameState.size[1] * frameState.pixelRatio;
  27373. if (this.canvas_.width != width || this.canvas_.height != height) {
  27374. this.canvas_.width = width;
  27375. this.canvas_.height = height;
  27376. }
  27377. gl.bindFramebuffer(ol.webgl.FRAMEBUFFER, null);
  27378. gl.clearColor(0, 0, 0, 0);
  27379. gl.clear(ol.webgl.COLOR_BUFFER_BIT);
  27380. gl.enable(ol.webgl.BLEND);
  27381. gl.viewport(0, 0, this.canvas_.width, this.canvas_.height);
  27382. for (i = 0, ii = layerStatesToDraw.length; i < ii; ++i) {
  27383. layerState = layerStatesToDraw[i];
  27384. layerRenderer = /** @type {ol.renderer.webgl.Layer} */ (this.getLayerRenderer(layerState.layer));
  27385. layerRenderer.composeFrame(frameState, layerState, context);
  27386. }
  27387. if (!this.renderedVisible_) {
  27388. this.canvas_.style.display = '';
  27389. this.renderedVisible_ = true;
  27390. }
  27391. this.calculateMatrices2D(frameState);
  27392. if (this.textureCache_.getCount() - this.textureCacheFrameMarkerCount_ >
  27393. ol.WEBGL_TEXTURE_CACHE_HIGH_WATER_MARK) {
  27394. frameState.postRenderFunctions.push(
  27395. /** @type {ol.PostRenderFunction} */ (this.expireCache_.bind(this))
  27396. );
  27397. }
  27398. if (!this.tileTextureQueue_.isEmpty()) {
  27399. frameState.postRenderFunctions.push(this.loadNextTileTexture_);
  27400. frameState.animate = true;
  27401. }
  27402. this.dispatchComposeEvent_(ol.render.EventType.POSTCOMPOSE, frameState);
  27403. this.scheduleRemoveUnusedLayerRenderers(frameState);
  27404. this.scheduleExpireIconCache(frameState);
  27405. };
  27406. /**
  27407. * @inheritDoc
  27408. */
  27409. ol.renderer.webgl.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg,
  27410. layerFilter, thisArg2) {
  27411. var result;
  27412. if (this.getGL().isContextLost()) {
  27413. return false;
  27414. }
  27415. var viewState = frameState.viewState;
  27416. var layerStates = frameState.layerStatesArray;
  27417. var numLayers = layerStates.length;
  27418. var i;
  27419. for (i = numLayers - 1; i >= 0; --i) {
  27420. var layerState = layerStates[i];
  27421. var layer = layerState.layer;
  27422. if (ol.layer.Layer.visibleAtResolution(layerState, viewState.resolution) &&
  27423. layerFilter.call(thisArg2, layer)) {
  27424. var layerRenderer = this.getLayerRenderer(layer);
  27425. result = layerRenderer.forEachFeatureAtCoordinate(
  27426. coordinate, frameState, hitTolerance, callback, thisArg);
  27427. if (result) {
  27428. return result;
  27429. }
  27430. }
  27431. }
  27432. return undefined;
  27433. };
  27434. /**
  27435. * @inheritDoc
  27436. */
  27437. ol.renderer.webgl.Map.prototype.hasFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, layerFilter, thisArg) {
  27438. var hasFeature = false;
  27439. if (this.getGL().isContextLost()) {
  27440. return false;
  27441. }
  27442. var viewState = frameState.viewState;
  27443. var layerStates = frameState.layerStatesArray;
  27444. var numLayers = layerStates.length;
  27445. var i;
  27446. for (i = numLayers - 1; i >= 0; --i) {
  27447. var layerState = layerStates[i];
  27448. var layer = layerState.layer;
  27449. if (ol.layer.Layer.visibleAtResolution(layerState, viewState.resolution) &&
  27450. layerFilter.call(thisArg, layer)) {
  27451. var layerRenderer = this.getLayerRenderer(layer);
  27452. hasFeature =
  27453. layerRenderer.hasFeatureAtCoordinate(coordinate, frameState);
  27454. if (hasFeature) {
  27455. return true;
  27456. }
  27457. }
  27458. }
  27459. return hasFeature;
  27460. };
  27461. /**
  27462. * @inheritDoc
  27463. */
  27464. ol.renderer.webgl.Map.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg,
  27465. layerFilter, thisArg2) {
  27466. if (this.getGL().isContextLost()) {
  27467. return false;
  27468. }
  27469. var viewState = frameState.viewState;
  27470. var result;
  27471. var layerStates = frameState.layerStatesArray;
  27472. var numLayers = layerStates.length;
  27473. var i;
  27474. for (i = numLayers - 1; i >= 0; --i) {
  27475. var layerState = layerStates[i];
  27476. var layer = layerState.layer;
  27477. if (ol.layer.Layer.visibleAtResolution(layerState, viewState.resolution) &&
  27478. layerFilter.call(thisArg, layer)) {
  27479. var layerRenderer = /** @type {ol.renderer.webgl.Layer} */ (this.getLayerRenderer(layer));
  27480. result = layerRenderer.forEachLayerAtPixel(
  27481. pixel, frameState, callback, thisArg);
  27482. if (result) {
  27483. return result;
  27484. }
  27485. }
  27486. }
  27487. return undefined;
  27488. };
  27489. }
  27490. // FIXME recheck layer/map projection compatibility when projection changes
  27491. // FIXME layer renderers should skip when they can't reproject
  27492. // FIXME add tilt and height?
  27493. goog.provide('ol.Map');
  27494. goog.require('ol');
  27495. goog.require('ol.Collection');
  27496. goog.require('ol.CollectionEventType');
  27497. goog.require('ol.MapBrowserEvent');
  27498. goog.require('ol.MapBrowserEventHandler');
  27499. goog.require('ol.MapBrowserEventType');
  27500. goog.require('ol.MapEvent');
  27501. goog.require('ol.MapEventType');
  27502. goog.require('ol.MapProperty');
  27503. goog.require('ol.Object');
  27504. goog.require('ol.ObjectEventType');
  27505. goog.require('ol.TileQueue');
  27506. goog.require('ol.View');
  27507. goog.require('ol.ViewHint');
  27508. goog.require('ol.asserts');
  27509. goog.require('ol.control');
  27510. goog.require('ol.dom');
  27511. goog.require('ol.events');
  27512. goog.require('ol.events.Event');
  27513. goog.require('ol.events.EventType');
  27514. goog.require('ol.extent');
  27515. goog.require('ol.functions');
  27516. goog.require('ol.has');
  27517. goog.require('ol.interaction');
  27518. goog.require('ol.layer.Group');
  27519. goog.require('ol.obj');
  27520. goog.require('ol.renderer.Map');
  27521. goog.require('ol.renderer.Type');
  27522. goog.require('ol.renderer.canvas.Map');
  27523. goog.require('ol.renderer.webgl.Map');
  27524. goog.require('ol.size');
  27525. goog.require('ol.structs.PriorityQueue');
  27526. goog.require('ol.transform');
  27527. /**
  27528. * @const
  27529. * @type {string}
  27530. */
  27531. ol.OL_URL = 'https://openlayers.org/';
  27532. /**
  27533. * @const
  27534. * @type {string}
  27535. */
  27536. ol.OL_LOGO_URL = 'data:image/png;base64,' +
  27537. 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAA3NCSVQICAjb4U/gAAAACXBI' +
  27538. 'WXMAAAHGAAABxgEXwfpGAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAA' +
  27539. 'AhNQTFRF////AP//AICAgP//AFVVQECA////K1VVSbbbYL/fJ05idsTYJFtbbcjbJllmZszW' +
  27540. 'WMTOIFhoHlNiZszTa9DdUcHNHlNlV8XRIVdiasrUHlZjIVZjaMnVH1RlIFRkH1RkH1ZlasvY' +
  27541. 'asvXVsPQH1VkacnVa8vWIVZjIFRjVMPQa8rXIVVkXsXRsNveIFVkIFZlIVVj3eDeh6GmbMvX' +
  27542. 'H1ZkIFRka8rWbMvXIFVkIFVjIFVkbMvWH1VjbMvWIFVlbcvWIFVla8vVIFVkbMvWbMvVH1Vk' +
  27543. 'bMvWIFVlbcvWIFVkbcvVbMvWjNPbIFVkU8LPwMzNIFVkbczWIFVkbsvWbMvXIFVkRnB8bcvW' +
  27544. '2+TkW8XRIFVkIlZlJVloJlpoKlxrLl9tMmJwOWd0Omh1RXF8TneCT3iDUHiDU8LPVMLPVcLP' +
  27545. 'VcPQVsPPVsPQV8PQWMTQWsTQW8TQXMXSXsXRX4SNX8bSYMfTYcfTYsfTY8jUZcfSZsnUaIqT' +
  27546. 'acrVasrVa8jTa8rWbI2VbMvWbcvWdJObdcvUdszUd8vVeJaee87Yfc3WgJyjhqGnitDYjaar' +
  27547. 'ldPZnrK2oNbborW5o9bbo9fbpLa6q9ndrL3ArtndscDDutzfu8fJwN7gwt7gxc/QyuHhy+Hi' +
  27548. 'zeHi0NfX0+Pj19zb1+Tj2uXk29/e3uLg3+Lh3+bl4uXj4ufl4+fl5Ofl5ufl5ujm5+jmySDn' +
  27549. 'BAAAAFp0Uk5TAAECAgMEBAYHCA0NDg4UGRogIiMmKSssLzU7PkJJT1JTVFliY2hrdHZ3foSF' +
  27550. 'hYeJjY2QkpugqbG1tre5w8zQ09XY3uXn6+zx8vT09vf4+Pj5+fr6/P39/f3+gz7SsAAAAVVJ' +
  27551. 'REFUOMtjYKA7EBDnwCPLrObS1BRiLoJLnte6CQy8FLHLCzs2QUG4FjZ5GbcmBDDjxJBXDWxC' +
  27552. 'Brb8aM4zbkIDzpLYnAcE9VXlJSWlZRU13koIeW57mGx5XjoMZEUqwxWYQaQbSzLSkYGfKFSe' +
  27553. '0QMsX5WbjgY0YS4MBplemI4BdGBW+DQ11eZiymfqQuXZIjqwyadPNoSZ4L+0FVM6e+oGI6g8' +
  27554. 'a9iKNT3o8kVzNkzRg5lgl7p4wyRUL9Yt2jAxVh6mQCogae6GmflI8p0r13VFWTHBQ0rWPW7a' +
  27555. 'hgWVcPm+9cuLoyy4kCJDzCm6d8PSFoh0zvQNC5OjDJhQopPPJqph1doJBUD5tnkbZiUEqaCn' +
  27556. 'B3bTqLTFG1bPn71kw4b+GFdpLElKIzRxxgYgWNYc5SCENVHKeUaltHdXx0dZ8uBI1hJ2UUDg' +
  27557. 'q82CM2MwKeibqAvSO7MCABq0wXEPiqWEAAAAAElFTkSuQmCC';
  27558. /**
  27559. * @type {Array.<ol.renderer.Type>}
  27560. * @const
  27561. */
  27562. ol.DEFAULT_RENDERER_TYPES = [
  27563. ol.renderer.Type.CANVAS,
  27564. ol.renderer.Type.WEBGL
  27565. ];
  27566. /**
  27567. * @classdesc
  27568. * The map is the core component of OpenLayers. For a map to render, a view,
  27569. * one or more layers, and a target container are needed:
  27570. *
  27571. * var map = new ol.Map({
  27572. * view: new ol.View({
  27573. * center: [0, 0],
  27574. * zoom: 1
  27575. * }),
  27576. * layers: [
  27577. * new ol.layer.Tile({
  27578. * source: new ol.source.OSM()
  27579. * })
  27580. * ],
  27581. * target: 'map'
  27582. * });
  27583. *
  27584. * The above snippet creates a map using a {@link ol.layer.Tile} to display
  27585. * {@link ol.source.OSM} OSM data and render it to a DOM element with the
  27586. * id `map`.
  27587. *
  27588. * The constructor places a viewport container (with CSS class name
  27589. * `ol-viewport`) in the target element (see `getViewport()`), and then two
  27590. * further elements within the viewport: one with CSS class name
  27591. * `ol-overlaycontainer-stopevent` for controls and some overlays, and one with
  27592. * CSS class name `ol-overlaycontainer` for other overlays (see the `stopEvent`
  27593. * option of {@link ol.Overlay} for the difference). The map itself is placed in
  27594. * a further element within the viewport.
  27595. *
  27596. * Layers are stored as a `ol.Collection` in layerGroups. A top-level group is
  27597. * provided by the library. This is what is accessed by `getLayerGroup` and
  27598. * `setLayerGroup`. Layers entered in the options are added to this group, and
  27599. * `addLayer` and `removeLayer` change the layer collection in the group.
  27600. * `getLayers` is a convenience function for `getLayerGroup().getLayers()`.
  27601. * Note that `ol.layer.Group` is a subclass of `ol.layer.Base`, so layers
  27602. * entered in the options or added with `addLayer` can be groups, which can
  27603. * contain further groups, and so on.
  27604. *
  27605. * @constructor
  27606. * @extends {ol.Object}
  27607. * @param {olx.MapOptions} options Map options.
  27608. * @fires ol.MapBrowserEvent
  27609. * @fires ol.MapEvent
  27610. * @fires ol.render.Event#postcompose
  27611. * @fires ol.render.Event#precompose
  27612. * @api
  27613. */
  27614. ol.Map = function(options) {
  27615. ol.Object.call(this);
  27616. var optionsInternal = ol.Map.createOptionsInternal(options);
  27617. /**
  27618. * @type {boolean}
  27619. * @private
  27620. */
  27621. this.loadTilesWhileAnimating_ =
  27622. options.loadTilesWhileAnimating !== undefined ?
  27623. options.loadTilesWhileAnimating : false;
  27624. /**
  27625. * @type {boolean}
  27626. * @private
  27627. */
  27628. this.loadTilesWhileInteracting_ =
  27629. options.loadTilesWhileInteracting !== undefined ?
  27630. options.loadTilesWhileInteracting : false;
  27631. /**
  27632. * @private
  27633. * @type {number}
  27634. */
  27635. this.pixelRatio_ = options.pixelRatio !== undefined ?
  27636. options.pixelRatio : ol.has.DEVICE_PIXEL_RATIO;
  27637. /**
  27638. * @private
  27639. * @type {Object.<string, string>}
  27640. */
  27641. this.logos_ = optionsInternal.logos;
  27642. /**
  27643. * @private
  27644. * @type {number|undefined}
  27645. */
  27646. this.animationDelayKey_;
  27647. /**
  27648. * @private
  27649. */
  27650. this.animationDelay_ = function() {
  27651. this.animationDelayKey_ = undefined;
  27652. this.renderFrame_.call(this, Date.now());
  27653. }.bind(this);
  27654. /**
  27655. * @private
  27656. * @type {ol.Transform}
  27657. */
  27658. this.coordinateToPixelTransform_ = ol.transform.create();
  27659. /**
  27660. * @private
  27661. * @type {ol.Transform}
  27662. */
  27663. this.pixelToCoordinateTransform_ = ol.transform.create();
  27664. /**
  27665. * @private
  27666. * @type {number}
  27667. */
  27668. this.frameIndex_ = 0;
  27669. /**
  27670. * @private
  27671. * @type {?olx.FrameState}
  27672. */
  27673. this.frameState_ = null;
  27674. /**
  27675. * The extent at the previous 'moveend' event.
  27676. * @private
  27677. * @type {ol.Extent}
  27678. */
  27679. this.previousExtent_ = null;
  27680. /**
  27681. * @private
  27682. * @type {?ol.EventsKey}
  27683. */
  27684. this.viewPropertyListenerKey_ = null;
  27685. /**
  27686. * @private
  27687. * @type {?ol.EventsKey}
  27688. */
  27689. this.viewChangeListenerKey_ = null;
  27690. /**
  27691. * @private
  27692. * @type {Array.<ol.EventsKey>}
  27693. */
  27694. this.layerGroupPropertyListenerKeys_ = null;
  27695. /**
  27696. * @private
  27697. * @type {Element}
  27698. */
  27699. this.viewport_ = document.createElement('DIV');
  27700. this.viewport_.className = 'ol-viewport' + (ol.has.TOUCH ? ' ol-touch' : '');
  27701. this.viewport_.style.position = 'relative';
  27702. this.viewport_.style.overflow = 'hidden';
  27703. this.viewport_.style.width = '100%';
  27704. this.viewport_.style.height = '100%';
  27705. // prevent page zoom on IE >= 10 browsers
  27706. this.viewport_.style.msTouchAction = 'none';
  27707. this.viewport_.style.touchAction = 'none';
  27708. /**
  27709. * @private
  27710. * @type {!Element}
  27711. */
  27712. this.overlayContainer_ = document.createElement('DIV');
  27713. this.overlayContainer_.className = 'ol-overlaycontainer';
  27714. this.viewport_.appendChild(this.overlayContainer_);
  27715. /**
  27716. * @private
  27717. * @type {!Element}
  27718. */
  27719. this.overlayContainerStopEvent_ = document.createElement('DIV');
  27720. this.overlayContainerStopEvent_.className = 'ol-overlaycontainer-stopevent';
  27721. var overlayEvents = [
  27722. ol.events.EventType.CLICK,
  27723. ol.events.EventType.DBLCLICK,
  27724. ol.events.EventType.MOUSEDOWN,
  27725. ol.events.EventType.TOUCHSTART,
  27726. ol.events.EventType.MSPOINTERDOWN,
  27727. ol.MapBrowserEventType.POINTERDOWN,
  27728. ol.events.EventType.MOUSEWHEEL,
  27729. ol.events.EventType.WHEEL
  27730. ];
  27731. for (var i = 0, ii = overlayEvents.length; i < ii; ++i) {
  27732. ol.events.listen(this.overlayContainerStopEvent_, overlayEvents[i],
  27733. ol.events.Event.stopPropagation);
  27734. }
  27735. this.viewport_.appendChild(this.overlayContainerStopEvent_);
  27736. /**
  27737. * @private
  27738. * @type {ol.MapBrowserEventHandler}
  27739. */
  27740. this.mapBrowserEventHandler_ = new ol.MapBrowserEventHandler(this, options.moveTolerance);
  27741. for (var key in ol.MapBrowserEventType) {
  27742. ol.events.listen(this.mapBrowserEventHandler_, ol.MapBrowserEventType[key],
  27743. this.handleMapBrowserEvent, this);
  27744. }
  27745. /**
  27746. * @private
  27747. * @type {Element|Document}
  27748. */
  27749. this.keyboardEventTarget_ = optionsInternal.keyboardEventTarget;
  27750. /**
  27751. * @private
  27752. * @type {Array.<ol.EventsKey>}
  27753. */
  27754. this.keyHandlerKeys_ = null;
  27755. ol.events.listen(this.viewport_, ol.events.EventType.WHEEL,
  27756. this.handleBrowserEvent, this);
  27757. ol.events.listen(this.viewport_, ol.events.EventType.MOUSEWHEEL,
  27758. this.handleBrowserEvent, this);
  27759. /**
  27760. * @type {ol.Collection.<ol.control.Control>}
  27761. * @private
  27762. */
  27763. this.controls_ = optionsInternal.controls;
  27764. /**
  27765. * @type {ol.Collection.<ol.interaction.Interaction>}
  27766. * @private
  27767. */
  27768. this.interactions_ = optionsInternal.interactions;
  27769. /**
  27770. * @type {ol.Collection.<ol.Overlay>}
  27771. * @private
  27772. */
  27773. this.overlays_ = optionsInternal.overlays;
  27774. /**
  27775. * A lookup of overlays by id.
  27776. * @private
  27777. * @type {Object.<string, ol.Overlay>}
  27778. */
  27779. this.overlayIdIndex_ = {};
  27780. /**
  27781. * @type {ol.renderer.Map}
  27782. * @private
  27783. */
  27784. this.renderer_ = new /** @type {Function} */ (optionsInternal.rendererConstructor)(this.viewport_, this);
  27785. /**
  27786. * @type {function(Event)|undefined}
  27787. * @private
  27788. */
  27789. this.handleResize_;
  27790. /**
  27791. * @private
  27792. * @type {ol.Coordinate}
  27793. */
  27794. this.focus_ = null;
  27795. /**
  27796. * @private
  27797. * @type {Array.<ol.PostRenderFunction>}
  27798. */
  27799. this.postRenderFunctions_ = [];
  27800. /**
  27801. * @private
  27802. * @type {ol.TileQueue}
  27803. */
  27804. this.tileQueue_ = new ol.TileQueue(
  27805. this.getTilePriority.bind(this),
  27806. this.handleTileChange_.bind(this));
  27807. /**
  27808. * Uids of features to skip at rendering time.
  27809. * @type {Object.<string, boolean>}
  27810. * @private
  27811. */
  27812. this.skippedFeatureUids_ = {};
  27813. ol.events.listen(
  27814. this, ol.Object.getChangeEventType(ol.MapProperty.LAYERGROUP),
  27815. this.handleLayerGroupChanged_, this);
  27816. ol.events.listen(this, ol.Object.getChangeEventType(ol.MapProperty.VIEW),
  27817. this.handleViewChanged_, this);
  27818. ol.events.listen(this, ol.Object.getChangeEventType(ol.MapProperty.SIZE),
  27819. this.handleSizeChanged_, this);
  27820. ol.events.listen(this, ol.Object.getChangeEventType(ol.MapProperty.TARGET),
  27821. this.handleTargetChanged_, this);
  27822. // setProperties will trigger the rendering of the map if the map
  27823. // is "defined" already.
  27824. this.setProperties(optionsInternal.values);
  27825. this.controls_.forEach(
  27826. /**
  27827. * @param {ol.control.Control} control Control.
  27828. * @this {ol.Map}
  27829. */
  27830. function(control) {
  27831. control.setMap(this);
  27832. }, this);
  27833. ol.events.listen(this.controls_, ol.CollectionEventType.ADD,
  27834. /**
  27835. * @param {ol.Collection.Event} event Collection event.
  27836. */
  27837. function(event) {
  27838. event.element.setMap(this);
  27839. }, this);
  27840. ol.events.listen(this.controls_, ol.CollectionEventType.REMOVE,
  27841. /**
  27842. * @param {ol.Collection.Event} event Collection event.
  27843. */
  27844. function(event) {
  27845. event.element.setMap(null);
  27846. }, this);
  27847. this.interactions_.forEach(
  27848. /**
  27849. * @param {ol.interaction.Interaction} interaction Interaction.
  27850. * @this {ol.Map}
  27851. */
  27852. function(interaction) {
  27853. interaction.setMap(this);
  27854. }, this);
  27855. ol.events.listen(this.interactions_, ol.CollectionEventType.ADD,
  27856. /**
  27857. * @param {ol.Collection.Event} event Collection event.
  27858. */
  27859. function(event) {
  27860. event.element.setMap(this);
  27861. }, this);
  27862. ol.events.listen(this.interactions_, ol.CollectionEventType.REMOVE,
  27863. /**
  27864. * @param {ol.Collection.Event} event Collection event.
  27865. */
  27866. function(event) {
  27867. event.element.setMap(null);
  27868. }, this);
  27869. this.overlays_.forEach(this.addOverlayInternal_, this);
  27870. ol.events.listen(this.overlays_, ol.CollectionEventType.ADD,
  27871. /**
  27872. * @param {ol.Collection.Event} event Collection event.
  27873. */
  27874. function(event) {
  27875. this.addOverlayInternal_(/** @type {ol.Overlay} */ (event.element));
  27876. }, this);
  27877. ol.events.listen(this.overlays_, ol.CollectionEventType.REMOVE,
  27878. /**
  27879. * @param {ol.Collection.Event} event Collection event.
  27880. */
  27881. function(event) {
  27882. var overlay = /** @type {ol.Overlay} */ (event.element);
  27883. var id = overlay.getId();
  27884. if (id !== undefined) {
  27885. delete this.overlayIdIndex_[id.toString()];
  27886. }
  27887. event.element.setMap(null);
  27888. }, this);
  27889. };
  27890. ol.inherits(ol.Map, ol.Object);
  27891. /**
  27892. * Add the given control to the map.
  27893. * @param {ol.control.Control} control Control.
  27894. * @api
  27895. */
  27896. ol.Map.prototype.addControl = function(control) {
  27897. this.getControls().push(control);
  27898. };
  27899. /**
  27900. * Add the given interaction to the map.
  27901. * @param {ol.interaction.Interaction} interaction Interaction to add.
  27902. * @api
  27903. */
  27904. ol.Map.prototype.addInteraction = function(interaction) {
  27905. this.getInteractions().push(interaction);
  27906. };
  27907. /**
  27908. * Adds the given layer to the top of this map. If you want to add a layer
  27909. * elsewhere in the stack, use `getLayers()` and the methods available on
  27910. * {@link ol.Collection}.
  27911. * @param {ol.layer.Base} layer Layer.
  27912. * @api
  27913. */
  27914. ol.Map.prototype.addLayer = function(layer) {
  27915. var layers = this.getLayerGroup().getLayers();
  27916. layers.push(layer);
  27917. };
  27918. /**
  27919. * Add the given overlay to the map.
  27920. * @param {ol.Overlay} overlay Overlay.
  27921. * @api
  27922. */
  27923. ol.Map.prototype.addOverlay = function(overlay) {
  27924. this.getOverlays().push(overlay);
  27925. };
  27926. /**
  27927. * This deals with map's overlay collection changes.
  27928. * @param {ol.Overlay} overlay Overlay.
  27929. * @private
  27930. */
  27931. ol.Map.prototype.addOverlayInternal_ = function(overlay) {
  27932. var id = overlay.getId();
  27933. if (id !== undefined) {
  27934. this.overlayIdIndex_[id.toString()] = overlay;
  27935. }
  27936. overlay.setMap(this);
  27937. };
  27938. /**
  27939. *
  27940. * @inheritDoc
  27941. */
  27942. ol.Map.prototype.disposeInternal = function() {
  27943. this.mapBrowserEventHandler_.dispose();
  27944. this.renderer_.dispose();
  27945. ol.events.unlisten(this.viewport_, ol.events.EventType.WHEEL,
  27946. this.handleBrowserEvent, this);
  27947. ol.events.unlisten(this.viewport_, ol.events.EventType.MOUSEWHEEL,
  27948. this.handleBrowserEvent, this);
  27949. if (this.handleResize_ !== undefined) {
  27950. window.removeEventListener(ol.events.EventType.RESIZE,
  27951. this.handleResize_, false);
  27952. this.handleResize_ = undefined;
  27953. }
  27954. if (this.animationDelayKey_) {
  27955. cancelAnimationFrame(this.animationDelayKey_);
  27956. this.animationDelayKey_ = undefined;
  27957. }
  27958. this.setTarget(null);
  27959. ol.Object.prototype.disposeInternal.call(this);
  27960. };
  27961. /**
  27962. * Detect features that intersect a pixel on the viewport, and execute a
  27963. * callback with each intersecting feature. Layers included in the detection can
  27964. * be configured through the `layerFilter` option in `opt_options`.
  27965. * @param {ol.Pixel} pixel Pixel.
  27966. * @param {function(this: S, (ol.Feature|ol.render.Feature),
  27967. * ol.layer.Layer): T} callback Feature callback. The callback will be
  27968. * called with two arguments. The first argument is one
  27969. * {@link ol.Feature feature} or
  27970. * {@link ol.render.Feature render feature} at the pixel, the second is
  27971. * the {@link ol.layer.Layer layer} of the feature and will be null for
  27972. * unmanaged layers. To stop detection, callback functions can return a
  27973. * truthy value.
  27974. * @param {olx.AtPixelOptions=} opt_options Optional options.
  27975. * @return {T|undefined} Callback result, i.e. the return value of last
  27976. * callback execution, or the first truthy callback return value.
  27977. * @template S,T
  27978. * @api
  27979. */
  27980. ol.Map.prototype.forEachFeatureAtPixel = function(pixel, callback, opt_options) {
  27981. if (!this.frameState_) {
  27982. return;
  27983. }
  27984. var coordinate = this.getCoordinateFromPixel(pixel);
  27985. opt_options = opt_options !== undefined ? opt_options : {};
  27986. var hitTolerance = opt_options.hitTolerance !== undefined ?
  27987. opt_options.hitTolerance * this.frameState_.pixelRatio : 0;
  27988. var layerFilter = opt_options.layerFilter !== undefined ?
  27989. opt_options.layerFilter : ol.functions.TRUE;
  27990. return this.renderer_.forEachFeatureAtCoordinate(
  27991. coordinate, this.frameState_, hitTolerance, callback, null,
  27992. layerFilter, null);
  27993. };
  27994. /**
  27995. * Get all features that intersect a pixel on the viewport.
  27996. * @param {ol.Pixel} pixel Pixel.
  27997. * @param {olx.AtPixelOptions=} opt_options Optional options.
  27998. * @return {Array.<ol.Feature|ol.render.Feature>} The detected features or
  27999. * `null` if none were found.
  28000. * @api
  28001. */
  28002. ol.Map.prototype.getFeaturesAtPixel = function(pixel, opt_options) {
  28003. var features = null;
  28004. this.forEachFeatureAtPixel(pixel, function(feature) {
  28005. if (!features) {
  28006. features = [];
  28007. }
  28008. features.push(feature);
  28009. }, opt_options);
  28010. return features;
  28011. };
  28012. /**
  28013. * Detect layers that have a color value at a pixel on the viewport, and
  28014. * execute a callback with each matching layer. Layers included in the
  28015. * detection can be configured through `opt_layerFilter`.
  28016. * @param {ol.Pixel} pixel Pixel.
  28017. * @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback
  28018. * Layer callback. This callback will receive two arguments: first is the
  28019. * {@link ol.layer.Layer layer}, second argument is an array representing
  28020. * [R, G, B, A] pixel values (0 - 255) and will be `null` for layer types
  28021. * that do not currently support this argument. To stop detection, callback
  28022. * functions can return a truthy value.
  28023. * @param {S=} opt_this Value to use as `this` when executing `callback`.
  28024. * @param {(function(this: U, ol.layer.Layer): boolean)=} opt_layerFilter Layer
  28025. * filter function. The filter function will receive one argument, the
  28026. * {@link ol.layer.Layer layer-candidate} and it should return a boolean
  28027. * value. Only layers which are visible and for which this function returns
  28028. * `true` will be tested for features. By default, all visible layers will
  28029. * be tested.
  28030. * @param {U=} opt_this2 Value to use as `this` when executing `layerFilter`.
  28031. * @return {T|undefined} Callback result, i.e. the return value of last
  28032. * callback execution, or the first truthy callback return value.
  28033. * @template S,T,U
  28034. * @api
  28035. */
  28036. ol.Map.prototype.forEachLayerAtPixel = function(pixel, callback, opt_this, opt_layerFilter, opt_this2) {
  28037. if (!this.frameState_) {
  28038. return;
  28039. }
  28040. var thisArg = opt_this !== undefined ? opt_this : null;
  28041. var layerFilter = opt_layerFilter !== undefined ?
  28042. opt_layerFilter : ol.functions.TRUE;
  28043. var thisArg2 = opt_this2 !== undefined ? opt_this2 : null;
  28044. return this.renderer_.forEachLayerAtPixel(
  28045. pixel, this.frameState_, callback, thisArg,
  28046. layerFilter, thisArg2);
  28047. };
  28048. /**
  28049. * Detect if features intersect a pixel on the viewport. Layers included in the
  28050. * detection can be configured through `opt_layerFilter`.
  28051. * @param {ol.Pixel} pixel Pixel.
  28052. * @param {olx.AtPixelOptions=} opt_options Optional options.
  28053. * @return {boolean} Is there a feature at the given pixel?
  28054. * @template U
  28055. * @api
  28056. */
  28057. ol.Map.prototype.hasFeatureAtPixel = function(pixel, opt_options) {
  28058. if (!this.frameState_) {
  28059. return false;
  28060. }
  28061. var coordinate = this.getCoordinateFromPixel(pixel);
  28062. opt_options = opt_options !== undefined ? opt_options : {};
  28063. var layerFilter = opt_options.layerFilter !== undefined ?
  28064. opt_options.layerFilter : ol.functions.TRUE;
  28065. var hitTolerance = opt_options.hitTolerance !== undefined ?
  28066. opt_options.hitTolerance * this.frameState_.pixelRatio : 0;
  28067. return this.renderer_.hasFeatureAtCoordinate(
  28068. coordinate, this.frameState_, hitTolerance, layerFilter, null);
  28069. };
  28070. /**
  28071. * Returns the coordinate in view projection for a browser event.
  28072. * @param {Event} event Event.
  28073. * @return {ol.Coordinate} Coordinate.
  28074. * @api
  28075. */
  28076. ol.Map.prototype.getEventCoordinate = function(event) {
  28077. return this.getCoordinateFromPixel(this.getEventPixel(event));
  28078. };
  28079. /**
  28080. * Returns the map pixel position for a browser event relative to the viewport.
  28081. * @param {Event} event Event.
  28082. * @return {ol.Pixel} Pixel.
  28083. * @api
  28084. */
  28085. ol.Map.prototype.getEventPixel = function(event) {
  28086. var viewportPosition = this.viewport_.getBoundingClientRect();
  28087. var eventPosition = event.changedTouches ? event.changedTouches[0] : event;
  28088. return [
  28089. eventPosition.clientX - viewportPosition.left,
  28090. eventPosition.clientY - viewportPosition.top
  28091. ];
  28092. };
  28093. /**
  28094. * Get the target in which this map is rendered.
  28095. * Note that this returns what is entered as an option or in setTarget:
  28096. * if that was an element, it returns an element; if a string, it returns that.
  28097. * @return {Element|string|undefined} The Element or id of the Element that the
  28098. * map is rendered in.
  28099. * @observable
  28100. * @api
  28101. */
  28102. ol.Map.prototype.getTarget = function() {
  28103. return /** @type {Element|string|undefined} */ (
  28104. this.get(ol.MapProperty.TARGET));
  28105. };
  28106. /**
  28107. * Get the DOM element into which this map is rendered. In contrast to
  28108. * `getTarget` this method always return an `Element`, or `null` if the
  28109. * map has no target.
  28110. * @return {Element} The element that the map is rendered in.
  28111. * @api
  28112. */
  28113. ol.Map.prototype.getTargetElement = function() {
  28114. var target = this.getTarget();
  28115. if (target !== undefined) {
  28116. return typeof target === 'string' ?
  28117. document.getElementById(target) :
  28118. target;
  28119. } else {
  28120. return null;
  28121. }
  28122. };
  28123. /**
  28124. * Get the coordinate for a given pixel. This returns a coordinate in the
  28125. * map view projection.
  28126. * @param {ol.Pixel} pixel Pixel position in the map viewport.
  28127. * @return {ol.Coordinate} The coordinate for the pixel position.
  28128. * @api
  28129. */
  28130. ol.Map.prototype.getCoordinateFromPixel = function(pixel) {
  28131. var frameState = this.frameState_;
  28132. if (!frameState) {
  28133. return null;
  28134. } else {
  28135. return ol.transform.apply(frameState.pixelToCoordinateTransform, pixel.slice());
  28136. }
  28137. };
  28138. /**
  28139. * Get the map controls. Modifying this collection changes the controls
  28140. * associated with the map.
  28141. * @return {ol.Collection.<ol.control.Control>} Controls.
  28142. * @api
  28143. */
  28144. ol.Map.prototype.getControls = function() {
  28145. return this.controls_;
  28146. };
  28147. /**
  28148. * Get the map overlays. Modifying this collection changes the overlays
  28149. * associated with the map.
  28150. * @return {ol.Collection.<ol.Overlay>} Overlays.
  28151. * @api
  28152. */
  28153. ol.Map.prototype.getOverlays = function() {
  28154. return this.overlays_;
  28155. };
  28156. /**
  28157. * Get an overlay by its identifier (the value returned by overlay.getId()).
  28158. * Note that the index treats string and numeric identifiers as the same. So
  28159. * `map.getOverlayById(2)` will return an overlay with id `'2'` or `2`.
  28160. * @param {string|number} id Overlay identifier.
  28161. * @return {ol.Overlay} Overlay.
  28162. * @api
  28163. */
  28164. ol.Map.prototype.getOverlayById = function(id) {
  28165. var overlay = this.overlayIdIndex_[id.toString()];
  28166. return overlay !== undefined ? overlay : null;
  28167. };
  28168. /**
  28169. * Get the map interactions. Modifying this collection changes the interactions
  28170. * associated with the map.
  28171. *
  28172. * Interactions are used for e.g. pan, zoom and rotate.
  28173. * @return {ol.Collection.<ol.interaction.Interaction>} Interactions.
  28174. * @api
  28175. */
  28176. ol.Map.prototype.getInteractions = function() {
  28177. return this.interactions_;
  28178. };
  28179. /**
  28180. * Get the layergroup associated with this map.
  28181. * @return {ol.layer.Group} A layer group containing the layers in this map.
  28182. * @observable
  28183. * @api
  28184. */
  28185. ol.Map.prototype.getLayerGroup = function() {
  28186. return /** @type {ol.layer.Group} */ (this.get(ol.MapProperty.LAYERGROUP));
  28187. };
  28188. /**
  28189. * Get the collection of layers associated with this map.
  28190. * @return {!ol.Collection.<ol.layer.Base>} Layers.
  28191. * @api
  28192. */
  28193. ol.Map.prototype.getLayers = function() {
  28194. var layers = this.getLayerGroup().getLayers();
  28195. return layers;
  28196. };
  28197. /**
  28198. * Get the pixel for a coordinate. This takes a coordinate in the map view
  28199. * projection and returns the corresponding pixel.
  28200. * @param {ol.Coordinate} coordinate A map coordinate.
  28201. * @return {ol.Pixel} A pixel position in the map viewport.
  28202. * @api
  28203. */
  28204. ol.Map.prototype.getPixelFromCoordinate = function(coordinate) {
  28205. var frameState = this.frameState_;
  28206. if (!frameState) {
  28207. return null;
  28208. } else {
  28209. return ol.transform.apply(frameState.coordinateToPixelTransform,
  28210. coordinate.slice(0, 2));
  28211. }
  28212. };
  28213. /**
  28214. * Get the map renderer.
  28215. * @return {ol.renderer.Map} Renderer
  28216. */
  28217. ol.Map.prototype.getRenderer = function() {
  28218. return this.renderer_;
  28219. };
  28220. /**
  28221. * Get the size of this map.
  28222. * @return {ol.Size|undefined} The size in pixels of the map in the DOM.
  28223. * @observable
  28224. * @api
  28225. */
  28226. ol.Map.prototype.getSize = function() {
  28227. return /** @type {ol.Size|undefined} */ (this.get(ol.MapProperty.SIZE));
  28228. };
  28229. /**
  28230. * Get the view associated with this map. A view manages properties such as
  28231. * center and resolution.
  28232. * @return {ol.View} The view that controls this map.
  28233. * @observable
  28234. * @api
  28235. */
  28236. ol.Map.prototype.getView = function() {
  28237. return /** @type {ol.View} */ (this.get(ol.MapProperty.VIEW));
  28238. };
  28239. /**
  28240. * Get the element that serves as the map viewport.
  28241. * @return {Element} Viewport.
  28242. * @api
  28243. */
  28244. ol.Map.prototype.getViewport = function() {
  28245. return this.viewport_;
  28246. };
  28247. /**
  28248. * Get the element that serves as the container for overlays. Elements added to
  28249. * this container will let mousedown and touchstart events through to the map,
  28250. * so clicks and gestures on an overlay will trigger {@link ol.MapBrowserEvent}
  28251. * events.
  28252. * @return {!Element} The map's overlay container.
  28253. */
  28254. ol.Map.prototype.getOverlayContainer = function() {
  28255. return this.overlayContainer_;
  28256. };
  28257. /**
  28258. * Get the element that serves as a container for overlays that don't allow
  28259. * event propagation. Elements added to this container won't let mousedown and
  28260. * touchstart events through to the map, so clicks and gestures on an overlay
  28261. * don't trigger any {@link ol.MapBrowserEvent}.
  28262. * @return {!Element} The map's overlay container that stops events.
  28263. */
  28264. ol.Map.prototype.getOverlayContainerStopEvent = function() {
  28265. return this.overlayContainerStopEvent_;
  28266. };
  28267. /**
  28268. * @param {ol.Tile} tile Tile.
  28269. * @param {string} tileSourceKey Tile source key.
  28270. * @param {ol.Coordinate} tileCenter Tile center.
  28271. * @param {number} tileResolution Tile resolution.
  28272. * @return {number} Tile priority.
  28273. */
  28274. ol.Map.prototype.getTilePriority = function(tile, tileSourceKey, tileCenter, tileResolution) {
  28275. // Filter out tiles at higher zoom levels than the current zoom level, or that
  28276. // are outside the visible extent.
  28277. var frameState = this.frameState_;
  28278. if (!frameState || !(tileSourceKey in frameState.wantedTiles)) {
  28279. return ol.structs.PriorityQueue.DROP;
  28280. }
  28281. if (!frameState.wantedTiles[tileSourceKey][tile.getKey()]) {
  28282. return ol.structs.PriorityQueue.DROP;
  28283. }
  28284. // Prioritize the highest zoom level tiles closest to the focus.
  28285. // Tiles at higher zoom levels are prioritized using Math.log(tileResolution).
  28286. // Within a zoom level, tiles are prioritized by the distance in pixels
  28287. // between the center of the tile and the focus. The factor of 65536 means
  28288. // that the prioritization should behave as desired for tiles up to
  28289. // 65536 * Math.log(2) = 45426 pixels from the focus.
  28290. var deltaX = tileCenter[0] - frameState.focus[0];
  28291. var deltaY = tileCenter[1] - frameState.focus[1];
  28292. return 65536 * Math.log(tileResolution) +
  28293. Math.sqrt(deltaX * deltaX + deltaY * deltaY) / tileResolution;
  28294. };
  28295. /**
  28296. * @param {Event} browserEvent Browser event.
  28297. * @param {string=} opt_type Type.
  28298. */
  28299. ol.Map.prototype.handleBrowserEvent = function(browserEvent, opt_type) {
  28300. var type = opt_type || browserEvent.type;
  28301. var mapBrowserEvent = new ol.MapBrowserEvent(type, this, browserEvent);
  28302. this.handleMapBrowserEvent(mapBrowserEvent);
  28303. };
  28304. /**
  28305. * @param {ol.MapBrowserEvent} mapBrowserEvent The event to handle.
  28306. */
  28307. ol.Map.prototype.handleMapBrowserEvent = function(mapBrowserEvent) {
  28308. if (!this.frameState_) {
  28309. // With no view defined, we cannot translate pixels into geographical
  28310. // coordinates so interactions cannot be used.
  28311. return;
  28312. }
  28313. this.focus_ = mapBrowserEvent.coordinate;
  28314. mapBrowserEvent.frameState = this.frameState_;
  28315. var interactionsArray = this.getInteractions().getArray();
  28316. var i;
  28317. if (this.dispatchEvent(mapBrowserEvent) !== false) {
  28318. for (i = interactionsArray.length - 1; i >= 0; i--) {
  28319. var interaction = interactionsArray[i];
  28320. if (!interaction.getActive()) {
  28321. continue;
  28322. }
  28323. var cont = interaction.handleEvent(mapBrowserEvent);
  28324. if (!cont) {
  28325. break;
  28326. }
  28327. }
  28328. }
  28329. };
  28330. /**
  28331. * @protected
  28332. */
  28333. ol.Map.prototype.handlePostRender = function() {
  28334. var frameState = this.frameState_;
  28335. // Manage the tile queue
  28336. // Image loads are expensive and a limited resource, so try to use them
  28337. // efficiently:
  28338. // * When the view is static we allow a large number of parallel tile loads
  28339. // to complete the frame as quickly as possible.
  28340. // * When animating or interacting, image loads can cause janks, so we reduce
  28341. // the maximum number of loads per frame and limit the number of parallel
  28342. // tile loads to remain reactive to view changes and to reduce the chance of
  28343. // loading tiles that will quickly disappear from view.
  28344. var tileQueue = this.tileQueue_;
  28345. if (!tileQueue.isEmpty()) {
  28346. var maxTotalLoading = 16;
  28347. var maxNewLoads = maxTotalLoading;
  28348. if (frameState) {
  28349. var hints = frameState.viewHints;
  28350. if (hints[ol.ViewHint.ANIMATING]) {
  28351. maxTotalLoading = this.loadTilesWhileAnimating_ ? 8 : 0;
  28352. maxNewLoads = 2;
  28353. }
  28354. if (hints[ol.ViewHint.INTERACTING]) {
  28355. maxTotalLoading = this.loadTilesWhileInteracting_ ? 8 : 0;
  28356. maxNewLoads = 2;
  28357. }
  28358. }
  28359. if (tileQueue.getTilesLoading() < maxTotalLoading) {
  28360. tileQueue.reprioritize(); // FIXME only call if view has changed
  28361. tileQueue.loadMoreTiles(maxTotalLoading, maxNewLoads);
  28362. }
  28363. }
  28364. var postRenderFunctions = this.postRenderFunctions_;
  28365. var i, ii;
  28366. for (i = 0, ii = postRenderFunctions.length; i < ii; ++i) {
  28367. postRenderFunctions[i](this, frameState);
  28368. }
  28369. postRenderFunctions.length = 0;
  28370. };
  28371. /**
  28372. * @private
  28373. */
  28374. ol.Map.prototype.handleSizeChanged_ = function() {
  28375. this.render();
  28376. };
  28377. /**
  28378. * @private
  28379. */
  28380. ol.Map.prototype.handleTargetChanged_ = function() {
  28381. // target may be undefined, null, a string or an Element.
  28382. // If it's a string we convert it to an Element before proceeding.
  28383. // If it's not now an Element we remove the viewport from the DOM.
  28384. // If it's an Element we append the viewport element to it.
  28385. var targetElement;
  28386. if (this.getTarget()) {
  28387. targetElement = this.getTargetElement();
  28388. }
  28389. if (this.keyHandlerKeys_) {
  28390. for (var i = 0, ii = this.keyHandlerKeys_.length; i < ii; ++i) {
  28391. ol.events.unlistenByKey(this.keyHandlerKeys_[i]);
  28392. }
  28393. this.keyHandlerKeys_ = null;
  28394. }
  28395. if (!targetElement) {
  28396. ol.dom.removeNode(this.viewport_);
  28397. if (this.handleResize_ !== undefined) {
  28398. window.removeEventListener(ol.events.EventType.RESIZE,
  28399. this.handleResize_, false);
  28400. this.handleResize_ = undefined;
  28401. }
  28402. } else {
  28403. targetElement.appendChild(this.viewport_);
  28404. var keyboardEventTarget = !this.keyboardEventTarget_ ?
  28405. targetElement : this.keyboardEventTarget_;
  28406. this.keyHandlerKeys_ = [
  28407. ol.events.listen(keyboardEventTarget, ol.events.EventType.KEYDOWN,
  28408. this.handleBrowserEvent, this),
  28409. ol.events.listen(keyboardEventTarget, ol.events.EventType.KEYPRESS,
  28410. this.handleBrowserEvent, this)
  28411. ];
  28412. if (!this.handleResize_) {
  28413. this.handleResize_ = this.updateSize.bind(this);
  28414. window.addEventListener(ol.events.EventType.RESIZE,
  28415. this.handleResize_, false);
  28416. }
  28417. }
  28418. this.updateSize();
  28419. // updateSize calls setSize, so no need to call this.render
  28420. // ourselves here.
  28421. };
  28422. /**
  28423. * @private
  28424. */
  28425. ol.Map.prototype.handleTileChange_ = function() {
  28426. this.render();
  28427. };
  28428. /**
  28429. * @private
  28430. */
  28431. ol.Map.prototype.handleViewPropertyChanged_ = function() {
  28432. this.render();
  28433. };
  28434. /**
  28435. * @private
  28436. */
  28437. ol.Map.prototype.handleViewChanged_ = function() {
  28438. if (this.viewPropertyListenerKey_) {
  28439. ol.events.unlistenByKey(this.viewPropertyListenerKey_);
  28440. this.viewPropertyListenerKey_ = null;
  28441. }
  28442. if (this.viewChangeListenerKey_) {
  28443. ol.events.unlistenByKey(this.viewChangeListenerKey_);
  28444. this.viewChangeListenerKey_ = null;
  28445. }
  28446. var view = this.getView();
  28447. if (view) {
  28448. this.viewport_.setAttribute('data-view', ol.getUid(view));
  28449. this.viewPropertyListenerKey_ = ol.events.listen(
  28450. view, ol.ObjectEventType.PROPERTYCHANGE,
  28451. this.handleViewPropertyChanged_, this);
  28452. this.viewChangeListenerKey_ = ol.events.listen(
  28453. view, ol.events.EventType.CHANGE,
  28454. this.handleViewPropertyChanged_, this);
  28455. }
  28456. this.render();
  28457. };
  28458. /**
  28459. * @private
  28460. */
  28461. ol.Map.prototype.handleLayerGroupChanged_ = function() {
  28462. if (this.layerGroupPropertyListenerKeys_) {
  28463. this.layerGroupPropertyListenerKeys_.forEach(ol.events.unlistenByKey);
  28464. this.layerGroupPropertyListenerKeys_ = null;
  28465. }
  28466. var layerGroup = this.getLayerGroup();
  28467. if (layerGroup) {
  28468. this.layerGroupPropertyListenerKeys_ = [
  28469. ol.events.listen(
  28470. layerGroup, ol.ObjectEventType.PROPERTYCHANGE,
  28471. this.render, this),
  28472. ol.events.listen(
  28473. layerGroup, ol.events.EventType.CHANGE,
  28474. this.render, this)
  28475. ];
  28476. }
  28477. this.render();
  28478. };
  28479. /**
  28480. * @return {boolean} Is rendered.
  28481. */
  28482. ol.Map.prototype.isRendered = function() {
  28483. return !!this.frameState_;
  28484. };
  28485. /**
  28486. * Requests an immediate render in a synchronous manner.
  28487. * @api
  28488. */
  28489. ol.Map.prototype.renderSync = function() {
  28490. if (this.animationDelayKey_) {
  28491. cancelAnimationFrame(this.animationDelayKey_);
  28492. }
  28493. this.animationDelay_();
  28494. };
  28495. /**
  28496. * Request a map rendering (at the next animation frame).
  28497. * @api
  28498. */
  28499. ol.Map.prototype.render = function() {
  28500. if (this.animationDelayKey_ === undefined) {
  28501. this.animationDelayKey_ = requestAnimationFrame(
  28502. this.animationDelay_);
  28503. }
  28504. };
  28505. /**
  28506. * Remove the given control from the map.
  28507. * @param {ol.control.Control} control Control.
  28508. * @return {ol.control.Control|undefined} The removed control (or undefined
  28509. * if the control was not found).
  28510. * @api
  28511. */
  28512. ol.Map.prototype.removeControl = function(control) {
  28513. return this.getControls().remove(control);
  28514. };
  28515. /**
  28516. * Remove the given interaction from the map.
  28517. * @param {ol.interaction.Interaction} interaction Interaction to remove.
  28518. * @return {ol.interaction.Interaction|undefined} The removed interaction (or
  28519. * undefined if the interaction was not found).
  28520. * @api
  28521. */
  28522. ol.Map.prototype.removeInteraction = function(interaction) {
  28523. return this.getInteractions().remove(interaction);
  28524. };
  28525. /**
  28526. * Removes the given layer from the map.
  28527. * @param {ol.layer.Base} layer Layer.
  28528. * @return {ol.layer.Base|undefined} The removed layer (or undefined if the
  28529. * layer was not found).
  28530. * @api
  28531. */
  28532. ol.Map.prototype.removeLayer = function(layer) {
  28533. var layers = this.getLayerGroup().getLayers();
  28534. return layers.remove(layer);
  28535. };
  28536. /**
  28537. * Remove the given overlay from the map.
  28538. * @param {ol.Overlay} overlay Overlay.
  28539. * @return {ol.Overlay|undefined} The removed overlay (or undefined
  28540. * if the overlay was not found).
  28541. * @api
  28542. */
  28543. ol.Map.prototype.removeOverlay = function(overlay) {
  28544. return this.getOverlays().remove(overlay);
  28545. };
  28546. /**
  28547. * @param {number} time Time.
  28548. * @private
  28549. */
  28550. ol.Map.prototype.renderFrame_ = function(time) {
  28551. var i, ii, viewState;
  28552. var size = this.getSize();
  28553. var view = this.getView();
  28554. var extent = ol.extent.createEmpty();
  28555. var previousFrameState = this.frameState_;
  28556. /** @type {?olx.FrameState} */
  28557. var frameState = null;
  28558. if (size !== undefined && ol.size.hasArea(size) && view && view.isDef()) {
  28559. var viewHints = view.getHints(this.frameState_ ? this.frameState_.viewHints : undefined);
  28560. var layerStatesArray = this.getLayerGroup().getLayerStatesArray();
  28561. var layerStates = {};
  28562. for (i = 0, ii = layerStatesArray.length; i < ii; ++i) {
  28563. layerStates[ol.getUid(layerStatesArray[i].layer)] = layerStatesArray[i];
  28564. }
  28565. viewState = view.getState();
  28566. frameState = /** @type {olx.FrameState} */ ({
  28567. animate: false,
  28568. attributions: {},
  28569. coordinateToPixelTransform: this.coordinateToPixelTransform_,
  28570. extent: extent,
  28571. focus: !this.focus_ ? viewState.center : this.focus_,
  28572. index: this.frameIndex_++,
  28573. layerStates: layerStates,
  28574. layerStatesArray: layerStatesArray,
  28575. logos: ol.obj.assign({}, this.logos_),
  28576. pixelRatio: this.pixelRatio_,
  28577. pixelToCoordinateTransform: this.pixelToCoordinateTransform_,
  28578. postRenderFunctions: [],
  28579. size: size,
  28580. skippedFeatureUids: this.skippedFeatureUids_,
  28581. tileQueue: this.tileQueue_,
  28582. time: time,
  28583. usedTiles: {},
  28584. viewState: viewState,
  28585. viewHints: viewHints,
  28586. wantedTiles: {}
  28587. });
  28588. }
  28589. if (frameState) {
  28590. frameState.extent = ol.extent.getForViewAndSize(viewState.center,
  28591. viewState.resolution, viewState.rotation, frameState.size, extent);
  28592. }
  28593. this.frameState_ = frameState;
  28594. this.renderer_.renderFrame(frameState);
  28595. if (frameState) {
  28596. if (frameState.animate) {
  28597. this.render();
  28598. }
  28599. Array.prototype.push.apply(
  28600. this.postRenderFunctions_, frameState.postRenderFunctions);
  28601. if (previousFrameState) {
  28602. var moveStart = !this.previousExtent_ ||
  28603. (!ol.extent.isEmpty(this.previousExtent_) &&
  28604. !ol.extent.equals(frameState.extent, this.previousExtent_));
  28605. if (moveStart) {
  28606. this.dispatchEvent(
  28607. new ol.MapEvent(ol.MapEventType.MOVESTART, this, previousFrameState));
  28608. this.previousExtent_ = ol.extent.createOrUpdateEmpty(this.previousExtent_);
  28609. }
  28610. }
  28611. var idle = this.previousExtent_ &&
  28612. !frameState.viewHints[ol.ViewHint.ANIMATING] &&
  28613. !frameState.viewHints[ol.ViewHint.INTERACTING] &&
  28614. !ol.extent.equals(frameState.extent, this.previousExtent_);
  28615. if (idle) {
  28616. this.dispatchEvent(
  28617. new ol.MapEvent(ol.MapEventType.MOVEEND, this, frameState));
  28618. ol.extent.clone(frameState.extent, this.previousExtent_);
  28619. }
  28620. }
  28621. this.dispatchEvent(
  28622. new ol.MapEvent(ol.MapEventType.POSTRENDER, this, frameState));
  28623. setTimeout(this.handlePostRender.bind(this), 0);
  28624. };
  28625. /**
  28626. * Sets the layergroup of this map.
  28627. * @param {ol.layer.Group} layerGroup A layer group containing the layers in
  28628. * this map.
  28629. * @observable
  28630. * @api
  28631. */
  28632. ol.Map.prototype.setLayerGroup = function(layerGroup) {
  28633. this.set(ol.MapProperty.LAYERGROUP, layerGroup);
  28634. };
  28635. /**
  28636. * Set the size of this map.
  28637. * @param {ol.Size|undefined} size The size in pixels of the map in the DOM.
  28638. * @observable
  28639. * @api
  28640. */
  28641. ol.Map.prototype.setSize = function(size) {
  28642. this.set(ol.MapProperty.SIZE, size);
  28643. };
  28644. /**
  28645. * Set the target element to render this map into.
  28646. * @param {Element|string|undefined} target The Element or id of the Element
  28647. * that the map is rendered in.
  28648. * @observable
  28649. * @api
  28650. */
  28651. ol.Map.prototype.setTarget = function(target) {
  28652. this.set(ol.MapProperty.TARGET, target);
  28653. };
  28654. /**
  28655. * Set the view for this map.
  28656. * @param {ol.View} view The view that controls this map.
  28657. * @observable
  28658. * @api
  28659. */
  28660. ol.Map.prototype.setView = function(view) {
  28661. this.set(ol.MapProperty.VIEW, view);
  28662. };
  28663. /**
  28664. * @param {ol.Feature} feature Feature.
  28665. */
  28666. ol.Map.prototype.skipFeature = function(feature) {
  28667. var featureUid = ol.getUid(feature).toString();
  28668. this.skippedFeatureUids_[featureUid] = true;
  28669. this.render();
  28670. };
  28671. /**
  28672. * Force a recalculation of the map viewport size. This should be called when
  28673. * third-party code changes the size of the map viewport.
  28674. * @api
  28675. */
  28676. ol.Map.prototype.updateSize = function() {
  28677. var targetElement = this.getTargetElement();
  28678. if (!targetElement) {
  28679. this.setSize(undefined);
  28680. } else {
  28681. var computedStyle = getComputedStyle(targetElement);
  28682. this.setSize([
  28683. targetElement.offsetWidth -
  28684. parseFloat(computedStyle['borderLeftWidth']) -
  28685. parseFloat(computedStyle['paddingLeft']) -
  28686. parseFloat(computedStyle['paddingRight']) -
  28687. parseFloat(computedStyle['borderRightWidth']),
  28688. targetElement.offsetHeight -
  28689. parseFloat(computedStyle['borderTopWidth']) -
  28690. parseFloat(computedStyle['paddingTop']) -
  28691. parseFloat(computedStyle['paddingBottom']) -
  28692. parseFloat(computedStyle['borderBottomWidth'])
  28693. ]);
  28694. }
  28695. };
  28696. /**
  28697. * @param {ol.Feature} feature Feature.
  28698. */
  28699. ol.Map.prototype.unskipFeature = function(feature) {
  28700. var featureUid = ol.getUid(feature).toString();
  28701. delete this.skippedFeatureUids_[featureUid];
  28702. this.render();
  28703. };
  28704. /**
  28705. * @param {olx.MapOptions} options Map options.
  28706. * @return {ol.MapOptionsInternal} Internal map options.
  28707. */
  28708. ol.Map.createOptionsInternal = function(options) {
  28709. /**
  28710. * @type {Element|Document}
  28711. */
  28712. var keyboardEventTarget = null;
  28713. if (options.keyboardEventTarget !== undefined) {
  28714. keyboardEventTarget = typeof options.keyboardEventTarget === 'string' ?
  28715. document.getElementById(options.keyboardEventTarget) :
  28716. options.keyboardEventTarget;
  28717. }
  28718. /**
  28719. * @type {Object.<string, *>}
  28720. */
  28721. var values = {};
  28722. var logos = {};
  28723. if (options.logo === undefined ||
  28724. (typeof options.logo === 'boolean' && options.logo)) {
  28725. logos[ol.OL_LOGO_URL] = ol.OL_URL;
  28726. } else {
  28727. var logo = options.logo;
  28728. if (typeof logo === 'string') {
  28729. logos[logo] = '';
  28730. } else if (logo instanceof HTMLElement) {
  28731. logos[ol.getUid(logo).toString()] = logo;
  28732. } else if (logo) {
  28733. ol.asserts.assert(typeof logo.href == 'string', 44); // `logo.href` should be a string.
  28734. ol.asserts.assert(typeof logo.src == 'string', 45); // `logo.src` should be a string.
  28735. logos[logo.src] = logo.href;
  28736. }
  28737. }
  28738. var layerGroup = (options.layers instanceof ol.layer.Group) ?
  28739. options.layers : new ol.layer.Group({layers: options.layers});
  28740. values[ol.MapProperty.LAYERGROUP] = layerGroup;
  28741. values[ol.MapProperty.TARGET] = options.target;
  28742. values[ol.MapProperty.VIEW] = options.view !== undefined ?
  28743. options.view : new ol.View();
  28744. /**
  28745. * @type {function(new: ol.renderer.Map, Element, ol.Map)}
  28746. */
  28747. var rendererConstructor = ol.renderer.Map;
  28748. /**
  28749. * @type {Array.<ol.renderer.Type>}
  28750. */
  28751. var rendererTypes;
  28752. if (options.renderer !== undefined) {
  28753. if (Array.isArray(options.renderer)) {
  28754. rendererTypes = options.renderer;
  28755. } else if (typeof options.renderer === 'string') {
  28756. rendererTypes = [options.renderer];
  28757. } else {
  28758. ol.asserts.assert(false, 46); // Incorrect format for `renderer` option
  28759. }
  28760. if (rendererTypes.indexOf(/** @type {ol.renderer.Type} */ ('dom')) >= 0) {
  28761. rendererTypes = rendererTypes.concat(ol.DEFAULT_RENDERER_TYPES);
  28762. }
  28763. } else {
  28764. rendererTypes = ol.DEFAULT_RENDERER_TYPES;
  28765. }
  28766. var i, ii;
  28767. for (i = 0, ii = rendererTypes.length; i < ii; ++i) {
  28768. /** @type {ol.renderer.Type} */
  28769. var rendererType = rendererTypes[i];
  28770. if (ol.ENABLE_CANVAS && rendererType == ol.renderer.Type.CANVAS) {
  28771. if (ol.has.CANVAS) {
  28772. rendererConstructor = ol.renderer.canvas.Map;
  28773. break;
  28774. }
  28775. } else if (ol.ENABLE_WEBGL && rendererType == ol.renderer.Type.WEBGL) {
  28776. if (ol.has.WEBGL) {
  28777. rendererConstructor = ol.renderer.webgl.Map;
  28778. break;
  28779. }
  28780. }
  28781. }
  28782. var controls;
  28783. if (options.controls !== undefined) {
  28784. if (Array.isArray(options.controls)) {
  28785. controls = new ol.Collection(options.controls.slice());
  28786. } else {
  28787. ol.asserts.assert(options.controls instanceof ol.Collection,
  28788. 47); // Expected `controls` to be an array or an `ol.Collection`
  28789. controls = options.controls;
  28790. }
  28791. } else {
  28792. controls = ol.control.defaults();
  28793. }
  28794. var interactions;
  28795. if (options.interactions !== undefined) {
  28796. if (Array.isArray(options.interactions)) {
  28797. interactions = new ol.Collection(options.interactions.slice());
  28798. } else {
  28799. ol.asserts.assert(options.interactions instanceof ol.Collection,
  28800. 48); // Expected `interactions` to be an array or an `ol.Collection`
  28801. interactions = options.interactions;
  28802. }
  28803. } else {
  28804. interactions = ol.interaction.defaults();
  28805. }
  28806. var overlays;
  28807. if (options.overlays !== undefined) {
  28808. if (Array.isArray(options.overlays)) {
  28809. overlays = new ol.Collection(options.overlays.slice());
  28810. } else {
  28811. ol.asserts.assert(options.overlays instanceof ol.Collection,
  28812. 49); // Expected `overlays` to be an array or an `ol.Collection`
  28813. overlays = options.overlays;
  28814. }
  28815. } else {
  28816. overlays = new ol.Collection();
  28817. }
  28818. return {
  28819. controls: controls,
  28820. interactions: interactions,
  28821. keyboardEventTarget: keyboardEventTarget,
  28822. logos: logos,
  28823. overlays: overlays,
  28824. rendererConstructor: rendererConstructor,
  28825. values: values
  28826. };
  28827. };
  28828. goog.provide('ol.OverlayPositioning');
  28829. /**
  28830. * Overlay position: `'bottom-left'`, `'bottom-center'`, `'bottom-right'`,
  28831. * `'center-left'`, `'center-center'`, `'center-right'`, `'top-left'`,
  28832. * `'top-center'`, `'top-right'`
  28833. * @enum {string}
  28834. */
  28835. ol.OverlayPositioning = {
  28836. BOTTOM_LEFT: 'bottom-left',
  28837. BOTTOM_CENTER: 'bottom-center',
  28838. BOTTOM_RIGHT: 'bottom-right',
  28839. CENTER_LEFT: 'center-left',
  28840. CENTER_CENTER: 'center-center',
  28841. CENTER_RIGHT: 'center-right',
  28842. TOP_LEFT: 'top-left',
  28843. TOP_CENTER: 'top-center',
  28844. TOP_RIGHT: 'top-right'
  28845. };
  28846. goog.provide('ol.Overlay');
  28847. goog.require('ol');
  28848. goog.require('ol.MapEventType');
  28849. goog.require('ol.Object');
  28850. goog.require('ol.OverlayPositioning');
  28851. goog.require('ol.css');
  28852. goog.require('ol.dom');
  28853. goog.require('ol.events');
  28854. goog.require('ol.extent');
  28855. /**
  28856. * @classdesc
  28857. * An element to be displayed over the map and attached to a single map
  28858. * location. Like {@link ol.control.Control}, Overlays are visible widgets.
  28859. * Unlike Controls, they are not in a fixed position on the screen, but are tied
  28860. * to a geographical coordinate, so panning the map will move an Overlay but not
  28861. * a Control.
  28862. *
  28863. * Example:
  28864. *
  28865. * var popup = new ol.Overlay({
  28866. * element: document.getElementById('popup')
  28867. * });
  28868. * popup.setPosition(coordinate);
  28869. * map.addOverlay(popup);
  28870. *
  28871. * @constructor
  28872. * @extends {ol.Object}
  28873. * @param {olx.OverlayOptions} options Overlay options.
  28874. * @api
  28875. */
  28876. ol.Overlay = function(options) {
  28877. ol.Object.call(this);
  28878. /**
  28879. * @private
  28880. * @type {number|string|undefined}
  28881. */
  28882. this.id_ = options.id;
  28883. /**
  28884. * @private
  28885. * @type {boolean}
  28886. */
  28887. this.insertFirst_ = options.insertFirst !== undefined ?
  28888. options.insertFirst : true;
  28889. /**
  28890. * @private
  28891. * @type {boolean}
  28892. */
  28893. this.stopEvent_ = options.stopEvent !== undefined ? options.stopEvent : true;
  28894. /**
  28895. * @private
  28896. * @type {Element}
  28897. */
  28898. this.element_ = document.createElement('DIV');
  28899. this.element_.className = 'ol-overlay-container ' + ol.css.CLASS_SELECTABLE;
  28900. this.element_.style.position = 'absolute';
  28901. /**
  28902. * @protected
  28903. * @type {boolean}
  28904. */
  28905. this.autoPan = options.autoPan !== undefined ? options.autoPan : false;
  28906. /**
  28907. * @private
  28908. * @type {olx.OverlayPanOptions}
  28909. */
  28910. this.autoPanAnimation_ = options.autoPanAnimation ||
  28911. /** @type {olx.OverlayPanOptions} */ ({});
  28912. /**
  28913. * @private
  28914. * @type {number}
  28915. */
  28916. this.autoPanMargin_ = options.autoPanMargin !== undefined ?
  28917. options.autoPanMargin : 20;
  28918. /**
  28919. * @private
  28920. * @type {{bottom_: string,
  28921. * left_: string,
  28922. * right_: string,
  28923. * top_: string,
  28924. * visible: boolean}}
  28925. */
  28926. this.rendered_ = {
  28927. bottom_: '',
  28928. left_: '',
  28929. right_: '',
  28930. top_: '',
  28931. visible: true
  28932. };
  28933. /**
  28934. * @private
  28935. * @type {?ol.EventsKey}
  28936. */
  28937. this.mapPostrenderListenerKey_ = null;
  28938. ol.events.listen(
  28939. this, ol.Object.getChangeEventType(ol.Overlay.Property_.ELEMENT),
  28940. this.handleElementChanged, this);
  28941. ol.events.listen(
  28942. this, ol.Object.getChangeEventType(ol.Overlay.Property_.MAP),
  28943. this.handleMapChanged, this);
  28944. ol.events.listen(
  28945. this, ol.Object.getChangeEventType(ol.Overlay.Property_.OFFSET),
  28946. this.handleOffsetChanged, this);
  28947. ol.events.listen(
  28948. this, ol.Object.getChangeEventType(ol.Overlay.Property_.POSITION),
  28949. this.handlePositionChanged, this);
  28950. ol.events.listen(
  28951. this, ol.Object.getChangeEventType(ol.Overlay.Property_.POSITIONING),
  28952. this.handlePositioningChanged, this);
  28953. if (options.element !== undefined) {
  28954. this.setElement(options.element);
  28955. }
  28956. this.setOffset(options.offset !== undefined ? options.offset : [0, 0]);
  28957. this.setPositioning(options.positioning !== undefined ?
  28958. /** @type {ol.OverlayPositioning} */ (options.positioning) :
  28959. ol.OverlayPositioning.TOP_LEFT);
  28960. if (options.position !== undefined) {
  28961. this.setPosition(options.position);
  28962. }
  28963. };
  28964. ol.inherits(ol.Overlay, ol.Object);
  28965. /**
  28966. * Get the DOM element of this overlay.
  28967. * @return {Element|undefined} The Element containing the overlay.
  28968. * @observable
  28969. * @api
  28970. */
  28971. ol.Overlay.prototype.getElement = function() {
  28972. return /** @type {Element|undefined} */ (
  28973. this.get(ol.Overlay.Property_.ELEMENT));
  28974. };
  28975. /**
  28976. * Get the overlay identifier which is set on constructor.
  28977. * @return {number|string|undefined} Id.
  28978. * @api
  28979. */
  28980. ol.Overlay.prototype.getId = function() {
  28981. return this.id_;
  28982. };
  28983. /**
  28984. * Get the map associated with this overlay.
  28985. * @return {ol.Map|undefined} The map that the overlay is part of.
  28986. * @observable
  28987. * @api
  28988. */
  28989. ol.Overlay.prototype.getMap = function() {
  28990. return /** @type {ol.Map|undefined} */ (
  28991. this.get(ol.Overlay.Property_.MAP));
  28992. };
  28993. /**
  28994. * Get the offset of this overlay.
  28995. * @return {Array.<number>} The offset.
  28996. * @observable
  28997. * @api
  28998. */
  28999. ol.Overlay.prototype.getOffset = function() {
  29000. return /** @type {Array.<number>} */ (
  29001. this.get(ol.Overlay.Property_.OFFSET));
  29002. };
  29003. /**
  29004. * Get the current position of this overlay.
  29005. * @return {ol.Coordinate|undefined} The spatial point that the overlay is
  29006. * anchored at.
  29007. * @observable
  29008. * @api
  29009. */
  29010. ol.Overlay.prototype.getPosition = function() {
  29011. return /** @type {ol.Coordinate|undefined} */ (
  29012. this.get(ol.Overlay.Property_.POSITION));
  29013. };
  29014. /**
  29015. * Get the current positioning of this overlay.
  29016. * @return {ol.OverlayPositioning} How the overlay is positioned
  29017. * relative to its point on the map.
  29018. * @observable
  29019. * @api
  29020. */
  29021. ol.Overlay.prototype.getPositioning = function() {
  29022. return /** @type {ol.OverlayPositioning} */ (
  29023. this.get(ol.Overlay.Property_.POSITIONING));
  29024. };
  29025. /**
  29026. * @protected
  29027. */
  29028. ol.Overlay.prototype.handleElementChanged = function() {
  29029. ol.dom.removeChildren(this.element_);
  29030. var element = this.getElement();
  29031. if (element) {
  29032. this.element_.appendChild(element);
  29033. }
  29034. };
  29035. /**
  29036. * @protected
  29037. */
  29038. ol.Overlay.prototype.handleMapChanged = function() {
  29039. if (this.mapPostrenderListenerKey_) {
  29040. ol.dom.removeNode(this.element_);
  29041. ol.events.unlistenByKey(this.mapPostrenderListenerKey_);
  29042. this.mapPostrenderListenerKey_ = null;
  29043. }
  29044. var map = this.getMap();
  29045. if (map) {
  29046. this.mapPostrenderListenerKey_ = ol.events.listen(map,
  29047. ol.MapEventType.POSTRENDER, this.render, this);
  29048. this.updatePixelPosition();
  29049. var container = this.stopEvent_ ?
  29050. map.getOverlayContainerStopEvent() : map.getOverlayContainer();
  29051. if (this.insertFirst_) {
  29052. container.insertBefore(this.element_, container.childNodes[0] || null);
  29053. } else {
  29054. container.appendChild(this.element_);
  29055. }
  29056. }
  29057. };
  29058. /**
  29059. * @protected
  29060. */
  29061. ol.Overlay.prototype.render = function() {
  29062. this.updatePixelPosition();
  29063. };
  29064. /**
  29065. * @protected
  29066. */
  29067. ol.Overlay.prototype.handleOffsetChanged = function() {
  29068. this.updatePixelPosition();
  29069. };
  29070. /**
  29071. * @protected
  29072. */
  29073. ol.Overlay.prototype.handlePositionChanged = function() {
  29074. this.updatePixelPosition();
  29075. if (this.get(ol.Overlay.Property_.POSITION) && this.autoPan) {
  29076. this.panIntoView_();
  29077. }
  29078. };
  29079. /**
  29080. * @protected
  29081. */
  29082. ol.Overlay.prototype.handlePositioningChanged = function() {
  29083. this.updatePixelPosition();
  29084. };
  29085. /**
  29086. * Set the DOM element to be associated with this overlay.
  29087. * @param {Element|undefined} element The Element containing the overlay.
  29088. * @observable
  29089. * @api
  29090. */
  29091. ol.Overlay.prototype.setElement = function(element) {
  29092. this.set(ol.Overlay.Property_.ELEMENT, element);
  29093. };
  29094. /**
  29095. * Set the map to be associated with this overlay.
  29096. * @param {ol.Map|undefined} map The map that the overlay is part of.
  29097. * @observable
  29098. * @api
  29099. */
  29100. ol.Overlay.prototype.setMap = function(map) {
  29101. this.set(ol.Overlay.Property_.MAP, map);
  29102. };
  29103. /**
  29104. * Set the offset for this overlay.
  29105. * @param {Array.<number>} offset Offset.
  29106. * @observable
  29107. * @api
  29108. */
  29109. ol.Overlay.prototype.setOffset = function(offset) {
  29110. this.set(ol.Overlay.Property_.OFFSET, offset);
  29111. };
  29112. /**
  29113. * Set the position for this overlay. If the position is `undefined` the
  29114. * overlay is hidden.
  29115. * @param {ol.Coordinate|undefined} position The spatial point that the overlay
  29116. * is anchored at.
  29117. * @observable
  29118. * @api
  29119. */
  29120. ol.Overlay.prototype.setPosition = function(position) {
  29121. this.set(ol.Overlay.Property_.POSITION, position);
  29122. };
  29123. /**
  29124. * Pan the map so that the overlay is entirely visible in the current viewport
  29125. * (if necessary).
  29126. * @private
  29127. */
  29128. ol.Overlay.prototype.panIntoView_ = function() {
  29129. var map = this.getMap();
  29130. if (!map || !map.getTargetElement()) {
  29131. return;
  29132. }
  29133. var mapRect = this.getRect_(map.getTargetElement(), map.getSize());
  29134. var element = /** @type {!Element} */ (this.getElement());
  29135. var overlayRect = this.getRect_(element,
  29136. [ol.dom.outerWidth(element), ol.dom.outerHeight(element)]);
  29137. var margin = this.autoPanMargin_;
  29138. if (!ol.extent.containsExtent(mapRect, overlayRect)) {
  29139. // the overlay is not completely inside the viewport, so pan the map
  29140. var offsetLeft = overlayRect[0] - mapRect[0];
  29141. var offsetRight = mapRect[2] - overlayRect[2];
  29142. var offsetTop = overlayRect[1] - mapRect[1];
  29143. var offsetBottom = mapRect[3] - overlayRect[3];
  29144. var delta = [0, 0];
  29145. if (offsetLeft < 0) {
  29146. // move map to the left
  29147. delta[0] = offsetLeft - margin;
  29148. } else if (offsetRight < 0) {
  29149. // move map to the right
  29150. delta[0] = Math.abs(offsetRight) + margin;
  29151. }
  29152. if (offsetTop < 0) {
  29153. // move map up
  29154. delta[1] = offsetTop - margin;
  29155. } else if (offsetBottom < 0) {
  29156. // move map down
  29157. delta[1] = Math.abs(offsetBottom) + margin;
  29158. }
  29159. if (delta[0] !== 0 || delta[1] !== 0) {
  29160. var center = /** @type {ol.Coordinate} */ (map.getView().getCenter());
  29161. var centerPx = map.getPixelFromCoordinate(center);
  29162. var newCenterPx = [
  29163. centerPx[0] + delta[0],
  29164. centerPx[1] + delta[1]
  29165. ];
  29166. map.getView().animate({
  29167. center: map.getCoordinateFromPixel(newCenterPx),
  29168. duration: this.autoPanAnimation_.duration,
  29169. easing: this.autoPanAnimation_.easing
  29170. });
  29171. }
  29172. }
  29173. };
  29174. /**
  29175. * Get the extent of an element relative to the document
  29176. * @param {Element|undefined} element The element.
  29177. * @param {ol.Size|undefined} size The size of the element.
  29178. * @return {ol.Extent} The extent.
  29179. * @private
  29180. */
  29181. ol.Overlay.prototype.getRect_ = function(element, size) {
  29182. var box = element.getBoundingClientRect();
  29183. var offsetX = box.left + window.pageXOffset;
  29184. var offsetY = box.top + window.pageYOffset;
  29185. return [
  29186. offsetX,
  29187. offsetY,
  29188. offsetX + size[0],
  29189. offsetY + size[1]
  29190. ];
  29191. };
  29192. /**
  29193. * Set the positioning for this overlay.
  29194. * @param {ol.OverlayPositioning} positioning how the overlay is
  29195. * positioned relative to its point on the map.
  29196. * @observable
  29197. * @api
  29198. */
  29199. ol.Overlay.prototype.setPositioning = function(positioning) {
  29200. this.set(ol.Overlay.Property_.POSITIONING, positioning);
  29201. };
  29202. /**
  29203. * Modify the visibility of the element.
  29204. * @param {boolean} visible Element visibility.
  29205. * @protected
  29206. */
  29207. ol.Overlay.prototype.setVisible = function(visible) {
  29208. if (this.rendered_.visible !== visible) {
  29209. this.element_.style.display = visible ? '' : 'none';
  29210. this.rendered_.visible = visible;
  29211. }
  29212. };
  29213. /**
  29214. * Update pixel position.
  29215. * @protected
  29216. */
  29217. ol.Overlay.prototype.updatePixelPosition = function() {
  29218. var map = this.getMap();
  29219. var position = this.getPosition();
  29220. if (!map || !map.isRendered() || !position) {
  29221. this.setVisible(false);
  29222. return;
  29223. }
  29224. var pixel = map.getPixelFromCoordinate(position);
  29225. var mapSize = map.getSize();
  29226. this.updateRenderedPosition(pixel, mapSize);
  29227. };
  29228. /**
  29229. * @param {ol.Pixel} pixel The pixel location.
  29230. * @param {ol.Size|undefined} mapSize The map size.
  29231. * @protected
  29232. */
  29233. ol.Overlay.prototype.updateRenderedPosition = function(pixel, mapSize) {
  29234. var style = this.element_.style;
  29235. var offset = this.getOffset();
  29236. var positioning = this.getPositioning();
  29237. this.setVisible(true);
  29238. var offsetX = offset[0];
  29239. var offsetY = offset[1];
  29240. if (positioning == ol.OverlayPositioning.BOTTOM_RIGHT ||
  29241. positioning == ol.OverlayPositioning.CENTER_RIGHT ||
  29242. positioning == ol.OverlayPositioning.TOP_RIGHT) {
  29243. if (this.rendered_.left_ !== '') {
  29244. this.rendered_.left_ = style.left = '';
  29245. }
  29246. var right = Math.round(mapSize[0] - pixel[0] - offsetX) + 'px';
  29247. if (this.rendered_.right_ != right) {
  29248. this.rendered_.right_ = style.right = right;
  29249. }
  29250. } else {
  29251. if (this.rendered_.right_ !== '') {
  29252. this.rendered_.right_ = style.right = '';
  29253. }
  29254. if (positioning == ol.OverlayPositioning.BOTTOM_CENTER ||
  29255. positioning == ol.OverlayPositioning.CENTER_CENTER ||
  29256. positioning == ol.OverlayPositioning.TOP_CENTER) {
  29257. offsetX -= this.element_.offsetWidth / 2;
  29258. }
  29259. var left = Math.round(pixel[0] + offsetX) + 'px';
  29260. if (this.rendered_.left_ != left) {
  29261. this.rendered_.left_ = style.left = left;
  29262. }
  29263. }
  29264. if (positioning == ol.OverlayPositioning.BOTTOM_LEFT ||
  29265. positioning == ol.OverlayPositioning.BOTTOM_CENTER ||
  29266. positioning == ol.OverlayPositioning.BOTTOM_RIGHT) {
  29267. if (this.rendered_.top_ !== '') {
  29268. this.rendered_.top_ = style.top = '';
  29269. }
  29270. var bottom = Math.round(mapSize[1] - pixel[1] - offsetY) + 'px';
  29271. if (this.rendered_.bottom_ != bottom) {
  29272. this.rendered_.bottom_ = style.bottom = bottom;
  29273. }
  29274. } else {
  29275. if (this.rendered_.bottom_ !== '') {
  29276. this.rendered_.bottom_ = style.bottom = '';
  29277. }
  29278. if (positioning == ol.OverlayPositioning.CENTER_LEFT ||
  29279. positioning == ol.OverlayPositioning.CENTER_CENTER ||
  29280. positioning == ol.OverlayPositioning.CENTER_RIGHT) {
  29281. offsetY -= this.element_.offsetHeight / 2;
  29282. }
  29283. var top = Math.round(pixel[1] + offsetY) + 'px';
  29284. if (this.rendered_.top_ != top) {
  29285. this.rendered_.top_ = style.top = top;
  29286. }
  29287. }
  29288. };
  29289. /**
  29290. * @enum {string}
  29291. * @private
  29292. */
  29293. ol.Overlay.Property_ = {
  29294. ELEMENT: 'element',
  29295. MAP: 'map',
  29296. OFFSET: 'offset',
  29297. POSITION: 'position',
  29298. POSITIONING: 'positioning'
  29299. };
  29300. goog.provide('ol.control.OverviewMap');
  29301. goog.require('ol');
  29302. goog.require('ol.Collection');
  29303. goog.require('ol.Map');
  29304. goog.require('ol.MapEventType');
  29305. goog.require('ol.MapProperty');
  29306. goog.require('ol.Object');
  29307. goog.require('ol.ObjectEventType');
  29308. goog.require('ol.Overlay');
  29309. goog.require('ol.OverlayPositioning');
  29310. goog.require('ol.ViewProperty');
  29311. goog.require('ol.control.Control');
  29312. goog.require('ol.coordinate');
  29313. goog.require('ol.css');
  29314. goog.require('ol.dom');
  29315. goog.require('ol.events');
  29316. goog.require('ol.events.EventType');
  29317. goog.require('ol.extent');
  29318. /**
  29319. * Create a new control with a map acting as an overview map for an other
  29320. * defined map.
  29321. * @constructor
  29322. * @extends {ol.control.Control}
  29323. * @param {olx.control.OverviewMapOptions=} opt_options OverviewMap options.
  29324. * @api
  29325. */
  29326. ol.control.OverviewMap = function(opt_options) {
  29327. var options = opt_options ? opt_options : {};
  29328. /**
  29329. * @type {boolean}
  29330. * @private
  29331. */
  29332. this.collapsed_ = options.collapsed !== undefined ? options.collapsed : true;
  29333. /**
  29334. * @private
  29335. * @type {boolean}
  29336. */
  29337. this.collapsible_ = options.collapsible !== undefined ?
  29338. options.collapsible : true;
  29339. if (!this.collapsible_) {
  29340. this.collapsed_ = false;
  29341. }
  29342. var className = options.className !== undefined ? options.className : 'ol-overviewmap';
  29343. var tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Overview map';
  29344. var collapseLabel = options.collapseLabel !== undefined ? options.collapseLabel : '\u00AB';
  29345. if (typeof collapseLabel === 'string') {
  29346. /**
  29347. * @private
  29348. * @type {Node}
  29349. */
  29350. this.collapseLabel_ = document.createElement('span');
  29351. this.collapseLabel_.textContent = collapseLabel;
  29352. } else {
  29353. this.collapseLabel_ = collapseLabel;
  29354. }
  29355. var label = options.label !== undefined ? options.label : '\u00BB';
  29356. if (typeof label === 'string') {
  29357. /**
  29358. * @private
  29359. * @type {Node}
  29360. */
  29361. this.label_ = document.createElement('span');
  29362. this.label_.textContent = label;
  29363. } else {
  29364. this.label_ = label;
  29365. }
  29366. var activeLabel = (this.collapsible_ && !this.collapsed_) ?
  29367. this.collapseLabel_ : this.label_;
  29368. var button = document.createElement('button');
  29369. button.setAttribute('type', 'button');
  29370. button.title = tipLabel;
  29371. button.appendChild(activeLabel);
  29372. ol.events.listen(button, ol.events.EventType.CLICK,
  29373. this.handleClick_, this);
  29374. /**
  29375. * @type {Element}
  29376. * @private
  29377. */
  29378. this.ovmapDiv_ = document.createElement('DIV');
  29379. this.ovmapDiv_.className = 'ol-overviewmap-map';
  29380. /**
  29381. * @type {ol.Map}
  29382. * @private
  29383. */
  29384. this.ovmap_ = new ol.Map({
  29385. controls: new ol.Collection(),
  29386. interactions: new ol.Collection(),
  29387. view: options.view
  29388. });
  29389. var ovmap = this.ovmap_;
  29390. if (options.layers) {
  29391. options.layers.forEach(
  29392. /**
  29393. * @param {ol.layer.Layer} layer Layer.
  29394. */
  29395. function(layer) {
  29396. ovmap.addLayer(layer);
  29397. }, this);
  29398. }
  29399. var box = document.createElement('DIV');
  29400. box.className = 'ol-overviewmap-box';
  29401. box.style.boxSizing = 'border-box';
  29402. /**
  29403. * @type {ol.Overlay}
  29404. * @private
  29405. */
  29406. this.boxOverlay_ = new ol.Overlay({
  29407. position: [0, 0],
  29408. positioning: ol.OverlayPositioning.BOTTOM_LEFT,
  29409. element: box
  29410. });
  29411. this.ovmap_.addOverlay(this.boxOverlay_);
  29412. var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
  29413. ol.css.CLASS_CONTROL +
  29414. (this.collapsed_ && this.collapsible_ ? ' ol-collapsed' : '') +
  29415. (this.collapsible_ ? '' : ' ol-uncollapsible');
  29416. var element = document.createElement('div');
  29417. element.className = cssClasses;
  29418. element.appendChild(this.ovmapDiv_);
  29419. element.appendChild(button);
  29420. var render = options.render ? options.render : ol.control.OverviewMap.render;
  29421. ol.control.Control.call(this, {
  29422. element: element,
  29423. render: render,
  29424. target: options.target
  29425. });
  29426. /* Interactive map */
  29427. var scope = this;
  29428. var overlay = this.boxOverlay_;
  29429. var overlayBox = this.boxOverlay_.getElement();
  29430. /* Functions definition */
  29431. var computeDesiredMousePosition = function(mousePosition) {
  29432. return {
  29433. clientX: mousePosition.clientX - (overlayBox.offsetWidth / 2),
  29434. clientY: mousePosition.clientY + (overlayBox.offsetHeight / 2)
  29435. };
  29436. };
  29437. var move = function(event) {
  29438. var coordinates = ovmap.getEventCoordinate(computeDesiredMousePosition(event));
  29439. overlay.setPosition(coordinates);
  29440. };
  29441. var endMoving = function(event) {
  29442. var coordinates = ovmap.getEventCoordinate(event);
  29443. scope.getMap().getView().setCenter(coordinates);
  29444. window.removeEventListener('mousemove', move);
  29445. window.removeEventListener('mouseup', endMoving);
  29446. };
  29447. /* Binding */
  29448. overlayBox.addEventListener('mousedown', function() {
  29449. window.addEventListener('mousemove', move);
  29450. window.addEventListener('mouseup', endMoving);
  29451. });
  29452. };
  29453. ol.inherits(ol.control.OverviewMap, ol.control.Control);
  29454. /**
  29455. * @inheritDoc
  29456. * @api
  29457. */
  29458. ol.control.OverviewMap.prototype.setMap = function(map) {
  29459. var oldMap = this.getMap();
  29460. if (map === oldMap) {
  29461. return;
  29462. }
  29463. if (oldMap) {
  29464. var oldView = oldMap.getView();
  29465. if (oldView) {
  29466. this.unbindView_(oldView);
  29467. }
  29468. this.ovmap_.setTarget(null);
  29469. }
  29470. ol.control.Control.prototype.setMap.call(this, map);
  29471. if (map) {
  29472. this.ovmap_.setTarget(this.ovmapDiv_);
  29473. this.listenerKeys.push(ol.events.listen(
  29474. map, ol.ObjectEventType.PROPERTYCHANGE,
  29475. this.handleMapPropertyChange_, this));
  29476. // TODO: to really support map switching, this would need to be reworked
  29477. if (this.ovmap_.getLayers().getLength() === 0) {
  29478. this.ovmap_.setLayerGroup(map.getLayerGroup());
  29479. }
  29480. var view = map.getView();
  29481. if (view) {
  29482. this.bindView_(view);
  29483. if (view.isDef()) {
  29484. this.ovmap_.updateSize();
  29485. this.resetExtent_();
  29486. }
  29487. }
  29488. }
  29489. };
  29490. /**
  29491. * Handle map property changes. This only deals with changes to the map's view.
  29492. * @param {ol.Object.Event} event The propertychange event.
  29493. * @private
  29494. */
  29495. ol.control.OverviewMap.prototype.handleMapPropertyChange_ = function(event) {
  29496. if (event.key === ol.MapProperty.VIEW) {
  29497. var oldView = /** @type {ol.View} */ (event.oldValue);
  29498. if (oldView) {
  29499. this.unbindView_(oldView);
  29500. }
  29501. var newView = this.getMap().getView();
  29502. this.bindView_(newView);
  29503. }
  29504. };
  29505. /**
  29506. * Register listeners for view property changes.
  29507. * @param {ol.View} view The view.
  29508. * @private
  29509. */
  29510. ol.control.OverviewMap.prototype.bindView_ = function(view) {
  29511. ol.events.listen(view,
  29512. ol.Object.getChangeEventType(ol.ViewProperty.ROTATION),
  29513. this.handleRotationChanged_, this);
  29514. };
  29515. /**
  29516. * Unregister listeners for view property changes.
  29517. * @param {ol.View} view The view.
  29518. * @private
  29519. */
  29520. ol.control.OverviewMap.prototype.unbindView_ = function(view) {
  29521. ol.events.unlisten(view,
  29522. ol.Object.getChangeEventType(ol.ViewProperty.ROTATION),
  29523. this.handleRotationChanged_, this);
  29524. };
  29525. /**
  29526. * Handle rotation changes to the main map.
  29527. * TODO: This should rotate the extent rectrangle instead of the
  29528. * overview map's view.
  29529. * @private
  29530. */
  29531. ol.control.OverviewMap.prototype.handleRotationChanged_ = function() {
  29532. this.ovmap_.getView().setRotation(this.getMap().getView().getRotation());
  29533. };
  29534. /**
  29535. * Update the overview map element.
  29536. * @param {ol.MapEvent} mapEvent Map event.
  29537. * @this {ol.control.OverviewMap}
  29538. * @api
  29539. */
  29540. ol.control.OverviewMap.render = function(mapEvent) {
  29541. this.validateExtent_();
  29542. this.updateBox_();
  29543. };
  29544. /**
  29545. * Reset the overview map extent if the box size (width or
  29546. * height) is less than the size of the overview map size times minRatio
  29547. * or is greater than the size of the overview size times maxRatio.
  29548. *
  29549. * If the map extent was not reset, the box size can fits in the defined
  29550. * ratio sizes. This method then checks if is contained inside the overview
  29551. * map current extent. If not, recenter the overview map to the current
  29552. * main map center location.
  29553. * @private
  29554. */
  29555. ol.control.OverviewMap.prototype.validateExtent_ = function() {
  29556. var map = this.getMap();
  29557. var ovmap = this.ovmap_;
  29558. if (!map.isRendered() || !ovmap.isRendered()) {
  29559. return;
  29560. }
  29561. var mapSize = /** @type {ol.Size} */ (map.getSize());
  29562. var view = map.getView();
  29563. var extent = view.calculateExtent(mapSize);
  29564. var ovmapSize = /** @type {ol.Size} */ (ovmap.getSize());
  29565. var ovview = ovmap.getView();
  29566. var ovextent = ovview.calculateExtent(ovmapSize);
  29567. var topLeftPixel =
  29568. ovmap.getPixelFromCoordinate(ol.extent.getTopLeft(extent));
  29569. var bottomRightPixel =
  29570. ovmap.getPixelFromCoordinate(ol.extent.getBottomRight(extent));
  29571. var boxWidth = Math.abs(topLeftPixel[0] - bottomRightPixel[0]);
  29572. var boxHeight = Math.abs(topLeftPixel[1] - bottomRightPixel[1]);
  29573. var ovmapWidth = ovmapSize[0];
  29574. var ovmapHeight = ovmapSize[1];
  29575. if (boxWidth < ovmapWidth * ol.OVERVIEWMAP_MIN_RATIO ||
  29576. boxHeight < ovmapHeight * ol.OVERVIEWMAP_MIN_RATIO ||
  29577. boxWidth > ovmapWidth * ol.OVERVIEWMAP_MAX_RATIO ||
  29578. boxHeight > ovmapHeight * ol.OVERVIEWMAP_MAX_RATIO) {
  29579. this.resetExtent_();
  29580. } else if (!ol.extent.containsExtent(ovextent, extent)) {
  29581. this.recenter_();
  29582. }
  29583. };
  29584. /**
  29585. * Reset the overview map extent to half calculated min and max ratio times
  29586. * the extent of the main map.
  29587. * @private
  29588. */
  29589. ol.control.OverviewMap.prototype.resetExtent_ = function() {
  29590. if (ol.OVERVIEWMAP_MAX_RATIO === 0 || ol.OVERVIEWMAP_MIN_RATIO === 0) {
  29591. return;
  29592. }
  29593. var map = this.getMap();
  29594. var ovmap = this.ovmap_;
  29595. var mapSize = /** @type {ol.Size} */ (map.getSize());
  29596. var view = map.getView();
  29597. var extent = view.calculateExtent(mapSize);
  29598. var ovview = ovmap.getView();
  29599. // get how many times the current map overview could hold different
  29600. // box sizes using the min and max ratio, pick the step in the middle used
  29601. // to calculate the extent from the main map to set it to the overview map,
  29602. var steps = Math.log(
  29603. ol.OVERVIEWMAP_MAX_RATIO / ol.OVERVIEWMAP_MIN_RATIO) / Math.LN2;
  29604. var ratio = 1 / (Math.pow(2, steps / 2) * ol.OVERVIEWMAP_MIN_RATIO);
  29605. ol.extent.scaleFromCenter(extent, ratio);
  29606. ovview.fit(extent);
  29607. };
  29608. /**
  29609. * Set the center of the overview map to the map center without changing its
  29610. * resolution.
  29611. * @private
  29612. */
  29613. ol.control.OverviewMap.prototype.recenter_ = function() {
  29614. var map = this.getMap();
  29615. var ovmap = this.ovmap_;
  29616. var view = map.getView();
  29617. var ovview = ovmap.getView();
  29618. ovview.setCenter(view.getCenter());
  29619. };
  29620. /**
  29621. * Update the box using the main map extent
  29622. * @private
  29623. */
  29624. ol.control.OverviewMap.prototype.updateBox_ = function() {
  29625. var map = this.getMap();
  29626. var ovmap = this.ovmap_;
  29627. if (!map.isRendered() || !ovmap.isRendered()) {
  29628. return;
  29629. }
  29630. var mapSize = /** @type {ol.Size} */ (map.getSize());
  29631. var view = map.getView();
  29632. var ovview = ovmap.getView();
  29633. var rotation = view.getRotation();
  29634. var overlay = this.boxOverlay_;
  29635. var box = this.boxOverlay_.getElement();
  29636. var extent = view.calculateExtent(mapSize);
  29637. var ovresolution = ovview.getResolution();
  29638. var bottomLeft = ol.extent.getBottomLeft(extent);
  29639. var topRight = ol.extent.getTopRight(extent);
  29640. // set position using bottom left coordinates
  29641. var rotateBottomLeft = this.calculateCoordinateRotate_(rotation, bottomLeft);
  29642. overlay.setPosition(rotateBottomLeft);
  29643. // set box size calculated from map extent size and overview map resolution
  29644. if (box) {
  29645. box.style.width = Math.abs((bottomLeft[0] - topRight[0]) / ovresolution) + 'px';
  29646. box.style.height = Math.abs((topRight[1] - bottomLeft[1]) / ovresolution) + 'px';
  29647. }
  29648. };
  29649. /**
  29650. * @param {number} rotation Target rotation.
  29651. * @param {ol.Coordinate} coordinate Coordinate.
  29652. * @return {ol.Coordinate|undefined} Coordinate for rotation and center anchor.
  29653. * @private
  29654. */
  29655. ol.control.OverviewMap.prototype.calculateCoordinateRotate_ = function(
  29656. rotation, coordinate) {
  29657. var coordinateRotate;
  29658. var map = this.getMap();
  29659. var view = map.getView();
  29660. var currentCenter = view.getCenter();
  29661. if (currentCenter) {
  29662. coordinateRotate = [
  29663. coordinate[0] - currentCenter[0],
  29664. coordinate[1] - currentCenter[1]
  29665. ];
  29666. ol.coordinate.rotate(coordinateRotate, rotation);
  29667. ol.coordinate.add(coordinateRotate, currentCenter);
  29668. }
  29669. return coordinateRotate;
  29670. };
  29671. /**
  29672. * @param {Event} event The event to handle
  29673. * @private
  29674. */
  29675. ol.control.OverviewMap.prototype.handleClick_ = function(event) {
  29676. event.preventDefault();
  29677. this.handleToggle_();
  29678. };
  29679. /**
  29680. * @private
  29681. */
  29682. ol.control.OverviewMap.prototype.handleToggle_ = function() {
  29683. this.element.classList.toggle('ol-collapsed');
  29684. if (this.collapsed_) {
  29685. ol.dom.replaceNode(this.collapseLabel_, this.label_);
  29686. } else {
  29687. ol.dom.replaceNode(this.label_, this.collapseLabel_);
  29688. }
  29689. this.collapsed_ = !this.collapsed_;
  29690. // manage overview map if it had not been rendered before and control
  29691. // is expanded
  29692. var ovmap = this.ovmap_;
  29693. if (!this.collapsed_ && !ovmap.isRendered()) {
  29694. ovmap.updateSize();
  29695. this.resetExtent_();
  29696. ol.events.listenOnce(ovmap, ol.MapEventType.POSTRENDER,
  29697. function(event) {
  29698. this.updateBox_();
  29699. },
  29700. this);
  29701. }
  29702. };
  29703. /**
  29704. * Return `true` if the overview map is collapsible, `false` otherwise.
  29705. * @return {boolean} True if the widget is collapsible.
  29706. * @api
  29707. */
  29708. ol.control.OverviewMap.prototype.getCollapsible = function() {
  29709. return this.collapsible_;
  29710. };
  29711. /**
  29712. * Set whether the overview map should be collapsible.
  29713. * @param {boolean} collapsible True if the widget is collapsible.
  29714. * @api
  29715. */
  29716. ol.control.OverviewMap.prototype.setCollapsible = function(collapsible) {
  29717. if (this.collapsible_ === collapsible) {
  29718. return;
  29719. }
  29720. this.collapsible_ = collapsible;
  29721. this.element.classList.toggle('ol-uncollapsible');
  29722. if (!collapsible && this.collapsed_) {
  29723. this.handleToggle_();
  29724. }
  29725. };
  29726. /**
  29727. * Collapse or expand the overview map according to the passed parameter. Will
  29728. * not do anything if the overview map isn't collapsible or if the current
  29729. * collapsed state is already the one requested.
  29730. * @param {boolean} collapsed True if the widget is collapsed.
  29731. * @api
  29732. */
  29733. ol.control.OverviewMap.prototype.setCollapsed = function(collapsed) {
  29734. if (!this.collapsible_ || this.collapsed_ === collapsed) {
  29735. return;
  29736. }
  29737. this.handleToggle_();
  29738. };
  29739. /**
  29740. * Determine if the overview map is collapsed.
  29741. * @return {boolean} The overview map is collapsed.
  29742. * @api
  29743. */
  29744. ol.control.OverviewMap.prototype.getCollapsed = function() {
  29745. return this.collapsed_;
  29746. };
  29747. /**
  29748. * Return the overview map.
  29749. * @return {ol.Map} Overview map.
  29750. * @api
  29751. */
  29752. ol.control.OverviewMap.prototype.getOverviewMap = function() {
  29753. return this.ovmap_;
  29754. };
  29755. goog.provide('ol.control.ScaleLineUnits');
  29756. /**
  29757. * Units for the scale line. Supported values are `'degrees'`, `'imperial'`,
  29758. * `'nautical'`, `'metric'`, `'us'`.
  29759. * @enum {string}
  29760. */
  29761. ol.control.ScaleLineUnits = {
  29762. DEGREES: 'degrees',
  29763. IMPERIAL: 'imperial',
  29764. NAUTICAL: 'nautical',
  29765. METRIC: 'metric',
  29766. US: 'us'
  29767. };
  29768. goog.provide('ol.control.ScaleLine');
  29769. goog.require('ol');
  29770. goog.require('ol.Object');
  29771. goog.require('ol.asserts');
  29772. goog.require('ol.control.Control');
  29773. goog.require('ol.control.ScaleLineUnits');
  29774. goog.require('ol.css');
  29775. goog.require('ol.events');
  29776. goog.require('ol.proj');
  29777. goog.require('ol.proj.Units');
  29778. /**
  29779. * @classdesc
  29780. * A control displaying rough y-axis distances, calculated for the center of the
  29781. * viewport. For conformal projections (e.g. EPSG:3857, the default view
  29782. * projection in OpenLayers), the scale is valid for all directions.
  29783. * No scale line will be shown when the y-axis distance of a pixel at the
  29784. * viewport center cannot be calculated in the view projection.
  29785. * By default the scale line will show in the bottom left portion of the map,
  29786. * but this can be changed by using the css selector `.ol-scale-line`.
  29787. *
  29788. * @constructor
  29789. * @extends {ol.control.Control}
  29790. * @param {olx.control.ScaleLineOptions=} opt_options Scale line options.
  29791. * @api
  29792. */
  29793. ol.control.ScaleLine = function(opt_options) {
  29794. var options = opt_options ? opt_options : {};
  29795. var className = options.className !== undefined ? options.className : 'ol-scale-line';
  29796. /**
  29797. * @private
  29798. * @type {Element}
  29799. */
  29800. this.innerElement_ = document.createElement('DIV');
  29801. this.innerElement_.className = className + '-inner';
  29802. /**
  29803. * @private
  29804. * @type {Element}
  29805. */
  29806. this.element_ = document.createElement('DIV');
  29807. this.element_.className = className + ' ' + ol.css.CLASS_UNSELECTABLE;
  29808. this.element_.appendChild(this.innerElement_);
  29809. /**
  29810. * @private
  29811. * @type {?olx.ViewState}
  29812. */
  29813. this.viewState_ = null;
  29814. /**
  29815. * @private
  29816. * @type {number}
  29817. */
  29818. this.minWidth_ = options.minWidth !== undefined ? options.minWidth : 64;
  29819. /**
  29820. * @private
  29821. * @type {boolean}
  29822. */
  29823. this.renderedVisible_ = false;
  29824. /**
  29825. * @private
  29826. * @type {number|undefined}
  29827. */
  29828. this.renderedWidth_ = undefined;
  29829. /**
  29830. * @private
  29831. * @type {string}
  29832. */
  29833. this.renderedHTML_ = '';
  29834. var render = options.render ? options.render : ol.control.ScaleLine.render;
  29835. ol.control.Control.call(this, {
  29836. element: this.element_,
  29837. render: render,
  29838. target: options.target
  29839. });
  29840. ol.events.listen(
  29841. this, ol.Object.getChangeEventType(ol.control.ScaleLine.Property_.UNITS),
  29842. this.handleUnitsChanged_, this);
  29843. this.setUnits(/** @type {ol.control.ScaleLineUnits} */ (options.units) ||
  29844. ol.control.ScaleLineUnits.METRIC);
  29845. };
  29846. ol.inherits(ol.control.ScaleLine, ol.control.Control);
  29847. /**
  29848. * @const
  29849. * @type {Array.<number>}
  29850. */
  29851. ol.control.ScaleLine.LEADING_DIGITS = [1, 2, 5];
  29852. /**
  29853. * Return the units to use in the scale line.
  29854. * @return {ol.control.ScaleLineUnits|undefined} The units to use in the scale
  29855. * line.
  29856. * @observable
  29857. * @api
  29858. */
  29859. ol.control.ScaleLine.prototype.getUnits = function() {
  29860. return /** @type {ol.control.ScaleLineUnits|undefined} */ (
  29861. this.get(ol.control.ScaleLine.Property_.UNITS));
  29862. };
  29863. /**
  29864. * Update the scale line element.
  29865. * @param {ol.MapEvent} mapEvent Map event.
  29866. * @this {ol.control.ScaleLine}
  29867. * @api
  29868. */
  29869. ol.control.ScaleLine.render = function(mapEvent) {
  29870. var frameState = mapEvent.frameState;
  29871. if (!frameState) {
  29872. this.viewState_ = null;
  29873. } else {
  29874. this.viewState_ = frameState.viewState;
  29875. }
  29876. this.updateElement_();
  29877. };
  29878. /**
  29879. * @private
  29880. */
  29881. ol.control.ScaleLine.prototype.handleUnitsChanged_ = function() {
  29882. this.updateElement_();
  29883. };
  29884. /**
  29885. * Set the units to use in the scale line.
  29886. * @param {ol.control.ScaleLineUnits} units The units to use in the scale line.
  29887. * @observable
  29888. * @api
  29889. */
  29890. ol.control.ScaleLine.prototype.setUnits = function(units) {
  29891. this.set(ol.control.ScaleLine.Property_.UNITS, units);
  29892. };
  29893. /**
  29894. * @private
  29895. */
  29896. ol.control.ScaleLine.prototype.updateElement_ = function() {
  29897. var viewState = this.viewState_;
  29898. if (!viewState) {
  29899. if (this.renderedVisible_) {
  29900. this.element_.style.display = 'none';
  29901. this.renderedVisible_ = false;
  29902. }
  29903. return;
  29904. }
  29905. var center = viewState.center;
  29906. var projection = viewState.projection;
  29907. var units = this.getUnits();
  29908. var pointResolutionUnits = units == ol.control.ScaleLineUnits.DEGREES ?
  29909. ol.proj.Units.DEGREES :
  29910. ol.proj.Units.METERS;
  29911. var pointResolution =
  29912. ol.proj.getPointResolution(projection, viewState.resolution, center, pointResolutionUnits);
  29913. var nominalCount = this.minWidth_ * pointResolution;
  29914. var suffix = '';
  29915. if (units == ol.control.ScaleLineUnits.DEGREES) {
  29916. var metersPerDegree = ol.proj.METERS_PER_UNIT[ol.proj.Units.DEGREES];
  29917. if (projection.getUnits() == ol.proj.Units.DEGREES) {
  29918. nominalCount *= metersPerDegree;
  29919. } else {
  29920. pointResolution /= metersPerDegree;
  29921. }
  29922. if (nominalCount < metersPerDegree / 60) {
  29923. suffix = '\u2033'; // seconds
  29924. pointResolution *= 3600;
  29925. } else if (nominalCount < metersPerDegree) {
  29926. suffix = '\u2032'; // minutes
  29927. pointResolution *= 60;
  29928. } else {
  29929. suffix = '\u00b0'; // degrees
  29930. }
  29931. } else if (units == ol.control.ScaleLineUnits.IMPERIAL) {
  29932. if (nominalCount < 0.9144) {
  29933. suffix = 'in';
  29934. pointResolution /= 0.0254;
  29935. } else if (nominalCount < 1609.344) {
  29936. suffix = 'ft';
  29937. pointResolution /= 0.3048;
  29938. } else {
  29939. suffix = 'mi';
  29940. pointResolution /= 1609.344;
  29941. }
  29942. } else if (units == ol.control.ScaleLineUnits.NAUTICAL) {
  29943. pointResolution /= 1852;
  29944. suffix = 'nm';
  29945. } else if (units == ol.control.ScaleLineUnits.METRIC) {
  29946. if (nominalCount < 0.001) {
  29947. suffix = 'μm';
  29948. pointResolution *= 1000000;
  29949. } else if (nominalCount < 1) {
  29950. suffix = 'mm';
  29951. pointResolution *= 1000;
  29952. } else if (nominalCount < 1000) {
  29953. suffix = 'm';
  29954. } else {
  29955. suffix = 'km';
  29956. pointResolution /= 1000;
  29957. }
  29958. } else if (units == ol.control.ScaleLineUnits.US) {
  29959. if (nominalCount < 0.9144) {
  29960. suffix = 'in';
  29961. pointResolution *= 39.37;
  29962. } else if (nominalCount < 1609.344) {
  29963. suffix = 'ft';
  29964. pointResolution /= 0.30480061;
  29965. } else {
  29966. suffix = 'mi';
  29967. pointResolution /= 1609.3472;
  29968. }
  29969. } else {
  29970. ol.asserts.assert(false, 33); // Invalid units
  29971. }
  29972. var i = 3 * Math.floor(
  29973. Math.log(this.minWidth_ * pointResolution) / Math.log(10));
  29974. var count, width;
  29975. while (true) {
  29976. count = ol.control.ScaleLine.LEADING_DIGITS[((i % 3) + 3) % 3] *
  29977. Math.pow(10, Math.floor(i / 3));
  29978. width = Math.round(count / pointResolution);
  29979. if (isNaN(width)) {
  29980. this.element_.style.display = 'none';
  29981. this.renderedVisible_ = false;
  29982. return;
  29983. } else if (width >= this.minWidth_) {
  29984. break;
  29985. }
  29986. ++i;
  29987. }
  29988. var html = count + ' ' + suffix;
  29989. if (this.renderedHTML_ != html) {
  29990. this.innerElement_.innerHTML = html;
  29991. this.renderedHTML_ = html;
  29992. }
  29993. if (this.renderedWidth_ != width) {
  29994. this.innerElement_.style.width = width + 'px';
  29995. this.renderedWidth_ = width;
  29996. }
  29997. if (!this.renderedVisible_) {
  29998. this.element_.style.display = '';
  29999. this.renderedVisible_ = true;
  30000. }
  30001. };
  30002. /**
  30003. * @enum {string}
  30004. * @private
  30005. */
  30006. ol.control.ScaleLine.Property_ = {
  30007. UNITS: 'units'
  30008. };
  30009. // FIXME should possibly show tooltip when dragging?
  30010. goog.provide('ol.control.ZoomSlider');
  30011. goog.require('ol');
  30012. goog.require('ol.ViewHint');
  30013. goog.require('ol.control.Control');
  30014. goog.require('ol.css');
  30015. goog.require('ol.easing');
  30016. goog.require('ol.events');
  30017. goog.require('ol.events.Event');
  30018. goog.require('ol.events.EventType');
  30019. goog.require('ol.math');
  30020. goog.require('ol.pointer.EventType');
  30021. goog.require('ol.pointer.PointerEventHandler');
  30022. /**
  30023. * @classdesc
  30024. * A slider type of control for zooming.
  30025. *
  30026. * Example:
  30027. *
  30028. * map.addControl(new ol.control.ZoomSlider());
  30029. *
  30030. * @constructor
  30031. * @extends {ol.control.Control}
  30032. * @param {olx.control.ZoomSliderOptions=} opt_options Zoom slider options.
  30033. * @api
  30034. */
  30035. ol.control.ZoomSlider = function(opt_options) {
  30036. var options = opt_options ? opt_options : {};
  30037. /**
  30038. * Will hold the current resolution of the view.
  30039. *
  30040. * @type {number|undefined}
  30041. * @private
  30042. */
  30043. this.currentResolution_ = undefined;
  30044. /**
  30045. * The direction of the slider. Will be determined from actual display of the
  30046. * container and defaults to ol.control.ZoomSlider.Direction_.VERTICAL.
  30047. *
  30048. * @type {ol.control.ZoomSlider.Direction_}
  30049. * @private
  30050. */
  30051. this.direction_ = ol.control.ZoomSlider.Direction_.VERTICAL;
  30052. /**
  30053. * @type {boolean}
  30054. * @private
  30055. */
  30056. this.dragging_;
  30057. /**
  30058. * @type {number}
  30059. * @private
  30060. */
  30061. this.heightLimit_ = 0;
  30062. /**
  30063. * @type {number}
  30064. * @private
  30065. */
  30066. this.widthLimit_ = 0;
  30067. /**
  30068. * @type {number|undefined}
  30069. * @private
  30070. */
  30071. this.previousX_;
  30072. /**
  30073. * @type {number|undefined}
  30074. * @private
  30075. */
  30076. this.previousY_;
  30077. /**
  30078. * The calculated thumb size (border box plus margins). Set when initSlider_
  30079. * is called.
  30080. * @type {ol.Size}
  30081. * @private
  30082. */
  30083. this.thumbSize_ = null;
  30084. /**
  30085. * Whether the slider is initialized.
  30086. * @type {boolean}
  30087. * @private
  30088. */
  30089. this.sliderInitialized_ = false;
  30090. /**
  30091. * @type {number}
  30092. * @private
  30093. */
  30094. this.duration_ = options.duration !== undefined ? options.duration : 200;
  30095. var className = options.className !== undefined ? options.className : 'ol-zoomslider';
  30096. var thumbElement = document.createElement('button');
  30097. thumbElement.setAttribute('type', 'button');
  30098. thumbElement.className = className + '-thumb ' + ol.css.CLASS_UNSELECTABLE;
  30099. var containerElement = document.createElement('div');
  30100. containerElement.className = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' + ol.css.CLASS_CONTROL;
  30101. containerElement.appendChild(thumbElement);
  30102. /**
  30103. * @type {ol.pointer.PointerEventHandler}
  30104. * @private
  30105. */
  30106. this.dragger_ = new ol.pointer.PointerEventHandler(containerElement);
  30107. ol.events.listen(this.dragger_, ol.pointer.EventType.POINTERDOWN,
  30108. this.handleDraggerStart_, this);
  30109. ol.events.listen(this.dragger_, ol.pointer.EventType.POINTERMOVE,
  30110. this.handleDraggerDrag_, this);
  30111. ol.events.listen(this.dragger_, ol.pointer.EventType.POINTERUP,
  30112. this.handleDraggerEnd_, this);
  30113. ol.events.listen(containerElement, ol.events.EventType.CLICK,
  30114. this.handleContainerClick_, this);
  30115. ol.events.listen(thumbElement, ol.events.EventType.CLICK,
  30116. ol.events.Event.stopPropagation);
  30117. var render = options.render ? options.render : ol.control.ZoomSlider.render;
  30118. ol.control.Control.call(this, {
  30119. element: containerElement,
  30120. render: render
  30121. });
  30122. };
  30123. ol.inherits(ol.control.ZoomSlider, ol.control.Control);
  30124. /**
  30125. * @inheritDoc
  30126. */
  30127. ol.control.ZoomSlider.prototype.disposeInternal = function() {
  30128. this.dragger_.dispose();
  30129. ol.control.Control.prototype.disposeInternal.call(this);
  30130. };
  30131. /**
  30132. * The enum for available directions.
  30133. *
  30134. * @enum {number}
  30135. * @private
  30136. */
  30137. ol.control.ZoomSlider.Direction_ = {
  30138. VERTICAL: 0,
  30139. HORIZONTAL: 1
  30140. };
  30141. /**
  30142. * @inheritDoc
  30143. */
  30144. ol.control.ZoomSlider.prototype.setMap = function(map) {
  30145. ol.control.Control.prototype.setMap.call(this, map);
  30146. if (map) {
  30147. map.render();
  30148. }
  30149. };
  30150. /**
  30151. * Initializes the slider element. This will determine and set this controls
  30152. * direction_ and also constrain the dragging of the thumb to always be within
  30153. * the bounds of the container.
  30154. *
  30155. * @private
  30156. */
  30157. ol.control.ZoomSlider.prototype.initSlider_ = function() {
  30158. var container = this.element;
  30159. var containerSize = {
  30160. width: container.offsetWidth, height: container.offsetHeight
  30161. };
  30162. var thumb = container.firstElementChild;
  30163. var computedStyle = getComputedStyle(thumb);
  30164. var thumbWidth = thumb.offsetWidth +
  30165. parseFloat(computedStyle['marginRight']) +
  30166. parseFloat(computedStyle['marginLeft']);
  30167. var thumbHeight = thumb.offsetHeight +
  30168. parseFloat(computedStyle['marginTop']) +
  30169. parseFloat(computedStyle['marginBottom']);
  30170. this.thumbSize_ = [thumbWidth, thumbHeight];
  30171. if (containerSize.width > containerSize.height) {
  30172. this.direction_ = ol.control.ZoomSlider.Direction_.HORIZONTAL;
  30173. this.widthLimit_ = containerSize.width - thumbWidth;
  30174. } else {
  30175. this.direction_ = ol.control.ZoomSlider.Direction_.VERTICAL;
  30176. this.heightLimit_ = containerSize.height - thumbHeight;
  30177. }
  30178. this.sliderInitialized_ = true;
  30179. };
  30180. /**
  30181. * Update the zoomslider element.
  30182. * @param {ol.MapEvent} mapEvent Map event.
  30183. * @this {ol.control.ZoomSlider}
  30184. * @api
  30185. */
  30186. ol.control.ZoomSlider.render = function(mapEvent) {
  30187. if (!mapEvent.frameState) {
  30188. return;
  30189. }
  30190. if (!this.sliderInitialized_) {
  30191. this.initSlider_();
  30192. }
  30193. var res = mapEvent.frameState.viewState.resolution;
  30194. if (res !== this.currentResolution_) {
  30195. this.currentResolution_ = res;
  30196. this.setThumbPosition_(res);
  30197. }
  30198. };
  30199. /**
  30200. * @param {Event} event The browser event to handle.
  30201. * @private
  30202. */
  30203. ol.control.ZoomSlider.prototype.handleContainerClick_ = function(event) {
  30204. var view = this.getMap().getView();
  30205. var relativePosition = this.getRelativePosition_(
  30206. event.offsetX - this.thumbSize_[0] / 2,
  30207. event.offsetY - this.thumbSize_[1] / 2);
  30208. var resolution = this.getResolutionForPosition_(relativePosition);
  30209. view.animate({
  30210. resolution: view.constrainResolution(resolution),
  30211. duration: this.duration_,
  30212. easing: ol.easing.easeOut
  30213. });
  30214. };
  30215. /**
  30216. * Handle dragger start events.
  30217. * @param {ol.pointer.PointerEvent} event The drag event.
  30218. * @private
  30219. */
  30220. ol.control.ZoomSlider.prototype.handleDraggerStart_ = function(event) {
  30221. if (!this.dragging_ && event.originalEvent.target === this.element.firstElementChild) {
  30222. this.getMap().getView().setHint(ol.ViewHint.INTERACTING, 1);
  30223. this.previousX_ = event.clientX;
  30224. this.previousY_ = event.clientY;
  30225. this.dragging_ = true;
  30226. }
  30227. };
  30228. /**
  30229. * Handle dragger drag events.
  30230. *
  30231. * @param {ol.pointer.PointerEvent|Event} event The drag event.
  30232. * @private
  30233. */
  30234. ol.control.ZoomSlider.prototype.handleDraggerDrag_ = function(event) {
  30235. if (this.dragging_) {
  30236. var element = this.element.firstElementChild;
  30237. var deltaX = event.clientX - this.previousX_ + parseInt(element.style.left, 10);
  30238. var deltaY = event.clientY - this.previousY_ + parseInt(element.style.top, 10);
  30239. var relativePosition = this.getRelativePosition_(deltaX, deltaY);
  30240. this.currentResolution_ = this.getResolutionForPosition_(relativePosition);
  30241. this.getMap().getView().setResolution(this.currentResolution_);
  30242. this.setThumbPosition_(this.currentResolution_);
  30243. this.previousX_ = event.clientX;
  30244. this.previousY_ = event.clientY;
  30245. }
  30246. };
  30247. /**
  30248. * Handle dragger end events.
  30249. * @param {ol.pointer.PointerEvent|Event} event The drag event.
  30250. * @private
  30251. */
  30252. ol.control.ZoomSlider.prototype.handleDraggerEnd_ = function(event) {
  30253. if (this.dragging_) {
  30254. var view = this.getMap().getView();
  30255. view.setHint(ol.ViewHint.INTERACTING, -1);
  30256. view.animate({
  30257. resolution: view.constrainResolution(this.currentResolution_),
  30258. duration: this.duration_,
  30259. easing: ol.easing.easeOut
  30260. });
  30261. this.dragging_ = false;
  30262. this.previousX_ = undefined;
  30263. this.previousY_ = undefined;
  30264. }
  30265. };
  30266. /**
  30267. * Positions the thumb inside its container according to the given resolution.
  30268. *
  30269. * @param {number} res The res.
  30270. * @private
  30271. */
  30272. ol.control.ZoomSlider.prototype.setThumbPosition_ = function(res) {
  30273. var position = this.getPositionForResolution_(res);
  30274. var thumb = this.element.firstElementChild;
  30275. if (this.direction_ == ol.control.ZoomSlider.Direction_.HORIZONTAL) {
  30276. thumb.style.left = this.widthLimit_ * position + 'px';
  30277. } else {
  30278. thumb.style.top = this.heightLimit_ * position + 'px';
  30279. }
  30280. };
  30281. /**
  30282. * Calculates the relative position of the thumb given x and y offsets. The
  30283. * relative position scales from 0 to 1. The x and y offsets are assumed to be
  30284. * in pixel units within the dragger limits.
  30285. *
  30286. * @param {number} x Pixel position relative to the left of the slider.
  30287. * @param {number} y Pixel position relative to the top of the slider.
  30288. * @return {number} The relative position of the thumb.
  30289. * @private
  30290. */
  30291. ol.control.ZoomSlider.prototype.getRelativePosition_ = function(x, y) {
  30292. var amount;
  30293. if (this.direction_ === ol.control.ZoomSlider.Direction_.HORIZONTAL) {
  30294. amount = x / this.widthLimit_;
  30295. } else {
  30296. amount = y / this.heightLimit_;
  30297. }
  30298. return ol.math.clamp(amount, 0, 1);
  30299. };
  30300. /**
  30301. * Calculates the corresponding resolution of the thumb given its relative
  30302. * position (where 0 is the minimum and 1 is the maximum).
  30303. *
  30304. * @param {number} position The relative position of the thumb.
  30305. * @return {number} The corresponding resolution.
  30306. * @private
  30307. */
  30308. ol.control.ZoomSlider.prototype.getResolutionForPosition_ = function(position) {
  30309. var fn = this.getMap().getView().getResolutionForValueFunction();
  30310. return fn(1 - position);
  30311. };
  30312. /**
  30313. * Determines the relative position of the slider for the given resolution. A
  30314. * relative position of 0 corresponds to the minimum view resolution. A
  30315. * relative position of 1 corresponds to the maximum view resolution.
  30316. *
  30317. * @param {number} res The resolution.
  30318. * @return {number} The relative position value (between 0 and 1).
  30319. * @private
  30320. */
  30321. ol.control.ZoomSlider.prototype.getPositionForResolution_ = function(res) {
  30322. var fn = this.getMap().getView().getValueForResolutionFunction();
  30323. return 1 - fn(res);
  30324. };
  30325. goog.provide('ol.control.ZoomToExtent');
  30326. goog.require('ol');
  30327. goog.require('ol.events');
  30328. goog.require('ol.events.EventType');
  30329. goog.require('ol.control.Control');
  30330. goog.require('ol.css');
  30331. /**
  30332. * @classdesc
  30333. * A button control which, when pressed, changes the map view to a specific
  30334. * extent. To style this control use the css selector `.ol-zoom-extent`.
  30335. *
  30336. * @constructor
  30337. * @extends {ol.control.Control}
  30338. * @param {olx.control.ZoomToExtentOptions=} opt_options Options.
  30339. * @api
  30340. */
  30341. ol.control.ZoomToExtent = function(opt_options) {
  30342. var options = opt_options ? opt_options : {};
  30343. /**
  30344. * @type {ol.Extent}
  30345. * @private
  30346. */
  30347. this.extent_ = options.extent ? options.extent : null;
  30348. var className = options.className !== undefined ? options.className :
  30349. 'ol-zoom-extent';
  30350. var label = options.label !== undefined ? options.label : 'E';
  30351. var tipLabel = options.tipLabel !== undefined ?
  30352. options.tipLabel : 'Fit to extent';
  30353. var button = document.createElement('button');
  30354. button.setAttribute('type', 'button');
  30355. button.title = tipLabel;
  30356. button.appendChild(
  30357. typeof label === 'string' ? document.createTextNode(label) : label
  30358. );
  30359. ol.events.listen(button, ol.events.EventType.CLICK,
  30360. this.handleClick_, this);
  30361. var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE + ' ' +
  30362. ol.css.CLASS_CONTROL;
  30363. var element = document.createElement('div');
  30364. element.className = cssClasses;
  30365. element.appendChild(button);
  30366. ol.control.Control.call(this, {
  30367. element: element,
  30368. target: options.target
  30369. });
  30370. };
  30371. ol.inherits(ol.control.ZoomToExtent, ol.control.Control);
  30372. /**
  30373. * @param {Event} event The event to handle
  30374. * @private
  30375. */
  30376. ol.control.ZoomToExtent.prototype.handleClick_ = function(event) {
  30377. event.preventDefault();
  30378. this.handleZoomToExtent_();
  30379. };
  30380. /**
  30381. * @private
  30382. */
  30383. ol.control.ZoomToExtent.prototype.handleZoomToExtent_ = function() {
  30384. var map = this.getMap();
  30385. var view = map.getView();
  30386. var extent = !this.extent_ ? view.getProjection().getExtent() : this.extent_;
  30387. view.fit(extent);
  30388. };
  30389. goog.provide('ol.DeviceOrientation');
  30390. goog.require('ol.events');
  30391. goog.require('ol');
  30392. goog.require('ol.Object');
  30393. goog.require('ol.has');
  30394. goog.require('ol.math');
  30395. /**
  30396. * @classdesc
  30397. * The ol.DeviceOrientation class provides access to information from
  30398. * DeviceOrientation events. See the [HTML 5 DeviceOrientation Specification](
  30399. * http://www.w3.org/TR/orientation-event/) for more details.
  30400. *
  30401. * Many new computers, and especially mobile phones
  30402. * and tablets, provide hardware support for device orientation. Web
  30403. * developers targeting mobile devices will be especially interested in this
  30404. * class.
  30405. *
  30406. * Device orientation data are relative to a common starting point. For mobile
  30407. * devices, the starting point is to lay your phone face up on a table with the
  30408. * top of the phone pointing north. This represents the zero state. All
  30409. * angles are then relative to this state. For computers, it is the same except
  30410. * the screen is open at 90 degrees.
  30411. *
  30412. * Device orientation is reported as three angles - `alpha`, `beta`, and
  30413. * `gamma` - relative to the starting position along the three planar axes X, Y
  30414. * and Z. The X axis runs from the left edge to the right edge through the
  30415. * middle of the device. Similarly, the Y axis runs from the bottom to the top
  30416. * of the device through the middle. The Z axis runs from the back to the front
  30417. * through the middle. In the starting position, the X axis points to the
  30418. * right, the Y axis points away from you and the Z axis points straight up
  30419. * from the device lying flat.
  30420. *
  30421. * The three angles representing the device orientation are relative to the
  30422. * three axes. `alpha` indicates how much the device has been rotated around the
  30423. * Z axis, which is commonly interpreted as the compass heading (see note
  30424. * below). `beta` indicates how much the device has been rotated around the X
  30425. * axis, or how much it is tilted from front to back. `gamma` indicates how
  30426. * much the device has been rotated around the Y axis, or how much it is tilted
  30427. * from left to right.
  30428. *
  30429. * For most browsers, the `alpha` value returns the compass heading so if the
  30430. * device points north, it will be 0. With Safari on iOS, the 0 value of
  30431. * `alpha` is calculated from when device orientation was first requested.
  30432. * ol.DeviceOrientation provides the `heading` property which normalizes this
  30433. * behavior across all browsers for you.
  30434. *
  30435. * It is important to note that the HTML 5 DeviceOrientation specification
  30436. * indicates that `alpha`, `beta` and `gamma` are in degrees while the
  30437. * equivalent properties in ol.DeviceOrientation are in radians for consistency
  30438. * with all other uses of angles throughout OpenLayers.
  30439. *
  30440. * To get notified of device orientation changes, register a listener for the
  30441. * generic `change` event on your `ol.DeviceOrientation` instance.
  30442. *
  30443. * @see {@link http://www.w3.org/TR/orientation-event/}
  30444. *
  30445. * @constructor
  30446. * @extends {ol.Object}
  30447. * @param {olx.DeviceOrientationOptions=} opt_options Options.
  30448. * @api
  30449. */
  30450. ol.DeviceOrientation = function(opt_options) {
  30451. ol.Object.call(this);
  30452. var options = opt_options ? opt_options : {};
  30453. /**
  30454. * @private
  30455. * @type {?ol.EventsKey}
  30456. */
  30457. this.listenerKey_ = null;
  30458. ol.events.listen(this,
  30459. ol.Object.getChangeEventType(ol.DeviceOrientation.Property_.TRACKING),
  30460. this.handleTrackingChanged_, this);
  30461. this.setTracking(options.tracking !== undefined ? options.tracking : false);
  30462. };
  30463. ol.inherits(ol.DeviceOrientation, ol.Object);
  30464. /**
  30465. * @inheritDoc
  30466. */
  30467. ol.DeviceOrientation.prototype.disposeInternal = function() {
  30468. this.setTracking(false);
  30469. ol.Object.prototype.disposeInternal.call(this);
  30470. };
  30471. /**
  30472. * @private
  30473. * @param {Event} originalEvent Event.
  30474. */
  30475. ol.DeviceOrientation.prototype.orientationChange_ = function(originalEvent) {
  30476. var event = /** @type {DeviceOrientationEvent} */ (originalEvent);
  30477. if (event.alpha !== null) {
  30478. var alpha = ol.math.toRadians(event.alpha);
  30479. this.set(ol.DeviceOrientation.Property_.ALPHA, alpha);
  30480. // event.absolute is undefined in iOS.
  30481. if (typeof event.absolute === 'boolean' && event.absolute) {
  30482. this.set(ol.DeviceOrientation.Property_.HEADING, alpha);
  30483. } else if (typeof event.webkitCompassHeading === 'number' &&
  30484. event.webkitCompassAccuracy != -1) {
  30485. var heading = ol.math.toRadians(event.webkitCompassHeading);
  30486. this.set(ol.DeviceOrientation.Property_.HEADING, heading);
  30487. }
  30488. }
  30489. if (event.beta !== null) {
  30490. this.set(ol.DeviceOrientation.Property_.BETA,
  30491. ol.math.toRadians(event.beta));
  30492. }
  30493. if (event.gamma !== null) {
  30494. this.set(ol.DeviceOrientation.Property_.GAMMA,
  30495. ol.math.toRadians(event.gamma));
  30496. }
  30497. this.changed();
  30498. };
  30499. /**
  30500. * Rotation around the device z-axis (in radians).
  30501. * @return {number|undefined} The euler angle in radians of the device from the
  30502. * standard Z axis.
  30503. * @observable
  30504. * @api
  30505. */
  30506. ol.DeviceOrientation.prototype.getAlpha = function() {
  30507. return /** @type {number|undefined} */ (
  30508. this.get(ol.DeviceOrientation.Property_.ALPHA));
  30509. };
  30510. /**
  30511. * Rotation around the device x-axis (in radians).
  30512. * @return {number|undefined} The euler angle in radians of the device from the
  30513. * planar X axis.
  30514. * @observable
  30515. * @api
  30516. */
  30517. ol.DeviceOrientation.prototype.getBeta = function() {
  30518. return /** @type {number|undefined} */ (
  30519. this.get(ol.DeviceOrientation.Property_.BETA));
  30520. };
  30521. /**
  30522. * Rotation around the device y-axis (in radians).
  30523. * @return {number|undefined} The euler angle in radians of the device from the
  30524. * planar Y axis.
  30525. * @observable
  30526. * @api
  30527. */
  30528. ol.DeviceOrientation.prototype.getGamma = function() {
  30529. return /** @type {number|undefined} */ (
  30530. this.get(ol.DeviceOrientation.Property_.GAMMA));
  30531. };
  30532. /**
  30533. * The heading of the device relative to north (in radians).
  30534. * @return {number|undefined} The heading of the device relative to north, in
  30535. * radians, normalizing for different browser behavior.
  30536. * @observable
  30537. * @api
  30538. */
  30539. ol.DeviceOrientation.prototype.getHeading = function() {
  30540. return /** @type {number|undefined} */ (
  30541. this.get(ol.DeviceOrientation.Property_.HEADING));
  30542. };
  30543. /**
  30544. * Determine if orientation is being tracked.
  30545. * @return {boolean} Changes in device orientation are being tracked.
  30546. * @observable
  30547. * @api
  30548. */
  30549. ol.DeviceOrientation.prototype.getTracking = function() {
  30550. return /** @type {boolean} */ (
  30551. this.get(ol.DeviceOrientation.Property_.TRACKING));
  30552. };
  30553. /**
  30554. * @private
  30555. */
  30556. ol.DeviceOrientation.prototype.handleTrackingChanged_ = function() {
  30557. if (ol.has.DEVICE_ORIENTATION) {
  30558. var tracking = this.getTracking();
  30559. if (tracking && !this.listenerKey_) {
  30560. this.listenerKey_ = ol.events.listen(window, 'deviceorientation',
  30561. this.orientationChange_, this);
  30562. } else if (!tracking && this.listenerKey_ !== null) {
  30563. ol.events.unlistenByKey(this.listenerKey_);
  30564. this.listenerKey_ = null;
  30565. }
  30566. }
  30567. };
  30568. /**
  30569. * Enable or disable tracking of device orientation events.
  30570. * @param {boolean} tracking The status of tracking changes to alpha, beta and
  30571. * gamma. If true, changes are tracked and reported immediately.
  30572. * @observable
  30573. * @api
  30574. */
  30575. ol.DeviceOrientation.prototype.setTracking = function(tracking) {
  30576. this.set(ol.DeviceOrientation.Property_.TRACKING, tracking);
  30577. };
  30578. /**
  30579. * @enum {string}
  30580. * @private
  30581. */
  30582. ol.DeviceOrientation.Property_ = {
  30583. ALPHA: 'alpha',
  30584. BETA: 'beta',
  30585. GAMMA: 'gamma',
  30586. HEADING: 'heading',
  30587. TRACKING: 'tracking'
  30588. };
  30589. goog.provide('ol.ImageState');
  30590. /**
  30591. * @enum {number}
  30592. */
  30593. ol.ImageState = {
  30594. IDLE: 0,
  30595. LOADING: 1,
  30596. LOADED: 2,
  30597. ERROR: 3
  30598. };
  30599. goog.provide('ol.style.Image');
  30600. /**
  30601. * @classdesc
  30602. * A base class used for creating subclasses and not instantiated in
  30603. * apps. Base class for {@link ol.style.Icon}, {@link ol.style.Circle} and
  30604. * {@link ol.style.RegularShape}.
  30605. *
  30606. * @constructor
  30607. * @abstract
  30608. * @param {ol.StyleImageOptions} options Options.
  30609. * @api
  30610. */
  30611. ol.style.Image = function(options) {
  30612. /**
  30613. * @private
  30614. * @type {number}
  30615. */
  30616. this.opacity_ = options.opacity;
  30617. /**
  30618. * @private
  30619. * @type {boolean}
  30620. */
  30621. this.rotateWithView_ = options.rotateWithView;
  30622. /**
  30623. * @private
  30624. * @type {number}
  30625. */
  30626. this.rotation_ = options.rotation;
  30627. /**
  30628. * @private
  30629. * @type {number}
  30630. */
  30631. this.scale_ = options.scale;
  30632. /**
  30633. * @private
  30634. * @type {boolean}
  30635. */
  30636. this.snapToPixel_ = options.snapToPixel;
  30637. };
  30638. /**
  30639. * Get the symbolizer opacity.
  30640. * @return {number} Opacity.
  30641. * @api
  30642. */
  30643. ol.style.Image.prototype.getOpacity = function() {
  30644. return this.opacity_;
  30645. };
  30646. /**
  30647. * Determine whether the symbolizer rotates with the map.
  30648. * @return {boolean} Rotate with map.
  30649. * @api
  30650. */
  30651. ol.style.Image.prototype.getRotateWithView = function() {
  30652. return this.rotateWithView_;
  30653. };
  30654. /**
  30655. * Get the symoblizer rotation.
  30656. * @return {number} Rotation.
  30657. * @api
  30658. */
  30659. ol.style.Image.prototype.getRotation = function() {
  30660. return this.rotation_;
  30661. };
  30662. /**
  30663. * Get the symbolizer scale.
  30664. * @return {number} Scale.
  30665. * @api
  30666. */
  30667. ol.style.Image.prototype.getScale = function() {
  30668. return this.scale_;
  30669. };
  30670. /**
  30671. * Determine whether the symbolizer should be snapped to a pixel.
  30672. * @return {boolean} The symbolizer should snap to a pixel.
  30673. * @api
  30674. */
  30675. ol.style.Image.prototype.getSnapToPixel = function() {
  30676. return this.snapToPixel_;
  30677. };
  30678. /**
  30679. * Get the anchor point in pixels. The anchor determines the center point for the
  30680. * symbolizer.
  30681. * @abstract
  30682. * @return {Array.<number>} Anchor.
  30683. */
  30684. ol.style.Image.prototype.getAnchor = function() {};
  30685. /**
  30686. * Get the image element for the symbolizer.
  30687. * @abstract
  30688. * @param {number} pixelRatio Pixel ratio.
  30689. * @return {HTMLCanvasElement|HTMLVideoElement|Image} Image element.
  30690. */
  30691. ol.style.Image.prototype.getImage = function(pixelRatio) {};
  30692. /**
  30693. * @abstract
  30694. * @param {number} pixelRatio Pixel ratio.
  30695. * @return {HTMLCanvasElement|HTMLVideoElement|Image} Image element.
  30696. */
  30697. ol.style.Image.prototype.getHitDetectionImage = function(pixelRatio) {};
  30698. /**
  30699. * @abstract
  30700. * @return {ol.ImageState} Image state.
  30701. */
  30702. ol.style.Image.prototype.getImageState = function() {};
  30703. /**
  30704. * @abstract
  30705. * @return {ol.Size} Image size.
  30706. */
  30707. ol.style.Image.prototype.getImageSize = function() {};
  30708. /**
  30709. * @abstract
  30710. * @return {ol.Size} Size of the hit-detection image.
  30711. */
  30712. ol.style.Image.prototype.getHitDetectionImageSize = function() {};
  30713. /**
  30714. * Get the origin of the symbolizer.
  30715. * @abstract
  30716. * @return {Array.<number>} Origin.
  30717. */
  30718. ol.style.Image.prototype.getOrigin = function() {};
  30719. /**
  30720. * Get the size of the symbolizer (in pixels).
  30721. * @abstract
  30722. * @return {ol.Size} Size.
  30723. */
  30724. ol.style.Image.prototype.getSize = function() {};
  30725. /**
  30726. * Set the opacity.
  30727. *
  30728. * @param {number} opacity Opacity.
  30729. * @api
  30730. */
  30731. ol.style.Image.prototype.setOpacity = function(opacity) {
  30732. this.opacity_ = opacity;
  30733. };
  30734. /**
  30735. * Set whether to rotate the style with the view.
  30736. *
  30737. * @param {boolean} rotateWithView Rotate with map.
  30738. */
  30739. ol.style.Image.prototype.setRotateWithView = function(rotateWithView) {
  30740. this.rotateWithView_ = rotateWithView;
  30741. };
  30742. /**
  30743. * Set the rotation.
  30744. *
  30745. * @param {number} rotation Rotation.
  30746. * @api
  30747. */
  30748. ol.style.Image.prototype.setRotation = function(rotation) {
  30749. this.rotation_ = rotation;
  30750. };
  30751. /**
  30752. * Set the scale.
  30753. *
  30754. * @param {number} scale Scale.
  30755. * @api
  30756. */
  30757. ol.style.Image.prototype.setScale = function(scale) {
  30758. this.scale_ = scale;
  30759. };
  30760. /**
  30761. * Set whether to snap the image to the closest pixel.
  30762. *
  30763. * @param {boolean} snapToPixel Snap to pixel?
  30764. */
  30765. ol.style.Image.prototype.setSnapToPixel = function(snapToPixel) {
  30766. this.snapToPixel_ = snapToPixel;
  30767. };
  30768. /**
  30769. * @abstract
  30770. * @param {function(this: T, ol.events.Event)} listener Listener function.
  30771. * @param {T} thisArg Value to use as `this` when executing `listener`.
  30772. * @return {ol.EventsKey|undefined} Listener key.
  30773. * @template T
  30774. */
  30775. ol.style.Image.prototype.listenImageChange = function(listener, thisArg) {};
  30776. /**
  30777. * Load not yet loaded URI.
  30778. * @abstract
  30779. */
  30780. ol.style.Image.prototype.load = function() {};
  30781. /**
  30782. * @abstract
  30783. * @param {function(this: T, ol.events.Event)} listener Listener function.
  30784. * @param {T} thisArg Value to use as `this` when executing `listener`.
  30785. * @template T
  30786. */
  30787. ol.style.Image.prototype.unlistenImageChange = function(listener, thisArg) {};
  30788. goog.provide('ol.style.RegularShape');
  30789. goog.require('ol');
  30790. goog.require('ol.colorlike');
  30791. goog.require('ol.dom');
  30792. goog.require('ol.has');
  30793. goog.require('ol.ImageState');
  30794. goog.require('ol.render.canvas');
  30795. goog.require('ol.style.Image');
  30796. /**
  30797. * @classdesc
  30798. * Set regular shape style for vector features. The resulting shape will be
  30799. * a regular polygon when `radius` is provided, or a star when `radius1` and
  30800. * `radius2` are provided.
  30801. *
  30802. * @constructor
  30803. * @param {olx.style.RegularShapeOptions} options Options.
  30804. * @extends {ol.style.Image}
  30805. * @api
  30806. */
  30807. ol.style.RegularShape = function(options) {
  30808. /**
  30809. * @private
  30810. * @type {Array.<string>}
  30811. */
  30812. this.checksums_ = null;
  30813. /**
  30814. * @private
  30815. * @type {HTMLCanvasElement}
  30816. */
  30817. this.canvas_ = null;
  30818. /**
  30819. * @private
  30820. * @type {HTMLCanvasElement}
  30821. */
  30822. this.hitDetectionCanvas_ = null;
  30823. /**
  30824. * @private
  30825. * @type {ol.style.Fill}
  30826. */
  30827. this.fill_ = options.fill !== undefined ? options.fill : null;
  30828. /**
  30829. * @private
  30830. * @type {Array.<number>}
  30831. */
  30832. this.origin_ = [0, 0];
  30833. /**
  30834. * @private
  30835. * @type {number}
  30836. */
  30837. this.points_ = options.points;
  30838. /**
  30839. * @protected
  30840. * @type {number}
  30841. */
  30842. this.radius_ = /** @type {number} */ (options.radius !== undefined ?
  30843. options.radius : options.radius1);
  30844. /**
  30845. * @private
  30846. * @type {number|undefined}
  30847. */
  30848. this.radius2_ = options.radius2;
  30849. /**
  30850. * @private
  30851. * @type {number}
  30852. */
  30853. this.angle_ = options.angle !== undefined ? options.angle : 0;
  30854. /**
  30855. * @private
  30856. * @type {ol.style.Stroke}
  30857. */
  30858. this.stroke_ = options.stroke !== undefined ? options.stroke : null;
  30859. /**
  30860. * @private
  30861. * @type {Array.<number>}
  30862. */
  30863. this.anchor_ = null;
  30864. /**
  30865. * @private
  30866. * @type {ol.Size}
  30867. */
  30868. this.size_ = null;
  30869. /**
  30870. * @private
  30871. * @type {ol.Size}
  30872. */
  30873. this.imageSize_ = null;
  30874. /**
  30875. * @private
  30876. * @type {ol.Size}
  30877. */
  30878. this.hitDetectionImageSize_ = null;
  30879. /**
  30880. * @protected
  30881. * @type {ol.style.AtlasManager|undefined}
  30882. */
  30883. this.atlasManager_ = options.atlasManager;
  30884. this.render_(this.atlasManager_);
  30885. /**
  30886. * @type {boolean}
  30887. */
  30888. var snapToPixel = options.snapToPixel !== undefined ?
  30889. options.snapToPixel : true;
  30890. /**
  30891. * @type {boolean}
  30892. */
  30893. var rotateWithView = options.rotateWithView !== undefined ?
  30894. options.rotateWithView : false;
  30895. ol.style.Image.call(this, {
  30896. opacity: 1,
  30897. rotateWithView: rotateWithView,
  30898. rotation: options.rotation !== undefined ? options.rotation : 0,
  30899. scale: 1,
  30900. snapToPixel: snapToPixel
  30901. });
  30902. };
  30903. ol.inherits(ol.style.RegularShape, ol.style.Image);
  30904. /**
  30905. * Clones the style. If an atlasmanager was provided to the original style it will be used in the cloned style, too.
  30906. * @return {ol.style.RegularShape} The cloned style.
  30907. * @api
  30908. */
  30909. ol.style.RegularShape.prototype.clone = function() {
  30910. var style = new ol.style.RegularShape({
  30911. fill: this.getFill() ? this.getFill().clone() : undefined,
  30912. points: this.getPoints(),
  30913. radius: this.getRadius(),
  30914. radius2: this.getRadius2(),
  30915. angle: this.getAngle(),
  30916. snapToPixel: this.getSnapToPixel(),
  30917. stroke: this.getStroke() ? this.getStroke().clone() : undefined,
  30918. rotation: this.getRotation(),
  30919. rotateWithView: this.getRotateWithView(),
  30920. atlasManager: this.atlasManager_
  30921. });
  30922. style.setOpacity(this.getOpacity());
  30923. style.setScale(this.getScale());
  30924. return style;
  30925. };
  30926. /**
  30927. * @inheritDoc
  30928. * @api
  30929. */
  30930. ol.style.RegularShape.prototype.getAnchor = function() {
  30931. return this.anchor_;
  30932. };
  30933. /**
  30934. * Get the angle used in generating the shape.
  30935. * @return {number} Shape's rotation in radians.
  30936. * @api
  30937. */
  30938. ol.style.RegularShape.prototype.getAngle = function() {
  30939. return this.angle_;
  30940. };
  30941. /**
  30942. * Get the fill style for the shape.
  30943. * @return {ol.style.Fill} Fill style.
  30944. * @api
  30945. */
  30946. ol.style.RegularShape.prototype.getFill = function() {
  30947. return this.fill_;
  30948. };
  30949. /**
  30950. * @inheritDoc
  30951. */
  30952. ol.style.RegularShape.prototype.getHitDetectionImage = function(pixelRatio) {
  30953. return this.hitDetectionCanvas_;
  30954. };
  30955. /**
  30956. * @inheritDoc
  30957. * @api
  30958. */
  30959. ol.style.RegularShape.prototype.getImage = function(pixelRatio) {
  30960. return this.canvas_;
  30961. };
  30962. /**
  30963. * @inheritDoc
  30964. */
  30965. ol.style.RegularShape.prototype.getImageSize = function() {
  30966. return this.imageSize_;
  30967. };
  30968. /**
  30969. * @inheritDoc
  30970. */
  30971. ol.style.RegularShape.prototype.getHitDetectionImageSize = function() {
  30972. return this.hitDetectionImageSize_;
  30973. };
  30974. /**
  30975. * @inheritDoc
  30976. */
  30977. ol.style.RegularShape.prototype.getImageState = function() {
  30978. return ol.ImageState.LOADED;
  30979. };
  30980. /**
  30981. * @inheritDoc
  30982. * @api
  30983. */
  30984. ol.style.RegularShape.prototype.getOrigin = function() {
  30985. return this.origin_;
  30986. };
  30987. /**
  30988. * Get the number of points for generating the shape.
  30989. * @return {number} Number of points for stars and regular polygons.
  30990. * @api
  30991. */
  30992. ol.style.RegularShape.prototype.getPoints = function() {
  30993. return this.points_;
  30994. };
  30995. /**
  30996. * Get the (primary) radius for the shape.
  30997. * @return {number} Radius.
  30998. * @api
  30999. */
  31000. ol.style.RegularShape.prototype.getRadius = function() {
  31001. return this.radius_;
  31002. };
  31003. /**
  31004. * Get the secondary radius for the shape.
  31005. * @return {number|undefined} Radius2.
  31006. * @api
  31007. */
  31008. ol.style.RegularShape.prototype.getRadius2 = function() {
  31009. return this.radius2_;
  31010. };
  31011. /**
  31012. * @inheritDoc
  31013. * @api
  31014. */
  31015. ol.style.RegularShape.prototype.getSize = function() {
  31016. return this.size_;
  31017. };
  31018. /**
  31019. * Get the stroke style for the shape.
  31020. * @return {ol.style.Stroke} Stroke style.
  31021. * @api
  31022. */
  31023. ol.style.RegularShape.prototype.getStroke = function() {
  31024. return this.stroke_;
  31025. };
  31026. /**
  31027. * @inheritDoc
  31028. */
  31029. ol.style.RegularShape.prototype.listenImageChange = function(listener, thisArg) {};
  31030. /**
  31031. * @inheritDoc
  31032. */
  31033. ol.style.RegularShape.prototype.load = function() {};
  31034. /**
  31035. * @inheritDoc
  31036. */
  31037. ol.style.RegularShape.prototype.unlistenImageChange = function(listener, thisArg) {};
  31038. /**
  31039. * @protected
  31040. * @param {ol.style.AtlasManager|undefined} atlasManager An atlas manager.
  31041. */
  31042. ol.style.RegularShape.prototype.render_ = function(atlasManager) {
  31043. var imageSize;
  31044. var lineCap = '';
  31045. var lineJoin = '';
  31046. var miterLimit = 0;
  31047. var lineDash = null;
  31048. var lineDashOffset = 0;
  31049. var strokeStyle;
  31050. var strokeWidth = 0;
  31051. if (this.stroke_) {
  31052. strokeStyle = this.stroke_.getColor();
  31053. if (strokeStyle === null) {
  31054. strokeStyle = ol.render.canvas.defaultStrokeStyle;
  31055. }
  31056. strokeStyle = ol.colorlike.asColorLike(strokeStyle);
  31057. strokeWidth = this.stroke_.getWidth();
  31058. if (strokeWidth === undefined) {
  31059. strokeWidth = ol.render.canvas.defaultLineWidth;
  31060. }
  31061. lineDash = this.stroke_.getLineDash();
  31062. lineDashOffset = this.stroke_.getLineDashOffset();
  31063. if (!ol.has.CANVAS_LINE_DASH) {
  31064. lineDash = null;
  31065. lineDashOffset = 0;
  31066. }
  31067. lineJoin = this.stroke_.getLineJoin();
  31068. if (lineJoin === undefined) {
  31069. lineJoin = ol.render.canvas.defaultLineJoin;
  31070. }
  31071. lineCap = this.stroke_.getLineCap();
  31072. if (lineCap === undefined) {
  31073. lineCap = ol.render.canvas.defaultLineCap;
  31074. }
  31075. miterLimit = this.stroke_.getMiterLimit();
  31076. if (miterLimit === undefined) {
  31077. miterLimit = ol.render.canvas.defaultMiterLimit;
  31078. }
  31079. }
  31080. var size = 2 * (this.radius_ + strokeWidth) + 1;
  31081. /** @type {ol.RegularShapeRenderOptions} */
  31082. var renderOptions = {
  31083. strokeStyle: strokeStyle,
  31084. strokeWidth: strokeWidth,
  31085. size: size,
  31086. lineCap: lineCap,
  31087. lineDash: lineDash,
  31088. lineDashOffset: lineDashOffset,
  31089. lineJoin: lineJoin,
  31090. miterLimit: miterLimit
  31091. };
  31092. if (atlasManager === undefined) {
  31093. // no atlas manager is used, create a new canvas
  31094. var context = ol.dom.createCanvasContext2D(size, size);
  31095. this.canvas_ = context.canvas;
  31096. // canvas.width and height are rounded to the closest integer
  31097. size = this.canvas_.width;
  31098. imageSize = size;
  31099. this.draw_(renderOptions, context, 0, 0);
  31100. this.createHitDetectionCanvas_(renderOptions);
  31101. } else {
  31102. // an atlas manager is used, add the symbol to an atlas
  31103. size = Math.round(size);
  31104. var hasCustomHitDetectionImage = !this.fill_;
  31105. var renderHitDetectionCallback;
  31106. if (hasCustomHitDetectionImage) {
  31107. // render the hit-detection image into a separate atlas image
  31108. renderHitDetectionCallback =
  31109. this.drawHitDetectionCanvas_.bind(this, renderOptions);
  31110. }
  31111. var id = this.getChecksum();
  31112. var info = atlasManager.add(
  31113. id, size, size, this.draw_.bind(this, renderOptions),
  31114. renderHitDetectionCallback);
  31115. this.canvas_ = info.image;
  31116. this.origin_ = [info.offsetX, info.offsetY];
  31117. imageSize = info.image.width;
  31118. if (hasCustomHitDetectionImage) {
  31119. this.hitDetectionCanvas_ = info.hitImage;
  31120. this.hitDetectionImageSize_ =
  31121. [info.hitImage.width, info.hitImage.height];
  31122. } else {
  31123. this.hitDetectionCanvas_ = this.canvas_;
  31124. this.hitDetectionImageSize_ = [imageSize, imageSize];
  31125. }
  31126. }
  31127. this.anchor_ = [size / 2, size / 2];
  31128. this.size_ = [size, size];
  31129. this.imageSize_ = [imageSize, imageSize];
  31130. };
  31131. /**
  31132. * @private
  31133. * @param {ol.RegularShapeRenderOptions} renderOptions Render options.
  31134. * @param {CanvasRenderingContext2D} context The rendering context.
  31135. * @param {number} x The origin for the symbol (x).
  31136. * @param {number} y The origin for the symbol (y).
  31137. */
  31138. ol.style.RegularShape.prototype.draw_ = function(renderOptions, context, x, y) {
  31139. var i, angle0, radiusC;
  31140. // reset transform
  31141. context.setTransform(1, 0, 0, 1, 0, 0);
  31142. // then move to (x, y)
  31143. context.translate(x, y);
  31144. context.beginPath();
  31145. var points = this.points_;
  31146. if (points === Infinity) {
  31147. context.arc(
  31148. renderOptions.size / 2, renderOptions.size / 2,
  31149. this.radius_, 0, 2 * Math.PI, true);
  31150. } else {
  31151. var radius2 = (this.radius2_ !== undefined) ? this.radius2_
  31152. : this.radius_;
  31153. if (radius2 !== this.radius_) {
  31154. points = 2 * points;
  31155. }
  31156. for (i = 0; i <= points; i++) {
  31157. angle0 = i * 2 * Math.PI / points - Math.PI / 2 + this.angle_;
  31158. radiusC = i % 2 === 0 ? this.radius_ : radius2;
  31159. context.lineTo(renderOptions.size / 2 + radiusC * Math.cos(angle0),
  31160. renderOptions.size / 2 + radiusC * Math.sin(angle0));
  31161. }
  31162. }
  31163. if (this.fill_) {
  31164. var color = this.fill_.getColor();
  31165. if (color === null) {
  31166. color = ol.render.canvas.defaultFillStyle;
  31167. }
  31168. context.fillStyle = ol.colorlike.asColorLike(color);
  31169. context.fill();
  31170. }
  31171. if (this.stroke_) {
  31172. context.strokeStyle = renderOptions.strokeStyle;
  31173. context.lineWidth = renderOptions.strokeWidth;
  31174. if (renderOptions.lineDash) {
  31175. context.setLineDash(renderOptions.lineDash);
  31176. context.lineDashOffset = renderOptions.lineDashOffset;
  31177. }
  31178. context.lineCap = renderOptions.lineCap;
  31179. context.lineJoin = renderOptions.lineJoin;
  31180. context.miterLimit = renderOptions.miterLimit;
  31181. context.stroke();
  31182. }
  31183. context.closePath();
  31184. };
  31185. /**
  31186. * @private
  31187. * @param {ol.RegularShapeRenderOptions} renderOptions Render options.
  31188. */
  31189. ol.style.RegularShape.prototype.createHitDetectionCanvas_ = function(renderOptions) {
  31190. this.hitDetectionImageSize_ = [renderOptions.size, renderOptions.size];
  31191. if (this.fill_) {
  31192. this.hitDetectionCanvas_ = this.canvas_;
  31193. return;
  31194. }
  31195. // if no fill style is set, create an extra hit-detection image with a
  31196. // default fill style
  31197. var context = ol.dom.createCanvasContext2D(renderOptions.size, renderOptions.size);
  31198. this.hitDetectionCanvas_ = context.canvas;
  31199. this.drawHitDetectionCanvas_(renderOptions, context, 0, 0);
  31200. };
  31201. /**
  31202. * @private
  31203. * @param {ol.RegularShapeRenderOptions} renderOptions Render options.
  31204. * @param {CanvasRenderingContext2D} context The context.
  31205. * @param {number} x The origin for the symbol (x).
  31206. * @param {number} y The origin for the symbol (y).
  31207. */
  31208. ol.style.RegularShape.prototype.drawHitDetectionCanvas_ = function(renderOptions, context, x, y) {
  31209. // reset transform
  31210. context.setTransform(1, 0, 0, 1, 0, 0);
  31211. // then move to (x, y)
  31212. context.translate(x, y);
  31213. context.beginPath();
  31214. var points = this.points_;
  31215. if (points === Infinity) {
  31216. context.arc(
  31217. renderOptions.size / 2, renderOptions.size / 2,
  31218. this.radius_, 0, 2 * Math.PI, true);
  31219. } else {
  31220. var radius2 = (this.radius2_ !== undefined) ? this.radius2_
  31221. : this.radius_;
  31222. if (radius2 !== this.radius_) {
  31223. points = 2 * points;
  31224. }
  31225. var i, radiusC, angle0;
  31226. for (i = 0; i <= points; i++) {
  31227. angle0 = i * 2 * Math.PI / points - Math.PI / 2 + this.angle_;
  31228. radiusC = i % 2 === 0 ? this.radius_ : radius2;
  31229. context.lineTo(renderOptions.size / 2 + radiusC * Math.cos(angle0),
  31230. renderOptions.size / 2 + radiusC * Math.sin(angle0));
  31231. }
  31232. }
  31233. context.fillStyle = ol.render.canvas.defaultFillStyle;
  31234. context.fill();
  31235. if (this.stroke_) {
  31236. context.strokeStyle = renderOptions.strokeStyle;
  31237. context.lineWidth = renderOptions.strokeWidth;
  31238. if (renderOptions.lineDash) {
  31239. context.setLineDash(renderOptions.lineDash);
  31240. context.lineDashOffset = renderOptions.lineDashOffset;
  31241. }
  31242. context.stroke();
  31243. }
  31244. context.closePath();
  31245. };
  31246. /**
  31247. * @return {string} The checksum.
  31248. */
  31249. ol.style.RegularShape.prototype.getChecksum = function() {
  31250. var strokeChecksum = this.stroke_ ?
  31251. this.stroke_.getChecksum() : '-';
  31252. var fillChecksum = this.fill_ ?
  31253. this.fill_.getChecksum() : '-';
  31254. var recalculate = !this.checksums_ ||
  31255. (strokeChecksum != this.checksums_[1] ||
  31256. fillChecksum != this.checksums_[2] ||
  31257. this.radius_ != this.checksums_[3] ||
  31258. this.radius2_ != this.checksums_[4] ||
  31259. this.angle_ != this.checksums_[5] ||
  31260. this.points_ != this.checksums_[6]);
  31261. if (recalculate) {
  31262. var checksum = 'r' + strokeChecksum + fillChecksum +
  31263. (this.radius_ !== undefined ? this.radius_.toString() : '-') +
  31264. (this.radius2_ !== undefined ? this.radius2_.toString() : '-') +
  31265. (this.angle_ !== undefined ? this.angle_.toString() : '-') +
  31266. (this.points_ !== undefined ? this.points_.toString() : '-');
  31267. this.checksums_ = [checksum, strokeChecksum, fillChecksum,
  31268. this.radius_, this.radius2_, this.angle_, this.points_];
  31269. }
  31270. return this.checksums_[0];
  31271. };
  31272. goog.provide('ol.style.Circle');
  31273. goog.require('ol');
  31274. goog.require('ol.style.RegularShape');
  31275. /**
  31276. * @classdesc
  31277. * Set circle style for vector features.
  31278. *
  31279. * @constructor
  31280. * @param {olx.style.CircleOptions=} opt_options Options.
  31281. * @extends {ol.style.RegularShape}
  31282. * @api
  31283. */
  31284. ol.style.Circle = function(opt_options) {
  31285. var options = opt_options || {};
  31286. ol.style.RegularShape.call(this, {
  31287. points: Infinity,
  31288. fill: options.fill,
  31289. radius: options.radius,
  31290. snapToPixel: options.snapToPixel,
  31291. stroke: options.stroke,
  31292. atlasManager: options.atlasManager
  31293. });
  31294. };
  31295. ol.inherits(ol.style.Circle, ol.style.RegularShape);
  31296. /**
  31297. * Clones the style. If an atlasmanager was provided to the original style it will be used in the cloned style, too.
  31298. * @return {ol.style.Circle} The cloned style.
  31299. * @override
  31300. * @api
  31301. */
  31302. ol.style.Circle.prototype.clone = function() {
  31303. var style = new ol.style.Circle({
  31304. fill: this.getFill() ? this.getFill().clone() : undefined,
  31305. stroke: this.getStroke() ? this.getStroke().clone() : undefined,
  31306. radius: this.getRadius(),
  31307. snapToPixel: this.getSnapToPixel(),
  31308. atlasManager: this.atlasManager_
  31309. });
  31310. style.setOpacity(this.getOpacity());
  31311. style.setScale(this.getScale());
  31312. return style;
  31313. };
  31314. /**
  31315. * Set the circle radius.
  31316. *
  31317. * @param {number} radius Circle radius.
  31318. * @api
  31319. */
  31320. ol.style.Circle.prototype.setRadius = function(radius) {
  31321. this.radius_ = radius;
  31322. this.render_(this.atlasManager_);
  31323. };
  31324. goog.provide('ol.style.Fill');
  31325. goog.require('ol');
  31326. goog.require('ol.color');
  31327. /**
  31328. * @classdesc
  31329. * Set fill style for vector features.
  31330. *
  31331. * @constructor
  31332. * @param {olx.style.FillOptions=} opt_options Options.
  31333. * @api
  31334. */
  31335. ol.style.Fill = function(opt_options) {
  31336. var options = opt_options || {};
  31337. /**
  31338. * @private
  31339. * @type {ol.Color|ol.ColorLike}
  31340. */
  31341. this.color_ = options.color !== undefined ? options.color : null;
  31342. /**
  31343. * @private
  31344. * @type {string|undefined}
  31345. */
  31346. this.checksum_ = undefined;
  31347. };
  31348. /**
  31349. * Clones the style. The color is not cloned if it is an {@link ol.ColorLike}.
  31350. * @return {ol.style.Fill} The cloned style.
  31351. * @api
  31352. */
  31353. ol.style.Fill.prototype.clone = function() {
  31354. var color = this.getColor();
  31355. return new ol.style.Fill({
  31356. color: (color && color.slice) ? color.slice() : color || undefined
  31357. });
  31358. };
  31359. /**
  31360. * Get the fill color.
  31361. * @return {ol.Color|ol.ColorLike} Color.
  31362. * @api
  31363. */
  31364. ol.style.Fill.prototype.getColor = function() {
  31365. return this.color_;
  31366. };
  31367. /**
  31368. * Set the color.
  31369. *
  31370. * @param {ol.Color|ol.ColorLike} color Color.
  31371. * @api
  31372. */
  31373. ol.style.Fill.prototype.setColor = function(color) {
  31374. this.color_ = color;
  31375. this.checksum_ = undefined;
  31376. };
  31377. /**
  31378. * @return {string} The checksum.
  31379. */
  31380. ol.style.Fill.prototype.getChecksum = function() {
  31381. if (this.checksum_ === undefined) {
  31382. if (
  31383. this.color_ instanceof CanvasPattern ||
  31384. this.color_ instanceof CanvasGradient
  31385. ) {
  31386. this.checksum_ = ol.getUid(this.color_).toString();
  31387. } else {
  31388. this.checksum_ = 'f' + (this.color_ ?
  31389. ol.color.asString(this.color_) : '-');
  31390. }
  31391. }
  31392. return this.checksum_;
  31393. };
  31394. goog.provide('ol.style.Style');
  31395. goog.require('ol.asserts');
  31396. goog.require('ol.geom.GeometryType');
  31397. goog.require('ol.style.Circle');
  31398. goog.require('ol.style.Fill');
  31399. goog.require('ol.style.Stroke');
  31400. /**
  31401. * @classdesc
  31402. * Container for vector feature rendering styles. Any changes made to the style
  31403. * or its children through `set*()` methods will not take effect until the
  31404. * feature or layer that uses the style is re-rendered.
  31405. *
  31406. * @constructor
  31407. * @struct
  31408. * @param {olx.style.StyleOptions=} opt_options Style options.
  31409. * @api
  31410. */
  31411. ol.style.Style = function(opt_options) {
  31412. var options = opt_options || {};
  31413. /**
  31414. * @private
  31415. * @type {string|ol.geom.Geometry|ol.StyleGeometryFunction}
  31416. */
  31417. this.geometry_ = null;
  31418. /**
  31419. * @private
  31420. * @type {!ol.StyleGeometryFunction}
  31421. */
  31422. this.geometryFunction_ = ol.style.Style.defaultGeometryFunction;
  31423. if (options.geometry !== undefined) {
  31424. this.setGeometry(options.geometry);
  31425. }
  31426. /**
  31427. * @private
  31428. * @type {ol.style.Fill}
  31429. */
  31430. this.fill_ = options.fill !== undefined ? options.fill : null;
  31431. /**
  31432. * @private
  31433. * @type {ol.style.Image}
  31434. */
  31435. this.image_ = options.image !== undefined ? options.image : null;
  31436. /**
  31437. * @private
  31438. * @type {ol.StyleRenderFunction|null}
  31439. */
  31440. this.renderer_ = options.renderer !== undefined ? options.renderer : null;
  31441. /**
  31442. * @private
  31443. * @type {ol.style.Stroke}
  31444. */
  31445. this.stroke_ = options.stroke !== undefined ? options.stroke : null;
  31446. /**
  31447. * @private
  31448. * @type {ol.style.Text}
  31449. */
  31450. this.text_ = options.text !== undefined ? options.text : null;
  31451. /**
  31452. * @private
  31453. * @type {number|undefined}
  31454. */
  31455. this.zIndex_ = options.zIndex;
  31456. };
  31457. /**
  31458. * Clones the style.
  31459. * @return {ol.style.Style} The cloned style.
  31460. * @api
  31461. */
  31462. ol.style.Style.prototype.clone = function() {
  31463. var geometry = this.getGeometry();
  31464. if (geometry && geometry.clone) {
  31465. geometry = geometry.clone();
  31466. }
  31467. return new ol.style.Style({
  31468. geometry: geometry,
  31469. fill: this.getFill() ? this.getFill().clone() : undefined,
  31470. image: this.getImage() ? this.getImage().clone() : undefined,
  31471. stroke: this.getStroke() ? this.getStroke().clone() : undefined,
  31472. text: this.getText() ? this.getText().clone() : undefined,
  31473. zIndex: this.getZIndex()
  31474. });
  31475. };
  31476. /**
  31477. * Get the custom renderer function that was configured with
  31478. * {@link #setRenderer} or the `renderer` constructor option.
  31479. * @return {ol.StyleRenderFunction|null} Custom renderer function.
  31480. * @api
  31481. */
  31482. ol.style.Style.prototype.getRenderer = function() {
  31483. return this.renderer_;
  31484. };
  31485. /**
  31486. * Sets a custom renderer function for this style. When set, `fill`, `stroke`
  31487. * and `image` options of the style will be ignored.
  31488. * @param {ol.StyleRenderFunction|null} renderer Custom renderer function.
  31489. * @api
  31490. */
  31491. ol.style.Style.prototype.setRenderer = function(renderer) {
  31492. this.renderer_ = renderer;
  31493. };
  31494. /**
  31495. * Get the geometry to be rendered.
  31496. * @return {string|ol.geom.Geometry|ol.StyleGeometryFunction}
  31497. * Feature property or geometry or function that returns the geometry that will
  31498. * be rendered with this style.
  31499. * @api
  31500. */
  31501. ol.style.Style.prototype.getGeometry = function() {
  31502. return this.geometry_;
  31503. };
  31504. /**
  31505. * Get the function used to generate a geometry for rendering.
  31506. * @return {!ol.StyleGeometryFunction} Function that is called with a feature
  31507. * and returns the geometry to render instead of the feature's geometry.
  31508. * @api
  31509. */
  31510. ol.style.Style.prototype.getGeometryFunction = function() {
  31511. return this.geometryFunction_;
  31512. };
  31513. /**
  31514. * Get the fill style.
  31515. * @return {ol.style.Fill} Fill style.
  31516. * @api
  31517. */
  31518. ol.style.Style.prototype.getFill = function() {
  31519. return this.fill_;
  31520. };
  31521. /**
  31522. * Set the fill style.
  31523. * @param {ol.style.Fill} fill Fill style.
  31524. * @api
  31525. */
  31526. ol.style.Style.prototype.setFill = function(fill) {
  31527. this.fill_ = fill;
  31528. };
  31529. /**
  31530. * Get the image style.
  31531. * @return {ol.style.Image} Image style.
  31532. * @api
  31533. */
  31534. ol.style.Style.prototype.getImage = function() {
  31535. return this.image_;
  31536. };
  31537. /**
  31538. * Set the image style.
  31539. * @param {ol.style.Image} image Image style.
  31540. * @api
  31541. */
  31542. ol.style.Style.prototype.setImage = function(image) {
  31543. this.image_ = image;
  31544. };
  31545. /**
  31546. * Get the stroke style.
  31547. * @return {ol.style.Stroke} Stroke style.
  31548. * @api
  31549. */
  31550. ol.style.Style.prototype.getStroke = function() {
  31551. return this.stroke_;
  31552. };
  31553. /**
  31554. * Set the stroke style.
  31555. * @param {ol.style.Stroke} stroke Stroke style.
  31556. * @api
  31557. */
  31558. ol.style.Style.prototype.setStroke = function(stroke) {
  31559. this.stroke_ = stroke;
  31560. };
  31561. /**
  31562. * Get the text style.
  31563. * @return {ol.style.Text} Text style.
  31564. * @api
  31565. */
  31566. ol.style.Style.prototype.getText = function() {
  31567. return this.text_;
  31568. };
  31569. /**
  31570. * Set the text style.
  31571. * @param {ol.style.Text} text Text style.
  31572. * @api
  31573. */
  31574. ol.style.Style.prototype.setText = function(text) {
  31575. this.text_ = text;
  31576. };
  31577. /**
  31578. * Get the z-index for the style.
  31579. * @return {number|undefined} ZIndex.
  31580. * @api
  31581. */
  31582. ol.style.Style.prototype.getZIndex = function() {
  31583. return this.zIndex_;
  31584. };
  31585. /**
  31586. * Set a geometry that is rendered instead of the feature's geometry.
  31587. *
  31588. * @param {string|ol.geom.Geometry|ol.StyleGeometryFunction} geometry
  31589. * Feature property or geometry or function returning a geometry to render
  31590. * for this style.
  31591. * @api
  31592. */
  31593. ol.style.Style.prototype.setGeometry = function(geometry) {
  31594. if (typeof geometry === 'function') {
  31595. this.geometryFunction_ = geometry;
  31596. } else if (typeof geometry === 'string') {
  31597. this.geometryFunction_ = function(feature) {
  31598. return /** @type {ol.geom.Geometry} */ (feature.get(geometry));
  31599. };
  31600. } else if (!geometry) {
  31601. this.geometryFunction_ = ol.style.Style.defaultGeometryFunction;
  31602. } else if (geometry !== undefined) {
  31603. this.geometryFunction_ = function() {
  31604. return /** @type {ol.geom.Geometry} */ (geometry);
  31605. };
  31606. }
  31607. this.geometry_ = geometry;
  31608. };
  31609. /**
  31610. * Set the z-index.
  31611. *
  31612. * @param {number|undefined} zIndex ZIndex.
  31613. * @api
  31614. */
  31615. ol.style.Style.prototype.setZIndex = function(zIndex) {
  31616. this.zIndex_ = zIndex;
  31617. };
  31618. /**
  31619. * Convert the provided object into a style function. Functions passed through
  31620. * unchanged. Arrays of ol.style.Style or single style objects wrapped in a
  31621. * new style function.
  31622. * @param {ol.StyleFunction|Array.<ol.style.Style>|ol.style.Style} obj
  31623. * A style function, a single style, or an array of styles.
  31624. * @return {ol.StyleFunction} A style function.
  31625. */
  31626. ol.style.Style.createFunction = function(obj) {
  31627. var styleFunction;
  31628. if (typeof obj === 'function') {
  31629. styleFunction = obj;
  31630. } else {
  31631. /**
  31632. * @type {Array.<ol.style.Style>}
  31633. */
  31634. var styles;
  31635. if (Array.isArray(obj)) {
  31636. styles = obj;
  31637. } else {
  31638. ol.asserts.assert(obj instanceof ol.style.Style,
  31639. 41); // Expected an `ol.style.Style` or an array of `ol.style.Style`
  31640. styles = [obj];
  31641. }
  31642. styleFunction = function() {
  31643. return styles;
  31644. };
  31645. }
  31646. return styleFunction;
  31647. };
  31648. /**
  31649. * @type {Array.<ol.style.Style>}
  31650. * @private
  31651. */
  31652. ol.style.Style.default_ = null;
  31653. /**
  31654. * @param {ol.Feature|ol.render.Feature} feature Feature.
  31655. * @param {number} resolution Resolution.
  31656. * @return {Array.<ol.style.Style>} Style.
  31657. */
  31658. ol.style.Style.defaultFunction = function(feature, resolution) {
  31659. // We don't use an immediately-invoked function
  31660. // and a closure so we don't get an error at script evaluation time in
  31661. // browsers that do not support Canvas. (ol.style.Circle does
  31662. // canvas.getContext('2d') at construction time, which will cause an.error
  31663. // in such browsers.)
  31664. if (!ol.style.Style.default_) {
  31665. var fill = new ol.style.Fill({
  31666. color: 'rgba(255,255,255,0.4)'
  31667. });
  31668. var stroke = new ol.style.Stroke({
  31669. color: '#3399CC',
  31670. width: 1.25
  31671. });
  31672. ol.style.Style.default_ = [
  31673. new ol.style.Style({
  31674. image: new ol.style.Circle({
  31675. fill: fill,
  31676. stroke: stroke,
  31677. radius: 5
  31678. }),
  31679. fill: fill,
  31680. stroke: stroke
  31681. })
  31682. ];
  31683. }
  31684. return ol.style.Style.default_;
  31685. };
  31686. /**
  31687. * Default styles for editing features.
  31688. * @return {Object.<ol.geom.GeometryType, Array.<ol.style.Style>>} Styles
  31689. */
  31690. ol.style.Style.createDefaultEditing = function() {
  31691. /** @type {Object.<ol.geom.GeometryType, Array.<ol.style.Style>>} */
  31692. var styles = {};
  31693. var white = [255, 255, 255, 1];
  31694. var blue = [0, 153, 255, 1];
  31695. var width = 3;
  31696. styles[ol.geom.GeometryType.POLYGON] = [
  31697. new ol.style.Style({
  31698. fill: new ol.style.Fill({
  31699. color: [255, 255, 255, 0.5]
  31700. })
  31701. })
  31702. ];
  31703. styles[ol.geom.GeometryType.MULTI_POLYGON] =
  31704. styles[ol.geom.GeometryType.POLYGON];
  31705. styles[ol.geom.GeometryType.LINE_STRING] = [
  31706. new ol.style.Style({
  31707. stroke: new ol.style.Stroke({
  31708. color: white,
  31709. width: width + 2
  31710. })
  31711. }),
  31712. new ol.style.Style({
  31713. stroke: new ol.style.Stroke({
  31714. color: blue,
  31715. width: width
  31716. })
  31717. })
  31718. ];
  31719. styles[ol.geom.GeometryType.MULTI_LINE_STRING] =
  31720. styles[ol.geom.GeometryType.LINE_STRING];
  31721. styles[ol.geom.GeometryType.CIRCLE] =
  31722. styles[ol.geom.GeometryType.POLYGON].concat(
  31723. styles[ol.geom.GeometryType.LINE_STRING]
  31724. );
  31725. styles[ol.geom.GeometryType.POINT] = [
  31726. new ol.style.Style({
  31727. image: new ol.style.Circle({
  31728. radius: width * 2,
  31729. fill: new ol.style.Fill({
  31730. color: blue
  31731. }),
  31732. stroke: new ol.style.Stroke({
  31733. color: white,
  31734. width: width / 2
  31735. })
  31736. }),
  31737. zIndex: Infinity
  31738. })
  31739. ];
  31740. styles[ol.geom.GeometryType.MULTI_POINT] =
  31741. styles[ol.geom.GeometryType.POINT];
  31742. styles[ol.geom.GeometryType.GEOMETRY_COLLECTION] =
  31743. styles[ol.geom.GeometryType.POLYGON].concat(
  31744. styles[ol.geom.GeometryType.LINE_STRING],
  31745. styles[ol.geom.GeometryType.POINT]
  31746. );
  31747. return styles;
  31748. };
  31749. /**
  31750. * Function that is called with a feature and returns its default geometry.
  31751. * @param {ol.Feature|ol.render.Feature} feature Feature to get the geometry
  31752. * for.
  31753. * @return {ol.geom.Geometry|ol.render.Feature|undefined} Geometry to render.
  31754. */
  31755. ol.style.Style.defaultGeometryFunction = function(feature) {
  31756. return feature.getGeometry();
  31757. };
  31758. goog.provide('ol.Feature');
  31759. goog.require('ol.asserts');
  31760. goog.require('ol.events');
  31761. goog.require('ol.events.EventType');
  31762. goog.require('ol');
  31763. goog.require('ol.Object');
  31764. goog.require('ol.geom.Geometry');
  31765. goog.require('ol.style.Style');
  31766. /**
  31767. * @classdesc
  31768. * A vector object for geographic features with a geometry and other
  31769. * attribute properties, similar to the features in vector file formats like
  31770. * GeoJSON.
  31771. *
  31772. * Features can be styled individually with `setStyle`; otherwise they use the
  31773. * style of their vector layer.
  31774. *
  31775. * Note that attribute properties are set as {@link ol.Object} properties on
  31776. * the feature object, so they are observable, and have get/set accessors.
  31777. *
  31778. * Typically, a feature has a single geometry property. You can set the
  31779. * geometry using the `setGeometry` method and get it with `getGeometry`.
  31780. * It is possible to store more than one geometry on a feature using attribute
  31781. * properties. By default, the geometry used for rendering is identified by
  31782. * the property name `geometry`. If you want to use another geometry property
  31783. * for rendering, use the `setGeometryName` method to change the attribute
  31784. * property associated with the geometry for the feature. For example:
  31785. *
  31786. * ```js
  31787. * var feature = new ol.Feature({
  31788. * geometry: new ol.geom.Polygon(polyCoords),
  31789. * labelPoint: new ol.geom.Point(labelCoords),
  31790. * name: 'My Polygon'
  31791. * });
  31792. *
  31793. * // get the polygon geometry
  31794. * var poly = feature.getGeometry();
  31795. *
  31796. * // Render the feature as a point using the coordinates from labelPoint
  31797. * feature.setGeometryName('labelPoint');
  31798. *
  31799. * // get the point geometry
  31800. * var point = feature.getGeometry();
  31801. * ```
  31802. *
  31803. * @constructor
  31804. * @extends {ol.Object}
  31805. * @param {ol.geom.Geometry|Object.<string, *>=} opt_geometryOrProperties
  31806. * You may pass a Geometry object directly, or an object literal
  31807. * containing properties. If you pass an object literal, you may
  31808. * include a Geometry associated with a `geometry` key.
  31809. * @api
  31810. */
  31811. ol.Feature = function(opt_geometryOrProperties) {
  31812. ol.Object.call(this);
  31813. /**
  31814. * @private
  31815. * @type {number|string|undefined}
  31816. */
  31817. this.id_ = undefined;
  31818. /**
  31819. * @type {string}
  31820. * @private
  31821. */
  31822. this.geometryName_ = 'geometry';
  31823. /**
  31824. * User provided style.
  31825. * @private
  31826. * @type {ol.style.Style|Array.<ol.style.Style>|
  31827. * ol.FeatureStyleFunction}
  31828. */
  31829. this.style_ = null;
  31830. /**
  31831. * @private
  31832. * @type {ol.FeatureStyleFunction|undefined}
  31833. */
  31834. this.styleFunction_ = undefined;
  31835. /**
  31836. * @private
  31837. * @type {?ol.EventsKey}
  31838. */
  31839. this.geometryChangeKey_ = null;
  31840. ol.events.listen(
  31841. this, ol.Object.getChangeEventType(this.geometryName_),
  31842. this.handleGeometryChanged_, this);
  31843. if (opt_geometryOrProperties !== undefined) {
  31844. if (opt_geometryOrProperties instanceof ol.geom.Geometry ||
  31845. !opt_geometryOrProperties) {
  31846. var geometry = opt_geometryOrProperties;
  31847. this.setGeometry(geometry);
  31848. } else {
  31849. /** @type {Object.<string, *>} */
  31850. var properties = opt_geometryOrProperties;
  31851. this.setProperties(properties);
  31852. }
  31853. }
  31854. };
  31855. ol.inherits(ol.Feature, ol.Object);
  31856. /**
  31857. * Clone this feature. If the original feature has a geometry it
  31858. * is also cloned. The feature id is not set in the clone.
  31859. * @return {ol.Feature} The clone.
  31860. * @api
  31861. */
  31862. ol.Feature.prototype.clone = function() {
  31863. var clone = new ol.Feature(this.getProperties());
  31864. clone.setGeometryName(this.getGeometryName());
  31865. var geometry = this.getGeometry();
  31866. if (geometry) {
  31867. clone.setGeometry(geometry.clone());
  31868. }
  31869. var style = this.getStyle();
  31870. if (style) {
  31871. clone.setStyle(style);
  31872. }
  31873. return clone;
  31874. };
  31875. /**
  31876. * Get the feature's default geometry. A feature may have any number of named
  31877. * geometries. The "default" geometry (the one that is rendered by default) is
  31878. * set when calling {@link ol.Feature#setGeometry}.
  31879. * @return {ol.geom.Geometry|undefined} The default geometry for the feature.
  31880. * @api
  31881. * @observable
  31882. */
  31883. ol.Feature.prototype.getGeometry = function() {
  31884. return /** @type {ol.geom.Geometry|undefined} */ (
  31885. this.get(this.geometryName_));
  31886. };
  31887. /**
  31888. * Get the feature identifier. This is a stable identifier for the feature and
  31889. * is either set when reading data from a remote source or set explicitly by
  31890. * calling {@link ol.Feature#setId}.
  31891. * @return {number|string|undefined} Id.
  31892. * @api
  31893. */
  31894. ol.Feature.prototype.getId = function() {
  31895. return this.id_;
  31896. };
  31897. /**
  31898. * Get the name of the feature's default geometry. By default, the default
  31899. * geometry is named `geometry`.
  31900. * @return {string} Get the property name associated with the default geometry
  31901. * for this feature.
  31902. * @api
  31903. */
  31904. ol.Feature.prototype.getGeometryName = function() {
  31905. return this.geometryName_;
  31906. };
  31907. /**
  31908. * Get the feature's style. Will return what was provided to the
  31909. * {@link ol.Feature#setStyle} method.
  31910. * @return {ol.style.Style|Array.<ol.style.Style>|
  31911. * ol.FeatureStyleFunction|ol.StyleFunction} The feature style.
  31912. * @api
  31913. */
  31914. ol.Feature.prototype.getStyle = function() {
  31915. return this.style_;
  31916. };
  31917. /**
  31918. * Get the feature's style function.
  31919. * @return {ol.FeatureStyleFunction|undefined} Return a function
  31920. * representing the current style of this feature.
  31921. * @api
  31922. */
  31923. ol.Feature.prototype.getStyleFunction = function() {
  31924. return this.styleFunction_;
  31925. };
  31926. /**
  31927. * @private
  31928. */
  31929. ol.Feature.prototype.handleGeometryChange_ = function() {
  31930. this.changed();
  31931. };
  31932. /**
  31933. * @private
  31934. */
  31935. ol.Feature.prototype.handleGeometryChanged_ = function() {
  31936. if (this.geometryChangeKey_) {
  31937. ol.events.unlistenByKey(this.geometryChangeKey_);
  31938. this.geometryChangeKey_ = null;
  31939. }
  31940. var geometry = this.getGeometry();
  31941. if (geometry) {
  31942. this.geometryChangeKey_ = ol.events.listen(geometry,
  31943. ol.events.EventType.CHANGE, this.handleGeometryChange_, this);
  31944. }
  31945. this.changed();
  31946. };
  31947. /**
  31948. * Set the default geometry for the feature. This will update the property
  31949. * with the name returned by {@link ol.Feature#getGeometryName}.
  31950. * @param {ol.geom.Geometry|undefined} geometry The new geometry.
  31951. * @api
  31952. * @observable
  31953. */
  31954. ol.Feature.prototype.setGeometry = function(geometry) {
  31955. this.set(this.geometryName_, geometry);
  31956. };
  31957. /**
  31958. * Set the style for the feature. This can be a single style object, an array
  31959. * of styles, or a function that takes a resolution and returns an array of
  31960. * styles. If it is `null` the feature has no style (a `null` style).
  31961. * @param {ol.style.Style|Array.<ol.style.Style>|
  31962. * ol.FeatureStyleFunction|ol.StyleFunction} style Style for this feature.
  31963. * @api
  31964. * @fires ol.events.Event#event:change
  31965. */
  31966. ol.Feature.prototype.setStyle = function(style) {
  31967. this.style_ = style;
  31968. this.styleFunction_ = !style ?
  31969. undefined : ol.Feature.createStyleFunction(style);
  31970. this.changed();
  31971. };
  31972. /**
  31973. * Set the feature id. The feature id is considered stable and may be used when
  31974. * requesting features or comparing identifiers returned from a remote source.
  31975. * The feature id can be used with the {@link ol.source.Vector#getFeatureById}
  31976. * method.
  31977. * @param {number|string|undefined} id The feature id.
  31978. * @api
  31979. * @fires ol.events.Event#event:change
  31980. */
  31981. ol.Feature.prototype.setId = function(id) {
  31982. this.id_ = id;
  31983. this.changed();
  31984. };
  31985. /**
  31986. * Set the property name to be used when getting the feature's default geometry.
  31987. * When calling {@link ol.Feature#getGeometry}, the value of the property with
  31988. * this name will be returned.
  31989. * @param {string} name The property name of the default geometry.
  31990. * @api
  31991. */
  31992. ol.Feature.prototype.setGeometryName = function(name) {
  31993. ol.events.unlisten(
  31994. this, ol.Object.getChangeEventType(this.geometryName_),
  31995. this.handleGeometryChanged_, this);
  31996. this.geometryName_ = name;
  31997. ol.events.listen(
  31998. this, ol.Object.getChangeEventType(this.geometryName_),
  31999. this.handleGeometryChanged_, this);
  32000. this.handleGeometryChanged_();
  32001. };
  32002. /**
  32003. * Convert the provided object into a feature style function. Functions passed
  32004. * through unchanged. Arrays of ol.style.Style or single style objects wrapped
  32005. * in a new feature style function.
  32006. * @param {ol.FeatureStyleFunction|!Array.<ol.style.Style>|!ol.style.Style} obj
  32007. * A feature style function, a single style, or an array of styles.
  32008. * @return {ol.FeatureStyleFunction} A style function.
  32009. */
  32010. ol.Feature.createStyleFunction = function(obj) {
  32011. var styleFunction;
  32012. if (typeof obj === 'function') {
  32013. if (obj.length == 2) {
  32014. styleFunction = function(resolution) {
  32015. return /** @type {ol.StyleFunction} */ (obj)(this, resolution);
  32016. };
  32017. } else {
  32018. styleFunction = obj;
  32019. }
  32020. } else {
  32021. /**
  32022. * @type {Array.<ol.style.Style>}
  32023. */
  32024. var styles;
  32025. if (Array.isArray(obj)) {
  32026. styles = obj;
  32027. } else {
  32028. ol.asserts.assert(obj instanceof ol.style.Style,
  32029. 41); // Expected an `ol.style.Style` or an array of `ol.style.Style`
  32030. styles = [obj];
  32031. }
  32032. styleFunction = function() {
  32033. return styles;
  32034. };
  32035. }
  32036. return styleFunction;
  32037. };
  32038. goog.provide('ol.format.FormatType');
  32039. /**
  32040. * @enum {string}
  32041. */
  32042. ol.format.FormatType = {
  32043. ARRAY_BUFFER: 'arraybuffer',
  32044. JSON: 'json',
  32045. TEXT: 'text',
  32046. XML: 'xml'
  32047. };
  32048. goog.provide('ol.xml');
  32049. goog.require('ol.array');
  32050. /**
  32051. * This document should be used when creating nodes for XML serializations. This
  32052. * document is also used by {@link ol.xml.createElementNS} and
  32053. * {@link ol.xml.setAttributeNS}
  32054. * @const
  32055. * @type {Document}
  32056. */
  32057. ol.xml.DOCUMENT = document.implementation.createDocument('', '', null);
  32058. /**
  32059. * @param {string} namespaceURI Namespace URI.
  32060. * @param {string} qualifiedName Qualified name.
  32061. * @return {Node} Node.
  32062. */
  32063. ol.xml.createElementNS = function(namespaceURI, qualifiedName) {
  32064. return ol.xml.DOCUMENT.createElementNS(namespaceURI, qualifiedName);
  32065. };
  32066. /**
  32067. * Recursively grab all text content of child nodes into a single string.
  32068. * @param {Node} node Node.
  32069. * @param {boolean} normalizeWhitespace Normalize whitespace: remove all line
  32070. * breaks.
  32071. * @return {string} All text content.
  32072. * @api
  32073. */
  32074. ol.xml.getAllTextContent = function(node, normalizeWhitespace) {
  32075. return ol.xml.getAllTextContent_(node, normalizeWhitespace, []).join('');
  32076. };
  32077. /**
  32078. * Recursively grab all text content of child nodes into a single string.
  32079. * @param {Node} node Node.
  32080. * @param {boolean} normalizeWhitespace Normalize whitespace: remove all line
  32081. * breaks.
  32082. * @param {Array.<string>} accumulator Accumulator.
  32083. * @private
  32084. * @return {Array.<string>} Accumulator.
  32085. */
  32086. ol.xml.getAllTextContent_ = function(node, normalizeWhitespace, accumulator) {
  32087. if (node.nodeType == Node.CDATA_SECTION_NODE ||
  32088. node.nodeType == Node.TEXT_NODE) {
  32089. if (normalizeWhitespace) {
  32090. accumulator.push(String(node.nodeValue).replace(/(\r\n|\r|\n)/g, ''));
  32091. } else {
  32092. accumulator.push(node.nodeValue);
  32093. }
  32094. } else {
  32095. var n;
  32096. for (n = node.firstChild; n; n = n.nextSibling) {
  32097. ol.xml.getAllTextContent_(n, normalizeWhitespace, accumulator);
  32098. }
  32099. }
  32100. return accumulator;
  32101. };
  32102. /**
  32103. * @param {?} value Value.
  32104. * @return {boolean} Is document.
  32105. */
  32106. ol.xml.isDocument = function(value) {
  32107. return value instanceof Document;
  32108. };
  32109. /**
  32110. * @param {?} value Value.
  32111. * @return {boolean} Is node.
  32112. */
  32113. ol.xml.isNode = function(value) {
  32114. return value instanceof Node;
  32115. };
  32116. /**
  32117. * @param {Node} node Node.
  32118. * @param {?string} namespaceURI Namespace URI.
  32119. * @param {string} name Attribute name.
  32120. * @return {string} Value
  32121. */
  32122. ol.xml.getAttributeNS = function(node, namespaceURI, name) {
  32123. return node.getAttributeNS(namespaceURI, name) || '';
  32124. };
  32125. /**
  32126. * @param {Node} node Node.
  32127. * @param {?string} namespaceURI Namespace URI.
  32128. * @param {string} name Attribute name.
  32129. * @param {string|number} value Value.
  32130. */
  32131. ol.xml.setAttributeNS = function(node, namespaceURI, name, value) {
  32132. node.setAttributeNS(namespaceURI, name, value);
  32133. };
  32134. /**
  32135. * Parse an XML string to an XML Document.
  32136. * @param {string} xml XML.
  32137. * @return {Document} Document.
  32138. * @api
  32139. */
  32140. ol.xml.parse = function(xml) {
  32141. return new DOMParser().parseFromString(xml, 'application/xml');
  32142. };
  32143. /**
  32144. * Make an array extender function for extending the array at the top of the
  32145. * object stack.
  32146. * @param {function(this: T, Node, Array.<*>): (Array.<*>|undefined)}
  32147. * valueReader Value reader.
  32148. * @param {T=} opt_this The object to use as `this` in `valueReader`.
  32149. * @return {ol.XmlParser} Parser.
  32150. * @template T
  32151. */
  32152. ol.xml.makeArrayExtender = function(valueReader, opt_this) {
  32153. return (
  32154. /**
  32155. * @param {Node} node Node.
  32156. * @param {Array.<*>} objectStack Object stack.
  32157. */
  32158. function(node, objectStack) {
  32159. var value = valueReader.call(opt_this, node, objectStack);
  32160. if (value !== undefined) {
  32161. var array = /** @type {Array.<*>} */
  32162. (objectStack[objectStack.length - 1]);
  32163. ol.array.extend(array, value);
  32164. }
  32165. });
  32166. };
  32167. /**
  32168. * Make an array pusher function for pushing to the array at the top of the
  32169. * object stack.
  32170. * @param {function(this: T, Node, Array.<*>): *} valueReader Value reader.
  32171. * @param {T=} opt_this The object to use as `this` in `valueReader`.
  32172. * @return {ol.XmlParser} Parser.
  32173. * @template T
  32174. */
  32175. ol.xml.makeArrayPusher = function(valueReader, opt_this) {
  32176. return (
  32177. /**
  32178. * @param {Node} node Node.
  32179. * @param {Array.<*>} objectStack Object stack.
  32180. */
  32181. function(node, objectStack) {
  32182. var value = valueReader.call(opt_this !== undefined ? opt_this : this,
  32183. node, objectStack);
  32184. if (value !== undefined) {
  32185. var array = objectStack[objectStack.length - 1];
  32186. array.push(value);
  32187. }
  32188. });
  32189. };
  32190. /**
  32191. * Make an object stack replacer function for replacing the object at the
  32192. * top of the stack.
  32193. * @param {function(this: T, Node, Array.<*>): *} valueReader Value reader.
  32194. * @param {T=} opt_this The object to use as `this` in `valueReader`.
  32195. * @return {ol.XmlParser} Parser.
  32196. * @template T
  32197. */
  32198. ol.xml.makeReplacer = function(valueReader, opt_this) {
  32199. return (
  32200. /**
  32201. * @param {Node} node Node.
  32202. * @param {Array.<*>} objectStack Object stack.
  32203. */
  32204. function(node, objectStack) {
  32205. var value = valueReader.call(opt_this !== undefined ? opt_this : this,
  32206. node, objectStack);
  32207. if (value !== undefined) {
  32208. objectStack[objectStack.length - 1] = value;
  32209. }
  32210. });
  32211. };
  32212. /**
  32213. * Make an object property pusher function for adding a property to the
  32214. * object at the top of the stack.
  32215. * @param {function(this: T, Node, Array.<*>): *} valueReader Value reader.
  32216. * @param {string=} opt_property Property.
  32217. * @param {T=} opt_this The object to use as `this` in `valueReader`.
  32218. * @return {ol.XmlParser} Parser.
  32219. * @template T
  32220. */
  32221. ol.xml.makeObjectPropertyPusher = function(valueReader, opt_property, opt_this) {
  32222. return (
  32223. /**
  32224. * @param {Node} node Node.
  32225. * @param {Array.<*>} objectStack Object stack.
  32226. */
  32227. function(node, objectStack) {
  32228. var value = valueReader.call(opt_this !== undefined ? opt_this : this,
  32229. node, objectStack);
  32230. if (value !== undefined) {
  32231. var object = /** @type {Object} */
  32232. (objectStack[objectStack.length - 1]);
  32233. var property = opt_property !== undefined ?
  32234. opt_property : node.localName;
  32235. var array;
  32236. if (property in object) {
  32237. array = object[property];
  32238. } else {
  32239. array = object[property] = [];
  32240. }
  32241. array.push(value);
  32242. }
  32243. });
  32244. };
  32245. /**
  32246. * Make an object property setter function.
  32247. * @param {function(this: T, Node, Array.<*>): *} valueReader Value reader.
  32248. * @param {string=} opt_property Property.
  32249. * @param {T=} opt_this The object to use as `this` in `valueReader`.
  32250. * @return {ol.XmlParser} Parser.
  32251. * @template T
  32252. */
  32253. ol.xml.makeObjectPropertySetter = function(valueReader, opt_property, opt_this) {
  32254. return (
  32255. /**
  32256. * @param {Node} node Node.
  32257. * @param {Array.<*>} objectStack Object stack.
  32258. */
  32259. function(node, objectStack) {
  32260. var value = valueReader.call(opt_this !== undefined ? opt_this : this,
  32261. node, objectStack);
  32262. if (value !== undefined) {
  32263. var object = /** @type {Object} */
  32264. (objectStack[objectStack.length - 1]);
  32265. var property = opt_property !== undefined ?
  32266. opt_property : node.localName;
  32267. object[property] = value;
  32268. }
  32269. });
  32270. };
  32271. /**
  32272. * Create a serializer that appends nodes written by its `nodeWriter` to its
  32273. * designated parent. The parent is the `node` of the
  32274. * {@link ol.XmlNodeStackItem} at the top of the `objectStack`.
  32275. * @param {function(this: T, Node, V, Array.<*>)}
  32276. * nodeWriter Node writer.
  32277. * @param {T=} opt_this The object to use as `this` in `nodeWriter`.
  32278. * @return {ol.XmlSerializer} Serializer.
  32279. * @template T, V
  32280. */
  32281. ol.xml.makeChildAppender = function(nodeWriter, opt_this) {
  32282. return function(node, value, objectStack) {
  32283. nodeWriter.call(opt_this !== undefined ? opt_this : this,
  32284. node, value, objectStack);
  32285. var parent = objectStack[objectStack.length - 1];
  32286. var parentNode = parent.node;
  32287. parentNode.appendChild(node);
  32288. };
  32289. };
  32290. /**
  32291. * Create a serializer that calls the provided `nodeWriter` from
  32292. * {@link ol.xml.serialize}. This can be used by the parent writer to have the
  32293. * 'nodeWriter' called with an array of values when the `nodeWriter` was
  32294. * designed to serialize a single item. An example would be a LineString
  32295. * geometry writer, which could be reused for writing MultiLineString
  32296. * geometries.
  32297. * @param {function(this: T, Node, V, Array.<*>)}
  32298. * nodeWriter Node writer.
  32299. * @param {T=} opt_this The object to use as `this` in `nodeWriter`.
  32300. * @return {ol.XmlSerializer} Serializer.
  32301. * @template T, V
  32302. */
  32303. ol.xml.makeArraySerializer = function(nodeWriter, opt_this) {
  32304. var serializersNS, nodeFactory;
  32305. return function(node, value, objectStack) {
  32306. if (serializersNS === undefined) {
  32307. serializersNS = {};
  32308. var serializers = {};
  32309. serializers[node.localName] = nodeWriter;
  32310. serializersNS[node.namespaceURI] = serializers;
  32311. nodeFactory = ol.xml.makeSimpleNodeFactory(node.localName);
  32312. }
  32313. ol.xml.serialize(serializersNS, nodeFactory, value, objectStack);
  32314. };
  32315. };
  32316. /**
  32317. * Create a node factory which can use the `opt_keys` passed to
  32318. * {@link ol.xml.serialize} or {@link ol.xml.pushSerializeAndPop} as node names,
  32319. * or a fixed node name. The namespace of the created nodes can either be fixed,
  32320. * or the parent namespace will be used.
  32321. * @param {string=} opt_nodeName Fixed node name which will be used for all
  32322. * created nodes. If not provided, the 3rd argument to the resulting node
  32323. * factory needs to be provided and will be the nodeName.
  32324. * @param {string=} opt_namespaceURI Fixed namespace URI which will be used for
  32325. * all created nodes. If not provided, the namespace of the parent node will
  32326. * be used.
  32327. * @return {function(*, Array.<*>, string=): (Node|undefined)} Node factory.
  32328. */
  32329. ol.xml.makeSimpleNodeFactory = function(opt_nodeName, opt_namespaceURI) {
  32330. var fixedNodeName = opt_nodeName;
  32331. return (
  32332. /**
  32333. * @param {*} value Value.
  32334. * @param {Array.<*>} objectStack Object stack.
  32335. * @param {string=} opt_nodeName Node name.
  32336. * @return {Node} Node.
  32337. */
  32338. function(value, objectStack, opt_nodeName) {
  32339. var context = objectStack[objectStack.length - 1];
  32340. var node = context.node;
  32341. var nodeName = fixedNodeName;
  32342. if (nodeName === undefined) {
  32343. nodeName = opt_nodeName;
  32344. }
  32345. var namespaceURI = opt_namespaceURI;
  32346. if (opt_namespaceURI === undefined) {
  32347. namespaceURI = node.namespaceURI;
  32348. }
  32349. return ol.xml.createElementNS(namespaceURI, /** @type {string} */ (nodeName));
  32350. }
  32351. );
  32352. };
  32353. /**
  32354. * A node factory that creates a node using the parent's `namespaceURI` and the
  32355. * `nodeName` passed by {@link ol.xml.serialize} or
  32356. * {@link ol.xml.pushSerializeAndPop} to the node factory.
  32357. * @const
  32358. * @type {function(*, Array.<*>, string=): (Node|undefined)}
  32359. */
  32360. ol.xml.OBJECT_PROPERTY_NODE_FACTORY = ol.xml.makeSimpleNodeFactory();
  32361. /**
  32362. * Create an array of `values` to be used with {@link ol.xml.serialize} or
  32363. * {@link ol.xml.pushSerializeAndPop}, where `orderedKeys` has to be provided as
  32364. * `opt_key` argument.
  32365. * @param {Object.<string, V>} object Key-value pairs for the sequence. Keys can
  32366. * be a subset of the `orderedKeys`.
  32367. * @param {Array.<string>} orderedKeys Keys in the order of the sequence.
  32368. * @return {Array.<V>} Values in the order of the sequence. The resulting array
  32369. * has the same length as the `orderedKeys` array. Values that are not
  32370. * present in `object` will be `undefined` in the resulting array.
  32371. * @template V
  32372. */
  32373. ol.xml.makeSequence = function(object, orderedKeys) {
  32374. var length = orderedKeys.length;
  32375. var sequence = new Array(length);
  32376. for (var i = 0; i < length; ++i) {
  32377. sequence[i] = object[orderedKeys[i]];
  32378. }
  32379. return sequence;
  32380. };
  32381. /**
  32382. * Create a namespaced structure, using the same values for each namespace.
  32383. * This can be used as a starting point for versioned parsers, when only a few
  32384. * values are version specific.
  32385. * @param {Array.<string>} namespaceURIs Namespace URIs.
  32386. * @param {T} structure Structure.
  32387. * @param {Object.<string, T>=} opt_structureNS Namespaced structure to add to.
  32388. * @return {Object.<string, T>} Namespaced structure.
  32389. * @template T
  32390. */
  32391. ol.xml.makeStructureNS = function(namespaceURIs, structure, opt_structureNS) {
  32392. /**
  32393. * @type {Object.<string, *>}
  32394. */
  32395. var structureNS = opt_structureNS !== undefined ? opt_structureNS : {};
  32396. var i, ii;
  32397. for (i = 0, ii = namespaceURIs.length; i < ii; ++i) {
  32398. structureNS[namespaceURIs[i]] = structure;
  32399. }
  32400. return structureNS;
  32401. };
  32402. /**
  32403. * Parse a node using the parsers and object stack.
  32404. * @param {Object.<string, Object.<string, ol.XmlParser>>} parsersNS
  32405. * Parsers by namespace.
  32406. * @param {Node} node Node.
  32407. * @param {Array.<*>} objectStack Object stack.
  32408. * @param {*=} opt_this The object to use as `this`.
  32409. */
  32410. ol.xml.parseNode = function(parsersNS, node, objectStack, opt_this) {
  32411. var n;
  32412. for (n = node.firstElementChild; n; n = n.nextElementSibling) {
  32413. var parsers = parsersNS[n.namespaceURI];
  32414. if (parsers !== undefined) {
  32415. var parser = parsers[n.localName];
  32416. if (parser !== undefined) {
  32417. parser.call(opt_this, n, objectStack);
  32418. }
  32419. }
  32420. }
  32421. };
  32422. /**
  32423. * Push an object on top of the stack, parse and return the popped object.
  32424. * @param {T} object Object.
  32425. * @param {Object.<string, Object.<string, ol.XmlParser>>} parsersNS
  32426. * Parsers by namespace.
  32427. * @param {Node} node Node.
  32428. * @param {Array.<*>} objectStack Object stack.
  32429. * @param {*=} opt_this The object to use as `this`.
  32430. * @return {T} Object.
  32431. * @template T
  32432. */
  32433. ol.xml.pushParseAndPop = function(
  32434. object, parsersNS, node, objectStack, opt_this) {
  32435. objectStack.push(object);
  32436. ol.xml.parseNode(parsersNS, node, objectStack, opt_this);
  32437. return objectStack.pop();
  32438. };
  32439. /**
  32440. * Walk through an array of `values` and call a serializer for each value.
  32441. * @param {Object.<string, Object.<string, ol.XmlSerializer>>} serializersNS
  32442. * Namespaced serializers.
  32443. * @param {function(this: T, *, Array.<*>, (string|undefined)): (Node|undefined)} nodeFactory
  32444. * Node factory. The `nodeFactory` creates the node whose namespace and name
  32445. * will be used to choose a node writer from `serializersNS`. This
  32446. * separation allows us to decide what kind of node to create, depending on
  32447. * the value we want to serialize. An example for this would be different
  32448. * geometry writers based on the geometry type.
  32449. * @param {Array.<*>} values Values to serialize. An example would be an array
  32450. * of {@link ol.Feature} instances.
  32451. * @param {Array.<*>} objectStack Node stack.
  32452. * @param {Array.<string>=} opt_keys Keys of the `values`. Will be passed to the
  32453. * `nodeFactory`. This is used for serializing object literals where the
  32454. * node name relates to the property key. The array length of `opt_keys` has
  32455. * to match the length of `values`. For serializing a sequence, `opt_keys`
  32456. * determines the order of the sequence.
  32457. * @param {T=} opt_this The object to use as `this` for the node factory and
  32458. * serializers.
  32459. * @template T
  32460. */
  32461. ol.xml.serialize = function(
  32462. serializersNS, nodeFactory, values, objectStack, opt_keys, opt_this) {
  32463. var length = (opt_keys !== undefined ? opt_keys : values).length;
  32464. var value, node;
  32465. for (var i = 0; i < length; ++i) {
  32466. value = values[i];
  32467. if (value !== undefined) {
  32468. node = nodeFactory.call(opt_this, value, objectStack,
  32469. opt_keys !== undefined ? opt_keys[i] : undefined);
  32470. if (node !== undefined) {
  32471. serializersNS[node.namespaceURI][node.localName]
  32472. .call(opt_this, node, value, objectStack);
  32473. }
  32474. }
  32475. }
  32476. };
  32477. /**
  32478. * @param {O} object Object.
  32479. * @param {Object.<string, Object.<string, ol.XmlSerializer>>} serializersNS
  32480. * Namespaced serializers.
  32481. * @param {function(this: T, *, Array.<*>, (string|undefined)): (Node|undefined)} nodeFactory
  32482. * Node factory. The `nodeFactory` creates the node whose namespace and name
  32483. * will be used to choose a node writer from `serializersNS`. This
  32484. * separation allows us to decide what kind of node to create, depending on
  32485. * the value we want to serialize. An example for this would be different
  32486. * geometry writers based on the geometry type.
  32487. * @param {Array.<*>} values Values to serialize. An example would be an array
  32488. * of {@link ol.Feature} instances.
  32489. * @param {Array.<*>} objectStack Node stack.
  32490. * @param {Array.<string>=} opt_keys Keys of the `values`. Will be passed to the
  32491. * `nodeFactory`. This is used for serializing object literals where the
  32492. * node name relates to the property key. The array length of `opt_keys` has
  32493. * to match the length of `values`. For serializing a sequence, `opt_keys`
  32494. * determines the order of the sequence.
  32495. * @param {T=} opt_this The object to use as `this` for the node factory and
  32496. * serializers.
  32497. * @return {O|undefined} Object.
  32498. * @template O, T
  32499. */
  32500. ol.xml.pushSerializeAndPop = function(object,
  32501. serializersNS, nodeFactory, values, objectStack, opt_keys, opt_this) {
  32502. objectStack.push(object);
  32503. ol.xml.serialize(
  32504. serializersNS, nodeFactory, values, objectStack, opt_keys, opt_this);
  32505. return objectStack.pop();
  32506. };
  32507. goog.provide('ol.featureloader');
  32508. goog.require('ol');
  32509. goog.require('ol.format.FormatType');
  32510. goog.require('ol.xml');
  32511. /**
  32512. * @param {string|ol.FeatureUrlFunction} url Feature URL service.
  32513. * @param {ol.format.Feature} format Feature format.
  32514. * @param {function(this:ol.VectorTile, Array.<ol.Feature>, ol.proj.Projection, ol.Extent)|function(this:ol.source.Vector, Array.<ol.Feature>)} success
  32515. * Function called with the loaded features and optionally with the data
  32516. * projection. Called with the vector tile or source as `this`.
  32517. * @param {function(this:ol.VectorTile)|function(this:ol.source.Vector)} failure
  32518. * Function called when loading failed. Called with the vector tile or
  32519. * source as `this`.
  32520. * @return {ol.FeatureLoader} The feature loader.
  32521. */
  32522. ol.featureloader.loadFeaturesXhr = function(url, format, success, failure) {
  32523. return (
  32524. /**
  32525. * @param {ol.Extent} extent Extent.
  32526. * @param {number} resolution Resolution.
  32527. * @param {ol.proj.Projection} projection Projection.
  32528. * @this {ol.source.Vector|ol.VectorTile}
  32529. */
  32530. function(extent, resolution, projection) {
  32531. var xhr = new XMLHttpRequest();
  32532. xhr.open('GET',
  32533. typeof url === 'function' ? url(extent, resolution, projection) : url,
  32534. true);
  32535. if (format.getType() == ol.format.FormatType.ARRAY_BUFFER) {
  32536. xhr.responseType = 'arraybuffer';
  32537. }
  32538. /**
  32539. * @param {Event} event Event.
  32540. * @private
  32541. */
  32542. xhr.onload = function(event) {
  32543. // status will be 0 for file:// urls
  32544. if (!xhr.status || xhr.status >= 200 && xhr.status < 300) {
  32545. var type = format.getType();
  32546. /** @type {Document|Node|Object|string|undefined} */
  32547. var source;
  32548. if (type == ol.format.FormatType.JSON ||
  32549. type == ol.format.FormatType.TEXT) {
  32550. source = xhr.responseText;
  32551. } else if (type == ol.format.FormatType.XML) {
  32552. source = xhr.responseXML;
  32553. if (!source) {
  32554. source = ol.xml.parse(xhr.responseText);
  32555. }
  32556. } else if (type == ol.format.FormatType.ARRAY_BUFFER) {
  32557. source = /** @type {ArrayBuffer} */ (xhr.response);
  32558. }
  32559. if (source) {
  32560. success.call(this, format.readFeatures(source,
  32561. {featureProjection: projection}),
  32562. format.readProjection(source), format.getLastExtent());
  32563. } else {
  32564. failure.call(this);
  32565. }
  32566. } else {
  32567. failure.call(this);
  32568. }
  32569. }.bind(this);
  32570. /**
  32571. * @private
  32572. */
  32573. xhr.onerror = function() {
  32574. failure.call(this);
  32575. }.bind(this);
  32576. xhr.send();
  32577. });
  32578. };
  32579. /**
  32580. * Create an XHR feature loader for a `url` and `format`. The feature loader
  32581. * loads features (with XHR), parses the features, and adds them to the
  32582. * vector source.
  32583. * @param {string|ol.FeatureUrlFunction} url Feature URL service.
  32584. * @param {ol.format.Feature} format Feature format.
  32585. * @return {ol.FeatureLoader} The feature loader.
  32586. * @api
  32587. */
  32588. ol.featureloader.xhr = function(url, format) {
  32589. return ol.featureloader.loadFeaturesXhr(url, format,
  32590. /**
  32591. * @param {Array.<ol.Feature>} features The loaded features.
  32592. * @param {ol.proj.Projection} dataProjection Data projection.
  32593. * @this {ol.source.Vector}
  32594. */
  32595. function(features, dataProjection) {
  32596. this.addFeatures(features);
  32597. }, /* FIXME handle error */ ol.nullFunction);
  32598. };
  32599. goog.provide('ol.format.Feature');
  32600. goog.require('ol.geom.Geometry');
  32601. goog.require('ol.obj');
  32602. goog.require('ol.proj');
  32603. /**
  32604. * @classdesc
  32605. * Abstract base class; normally only used for creating subclasses and not
  32606. * instantiated in apps.
  32607. * Base class for feature formats.
  32608. * {ol.format.Feature} subclasses provide the ability to decode and encode
  32609. * {@link ol.Feature} objects from a variety of commonly used geospatial
  32610. * file formats. See the documentation for each format for more details.
  32611. *
  32612. * @constructor
  32613. * @abstract
  32614. * @api
  32615. */
  32616. ol.format.Feature = function() {
  32617. /**
  32618. * @protected
  32619. * @type {ol.proj.Projection}
  32620. */
  32621. this.defaultDataProjection = null;
  32622. /**
  32623. * @protected
  32624. * @type {ol.proj.Projection}
  32625. */
  32626. this.defaultFeatureProjection = null;
  32627. };
  32628. /**
  32629. * Adds the data projection to the read options.
  32630. * @param {Document|Node|Object|string} source Source.
  32631. * @param {olx.format.ReadOptions=} opt_options Options.
  32632. * @return {olx.format.ReadOptions|undefined} Options.
  32633. * @protected
  32634. */
  32635. ol.format.Feature.prototype.getReadOptions = function(source, opt_options) {
  32636. var options;
  32637. if (opt_options) {
  32638. options = {
  32639. dataProjection: opt_options.dataProjection ?
  32640. opt_options.dataProjection : this.readProjection(source),
  32641. featureProjection: opt_options.featureProjection
  32642. };
  32643. }
  32644. return this.adaptOptions(options);
  32645. };
  32646. /**
  32647. * Sets the `defaultDataProjection` on the options, if no `dataProjection`
  32648. * is set.
  32649. * @param {olx.format.WriteOptions|olx.format.ReadOptions|undefined} options
  32650. * Options.
  32651. * @protected
  32652. * @return {olx.format.WriteOptions|olx.format.ReadOptions|undefined}
  32653. * Updated options.
  32654. */
  32655. ol.format.Feature.prototype.adaptOptions = function(options) {
  32656. return ol.obj.assign({
  32657. dataProjection: this.defaultDataProjection,
  32658. featureProjection: this.defaultFeatureProjection
  32659. }, options);
  32660. };
  32661. /**
  32662. * Get the extent from the source of the last {@link readFeatures} call.
  32663. * @return {ol.Extent} Tile extent.
  32664. */
  32665. ol.format.Feature.prototype.getLastExtent = function() {
  32666. return null;
  32667. };
  32668. /**
  32669. * @abstract
  32670. * @return {ol.format.FormatType} Format.
  32671. */
  32672. ol.format.Feature.prototype.getType = function() {};
  32673. /**
  32674. * Read a single feature from a source.
  32675. *
  32676. * @abstract
  32677. * @param {Document|Node|Object|string} source Source.
  32678. * @param {olx.format.ReadOptions=} opt_options Read options.
  32679. * @return {ol.Feature} Feature.
  32680. */
  32681. ol.format.Feature.prototype.readFeature = function(source, opt_options) {};
  32682. /**
  32683. * Read all features from a source.
  32684. *
  32685. * @abstract
  32686. * @param {Document|Node|ArrayBuffer|Object|string} source Source.
  32687. * @param {olx.format.ReadOptions=} opt_options Read options.
  32688. * @return {Array.<ol.Feature>} Features.
  32689. */
  32690. ol.format.Feature.prototype.readFeatures = function(source, opt_options) {};
  32691. /**
  32692. * Read a single geometry from a source.
  32693. *
  32694. * @abstract
  32695. * @param {Document|Node|Object|string} source Source.
  32696. * @param {olx.format.ReadOptions=} opt_options Read options.
  32697. * @return {ol.geom.Geometry} Geometry.
  32698. */
  32699. ol.format.Feature.prototype.readGeometry = function(source, opt_options) {};
  32700. /**
  32701. * Read the projection from a source.
  32702. *
  32703. * @abstract
  32704. * @param {Document|Node|Object|string} source Source.
  32705. * @return {ol.proj.Projection} Projection.
  32706. */
  32707. ol.format.Feature.prototype.readProjection = function(source) {};
  32708. /**
  32709. * Encode a feature in this format.
  32710. *
  32711. * @abstract
  32712. * @param {ol.Feature} feature Feature.
  32713. * @param {olx.format.WriteOptions=} opt_options Write options.
  32714. * @return {string} Result.
  32715. */
  32716. ol.format.Feature.prototype.writeFeature = function(feature, opt_options) {};
  32717. /**
  32718. * Encode an array of features in this format.
  32719. *
  32720. * @abstract
  32721. * @param {Array.<ol.Feature>} features Features.
  32722. * @param {olx.format.WriteOptions=} opt_options Write options.
  32723. * @return {string} Result.
  32724. */
  32725. ol.format.Feature.prototype.writeFeatures = function(features, opt_options) {};
  32726. /**
  32727. * Write a single geometry in this format.
  32728. *
  32729. * @abstract
  32730. * @param {ol.geom.Geometry} geometry Geometry.
  32731. * @param {olx.format.WriteOptions=} opt_options Write options.
  32732. * @return {string} Result.
  32733. */
  32734. ol.format.Feature.prototype.writeGeometry = function(geometry, opt_options) {};
  32735. /**
  32736. * @param {ol.geom.Geometry|ol.Extent} geometry Geometry.
  32737. * @param {boolean} write Set to true for writing, false for reading.
  32738. * @param {(olx.format.WriteOptions|olx.format.ReadOptions)=} opt_options
  32739. * Options.
  32740. * @return {ol.geom.Geometry|ol.Extent} Transformed geometry.
  32741. * @protected
  32742. */
  32743. ol.format.Feature.transformWithOptions = function(
  32744. geometry, write, opt_options) {
  32745. var featureProjection = opt_options ?
  32746. ol.proj.get(opt_options.featureProjection) : null;
  32747. var dataProjection = opt_options ?
  32748. ol.proj.get(opt_options.dataProjection) : null;
  32749. /**
  32750. * @type {ol.geom.Geometry|ol.Extent}
  32751. */
  32752. var transformed;
  32753. if (featureProjection && dataProjection &&
  32754. !ol.proj.equivalent(featureProjection, dataProjection)) {
  32755. if (geometry instanceof ol.geom.Geometry) {
  32756. transformed = (write ? geometry.clone() : geometry).transform(
  32757. write ? featureProjection : dataProjection,
  32758. write ? dataProjection : featureProjection);
  32759. } else {
  32760. // FIXME this is necessary because ol.format.GML treats extents
  32761. // as geometries
  32762. transformed = ol.proj.transformExtent(
  32763. geometry,
  32764. dataProjection,
  32765. featureProjection);
  32766. }
  32767. } else {
  32768. transformed = geometry;
  32769. }
  32770. if (write && opt_options && opt_options.decimals !== undefined) {
  32771. var power = Math.pow(10, opt_options.decimals);
  32772. // if decimals option on write, round each coordinate appropriately
  32773. /**
  32774. * @param {Array.<number>} coordinates Coordinates.
  32775. * @return {Array.<number>} Transformed coordinates.
  32776. */
  32777. var transform = function(coordinates) {
  32778. for (var i = 0, ii = coordinates.length; i < ii; ++i) {
  32779. coordinates[i] = Math.round(coordinates[i] * power) / power;
  32780. }
  32781. return coordinates;
  32782. };
  32783. if (transformed === geometry) {
  32784. transformed = transformed.clone();
  32785. }
  32786. transformed.applyTransform(transform);
  32787. }
  32788. return transformed;
  32789. };
  32790. goog.provide('ol.format.JSONFeature');
  32791. goog.require('ol');
  32792. goog.require('ol.format.Feature');
  32793. goog.require('ol.format.FormatType');
  32794. /**
  32795. * @classdesc
  32796. * Abstract base class; normally only used for creating subclasses and not
  32797. * instantiated in apps.
  32798. * Base class for JSON feature formats.
  32799. *
  32800. * @constructor
  32801. * @abstract
  32802. * @extends {ol.format.Feature}
  32803. */
  32804. ol.format.JSONFeature = function() {
  32805. ol.format.Feature.call(this);
  32806. };
  32807. ol.inherits(ol.format.JSONFeature, ol.format.Feature);
  32808. /**
  32809. * @param {Document|Node|Object|string} source Source.
  32810. * @private
  32811. * @return {Object} Object.
  32812. */
  32813. ol.format.JSONFeature.prototype.getObject_ = function(source) {
  32814. if (typeof source === 'string') {
  32815. var object = JSON.parse(source);
  32816. return object ? /** @type {Object} */ (object) : null;
  32817. } else if (source !== null) {
  32818. return source;
  32819. } else {
  32820. return null;
  32821. }
  32822. };
  32823. /**
  32824. * @inheritDoc
  32825. */
  32826. ol.format.JSONFeature.prototype.getType = function() {
  32827. return ol.format.FormatType.JSON;
  32828. };
  32829. /**
  32830. * @inheritDoc
  32831. */
  32832. ol.format.JSONFeature.prototype.readFeature = function(source, opt_options) {
  32833. return this.readFeatureFromObject(
  32834. this.getObject_(source), this.getReadOptions(source, opt_options));
  32835. };
  32836. /**
  32837. * @inheritDoc
  32838. */
  32839. ol.format.JSONFeature.prototype.readFeatures = function(source, opt_options) {
  32840. return this.readFeaturesFromObject(
  32841. this.getObject_(source), this.getReadOptions(source, opt_options));
  32842. };
  32843. /**
  32844. * @abstract
  32845. * @param {Object} object Object.
  32846. * @param {olx.format.ReadOptions=} opt_options Read options.
  32847. * @protected
  32848. * @return {ol.Feature} Feature.
  32849. */
  32850. ol.format.JSONFeature.prototype.readFeatureFromObject = function(object, opt_options) {};
  32851. /**
  32852. * @abstract
  32853. * @param {Object} object Object.
  32854. * @param {olx.format.ReadOptions=} opt_options Read options.
  32855. * @protected
  32856. * @return {Array.<ol.Feature>} Features.
  32857. */
  32858. ol.format.JSONFeature.prototype.readFeaturesFromObject = function(object, opt_options) {};
  32859. /**
  32860. * @inheritDoc
  32861. */
  32862. ol.format.JSONFeature.prototype.readGeometry = function(source, opt_options) {
  32863. return this.readGeometryFromObject(
  32864. this.getObject_(source), this.getReadOptions(source, opt_options));
  32865. };
  32866. /**
  32867. * @abstract
  32868. * @param {Object} object Object.
  32869. * @param {olx.format.ReadOptions=} opt_options Read options.
  32870. * @protected
  32871. * @return {ol.geom.Geometry} Geometry.
  32872. */
  32873. ol.format.JSONFeature.prototype.readGeometryFromObject = function(object, opt_options) {};
  32874. /**
  32875. * @inheritDoc
  32876. */
  32877. ol.format.JSONFeature.prototype.readProjection = function(source) {
  32878. return this.readProjectionFromObject(this.getObject_(source));
  32879. };
  32880. /**
  32881. * @abstract
  32882. * @param {Object} object Object.
  32883. * @protected
  32884. * @return {ol.proj.Projection} Projection.
  32885. */
  32886. ol.format.JSONFeature.prototype.readProjectionFromObject = function(object) {};
  32887. /**
  32888. * @inheritDoc
  32889. */
  32890. ol.format.JSONFeature.prototype.writeFeature = function(feature, opt_options) {
  32891. return JSON.stringify(this.writeFeatureObject(feature, opt_options));
  32892. };
  32893. /**
  32894. * @abstract
  32895. * @param {ol.Feature} feature Feature.
  32896. * @param {olx.format.WriteOptions=} opt_options Write options.
  32897. * @return {Object} Object.
  32898. */
  32899. ol.format.JSONFeature.prototype.writeFeatureObject = function(feature, opt_options) {};
  32900. /**
  32901. * @inheritDoc
  32902. */
  32903. ol.format.JSONFeature.prototype.writeFeatures = function(features, opt_options) {
  32904. return JSON.stringify(this.writeFeaturesObject(features, opt_options));
  32905. };
  32906. /**
  32907. * @abstract
  32908. * @param {Array.<ol.Feature>} features Features.
  32909. * @param {olx.format.WriteOptions=} opt_options Write options.
  32910. * @return {Object} Object.
  32911. */
  32912. ol.format.JSONFeature.prototype.writeFeaturesObject = function(features, opt_options) {};
  32913. /**
  32914. * @inheritDoc
  32915. */
  32916. ol.format.JSONFeature.prototype.writeGeometry = function(geometry, opt_options) {
  32917. return JSON.stringify(this.writeGeometryObject(geometry, opt_options));
  32918. };
  32919. /**
  32920. * @abstract
  32921. * @param {ol.geom.Geometry} geometry Geometry.
  32922. * @param {olx.format.WriteOptions=} opt_options Write options.
  32923. * @return {Object} Object.
  32924. */
  32925. ol.format.JSONFeature.prototype.writeGeometryObject = function(geometry, opt_options) {};
  32926. goog.provide('ol.geom.flat.interpolate');
  32927. goog.require('ol.array');
  32928. goog.require('ol.math');
  32929. /**
  32930. * @param {Array.<number>} flatCoordinates Flat coordinates.
  32931. * @param {number} offset Offset.
  32932. * @param {number} end End.
  32933. * @param {number} stride Stride.
  32934. * @param {number} fraction Fraction.
  32935. * @param {Array.<number>=} opt_dest Destination.
  32936. * @return {Array.<number>} Destination.
  32937. */
  32938. ol.geom.flat.interpolate.lineString = function(flatCoordinates, offset, end, stride, fraction, opt_dest) {
  32939. var pointX = NaN;
  32940. var pointY = NaN;
  32941. var n = (end - offset) / stride;
  32942. if (n === 1) {
  32943. pointX = flatCoordinates[offset];
  32944. pointY = flatCoordinates[offset + 1];
  32945. } else if (n == 2) {
  32946. pointX = (1 - fraction) * flatCoordinates[offset] +
  32947. fraction * flatCoordinates[offset + stride];
  32948. pointY = (1 - fraction) * flatCoordinates[offset + 1] +
  32949. fraction * flatCoordinates[offset + stride + 1];
  32950. } else if (n !== 0) {
  32951. var x1 = flatCoordinates[offset];
  32952. var y1 = flatCoordinates[offset + 1];
  32953. var length = 0;
  32954. var cumulativeLengths = [0];
  32955. var i;
  32956. for (i = offset + stride; i < end; i += stride) {
  32957. var x2 = flatCoordinates[i];
  32958. var y2 = flatCoordinates[i + 1];
  32959. length += Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
  32960. cumulativeLengths.push(length);
  32961. x1 = x2;
  32962. y1 = y2;
  32963. }
  32964. var target = fraction * length;
  32965. var index = ol.array.binarySearch(cumulativeLengths, target);
  32966. if (index < 0) {
  32967. var t = (target - cumulativeLengths[-index - 2]) /
  32968. (cumulativeLengths[-index - 1] - cumulativeLengths[-index - 2]);
  32969. var o = offset + (-index - 2) * stride;
  32970. pointX = ol.math.lerp(
  32971. flatCoordinates[o], flatCoordinates[o + stride], t);
  32972. pointY = ol.math.lerp(
  32973. flatCoordinates[o + 1], flatCoordinates[o + stride + 1], t);
  32974. } else {
  32975. pointX = flatCoordinates[offset + index * stride];
  32976. pointY = flatCoordinates[offset + index * stride + 1];
  32977. }
  32978. }
  32979. if (opt_dest) {
  32980. opt_dest[0] = pointX;
  32981. opt_dest[1] = pointY;
  32982. return opt_dest;
  32983. } else {
  32984. return [pointX, pointY];
  32985. }
  32986. };
  32987. /**
  32988. * @param {Array.<number>} flatCoordinates Flat coordinates.
  32989. * @param {number} offset Offset.
  32990. * @param {number} end End.
  32991. * @param {number} stride Stride.
  32992. * @param {number} m M.
  32993. * @param {boolean} extrapolate Extrapolate.
  32994. * @return {ol.Coordinate} Coordinate.
  32995. */
  32996. ol.geom.flat.interpolate.lineStringCoordinateAtM = function(flatCoordinates, offset, end, stride, m, extrapolate) {
  32997. if (end == offset) {
  32998. return null;
  32999. }
  33000. var coordinate;
  33001. if (m < flatCoordinates[offset + stride - 1]) {
  33002. if (extrapolate) {
  33003. coordinate = flatCoordinates.slice(offset, offset + stride);
  33004. coordinate[stride - 1] = m;
  33005. return coordinate;
  33006. } else {
  33007. return null;
  33008. }
  33009. } else if (flatCoordinates[end - 1] < m) {
  33010. if (extrapolate) {
  33011. coordinate = flatCoordinates.slice(end - stride, end);
  33012. coordinate[stride - 1] = m;
  33013. return coordinate;
  33014. } else {
  33015. return null;
  33016. }
  33017. }
  33018. // FIXME use O(1) search
  33019. if (m == flatCoordinates[offset + stride - 1]) {
  33020. return flatCoordinates.slice(offset, offset + stride);
  33021. }
  33022. var lo = offset / stride;
  33023. var hi = end / stride;
  33024. while (lo < hi) {
  33025. var mid = (lo + hi) >> 1;
  33026. if (m < flatCoordinates[(mid + 1) * stride - 1]) {
  33027. hi = mid;
  33028. } else {
  33029. lo = mid + 1;
  33030. }
  33031. }
  33032. var m0 = flatCoordinates[lo * stride - 1];
  33033. if (m == m0) {
  33034. return flatCoordinates.slice((lo - 1) * stride, (lo - 1) * stride + stride);
  33035. }
  33036. var m1 = flatCoordinates[(lo + 1) * stride - 1];
  33037. var t = (m - m0) / (m1 - m0);
  33038. coordinate = [];
  33039. var i;
  33040. for (i = 0; i < stride - 1; ++i) {
  33041. coordinate.push(ol.math.lerp(flatCoordinates[(lo - 1) * stride + i],
  33042. flatCoordinates[lo * stride + i], t));
  33043. }
  33044. coordinate.push(m);
  33045. return coordinate;
  33046. };
  33047. /**
  33048. * @param {Array.<number>} flatCoordinates Flat coordinates.
  33049. * @param {number} offset Offset.
  33050. * @param {Array.<number>} ends Ends.
  33051. * @param {number} stride Stride.
  33052. * @param {number} m M.
  33053. * @param {boolean} extrapolate Extrapolate.
  33054. * @param {boolean} interpolate Interpolate.
  33055. * @return {ol.Coordinate} Coordinate.
  33056. */
  33057. ol.geom.flat.interpolate.lineStringsCoordinateAtM = function(
  33058. flatCoordinates, offset, ends, stride, m, extrapolate, interpolate) {
  33059. if (interpolate) {
  33060. return ol.geom.flat.interpolate.lineStringCoordinateAtM(
  33061. flatCoordinates, offset, ends[ends.length - 1], stride, m, extrapolate);
  33062. }
  33063. var coordinate;
  33064. if (m < flatCoordinates[stride - 1]) {
  33065. if (extrapolate) {
  33066. coordinate = flatCoordinates.slice(0, stride);
  33067. coordinate[stride - 1] = m;
  33068. return coordinate;
  33069. } else {
  33070. return null;
  33071. }
  33072. }
  33073. if (flatCoordinates[flatCoordinates.length - 1] < m) {
  33074. if (extrapolate) {
  33075. coordinate = flatCoordinates.slice(flatCoordinates.length - stride);
  33076. coordinate[stride - 1] = m;
  33077. return coordinate;
  33078. } else {
  33079. return null;
  33080. }
  33081. }
  33082. var i, ii;
  33083. for (i = 0, ii = ends.length; i < ii; ++i) {
  33084. var end = ends[i];
  33085. if (offset == end) {
  33086. continue;
  33087. }
  33088. if (m < flatCoordinates[offset + stride - 1]) {
  33089. return null;
  33090. } else if (m <= flatCoordinates[end - 1]) {
  33091. return ol.geom.flat.interpolate.lineStringCoordinateAtM(
  33092. flatCoordinates, offset, end, stride, m, false);
  33093. }
  33094. offset = end;
  33095. }
  33096. return null;
  33097. };
  33098. goog.provide('ol.geom.flat.length');
  33099. /**
  33100. * @param {Array.<number>} flatCoordinates Flat coordinates.
  33101. * @param {number} offset Offset.
  33102. * @param {number} end End.
  33103. * @param {number} stride Stride.
  33104. * @return {number} Length.
  33105. */
  33106. ol.geom.flat.length.lineString = function(flatCoordinates, offset, end, stride) {
  33107. var x1 = flatCoordinates[offset];
  33108. var y1 = flatCoordinates[offset + 1];
  33109. var length = 0;
  33110. var i;
  33111. for (i = offset + stride; i < end; i += stride) {
  33112. var x2 = flatCoordinates[i];
  33113. var y2 = flatCoordinates[i + 1];
  33114. length += Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
  33115. x1 = x2;
  33116. y1 = y2;
  33117. }
  33118. return length;
  33119. };
  33120. /**
  33121. * @param {Array.<number>} flatCoordinates Flat coordinates.
  33122. * @param {number} offset Offset.
  33123. * @param {number} end End.
  33124. * @param {number} stride Stride.
  33125. * @return {number} Perimeter.
  33126. */
  33127. ol.geom.flat.length.linearRing = function(flatCoordinates, offset, end, stride) {
  33128. var perimeter =
  33129. ol.geom.flat.length.lineString(flatCoordinates, offset, end, stride);
  33130. var dx = flatCoordinates[end - stride] - flatCoordinates[offset];
  33131. var dy = flatCoordinates[end - stride + 1] - flatCoordinates[offset + 1];
  33132. perimeter += Math.sqrt(dx * dx + dy * dy);
  33133. return perimeter;
  33134. };
  33135. goog.provide('ol.geom.LineString');
  33136. goog.require('ol');
  33137. goog.require('ol.array');
  33138. goog.require('ol.extent');
  33139. goog.require('ol.geom.GeometryLayout');
  33140. goog.require('ol.geom.GeometryType');
  33141. goog.require('ol.geom.SimpleGeometry');
  33142. goog.require('ol.geom.flat.closest');
  33143. goog.require('ol.geom.flat.deflate');
  33144. goog.require('ol.geom.flat.inflate');
  33145. goog.require('ol.geom.flat.interpolate');
  33146. goog.require('ol.geom.flat.intersectsextent');
  33147. goog.require('ol.geom.flat.length');
  33148. goog.require('ol.geom.flat.segments');
  33149. goog.require('ol.geom.flat.simplify');
  33150. /**
  33151. * @classdesc
  33152. * Linestring geometry.
  33153. *
  33154. * @constructor
  33155. * @extends {ol.geom.SimpleGeometry}
  33156. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  33157. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  33158. * @api
  33159. */
  33160. ol.geom.LineString = function(coordinates, opt_layout) {
  33161. ol.geom.SimpleGeometry.call(this);
  33162. /**
  33163. * @private
  33164. * @type {ol.Coordinate}
  33165. */
  33166. this.flatMidpoint_ = null;
  33167. /**
  33168. * @private
  33169. * @type {number}
  33170. */
  33171. this.flatMidpointRevision_ = -1;
  33172. /**
  33173. * @private
  33174. * @type {number}
  33175. */
  33176. this.maxDelta_ = -1;
  33177. /**
  33178. * @private
  33179. * @type {number}
  33180. */
  33181. this.maxDeltaRevision_ = -1;
  33182. this.setCoordinates(coordinates, opt_layout);
  33183. };
  33184. ol.inherits(ol.geom.LineString, ol.geom.SimpleGeometry);
  33185. /**
  33186. * Append the passed coordinate to the coordinates of the linestring.
  33187. * @param {ol.Coordinate} coordinate Coordinate.
  33188. * @api
  33189. */
  33190. ol.geom.LineString.prototype.appendCoordinate = function(coordinate) {
  33191. if (!this.flatCoordinates) {
  33192. this.flatCoordinates = coordinate.slice();
  33193. } else {
  33194. ol.array.extend(this.flatCoordinates, coordinate);
  33195. }
  33196. this.changed();
  33197. };
  33198. /**
  33199. * Make a complete copy of the geometry.
  33200. * @return {!ol.geom.LineString} Clone.
  33201. * @override
  33202. * @api
  33203. */
  33204. ol.geom.LineString.prototype.clone = function() {
  33205. var lineString = new ol.geom.LineString(null);
  33206. lineString.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
  33207. return lineString;
  33208. };
  33209. /**
  33210. * @inheritDoc
  33211. */
  33212. ol.geom.LineString.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  33213. if (minSquaredDistance <
  33214. ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
  33215. return minSquaredDistance;
  33216. }
  33217. if (this.maxDeltaRevision_ != this.getRevision()) {
  33218. this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getMaxSquaredDelta(
  33219. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, 0));
  33220. this.maxDeltaRevision_ = this.getRevision();
  33221. }
  33222. return ol.geom.flat.closest.getClosestPoint(
  33223. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
  33224. this.maxDelta_, false, x, y, closestPoint, minSquaredDistance);
  33225. };
  33226. /**
  33227. * Iterate over each segment, calling the provided callback.
  33228. * If the callback returns a truthy value the function returns that
  33229. * value immediately. Otherwise the function returns `false`.
  33230. *
  33231. * @param {function(this: S, ol.Coordinate, ol.Coordinate): T} callback Function
  33232. * called for each segment.
  33233. * @param {S=} opt_this The object to be used as the value of 'this'
  33234. * within callback.
  33235. * @return {T|boolean} Value.
  33236. * @template T,S
  33237. * @api
  33238. */
  33239. ol.geom.LineString.prototype.forEachSegment = function(callback, opt_this) {
  33240. return ol.geom.flat.segments.forEach(this.flatCoordinates, 0,
  33241. this.flatCoordinates.length, this.stride, callback, opt_this);
  33242. };
  33243. /**
  33244. * Returns the coordinate at `m` using linear interpolation, or `null` if no
  33245. * such coordinate exists.
  33246. *
  33247. * `opt_extrapolate` controls extrapolation beyond the range of Ms in the
  33248. * MultiLineString. If `opt_extrapolate` is `true` then Ms less than the first
  33249. * M will return the first coordinate and Ms greater than the last M will
  33250. * return the last coordinate.
  33251. *
  33252. * @param {number} m M.
  33253. * @param {boolean=} opt_extrapolate Extrapolate. Default is `false`.
  33254. * @return {ol.Coordinate} Coordinate.
  33255. * @api
  33256. */
  33257. ol.geom.LineString.prototype.getCoordinateAtM = function(m, opt_extrapolate) {
  33258. if (this.layout != ol.geom.GeometryLayout.XYM &&
  33259. this.layout != ol.geom.GeometryLayout.XYZM) {
  33260. return null;
  33261. }
  33262. var extrapolate = opt_extrapolate !== undefined ? opt_extrapolate : false;
  33263. return ol.geom.flat.interpolate.lineStringCoordinateAtM(this.flatCoordinates, 0,
  33264. this.flatCoordinates.length, this.stride, m, extrapolate);
  33265. };
  33266. /**
  33267. * Return the coordinates of the linestring.
  33268. * @return {Array.<ol.Coordinate>} Coordinates.
  33269. * @override
  33270. * @api
  33271. */
  33272. ol.geom.LineString.prototype.getCoordinates = function() {
  33273. return ol.geom.flat.inflate.coordinates(
  33274. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
  33275. };
  33276. /**
  33277. * Return the coordinate at the provided fraction along the linestring.
  33278. * The `fraction` is a number between 0 and 1, where 0 is the start of the
  33279. * linestring and 1 is the end.
  33280. * @param {number} fraction Fraction.
  33281. * @param {ol.Coordinate=} opt_dest Optional coordinate whose values will
  33282. * be modified. If not provided, a new coordinate will be returned.
  33283. * @return {ol.Coordinate} Coordinate of the interpolated point.
  33284. * @api
  33285. */
  33286. ol.geom.LineString.prototype.getCoordinateAt = function(fraction, opt_dest) {
  33287. return ol.geom.flat.interpolate.lineString(
  33288. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
  33289. fraction, opt_dest);
  33290. };
  33291. /**
  33292. * Return the length of the linestring on projected plane.
  33293. * @return {number} Length (on projected plane).
  33294. * @api
  33295. */
  33296. ol.geom.LineString.prototype.getLength = function() {
  33297. return ol.geom.flat.length.lineString(
  33298. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
  33299. };
  33300. /**
  33301. * @return {Array.<number>} Flat midpoint.
  33302. */
  33303. ol.geom.LineString.prototype.getFlatMidpoint = function() {
  33304. if (this.flatMidpointRevision_ != this.getRevision()) {
  33305. this.flatMidpoint_ = this.getCoordinateAt(0.5, this.flatMidpoint_);
  33306. this.flatMidpointRevision_ = this.getRevision();
  33307. }
  33308. return this.flatMidpoint_;
  33309. };
  33310. /**
  33311. * @inheritDoc
  33312. */
  33313. ol.geom.LineString.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
  33314. var simplifiedFlatCoordinates = [];
  33315. simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeucker(
  33316. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
  33317. squaredTolerance, simplifiedFlatCoordinates, 0);
  33318. var simplifiedLineString = new ol.geom.LineString(null);
  33319. simplifiedLineString.setFlatCoordinates(
  33320. ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates);
  33321. return simplifiedLineString;
  33322. };
  33323. /**
  33324. * @inheritDoc
  33325. * @api
  33326. */
  33327. ol.geom.LineString.prototype.getType = function() {
  33328. return ol.geom.GeometryType.LINE_STRING;
  33329. };
  33330. /**
  33331. * @inheritDoc
  33332. * @api
  33333. */
  33334. ol.geom.LineString.prototype.intersectsExtent = function(extent) {
  33335. return ol.geom.flat.intersectsextent.lineString(
  33336. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
  33337. extent);
  33338. };
  33339. /**
  33340. * Set the coordinates of the linestring.
  33341. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  33342. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  33343. * @override
  33344. * @api
  33345. */
  33346. ol.geom.LineString.prototype.setCoordinates = function(coordinates, opt_layout) {
  33347. if (!coordinates) {
  33348. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
  33349. } else {
  33350. this.setLayout(opt_layout, coordinates, 1);
  33351. if (!this.flatCoordinates) {
  33352. this.flatCoordinates = [];
  33353. }
  33354. this.flatCoordinates.length = ol.geom.flat.deflate.coordinates(
  33355. this.flatCoordinates, 0, coordinates, this.stride);
  33356. this.changed();
  33357. }
  33358. };
  33359. /**
  33360. * @param {ol.geom.GeometryLayout} layout Layout.
  33361. * @param {Array.<number>} flatCoordinates Flat coordinates.
  33362. */
  33363. ol.geom.LineString.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
  33364. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  33365. this.changed();
  33366. };
  33367. goog.provide('ol.geom.MultiLineString');
  33368. goog.require('ol');
  33369. goog.require('ol.array');
  33370. goog.require('ol.extent');
  33371. goog.require('ol.geom.GeometryLayout');
  33372. goog.require('ol.geom.GeometryType');
  33373. goog.require('ol.geom.LineString');
  33374. goog.require('ol.geom.SimpleGeometry');
  33375. goog.require('ol.geom.flat.closest');
  33376. goog.require('ol.geom.flat.deflate');
  33377. goog.require('ol.geom.flat.inflate');
  33378. goog.require('ol.geom.flat.interpolate');
  33379. goog.require('ol.geom.flat.intersectsextent');
  33380. goog.require('ol.geom.flat.simplify');
  33381. /**
  33382. * @classdesc
  33383. * Multi-linestring geometry.
  33384. *
  33385. * @constructor
  33386. * @extends {ol.geom.SimpleGeometry}
  33387. * @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
  33388. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  33389. * @api
  33390. */
  33391. ol.geom.MultiLineString = function(coordinates, opt_layout) {
  33392. ol.geom.SimpleGeometry.call(this);
  33393. /**
  33394. * @type {Array.<number>}
  33395. * @private
  33396. */
  33397. this.ends_ = [];
  33398. /**
  33399. * @private
  33400. * @type {number}
  33401. */
  33402. this.maxDelta_ = -1;
  33403. /**
  33404. * @private
  33405. * @type {number}
  33406. */
  33407. this.maxDeltaRevision_ = -1;
  33408. this.setCoordinates(coordinates, opt_layout);
  33409. };
  33410. ol.inherits(ol.geom.MultiLineString, ol.geom.SimpleGeometry);
  33411. /**
  33412. * Append the passed linestring to the multilinestring.
  33413. * @param {ol.geom.LineString} lineString LineString.
  33414. * @api
  33415. */
  33416. ol.geom.MultiLineString.prototype.appendLineString = function(lineString) {
  33417. if (!this.flatCoordinates) {
  33418. this.flatCoordinates = lineString.getFlatCoordinates().slice();
  33419. } else {
  33420. ol.array.extend(
  33421. this.flatCoordinates, lineString.getFlatCoordinates().slice());
  33422. }
  33423. this.ends_.push(this.flatCoordinates.length);
  33424. this.changed();
  33425. };
  33426. /**
  33427. * Make a complete copy of the geometry.
  33428. * @return {!ol.geom.MultiLineString} Clone.
  33429. * @override
  33430. * @api
  33431. */
  33432. ol.geom.MultiLineString.prototype.clone = function() {
  33433. var multiLineString = new ol.geom.MultiLineString(null);
  33434. multiLineString.setFlatCoordinates(
  33435. this.layout, this.flatCoordinates.slice(), this.ends_.slice());
  33436. return multiLineString;
  33437. };
  33438. /**
  33439. * @inheritDoc
  33440. */
  33441. ol.geom.MultiLineString.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  33442. if (minSquaredDistance <
  33443. ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
  33444. return minSquaredDistance;
  33445. }
  33446. if (this.maxDeltaRevision_ != this.getRevision()) {
  33447. this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getsMaxSquaredDelta(
  33448. this.flatCoordinates, 0, this.ends_, this.stride, 0));
  33449. this.maxDeltaRevision_ = this.getRevision();
  33450. }
  33451. return ol.geom.flat.closest.getsClosestPoint(
  33452. this.flatCoordinates, 0, this.ends_, this.stride,
  33453. this.maxDelta_, false, x, y, closestPoint, minSquaredDistance);
  33454. };
  33455. /**
  33456. * Returns the coordinate at `m` using linear interpolation, or `null` if no
  33457. * such coordinate exists.
  33458. *
  33459. * `opt_extrapolate` controls extrapolation beyond the range of Ms in the
  33460. * MultiLineString. If `opt_extrapolate` is `true` then Ms less than the first
  33461. * M will return the first coordinate and Ms greater than the last M will
  33462. * return the last coordinate.
  33463. *
  33464. * `opt_interpolate` controls interpolation between consecutive LineStrings
  33465. * within the MultiLineString. If `opt_interpolate` is `true` the coordinates
  33466. * will be linearly interpolated between the last coordinate of one LineString
  33467. * and the first coordinate of the next LineString. If `opt_interpolate` is
  33468. * `false` then the function will return `null` for Ms falling between
  33469. * LineStrings.
  33470. *
  33471. * @param {number} m M.
  33472. * @param {boolean=} opt_extrapolate Extrapolate. Default is `false`.
  33473. * @param {boolean=} opt_interpolate Interpolate. Default is `false`.
  33474. * @return {ol.Coordinate} Coordinate.
  33475. * @api
  33476. */
  33477. ol.geom.MultiLineString.prototype.getCoordinateAtM = function(m, opt_extrapolate, opt_interpolate) {
  33478. if ((this.layout != ol.geom.GeometryLayout.XYM &&
  33479. this.layout != ol.geom.GeometryLayout.XYZM) ||
  33480. this.flatCoordinates.length === 0) {
  33481. return null;
  33482. }
  33483. var extrapolate = opt_extrapolate !== undefined ? opt_extrapolate : false;
  33484. var interpolate = opt_interpolate !== undefined ? opt_interpolate : false;
  33485. return ol.geom.flat.interpolate.lineStringsCoordinateAtM(this.flatCoordinates, 0,
  33486. this.ends_, this.stride, m, extrapolate, interpolate);
  33487. };
  33488. /**
  33489. * Return the coordinates of the multilinestring.
  33490. * @return {Array.<Array.<ol.Coordinate>>} Coordinates.
  33491. * @override
  33492. * @api
  33493. */
  33494. ol.geom.MultiLineString.prototype.getCoordinates = function() {
  33495. return ol.geom.flat.inflate.coordinatess(
  33496. this.flatCoordinates, 0, this.ends_, this.stride);
  33497. };
  33498. /**
  33499. * @return {Array.<number>} Ends.
  33500. */
  33501. ol.geom.MultiLineString.prototype.getEnds = function() {
  33502. return this.ends_;
  33503. };
  33504. /**
  33505. * Return the linestring at the specified index.
  33506. * @param {number} index Index.
  33507. * @return {ol.geom.LineString} LineString.
  33508. * @api
  33509. */
  33510. ol.geom.MultiLineString.prototype.getLineString = function(index) {
  33511. if (index < 0 || this.ends_.length <= index) {
  33512. return null;
  33513. }
  33514. var lineString = new ol.geom.LineString(null);
  33515. lineString.setFlatCoordinates(this.layout, this.flatCoordinates.slice(
  33516. index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]));
  33517. return lineString;
  33518. };
  33519. /**
  33520. * Return the linestrings of this multilinestring.
  33521. * @return {Array.<ol.geom.LineString>} LineStrings.
  33522. * @api
  33523. */
  33524. ol.geom.MultiLineString.prototype.getLineStrings = function() {
  33525. var flatCoordinates = this.flatCoordinates;
  33526. var ends = this.ends_;
  33527. var layout = this.layout;
  33528. /** @type {Array.<ol.geom.LineString>} */
  33529. var lineStrings = [];
  33530. var offset = 0;
  33531. var i, ii;
  33532. for (i = 0, ii = ends.length; i < ii; ++i) {
  33533. var end = ends[i];
  33534. var lineString = new ol.geom.LineString(null);
  33535. lineString.setFlatCoordinates(layout, flatCoordinates.slice(offset, end));
  33536. lineStrings.push(lineString);
  33537. offset = end;
  33538. }
  33539. return lineStrings;
  33540. };
  33541. /**
  33542. * @return {Array.<number>} Flat midpoints.
  33543. */
  33544. ol.geom.MultiLineString.prototype.getFlatMidpoints = function() {
  33545. var midpoints = [];
  33546. var flatCoordinates = this.flatCoordinates;
  33547. var offset = 0;
  33548. var ends = this.ends_;
  33549. var stride = this.stride;
  33550. var i, ii;
  33551. for (i = 0, ii = ends.length; i < ii; ++i) {
  33552. var end = ends[i];
  33553. var midpoint = ol.geom.flat.interpolate.lineString(
  33554. flatCoordinates, offset, end, stride, 0.5);
  33555. ol.array.extend(midpoints, midpoint);
  33556. offset = end;
  33557. }
  33558. return midpoints;
  33559. };
  33560. /**
  33561. * @inheritDoc
  33562. */
  33563. ol.geom.MultiLineString.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
  33564. var simplifiedFlatCoordinates = [];
  33565. var simplifiedEnds = [];
  33566. simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeuckers(
  33567. this.flatCoordinates, 0, this.ends_, this.stride, squaredTolerance,
  33568. simplifiedFlatCoordinates, 0, simplifiedEnds);
  33569. var simplifiedMultiLineString = new ol.geom.MultiLineString(null);
  33570. simplifiedMultiLineString.setFlatCoordinates(
  33571. ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates, simplifiedEnds);
  33572. return simplifiedMultiLineString;
  33573. };
  33574. /**
  33575. * @inheritDoc
  33576. * @api
  33577. */
  33578. ol.geom.MultiLineString.prototype.getType = function() {
  33579. return ol.geom.GeometryType.MULTI_LINE_STRING;
  33580. };
  33581. /**
  33582. * @inheritDoc
  33583. * @api
  33584. */
  33585. ol.geom.MultiLineString.prototype.intersectsExtent = function(extent) {
  33586. return ol.geom.flat.intersectsextent.lineStrings(
  33587. this.flatCoordinates, 0, this.ends_, this.stride, extent);
  33588. };
  33589. /**
  33590. * Set the coordinates of the multilinestring.
  33591. * @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
  33592. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  33593. * @override
  33594. * @api
  33595. */
  33596. ol.geom.MultiLineString.prototype.setCoordinates = function(coordinates, opt_layout) {
  33597. if (!coordinates) {
  33598. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.ends_);
  33599. } else {
  33600. this.setLayout(opt_layout, coordinates, 2);
  33601. if (!this.flatCoordinates) {
  33602. this.flatCoordinates = [];
  33603. }
  33604. var ends = ol.geom.flat.deflate.coordinatess(
  33605. this.flatCoordinates, 0, coordinates, this.stride, this.ends_);
  33606. this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1];
  33607. this.changed();
  33608. }
  33609. };
  33610. /**
  33611. * @param {ol.geom.GeometryLayout} layout Layout.
  33612. * @param {Array.<number>} flatCoordinates Flat coordinates.
  33613. * @param {Array.<number>} ends Ends.
  33614. */
  33615. ol.geom.MultiLineString.prototype.setFlatCoordinates = function(layout, flatCoordinates, ends) {
  33616. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  33617. this.ends_ = ends;
  33618. this.changed();
  33619. };
  33620. /**
  33621. * @param {Array.<ol.geom.LineString>} lineStrings LineStrings.
  33622. */
  33623. ol.geom.MultiLineString.prototype.setLineStrings = function(lineStrings) {
  33624. var layout = this.getLayout();
  33625. var flatCoordinates = [];
  33626. var ends = [];
  33627. var i, ii;
  33628. for (i = 0, ii = lineStrings.length; i < ii; ++i) {
  33629. var lineString = lineStrings[i];
  33630. if (i === 0) {
  33631. layout = lineString.getLayout();
  33632. }
  33633. ol.array.extend(flatCoordinates, lineString.getFlatCoordinates());
  33634. ends.push(flatCoordinates.length);
  33635. }
  33636. this.setFlatCoordinates(layout, flatCoordinates, ends);
  33637. };
  33638. goog.provide('ol.geom.MultiPoint');
  33639. goog.require('ol');
  33640. goog.require('ol.array');
  33641. goog.require('ol.extent');
  33642. goog.require('ol.geom.GeometryLayout');
  33643. goog.require('ol.geom.GeometryType');
  33644. goog.require('ol.geom.Point');
  33645. goog.require('ol.geom.SimpleGeometry');
  33646. goog.require('ol.geom.flat.deflate');
  33647. goog.require('ol.geom.flat.inflate');
  33648. goog.require('ol.math');
  33649. /**
  33650. * @classdesc
  33651. * Multi-point geometry.
  33652. *
  33653. * @constructor
  33654. * @extends {ol.geom.SimpleGeometry}
  33655. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  33656. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  33657. * @api
  33658. */
  33659. ol.geom.MultiPoint = function(coordinates, opt_layout) {
  33660. ol.geom.SimpleGeometry.call(this);
  33661. this.setCoordinates(coordinates, opt_layout);
  33662. };
  33663. ol.inherits(ol.geom.MultiPoint, ol.geom.SimpleGeometry);
  33664. /**
  33665. * Append the passed point to this multipoint.
  33666. * @param {ol.geom.Point} point Point.
  33667. * @api
  33668. */
  33669. ol.geom.MultiPoint.prototype.appendPoint = function(point) {
  33670. if (!this.flatCoordinates) {
  33671. this.flatCoordinates = point.getFlatCoordinates().slice();
  33672. } else {
  33673. ol.array.extend(this.flatCoordinates, point.getFlatCoordinates());
  33674. }
  33675. this.changed();
  33676. };
  33677. /**
  33678. * Make a complete copy of the geometry.
  33679. * @return {!ol.geom.MultiPoint} Clone.
  33680. * @override
  33681. * @api
  33682. */
  33683. ol.geom.MultiPoint.prototype.clone = function() {
  33684. var multiPoint = new ol.geom.MultiPoint(null);
  33685. multiPoint.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
  33686. return multiPoint;
  33687. };
  33688. /**
  33689. * @inheritDoc
  33690. */
  33691. ol.geom.MultiPoint.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  33692. if (minSquaredDistance <
  33693. ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
  33694. return minSquaredDistance;
  33695. }
  33696. var flatCoordinates = this.flatCoordinates;
  33697. var stride = this.stride;
  33698. var i, ii, j;
  33699. for (i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
  33700. var squaredDistance = ol.math.squaredDistance(
  33701. x, y, flatCoordinates[i], flatCoordinates[i + 1]);
  33702. if (squaredDistance < minSquaredDistance) {
  33703. minSquaredDistance = squaredDistance;
  33704. for (j = 0; j < stride; ++j) {
  33705. closestPoint[j] = flatCoordinates[i + j];
  33706. }
  33707. closestPoint.length = stride;
  33708. }
  33709. }
  33710. return minSquaredDistance;
  33711. };
  33712. /**
  33713. * Return the coordinates of the multipoint.
  33714. * @return {Array.<ol.Coordinate>} Coordinates.
  33715. * @override
  33716. * @api
  33717. */
  33718. ol.geom.MultiPoint.prototype.getCoordinates = function() {
  33719. return ol.geom.flat.inflate.coordinates(
  33720. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
  33721. };
  33722. /**
  33723. * Return the point at the specified index.
  33724. * @param {number} index Index.
  33725. * @return {ol.geom.Point} Point.
  33726. * @api
  33727. */
  33728. ol.geom.MultiPoint.prototype.getPoint = function(index) {
  33729. var n = !this.flatCoordinates ?
  33730. 0 : this.flatCoordinates.length / this.stride;
  33731. if (index < 0 || n <= index) {
  33732. return null;
  33733. }
  33734. var point = new ol.geom.Point(null);
  33735. point.setFlatCoordinates(this.layout, this.flatCoordinates.slice(
  33736. index * this.stride, (index + 1) * this.stride));
  33737. return point;
  33738. };
  33739. /**
  33740. * Return the points of this multipoint.
  33741. * @return {Array.<ol.geom.Point>} Points.
  33742. * @api
  33743. */
  33744. ol.geom.MultiPoint.prototype.getPoints = function() {
  33745. var flatCoordinates = this.flatCoordinates;
  33746. var layout = this.layout;
  33747. var stride = this.stride;
  33748. /** @type {Array.<ol.geom.Point>} */
  33749. var points = [];
  33750. var i, ii;
  33751. for (i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
  33752. var point = new ol.geom.Point(null);
  33753. point.setFlatCoordinates(layout, flatCoordinates.slice(i, i + stride));
  33754. points.push(point);
  33755. }
  33756. return points;
  33757. };
  33758. /**
  33759. * @inheritDoc
  33760. * @api
  33761. */
  33762. ol.geom.MultiPoint.prototype.getType = function() {
  33763. return ol.geom.GeometryType.MULTI_POINT;
  33764. };
  33765. /**
  33766. * @inheritDoc
  33767. * @api
  33768. */
  33769. ol.geom.MultiPoint.prototype.intersectsExtent = function(extent) {
  33770. var flatCoordinates = this.flatCoordinates;
  33771. var stride = this.stride;
  33772. var i, ii, x, y;
  33773. for (i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
  33774. x = flatCoordinates[i];
  33775. y = flatCoordinates[i + 1];
  33776. if (ol.extent.containsXY(extent, x, y)) {
  33777. return true;
  33778. }
  33779. }
  33780. return false;
  33781. };
  33782. /**
  33783. * Set the coordinates of the multipoint.
  33784. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  33785. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  33786. * @override
  33787. * @api
  33788. */
  33789. ol.geom.MultiPoint.prototype.setCoordinates = function(coordinates, opt_layout) {
  33790. if (!coordinates) {
  33791. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
  33792. } else {
  33793. this.setLayout(opt_layout, coordinates, 1);
  33794. if (!this.flatCoordinates) {
  33795. this.flatCoordinates = [];
  33796. }
  33797. this.flatCoordinates.length = ol.geom.flat.deflate.coordinates(
  33798. this.flatCoordinates, 0, coordinates, this.stride);
  33799. this.changed();
  33800. }
  33801. };
  33802. /**
  33803. * @param {ol.geom.GeometryLayout} layout Layout.
  33804. * @param {Array.<number>} flatCoordinates Flat coordinates.
  33805. */
  33806. ol.geom.MultiPoint.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
  33807. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  33808. this.changed();
  33809. };
  33810. goog.provide('ol.geom.flat.center');
  33811. goog.require('ol.extent');
  33812. /**
  33813. * @param {Array.<number>} flatCoordinates Flat coordinates.
  33814. * @param {number} offset Offset.
  33815. * @param {Array.<Array.<number>>} endss Endss.
  33816. * @param {number} stride Stride.
  33817. * @return {Array.<number>} Flat centers.
  33818. */
  33819. ol.geom.flat.center.linearRingss = function(flatCoordinates, offset, endss, stride) {
  33820. var flatCenters = [];
  33821. var i, ii;
  33822. var extent = ol.extent.createEmpty();
  33823. for (i = 0, ii = endss.length; i < ii; ++i) {
  33824. var ends = endss[i];
  33825. extent = ol.extent.createOrUpdateFromFlatCoordinates(
  33826. flatCoordinates, offset, ends[0], stride);
  33827. flatCenters.push((extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2);
  33828. offset = ends[ends.length - 1];
  33829. }
  33830. return flatCenters;
  33831. };
  33832. goog.provide('ol.geom.MultiPolygon');
  33833. goog.require('ol');
  33834. goog.require('ol.array');
  33835. goog.require('ol.extent');
  33836. goog.require('ol.geom.GeometryLayout');
  33837. goog.require('ol.geom.GeometryType');
  33838. goog.require('ol.geom.MultiPoint');
  33839. goog.require('ol.geom.Polygon');
  33840. goog.require('ol.geom.SimpleGeometry');
  33841. goog.require('ol.geom.flat.area');
  33842. goog.require('ol.geom.flat.center');
  33843. goog.require('ol.geom.flat.closest');
  33844. goog.require('ol.geom.flat.contains');
  33845. goog.require('ol.geom.flat.deflate');
  33846. goog.require('ol.geom.flat.inflate');
  33847. goog.require('ol.geom.flat.interiorpoint');
  33848. goog.require('ol.geom.flat.intersectsextent');
  33849. goog.require('ol.geom.flat.orient');
  33850. goog.require('ol.geom.flat.simplify');
  33851. /**
  33852. * @classdesc
  33853. * Multi-polygon geometry.
  33854. *
  33855. * @constructor
  33856. * @extends {ol.geom.SimpleGeometry}
  33857. * @param {Array.<Array.<Array.<ol.Coordinate>>>} coordinates Coordinates.
  33858. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  33859. * @api
  33860. */
  33861. ol.geom.MultiPolygon = function(coordinates, opt_layout) {
  33862. ol.geom.SimpleGeometry.call(this);
  33863. /**
  33864. * @type {Array.<Array.<number>>}
  33865. * @private
  33866. */
  33867. this.endss_ = [];
  33868. /**
  33869. * @private
  33870. * @type {number}
  33871. */
  33872. this.flatInteriorPointsRevision_ = -1;
  33873. /**
  33874. * @private
  33875. * @type {Array.<number>}
  33876. */
  33877. this.flatInteriorPoints_ = null;
  33878. /**
  33879. * @private
  33880. * @type {number}
  33881. */
  33882. this.maxDelta_ = -1;
  33883. /**
  33884. * @private
  33885. * @type {number}
  33886. */
  33887. this.maxDeltaRevision_ = -1;
  33888. /**
  33889. * @private
  33890. * @type {number}
  33891. */
  33892. this.orientedRevision_ = -1;
  33893. /**
  33894. * @private
  33895. * @type {Array.<number>}
  33896. */
  33897. this.orientedFlatCoordinates_ = null;
  33898. this.setCoordinates(coordinates, opt_layout);
  33899. };
  33900. ol.inherits(ol.geom.MultiPolygon, ol.geom.SimpleGeometry);
  33901. /**
  33902. * Append the passed polygon to this multipolygon.
  33903. * @param {ol.geom.Polygon} polygon Polygon.
  33904. * @api
  33905. */
  33906. ol.geom.MultiPolygon.prototype.appendPolygon = function(polygon) {
  33907. /** @type {Array.<number>} */
  33908. var ends;
  33909. if (!this.flatCoordinates) {
  33910. this.flatCoordinates = polygon.getFlatCoordinates().slice();
  33911. ends = polygon.getEnds().slice();
  33912. this.endss_.push();
  33913. } else {
  33914. var offset = this.flatCoordinates.length;
  33915. ol.array.extend(this.flatCoordinates, polygon.getFlatCoordinates());
  33916. ends = polygon.getEnds().slice();
  33917. var i, ii;
  33918. for (i = 0, ii = ends.length; i < ii; ++i) {
  33919. ends[i] += offset;
  33920. }
  33921. }
  33922. this.endss_.push(ends);
  33923. this.changed();
  33924. };
  33925. /**
  33926. * Make a complete copy of the geometry.
  33927. * @return {!ol.geom.MultiPolygon} Clone.
  33928. * @override
  33929. * @api
  33930. */
  33931. ol.geom.MultiPolygon.prototype.clone = function() {
  33932. var multiPolygon = new ol.geom.MultiPolygon(null);
  33933. var len = this.endss_.length;
  33934. var newEndss = new Array(len);
  33935. for (var i = 0; i < len; ++i) {
  33936. newEndss[i] = this.endss_[i].slice();
  33937. }
  33938. multiPolygon.setFlatCoordinates(
  33939. this.layout, this.flatCoordinates.slice(), newEndss);
  33940. return multiPolygon;
  33941. };
  33942. /**
  33943. * @inheritDoc
  33944. */
  33945. ol.geom.MultiPolygon.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  33946. if (minSquaredDistance <
  33947. ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
  33948. return minSquaredDistance;
  33949. }
  33950. if (this.maxDeltaRevision_ != this.getRevision()) {
  33951. this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getssMaxSquaredDelta(
  33952. this.flatCoordinates, 0, this.endss_, this.stride, 0));
  33953. this.maxDeltaRevision_ = this.getRevision();
  33954. }
  33955. return ol.geom.flat.closest.getssClosestPoint(
  33956. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride,
  33957. this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);
  33958. };
  33959. /**
  33960. * @inheritDoc
  33961. */
  33962. ol.geom.MultiPolygon.prototype.containsXY = function(x, y) {
  33963. return ol.geom.flat.contains.linearRingssContainsXY(
  33964. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, x, y);
  33965. };
  33966. /**
  33967. * Return the area of the multipolygon on projected plane.
  33968. * @return {number} Area (on projected plane).
  33969. * @api
  33970. */
  33971. ol.geom.MultiPolygon.prototype.getArea = function() {
  33972. return ol.geom.flat.area.linearRingss(
  33973. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride);
  33974. };
  33975. /**
  33976. * Get the coordinate array for this geometry. This array has the structure
  33977. * of a GeoJSON coordinate array for multi-polygons.
  33978. *
  33979. * @param {boolean=} opt_right Orient coordinates according to the right-hand
  33980. * rule (counter-clockwise for exterior and clockwise for interior rings).
  33981. * If `false`, coordinates will be oriented according to the left-hand rule
  33982. * (clockwise for exterior and counter-clockwise for interior rings).
  33983. * By default, coordinate orientation will depend on how the geometry was
  33984. * constructed.
  33985. * @return {Array.<Array.<Array.<ol.Coordinate>>>} Coordinates.
  33986. * @override
  33987. * @api
  33988. */
  33989. ol.geom.MultiPolygon.prototype.getCoordinates = function(opt_right) {
  33990. var flatCoordinates;
  33991. if (opt_right !== undefined) {
  33992. flatCoordinates = this.getOrientedFlatCoordinates().slice();
  33993. ol.geom.flat.orient.orientLinearRingss(
  33994. flatCoordinates, 0, this.endss_, this.stride, opt_right);
  33995. } else {
  33996. flatCoordinates = this.flatCoordinates;
  33997. }
  33998. return ol.geom.flat.inflate.coordinatesss(
  33999. flatCoordinates, 0, this.endss_, this.stride);
  34000. };
  34001. /**
  34002. * @return {Array.<Array.<number>>} Endss.
  34003. */
  34004. ol.geom.MultiPolygon.prototype.getEndss = function() {
  34005. return this.endss_;
  34006. };
  34007. /**
  34008. * @return {Array.<number>} Flat interior points.
  34009. */
  34010. ol.geom.MultiPolygon.prototype.getFlatInteriorPoints = function() {
  34011. if (this.flatInteriorPointsRevision_ != this.getRevision()) {
  34012. var flatCenters = ol.geom.flat.center.linearRingss(
  34013. this.flatCoordinates, 0, this.endss_, this.stride);
  34014. this.flatInteriorPoints_ = ol.geom.flat.interiorpoint.linearRingss(
  34015. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride,
  34016. flatCenters);
  34017. this.flatInteriorPointsRevision_ = this.getRevision();
  34018. }
  34019. return this.flatInteriorPoints_;
  34020. };
  34021. /**
  34022. * Return the interior points as {@link ol.geom.MultiPoint multipoint}.
  34023. * @return {ol.geom.MultiPoint} Interior points.
  34024. * @api
  34025. */
  34026. ol.geom.MultiPolygon.prototype.getInteriorPoints = function() {
  34027. var interiorPoints = new ol.geom.MultiPoint(null);
  34028. interiorPoints.setFlatCoordinates(ol.geom.GeometryLayout.XY,
  34029. this.getFlatInteriorPoints().slice());
  34030. return interiorPoints;
  34031. };
  34032. /**
  34033. * @return {Array.<number>} Oriented flat coordinates.
  34034. */
  34035. ol.geom.MultiPolygon.prototype.getOrientedFlatCoordinates = function() {
  34036. if (this.orientedRevision_ != this.getRevision()) {
  34037. var flatCoordinates = this.flatCoordinates;
  34038. if (ol.geom.flat.orient.linearRingssAreOriented(
  34039. flatCoordinates, 0, this.endss_, this.stride)) {
  34040. this.orientedFlatCoordinates_ = flatCoordinates;
  34041. } else {
  34042. this.orientedFlatCoordinates_ = flatCoordinates.slice();
  34043. this.orientedFlatCoordinates_.length =
  34044. ol.geom.flat.orient.orientLinearRingss(
  34045. this.orientedFlatCoordinates_, 0, this.endss_, this.stride);
  34046. }
  34047. this.orientedRevision_ = this.getRevision();
  34048. }
  34049. return this.orientedFlatCoordinates_;
  34050. };
  34051. /**
  34052. * @inheritDoc
  34053. */
  34054. ol.geom.MultiPolygon.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
  34055. var simplifiedFlatCoordinates = [];
  34056. var simplifiedEndss = [];
  34057. simplifiedFlatCoordinates.length = ol.geom.flat.simplify.quantizess(
  34058. this.flatCoordinates, 0, this.endss_, this.stride,
  34059. Math.sqrt(squaredTolerance),
  34060. simplifiedFlatCoordinates, 0, simplifiedEndss);
  34061. var simplifiedMultiPolygon = new ol.geom.MultiPolygon(null);
  34062. simplifiedMultiPolygon.setFlatCoordinates(
  34063. ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates, simplifiedEndss);
  34064. return simplifiedMultiPolygon;
  34065. };
  34066. /**
  34067. * Return the polygon at the specified index.
  34068. * @param {number} index Index.
  34069. * @return {ol.geom.Polygon} Polygon.
  34070. * @api
  34071. */
  34072. ol.geom.MultiPolygon.prototype.getPolygon = function(index) {
  34073. if (index < 0 || this.endss_.length <= index) {
  34074. return null;
  34075. }
  34076. var offset;
  34077. if (index === 0) {
  34078. offset = 0;
  34079. } else {
  34080. var prevEnds = this.endss_[index - 1];
  34081. offset = prevEnds[prevEnds.length - 1];
  34082. }
  34083. var ends = this.endss_[index].slice();
  34084. var end = ends[ends.length - 1];
  34085. if (offset !== 0) {
  34086. var i, ii;
  34087. for (i = 0, ii = ends.length; i < ii; ++i) {
  34088. ends[i] -= offset;
  34089. }
  34090. }
  34091. var polygon = new ol.geom.Polygon(null);
  34092. polygon.setFlatCoordinates(
  34093. this.layout, this.flatCoordinates.slice(offset, end), ends);
  34094. return polygon;
  34095. };
  34096. /**
  34097. * Return the polygons of this multipolygon.
  34098. * @return {Array.<ol.geom.Polygon>} Polygons.
  34099. * @api
  34100. */
  34101. ol.geom.MultiPolygon.prototype.getPolygons = function() {
  34102. var layout = this.layout;
  34103. var flatCoordinates = this.flatCoordinates;
  34104. var endss = this.endss_;
  34105. var polygons = [];
  34106. var offset = 0;
  34107. var i, ii, j, jj;
  34108. for (i = 0, ii = endss.length; i < ii; ++i) {
  34109. var ends = endss[i].slice();
  34110. var end = ends[ends.length - 1];
  34111. if (offset !== 0) {
  34112. for (j = 0, jj = ends.length; j < jj; ++j) {
  34113. ends[j] -= offset;
  34114. }
  34115. }
  34116. var polygon = new ol.geom.Polygon(null);
  34117. polygon.setFlatCoordinates(
  34118. layout, flatCoordinates.slice(offset, end), ends);
  34119. polygons.push(polygon);
  34120. offset = end;
  34121. }
  34122. return polygons;
  34123. };
  34124. /**
  34125. * @inheritDoc
  34126. * @api
  34127. */
  34128. ol.geom.MultiPolygon.prototype.getType = function() {
  34129. return ol.geom.GeometryType.MULTI_POLYGON;
  34130. };
  34131. /**
  34132. * @inheritDoc
  34133. * @api
  34134. */
  34135. ol.geom.MultiPolygon.prototype.intersectsExtent = function(extent) {
  34136. return ol.geom.flat.intersectsextent.linearRingss(
  34137. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, extent);
  34138. };
  34139. /**
  34140. * Set the coordinates of the multipolygon.
  34141. * @param {Array.<Array.<Array.<ol.Coordinate>>>} coordinates Coordinates.
  34142. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  34143. * @override
  34144. * @api
  34145. */
  34146. ol.geom.MultiPolygon.prototype.setCoordinates = function(coordinates, opt_layout) {
  34147. if (!coordinates) {
  34148. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.endss_);
  34149. } else {
  34150. this.setLayout(opt_layout, coordinates, 3);
  34151. if (!this.flatCoordinates) {
  34152. this.flatCoordinates = [];
  34153. }
  34154. var endss = ol.geom.flat.deflate.coordinatesss(
  34155. this.flatCoordinates, 0, coordinates, this.stride, this.endss_);
  34156. if (endss.length === 0) {
  34157. this.flatCoordinates.length = 0;
  34158. } else {
  34159. var lastEnds = endss[endss.length - 1];
  34160. this.flatCoordinates.length = lastEnds.length === 0 ?
  34161. 0 : lastEnds[lastEnds.length - 1];
  34162. }
  34163. this.changed();
  34164. }
  34165. };
  34166. /**
  34167. * @param {ol.geom.GeometryLayout} layout Layout.
  34168. * @param {Array.<number>} flatCoordinates Flat coordinates.
  34169. * @param {Array.<Array.<number>>} endss Endss.
  34170. */
  34171. ol.geom.MultiPolygon.prototype.setFlatCoordinates = function(layout, flatCoordinates, endss) {
  34172. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  34173. this.endss_ = endss;
  34174. this.changed();
  34175. };
  34176. /**
  34177. * @param {Array.<ol.geom.Polygon>} polygons Polygons.
  34178. */
  34179. ol.geom.MultiPolygon.prototype.setPolygons = function(polygons) {
  34180. var layout = this.getLayout();
  34181. var flatCoordinates = [];
  34182. var endss = [];
  34183. var i, ii, ends;
  34184. for (i = 0, ii = polygons.length; i < ii; ++i) {
  34185. var polygon = polygons[i];
  34186. if (i === 0) {
  34187. layout = polygon.getLayout();
  34188. }
  34189. var offset = flatCoordinates.length;
  34190. ends = polygon.getEnds();
  34191. var j, jj;
  34192. for (j = 0, jj = ends.length; j < jj; ++j) {
  34193. ends[j] += offset;
  34194. }
  34195. ol.array.extend(flatCoordinates, polygon.getFlatCoordinates());
  34196. endss.push(ends);
  34197. }
  34198. this.setFlatCoordinates(layout, flatCoordinates, endss);
  34199. };
  34200. goog.provide('ol.format.EsriJSON');
  34201. goog.require('ol');
  34202. goog.require('ol.Feature');
  34203. goog.require('ol.asserts');
  34204. goog.require('ol.extent');
  34205. goog.require('ol.format.Feature');
  34206. goog.require('ol.format.JSONFeature');
  34207. goog.require('ol.geom.GeometryLayout');
  34208. goog.require('ol.geom.GeometryType');
  34209. goog.require('ol.geom.LineString');
  34210. goog.require('ol.geom.LinearRing');
  34211. goog.require('ol.geom.MultiLineString');
  34212. goog.require('ol.geom.MultiPoint');
  34213. goog.require('ol.geom.MultiPolygon');
  34214. goog.require('ol.geom.Point');
  34215. goog.require('ol.geom.Polygon');
  34216. goog.require('ol.geom.flat.deflate');
  34217. goog.require('ol.geom.flat.orient');
  34218. goog.require('ol.obj');
  34219. goog.require('ol.proj');
  34220. /**
  34221. * @classdesc
  34222. * Feature format for reading and writing data in the EsriJSON format.
  34223. *
  34224. * @constructor
  34225. * @extends {ol.format.JSONFeature}
  34226. * @param {olx.format.EsriJSONOptions=} opt_options Options.
  34227. * @api
  34228. */
  34229. ol.format.EsriJSON = function(opt_options) {
  34230. var options = opt_options ? opt_options : {};
  34231. ol.format.JSONFeature.call(this);
  34232. /**
  34233. * Name of the geometry attribute for features.
  34234. * @type {string|undefined}
  34235. * @private
  34236. */
  34237. this.geometryName_ = options.geometryName;
  34238. };
  34239. ol.inherits(ol.format.EsriJSON, ol.format.JSONFeature);
  34240. /**
  34241. * @param {EsriJSONGeometry} object Object.
  34242. * @param {olx.format.ReadOptions=} opt_options Read options.
  34243. * @private
  34244. * @return {ol.geom.Geometry} Geometry.
  34245. */
  34246. ol.format.EsriJSON.readGeometry_ = function(object, opt_options) {
  34247. if (!object) {
  34248. return null;
  34249. }
  34250. /** @type {ol.geom.GeometryType} */
  34251. var type;
  34252. if (typeof object.x === 'number' && typeof object.y === 'number') {
  34253. type = ol.geom.GeometryType.POINT;
  34254. } else if (object.points) {
  34255. type = ol.geom.GeometryType.MULTI_POINT;
  34256. } else if (object.paths) {
  34257. if (object.paths.length === 1) {
  34258. type = ol.geom.GeometryType.LINE_STRING;
  34259. } else {
  34260. type = ol.geom.GeometryType.MULTI_LINE_STRING;
  34261. }
  34262. } else if (object.rings) {
  34263. var layout = ol.format.EsriJSON.getGeometryLayout_(object);
  34264. var rings = ol.format.EsriJSON.convertRings_(object.rings, layout);
  34265. object = /** @type {EsriJSONGeometry} */(ol.obj.assign({}, object));
  34266. if (rings.length === 1) {
  34267. type = ol.geom.GeometryType.POLYGON;
  34268. object.rings = rings[0];
  34269. } else {
  34270. type = ol.geom.GeometryType.MULTI_POLYGON;
  34271. object.rings = rings;
  34272. }
  34273. }
  34274. var geometryReader = ol.format.EsriJSON.GEOMETRY_READERS_[type];
  34275. return /** @type {ol.geom.Geometry} */ (
  34276. ol.format.Feature.transformWithOptions(
  34277. geometryReader(object), false, opt_options));
  34278. };
  34279. /**
  34280. * Determines inner and outer rings.
  34281. * Checks if any polygons in this array contain any other polygons in this
  34282. * array. It is used for checking for holes.
  34283. * Logic inspired by: https://github.com/Esri/terraformer-arcgis-parser
  34284. * @param {Array.<!Array.<!Array.<number>>>} rings Rings.
  34285. * @param {ol.geom.GeometryLayout} layout Geometry layout.
  34286. * @private
  34287. * @return {Array.<!Array.<!Array.<number>>>} Transformed rings.
  34288. */
  34289. ol.format.EsriJSON.convertRings_ = function(rings, layout) {
  34290. var flatRing = [];
  34291. var outerRings = [];
  34292. var holes = [];
  34293. var i, ii;
  34294. for (i = 0, ii = rings.length; i < ii; ++i) {
  34295. flatRing.length = 0;
  34296. ol.geom.flat.deflate.coordinates(flatRing, 0, rings[i], layout.length);
  34297. // is this ring an outer ring? is it clockwise?
  34298. var clockwise = ol.geom.flat.orient.linearRingIsClockwise(flatRing, 0,
  34299. flatRing.length, layout.length);
  34300. if (clockwise) {
  34301. outerRings.push([rings[i]]);
  34302. } else {
  34303. holes.push(rings[i]);
  34304. }
  34305. }
  34306. while (holes.length) {
  34307. var hole = holes.shift();
  34308. var matched = false;
  34309. // loop over all outer rings and see if they contain our hole.
  34310. for (i = outerRings.length - 1; i >= 0; i--) {
  34311. var outerRing = outerRings[i][0];
  34312. var containsHole = ol.extent.containsExtent(
  34313. new ol.geom.LinearRing(outerRing).getExtent(),
  34314. new ol.geom.LinearRing(hole).getExtent()
  34315. );
  34316. if (containsHole) {
  34317. // the hole is contained push it into our polygon
  34318. outerRings[i].push(hole);
  34319. matched = true;
  34320. break;
  34321. }
  34322. }
  34323. if (!matched) {
  34324. // no outer rings contain this hole turn it into and outer
  34325. // ring (reverse it)
  34326. outerRings.push([hole.reverse()]);
  34327. }
  34328. }
  34329. return outerRings;
  34330. };
  34331. /**
  34332. * @param {EsriJSONGeometry} object Object.
  34333. * @private
  34334. * @return {ol.geom.Geometry} Point.
  34335. */
  34336. ol.format.EsriJSON.readPointGeometry_ = function(object) {
  34337. var point;
  34338. if (object.m !== undefined && object.z !== undefined) {
  34339. point = new ol.geom.Point([object.x, object.y, object.z, object.m],
  34340. ol.geom.GeometryLayout.XYZM);
  34341. } else if (object.z !== undefined) {
  34342. point = new ol.geom.Point([object.x, object.y, object.z],
  34343. ol.geom.GeometryLayout.XYZ);
  34344. } else if (object.m !== undefined) {
  34345. point = new ol.geom.Point([object.x, object.y, object.m],
  34346. ol.geom.GeometryLayout.XYM);
  34347. } else {
  34348. point = new ol.geom.Point([object.x, object.y]);
  34349. }
  34350. return point;
  34351. };
  34352. /**
  34353. * @param {EsriJSONGeometry} object Object.
  34354. * @private
  34355. * @return {ol.geom.Geometry} LineString.
  34356. */
  34357. ol.format.EsriJSON.readLineStringGeometry_ = function(object) {
  34358. var layout = ol.format.EsriJSON.getGeometryLayout_(object);
  34359. return new ol.geom.LineString(object.paths[0], layout);
  34360. };
  34361. /**
  34362. * @param {EsriJSONGeometry} object Object.
  34363. * @private
  34364. * @return {ol.geom.Geometry} MultiLineString.
  34365. */
  34366. ol.format.EsriJSON.readMultiLineStringGeometry_ = function(object) {
  34367. var layout = ol.format.EsriJSON.getGeometryLayout_(object);
  34368. return new ol.geom.MultiLineString(object.paths, layout);
  34369. };
  34370. /**
  34371. * @param {EsriJSONGeometry} object Object.
  34372. * @private
  34373. * @return {ol.geom.GeometryLayout} The geometry layout to use.
  34374. */
  34375. ol.format.EsriJSON.getGeometryLayout_ = function(object) {
  34376. var layout = ol.geom.GeometryLayout.XY;
  34377. if (object.hasZ === true && object.hasM === true) {
  34378. layout = ol.geom.GeometryLayout.XYZM;
  34379. } else if (object.hasZ === true) {
  34380. layout = ol.geom.GeometryLayout.XYZ;
  34381. } else if (object.hasM === true) {
  34382. layout = ol.geom.GeometryLayout.XYM;
  34383. }
  34384. return layout;
  34385. };
  34386. /**
  34387. * @param {EsriJSONGeometry} object Object.
  34388. * @private
  34389. * @return {ol.geom.Geometry} MultiPoint.
  34390. */
  34391. ol.format.EsriJSON.readMultiPointGeometry_ = function(object) {
  34392. var layout = ol.format.EsriJSON.getGeometryLayout_(object);
  34393. return new ol.geom.MultiPoint(object.points, layout);
  34394. };
  34395. /**
  34396. * @param {EsriJSONGeometry} object Object.
  34397. * @private
  34398. * @return {ol.geom.Geometry} MultiPolygon.
  34399. */
  34400. ol.format.EsriJSON.readMultiPolygonGeometry_ = function(object) {
  34401. var layout = ol.format.EsriJSON.getGeometryLayout_(object);
  34402. return new ol.geom.MultiPolygon(
  34403. /** @type {Array.<Array.<Array.<Array.<number>>>>} */(object.rings),
  34404. layout);
  34405. };
  34406. /**
  34407. * @param {EsriJSONGeometry} object Object.
  34408. * @private
  34409. * @return {ol.geom.Geometry} Polygon.
  34410. */
  34411. ol.format.EsriJSON.readPolygonGeometry_ = function(object) {
  34412. var layout = ol.format.EsriJSON.getGeometryLayout_(object);
  34413. return new ol.geom.Polygon(object.rings, layout);
  34414. };
  34415. /**
  34416. * @param {ol.geom.Geometry} geometry Geometry.
  34417. * @param {olx.format.WriteOptions=} opt_options Write options.
  34418. * @private
  34419. * @return {EsriJSONGeometry} EsriJSON geometry.
  34420. */
  34421. ol.format.EsriJSON.writePointGeometry_ = function(geometry, opt_options) {
  34422. var coordinates = /** @type {ol.geom.Point} */ (geometry).getCoordinates();
  34423. var esriJSON;
  34424. var layout = /** @type {ol.geom.Point} */ (geometry).getLayout();
  34425. if (layout === ol.geom.GeometryLayout.XYZ) {
  34426. esriJSON = /** @type {EsriJSONPoint} */ ({
  34427. x: coordinates[0],
  34428. y: coordinates[1],
  34429. z: coordinates[2]
  34430. });
  34431. } else if (layout === ol.geom.GeometryLayout.XYM) {
  34432. esriJSON = /** @type {EsriJSONPoint} */ ({
  34433. x: coordinates[0],
  34434. y: coordinates[1],
  34435. m: coordinates[2]
  34436. });
  34437. } else if (layout === ol.geom.GeometryLayout.XYZM) {
  34438. esriJSON = /** @type {EsriJSONPoint} */ ({
  34439. x: coordinates[0],
  34440. y: coordinates[1],
  34441. z: coordinates[2],
  34442. m: coordinates[3]
  34443. });
  34444. } else if (layout === ol.geom.GeometryLayout.XY) {
  34445. esriJSON = /** @type {EsriJSONPoint} */ ({
  34446. x: coordinates[0],
  34447. y: coordinates[1]
  34448. });
  34449. } else {
  34450. ol.asserts.assert(false, 34); // Invalid geometry layout
  34451. }
  34452. return /** @type {EsriJSONGeometry} */ (esriJSON);
  34453. };
  34454. /**
  34455. * @param {ol.geom.SimpleGeometry} geometry Geometry.
  34456. * @private
  34457. * @return {Object} Object with boolean hasZ and hasM keys.
  34458. */
  34459. ol.format.EsriJSON.getHasZM_ = function(geometry) {
  34460. var layout = geometry.getLayout();
  34461. return {
  34462. hasZ: (layout === ol.geom.GeometryLayout.XYZ ||
  34463. layout === ol.geom.GeometryLayout.XYZM),
  34464. hasM: (layout === ol.geom.GeometryLayout.XYM ||
  34465. layout === ol.geom.GeometryLayout.XYZM)
  34466. };
  34467. };
  34468. /**
  34469. * @param {ol.geom.Geometry} geometry Geometry.
  34470. * @param {olx.format.WriteOptions=} opt_options Write options.
  34471. * @private
  34472. * @return {EsriJSONPolyline} EsriJSON geometry.
  34473. */
  34474. ol.format.EsriJSON.writeLineStringGeometry_ = function(geometry, opt_options) {
  34475. var hasZM = ol.format.EsriJSON.getHasZM_(/** @type {ol.geom.LineString} */(geometry));
  34476. return /** @type {EsriJSONPolyline} */ ({
  34477. hasZ: hasZM.hasZ,
  34478. hasM: hasZM.hasM,
  34479. paths: [
  34480. /** @type {ol.geom.LineString} */ (geometry).getCoordinates()
  34481. ]
  34482. });
  34483. };
  34484. /**
  34485. * @param {ol.geom.Geometry} geometry Geometry.
  34486. * @param {olx.format.WriteOptions=} opt_options Write options.
  34487. * @private
  34488. * @return {EsriJSONPolygon} EsriJSON geometry.
  34489. */
  34490. ol.format.EsriJSON.writePolygonGeometry_ = function(geometry, opt_options) {
  34491. // Esri geometries use the left-hand rule
  34492. var hasZM = ol.format.EsriJSON.getHasZM_(/** @type {ol.geom.Polygon} */(geometry));
  34493. return /** @type {EsriJSONPolygon} */ ({
  34494. hasZ: hasZM.hasZ,
  34495. hasM: hasZM.hasM,
  34496. rings: /** @type {ol.geom.Polygon} */ (geometry).getCoordinates(false)
  34497. });
  34498. };
  34499. /**
  34500. * @param {ol.geom.Geometry} geometry Geometry.
  34501. * @param {olx.format.WriteOptions=} opt_options Write options.
  34502. * @private
  34503. * @return {EsriJSONPolyline} EsriJSON geometry.
  34504. */
  34505. ol.format.EsriJSON.writeMultiLineStringGeometry_ = function(geometry, opt_options) {
  34506. var hasZM = ol.format.EsriJSON.getHasZM_(/** @type {ol.geom.MultiLineString} */(geometry));
  34507. return /** @type {EsriJSONPolyline} */ ({
  34508. hasZ: hasZM.hasZ,
  34509. hasM: hasZM.hasM,
  34510. paths: /** @type {ol.geom.MultiLineString} */ (geometry).getCoordinates()
  34511. });
  34512. };
  34513. /**
  34514. * @param {ol.geom.Geometry} geometry Geometry.
  34515. * @param {olx.format.WriteOptions=} opt_options Write options.
  34516. * @private
  34517. * @return {EsriJSONMultipoint} EsriJSON geometry.
  34518. */
  34519. ol.format.EsriJSON.writeMultiPointGeometry_ = function(geometry, opt_options) {
  34520. var hasZM = ol.format.EsriJSON.getHasZM_(/** @type {ol.geom.MultiPoint} */(geometry));
  34521. return /** @type {EsriJSONMultipoint} */ ({
  34522. hasZ: hasZM.hasZ,
  34523. hasM: hasZM.hasM,
  34524. points: /** @type {ol.geom.MultiPoint} */ (geometry).getCoordinates()
  34525. });
  34526. };
  34527. /**
  34528. * @param {ol.geom.Geometry} geometry Geometry.
  34529. * @param {olx.format.WriteOptions=} opt_options Write options.
  34530. * @private
  34531. * @return {EsriJSONPolygon} EsriJSON geometry.
  34532. */
  34533. ol.format.EsriJSON.writeMultiPolygonGeometry_ = function(geometry,
  34534. opt_options) {
  34535. var hasZM = ol.format.EsriJSON.getHasZM_(/** @type {ol.geom.MultiPolygon} */(geometry));
  34536. var coordinates = /** @type {ol.geom.MultiPolygon} */ (geometry).getCoordinates(false);
  34537. var output = [];
  34538. for (var i = 0; i < coordinates.length; i++) {
  34539. for (var x = coordinates[i].length - 1; x >= 0; x--) {
  34540. output.push(coordinates[i][x]);
  34541. }
  34542. }
  34543. return /** @type {EsriJSONPolygon} */ ({
  34544. hasZ: hasZM.hasZ,
  34545. hasM: hasZM.hasM,
  34546. rings: output
  34547. });
  34548. };
  34549. /**
  34550. * @const
  34551. * @private
  34552. * @type {Object.<ol.geom.GeometryType, function(EsriJSONGeometry): ol.geom.Geometry>}
  34553. */
  34554. ol.format.EsriJSON.GEOMETRY_READERS_ = {};
  34555. ol.format.EsriJSON.GEOMETRY_READERS_[ol.geom.GeometryType.POINT] =
  34556. ol.format.EsriJSON.readPointGeometry_;
  34557. ol.format.EsriJSON.GEOMETRY_READERS_[ol.geom.GeometryType.LINE_STRING] =
  34558. ol.format.EsriJSON.readLineStringGeometry_;
  34559. ol.format.EsriJSON.GEOMETRY_READERS_[ol.geom.GeometryType.POLYGON] =
  34560. ol.format.EsriJSON.readPolygonGeometry_;
  34561. ol.format.EsriJSON.GEOMETRY_READERS_[ol.geom.GeometryType.MULTI_POINT] =
  34562. ol.format.EsriJSON.readMultiPointGeometry_;
  34563. ol.format.EsriJSON.GEOMETRY_READERS_[ol.geom.GeometryType.MULTI_LINE_STRING] =
  34564. ol.format.EsriJSON.readMultiLineStringGeometry_;
  34565. ol.format.EsriJSON.GEOMETRY_READERS_[ol.geom.GeometryType.MULTI_POLYGON] =
  34566. ol.format.EsriJSON.readMultiPolygonGeometry_;
  34567. /**
  34568. * @const
  34569. * @private
  34570. * @type {Object.<string, function(ol.geom.Geometry, olx.format.WriteOptions=): (EsriJSONGeometry)>}
  34571. */
  34572. ol.format.EsriJSON.GEOMETRY_WRITERS_ = {};
  34573. ol.format.EsriJSON.GEOMETRY_WRITERS_[ol.geom.GeometryType.POINT] =
  34574. ol.format.EsriJSON.writePointGeometry_;
  34575. ol.format.EsriJSON.GEOMETRY_WRITERS_[ol.geom.GeometryType.LINE_STRING] =
  34576. ol.format.EsriJSON.writeLineStringGeometry_;
  34577. ol.format.EsriJSON.GEOMETRY_WRITERS_[ol.geom.GeometryType.POLYGON] =
  34578. ol.format.EsriJSON.writePolygonGeometry_;
  34579. ol.format.EsriJSON.GEOMETRY_WRITERS_[ol.geom.GeometryType.MULTI_POINT] =
  34580. ol.format.EsriJSON.writeMultiPointGeometry_;
  34581. ol.format.EsriJSON.GEOMETRY_WRITERS_[ol.geom.GeometryType.MULTI_LINE_STRING] =
  34582. ol.format.EsriJSON.writeMultiLineStringGeometry_;
  34583. ol.format.EsriJSON.GEOMETRY_WRITERS_[ol.geom.GeometryType.MULTI_POLYGON] =
  34584. ol.format.EsriJSON.writeMultiPolygonGeometry_;
  34585. /**
  34586. * Read a feature from a EsriJSON Feature source. Only works for Feature,
  34587. * use `readFeatures` to read FeatureCollection source.
  34588. *
  34589. * @function
  34590. * @param {ArrayBuffer|Document|Node|Object|string} source Source.
  34591. * @param {olx.format.ReadOptions=} opt_options Read options.
  34592. * @return {ol.Feature} Feature.
  34593. * @api
  34594. */
  34595. ol.format.EsriJSON.prototype.readFeature;
  34596. /**
  34597. * Read all features from a EsriJSON source. Works with both Feature and
  34598. * FeatureCollection sources.
  34599. *
  34600. * @function
  34601. * @param {ArrayBuffer|Document|Node|Object|string} source Source.
  34602. * @param {olx.format.ReadOptions=} opt_options Read options.
  34603. * @return {Array.<ol.Feature>} Features.
  34604. * @api
  34605. */
  34606. ol.format.EsriJSON.prototype.readFeatures;
  34607. /**
  34608. * @inheritDoc
  34609. */
  34610. ol.format.EsriJSON.prototype.readFeatureFromObject = function(
  34611. object, opt_options) {
  34612. var esriJSONFeature = /** @type {EsriJSONFeature} */ (object);
  34613. var geometry = ol.format.EsriJSON.readGeometry_(esriJSONFeature.geometry,
  34614. opt_options);
  34615. var feature = new ol.Feature();
  34616. if (this.geometryName_) {
  34617. feature.setGeometryName(this.geometryName_);
  34618. }
  34619. feature.setGeometry(geometry);
  34620. if (opt_options && opt_options.idField &&
  34621. esriJSONFeature.attributes[opt_options.idField]) {
  34622. feature.setId(/** @type {number} */(
  34623. esriJSONFeature.attributes[opt_options.idField]));
  34624. }
  34625. if (esriJSONFeature.attributes) {
  34626. feature.setProperties(esriJSONFeature.attributes);
  34627. }
  34628. return feature;
  34629. };
  34630. /**
  34631. * @inheritDoc
  34632. */
  34633. ol.format.EsriJSON.prototype.readFeaturesFromObject = function(
  34634. object, opt_options) {
  34635. var esriJSONObject = /** @type {EsriJSONObject} */ (object);
  34636. var options = opt_options ? opt_options : {};
  34637. if (esriJSONObject.features) {
  34638. var esriJSONFeatureCollection = /** @type {EsriJSONFeatureCollection} */
  34639. (object);
  34640. /** @type {Array.<ol.Feature>} */
  34641. var features = [];
  34642. var esriJSONFeatures = esriJSONFeatureCollection.features;
  34643. var i, ii;
  34644. options.idField = object.objectIdFieldName;
  34645. for (i = 0, ii = esriJSONFeatures.length; i < ii; ++i) {
  34646. features.push(this.readFeatureFromObject(esriJSONFeatures[i],
  34647. options));
  34648. }
  34649. return features;
  34650. } else {
  34651. return [this.readFeatureFromObject(object, options)];
  34652. }
  34653. };
  34654. /**
  34655. * Read a geometry from a EsriJSON source.
  34656. *
  34657. * @function
  34658. * @param {ArrayBuffer|Document|Node|Object|string} source Source.
  34659. * @param {olx.format.ReadOptions=} opt_options Read options.
  34660. * @return {ol.geom.Geometry} Geometry.
  34661. * @api
  34662. */
  34663. ol.format.EsriJSON.prototype.readGeometry;
  34664. /**
  34665. * @inheritDoc
  34666. */
  34667. ol.format.EsriJSON.prototype.readGeometryFromObject = function(
  34668. object, opt_options) {
  34669. return ol.format.EsriJSON.readGeometry_(
  34670. /** @type {EsriJSONGeometry} */(object), opt_options);
  34671. };
  34672. /**
  34673. * Read the projection from a EsriJSON source.
  34674. *
  34675. * @function
  34676. * @param {ArrayBuffer|Document|Node|Object|string} source Source.
  34677. * @return {ol.proj.Projection} Projection.
  34678. * @api
  34679. */
  34680. ol.format.EsriJSON.prototype.readProjection;
  34681. /**
  34682. * @inheritDoc
  34683. */
  34684. ol.format.EsriJSON.prototype.readProjectionFromObject = function(object) {
  34685. var esriJSONObject = /** @type {EsriJSONObject} */ (object);
  34686. if (esriJSONObject.spatialReference && esriJSONObject.spatialReference.wkid) {
  34687. var crs = esriJSONObject.spatialReference.wkid;
  34688. return ol.proj.get('EPSG:' + crs);
  34689. } else {
  34690. return null;
  34691. }
  34692. };
  34693. /**
  34694. * @param {ol.geom.Geometry} geometry Geometry.
  34695. * @param {olx.format.WriteOptions=} opt_options Write options.
  34696. * @private
  34697. * @return {EsriJSONGeometry} EsriJSON geometry.
  34698. */
  34699. ol.format.EsriJSON.writeGeometry_ = function(geometry, opt_options) {
  34700. var geometryWriter = ol.format.EsriJSON.GEOMETRY_WRITERS_[geometry.getType()];
  34701. return geometryWriter(/** @type {ol.geom.Geometry} */(
  34702. ol.format.Feature.transformWithOptions(geometry, true, opt_options)),
  34703. opt_options);
  34704. };
  34705. /**
  34706. * Encode a geometry as a EsriJSON string.
  34707. *
  34708. * @function
  34709. * @param {ol.geom.Geometry} geometry Geometry.
  34710. * @param {olx.format.WriteOptions=} opt_options Write options.
  34711. * @return {string} EsriJSON.
  34712. * @api
  34713. */
  34714. ol.format.EsriJSON.prototype.writeGeometry;
  34715. /**
  34716. * Encode a geometry as a EsriJSON object.
  34717. *
  34718. * @param {ol.geom.Geometry} geometry Geometry.
  34719. * @param {olx.format.WriteOptions=} opt_options Write options.
  34720. * @return {EsriJSONGeometry} Object.
  34721. * @override
  34722. * @api
  34723. */
  34724. ol.format.EsriJSON.prototype.writeGeometryObject = function(geometry,
  34725. opt_options) {
  34726. return ol.format.EsriJSON.writeGeometry_(geometry,
  34727. this.adaptOptions(opt_options));
  34728. };
  34729. /**
  34730. * Encode a feature as a EsriJSON Feature string.
  34731. *
  34732. * @function
  34733. * @param {ol.Feature} feature Feature.
  34734. * @param {olx.format.WriteOptions=} opt_options Write options.
  34735. * @return {string} EsriJSON.
  34736. * @api
  34737. */
  34738. ol.format.EsriJSON.prototype.writeFeature;
  34739. /**
  34740. * Encode a feature as a esriJSON Feature object.
  34741. *
  34742. * @param {ol.Feature} feature Feature.
  34743. * @param {olx.format.WriteOptions=} opt_options Write options.
  34744. * @return {Object} Object.
  34745. * @override
  34746. * @api
  34747. */
  34748. ol.format.EsriJSON.prototype.writeFeatureObject = function(
  34749. feature, opt_options) {
  34750. opt_options = this.adaptOptions(opt_options);
  34751. var object = {};
  34752. var geometry = feature.getGeometry();
  34753. if (geometry) {
  34754. object['geometry'] =
  34755. ol.format.EsriJSON.writeGeometry_(geometry, opt_options);
  34756. if (opt_options && opt_options.featureProjection) {
  34757. object['geometry']['spatialReference'] = /** @type {EsriJSONCRS} */({
  34758. wkid: ol.proj.get(
  34759. opt_options.featureProjection).getCode().split(':').pop()
  34760. });
  34761. }
  34762. }
  34763. var properties = feature.getProperties();
  34764. delete properties[feature.getGeometryName()];
  34765. if (!ol.obj.isEmpty(properties)) {
  34766. object['attributes'] = properties;
  34767. } else {
  34768. object['attributes'] = {};
  34769. }
  34770. return object;
  34771. };
  34772. /**
  34773. * Encode an array of features as EsriJSON.
  34774. *
  34775. * @function
  34776. * @param {Array.<ol.Feature>} features Features.
  34777. * @param {olx.format.WriteOptions=} opt_options Write options.
  34778. * @return {string} EsriJSON.
  34779. * @api
  34780. */
  34781. ol.format.EsriJSON.prototype.writeFeatures;
  34782. /**
  34783. * Encode an array of features as a EsriJSON object.
  34784. *
  34785. * @param {Array.<ol.Feature>} features Features.
  34786. * @param {olx.format.WriteOptions=} opt_options Write options.
  34787. * @return {Object} EsriJSON Object.
  34788. * @override
  34789. * @api
  34790. */
  34791. ol.format.EsriJSON.prototype.writeFeaturesObject = function(features, opt_options) {
  34792. opt_options = this.adaptOptions(opt_options);
  34793. var objects = [];
  34794. var i, ii;
  34795. for (i = 0, ii = features.length; i < ii; ++i) {
  34796. objects.push(this.writeFeatureObject(features[i], opt_options));
  34797. }
  34798. return /** @type {EsriJSONFeatureCollection} */ ({
  34799. 'features': objects
  34800. });
  34801. };
  34802. goog.provide('ol.format.filter.Filter');
  34803. /**
  34804. * @classdesc
  34805. * Abstract class; normally only used for creating subclasses and not instantiated in apps.
  34806. * Base class for WFS GetFeature filters.
  34807. *
  34808. * @constructor
  34809. * @param {!string} tagName The XML tag name for this filter.
  34810. * @struct
  34811. * @api
  34812. */
  34813. ol.format.filter.Filter = function(tagName) {
  34814. /**
  34815. * @private
  34816. * @type {!string}
  34817. */
  34818. this.tagName_ = tagName;
  34819. };
  34820. /**
  34821. * The XML tag name for a filter.
  34822. * @returns {!string} Name.
  34823. */
  34824. ol.format.filter.Filter.prototype.getTagName = function() {
  34825. return this.tagName_;
  34826. };
  34827. goog.provide('ol.format.filter.LogicalNary');
  34828. goog.require('ol');
  34829. goog.require('ol.asserts');
  34830. goog.require('ol.format.filter.Filter');
  34831. /**
  34832. * @classdesc
  34833. * Abstract class; normally only used for creating subclasses and not instantiated in apps.
  34834. * Base class for WFS GetFeature n-ary logical filters.
  34835. *
  34836. * @constructor
  34837. * @param {!string} tagName The XML tag name for this filter.
  34838. * @param {...ol.format.filter.Filter} conditions Conditions.
  34839. * @extends {ol.format.filter.Filter}
  34840. */
  34841. ol.format.filter.LogicalNary = function(tagName, conditions) {
  34842. ol.format.filter.Filter.call(this, tagName);
  34843. /**
  34844. * @public
  34845. * @type {Array.<ol.format.filter.Filter>}
  34846. */
  34847. this.conditions = Array.prototype.slice.call(arguments, 1);
  34848. ol.asserts.assert(this.conditions.length >= 2, 57); // At least 2 conditions are required.
  34849. };
  34850. ol.inherits(ol.format.filter.LogicalNary, ol.format.filter.Filter);
  34851. goog.provide('ol.format.filter.And');
  34852. goog.require('ol');
  34853. goog.require('ol.format.filter.LogicalNary');
  34854. /**
  34855. * @classdesc
  34856. * Represents a logical `<And>` operator between two or more filter conditions.
  34857. *
  34858. * @constructor
  34859. * @param {...ol.format.filter.Filter} conditions Conditions.
  34860. * @extends {ol.format.filter.LogicalNary}
  34861. * @api
  34862. */
  34863. ol.format.filter.And = function(conditions) {
  34864. var params = ['And'].concat(Array.prototype.slice.call(arguments));
  34865. ol.format.filter.LogicalNary.apply(this, params);
  34866. };
  34867. ol.inherits(ol.format.filter.And, ol.format.filter.LogicalNary);
  34868. goog.provide('ol.format.filter.Bbox');
  34869. goog.require('ol');
  34870. goog.require('ol.format.filter.Filter');
  34871. /**
  34872. * @classdesc
  34873. * Represents a `<BBOX>` operator to test whether a geometry-valued property
  34874. * intersects a fixed bounding box
  34875. *
  34876. * @constructor
  34877. * @param {!string} geometryName Geometry name to use.
  34878. * @param {!ol.Extent} extent Extent.
  34879. * @param {string=} opt_srsName SRS name. No srsName attribute will be
  34880. * set on geometries when this is not provided.
  34881. * @extends {ol.format.filter.Filter}
  34882. * @api
  34883. */
  34884. ol.format.filter.Bbox = function(geometryName, extent, opt_srsName) {
  34885. ol.format.filter.Filter.call(this, 'BBOX');
  34886. /**
  34887. * @public
  34888. * @type {!string}
  34889. */
  34890. this.geometryName = geometryName;
  34891. /**
  34892. * @public
  34893. * @type {ol.Extent}
  34894. */
  34895. this.extent = extent;
  34896. /**
  34897. * @public
  34898. * @type {string|undefined}
  34899. */
  34900. this.srsName = opt_srsName;
  34901. };
  34902. ol.inherits(ol.format.filter.Bbox, ol.format.filter.Filter);
  34903. goog.provide('ol.format.filter.Comparison');
  34904. goog.require('ol');
  34905. goog.require('ol.format.filter.Filter');
  34906. /**
  34907. * @classdesc
  34908. * Abstract class; normally only used for creating subclasses and not instantiated in apps.
  34909. * Base class for WFS GetFeature property comparison filters.
  34910. *
  34911. * @constructor
  34912. * @param {!string} tagName The XML tag name for this filter.
  34913. * @param {!string} propertyName Name of the context property to compare.
  34914. * @extends {ol.format.filter.Filter}
  34915. * @api
  34916. */
  34917. ol.format.filter.Comparison = function(tagName, propertyName) {
  34918. ol.format.filter.Filter.call(this, tagName);
  34919. /**
  34920. * @public
  34921. * @type {!string}
  34922. */
  34923. this.propertyName = propertyName;
  34924. };
  34925. ol.inherits(ol.format.filter.Comparison, ol.format.filter.Filter);
  34926. goog.provide('ol.format.filter.During');
  34927. goog.require('ol');
  34928. goog.require('ol.format.filter.Comparison');
  34929. /**
  34930. * @classdesc
  34931. * Represents a `<During>` comparison operator.
  34932. *
  34933. * @constructor
  34934. * @param {!string} propertyName Name of the context property to compare.
  34935. * @param {!string} begin The begin date in ISO-8601 format.
  34936. * @param {!string} end The end date in ISO-8601 format.
  34937. * @extends {ol.format.filter.Comparison}
  34938. * @api
  34939. */
  34940. ol.format.filter.During = function(propertyName, begin, end) {
  34941. ol.format.filter.Comparison.call(this, 'During', propertyName);
  34942. /**
  34943. * @public
  34944. * @type {!string}
  34945. */
  34946. this.begin = begin;
  34947. /**
  34948. * @public
  34949. * @type {!string}
  34950. */
  34951. this.end = end;
  34952. };
  34953. ol.inherits(ol.format.filter.During, ol.format.filter.Comparison);
  34954. goog.provide('ol.format.filter.ComparisonBinary');
  34955. goog.require('ol');
  34956. goog.require('ol.format.filter.Comparison');
  34957. /**
  34958. * @classdesc
  34959. * Abstract class; normally only used for creating subclasses and not instantiated in apps.
  34960. * Base class for WFS GetFeature property binary comparison filters.
  34961. *
  34962. * @constructor
  34963. * @param {!string} tagName The XML tag name for this filter.
  34964. * @param {!string} propertyName Name of the context property to compare.
  34965. * @param {!(string|number)} expression The value to compare.
  34966. * @param {boolean=} opt_matchCase Case-sensitive?
  34967. * @extends {ol.format.filter.Comparison}
  34968. * @api
  34969. */
  34970. ol.format.filter.ComparisonBinary = function(
  34971. tagName, propertyName, expression, opt_matchCase) {
  34972. ol.format.filter.Comparison.call(this, tagName, propertyName);
  34973. /**
  34974. * @public
  34975. * @type {!(string|number)}
  34976. */
  34977. this.expression = expression;
  34978. /**
  34979. * @public
  34980. * @type {boolean|undefined}
  34981. */
  34982. this.matchCase = opt_matchCase;
  34983. };
  34984. ol.inherits(ol.format.filter.ComparisonBinary, ol.format.filter.Comparison);
  34985. goog.provide('ol.format.filter.EqualTo');
  34986. goog.require('ol');
  34987. goog.require('ol.format.filter.ComparisonBinary');
  34988. /**
  34989. * @classdesc
  34990. * Represents a `<PropertyIsEqualTo>` comparison operator.
  34991. *
  34992. * @constructor
  34993. * @param {!string} propertyName Name of the context property to compare.
  34994. * @param {!(string|number)} expression The value to compare.
  34995. * @param {boolean=} opt_matchCase Case-sensitive?
  34996. * @extends {ol.format.filter.ComparisonBinary}
  34997. * @api
  34998. */
  34999. ol.format.filter.EqualTo = function(propertyName, expression, opt_matchCase) {
  35000. ol.format.filter.ComparisonBinary.call(this, 'PropertyIsEqualTo', propertyName, expression, opt_matchCase);
  35001. };
  35002. ol.inherits(ol.format.filter.EqualTo, ol.format.filter.ComparisonBinary);
  35003. goog.provide('ol.format.filter.GreaterThan');
  35004. goog.require('ol');
  35005. goog.require('ol.format.filter.ComparisonBinary');
  35006. /**
  35007. * @classdesc
  35008. * Represents a `<PropertyIsGreaterThan>` comparison operator.
  35009. *
  35010. * @constructor
  35011. * @param {!string} propertyName Name of the context property to compare.
  35012. * @param {!number} expression The value to compare.
  35013. * @extends {ol.format.filter.ComparisonBinary}
  35014. * @api
  35015. */
  35016. ol.format.filter.GreaterThan = function(propertyName, expression) {
  35017. ol.format.filter.ComparisonBinary.call(this, 'PropertyIsGreaterThan', propertyName, expression);
  35018. };
  35019. ol.inherits(ol.format.filter.GreaterThan, ol.format.filter.ComparisonBinary);
  35020. goog.provide('ol.format.filter.GreaterThanOrEqualTo');
  35021. goog.require('ol');
  35022. goog.require('ol.format.filter.ComparisonBinary');
  35023. /**
  35024. * @classdesc
  35025. * Represents a `<PropertyIsGreaterThanOrEqualTo>` comparison operator.
  35026. *
  35027. * @constructor
  35028. * @param {!string} propertyName Name of the context property to compare.
  35029. * @param {!number} expression The value to compare.
  35030. * @extends {ol.format.filter.ComparisonBinary}
  35031. * @api
  35032. */
  35033. ol.format.filter.GreaterThanOrEqualTo = function(propertyName, expression) {
  35034. ol.format.filter.ComparisonBinary.call(this, 'PropertyIsGreaterThanOrEqualTo', propertyName, expression);
  35035. };
  35036. ol.inherits(ol.format.filter.GreaterThanOrEqualTo, ol.format.filter.ComparisonBinary);
  35037. goog.provide('ol.format.filter.Spatial');
  35038. goog.require('ol');
  35039. goog.require('ol.format.filter.Filter');
  35040. /**
  35041. * @classdesc
  35042. * Represents a spatial operator to test whether a geometry-valued property
  35043. * relates to a given geometry.
  35044. *
  35045. * @constructor
  35046. * @param {!string} tagName The XML tag name for this filter.
  35047. * @param {!string} geometryName Geometry name to use.
  35048. * @param {!ol.geom.Geometry} geometry Geometry.
  35049. * @param {string=} opt_srsName SRS name. No srsName attribute will be
  35050. * set on geometries when this is not provided.
  35051. * @extends {ol.format.filter.Filter}
  35052. * @api
  35053. */
  35054. ol.format.filter.Spatial = function(tagName, geometryName, geometry, opt_srsName) {
  35055. ol.format.filter.Filter.call(this, tagName);
  35056. /**
  35057. * @public
  35058. * @type {!string}
  35059. */
  35060. this.geometryName = geometryName || 'the_geom';
  35061. /**
  35062. * @public
  35063. * @type {ol.geom.Geometry}
  35064. */
  35065. this.geometry = geometry;
  35066. /**
  35067. * @public
  35068. * @type {string|undefined}
  35069. */
  35070. this.srsName = opt_srsName;
  35071. };
  35072. ol.inherits(ol.format.filter.Spatial, ol.format.filter.Filter);
  35073. goog.provide('ol.format.filter.Intersects');
  35074. goog.require('ol');
  35075. goog.require('ol.format.filter.Spatial');
  35076. /**
  35077. * @classdesc
  35078. * Represents a `<Intersects>` operator to test whether a geometry-valued property
  35079. * intersects a given geometry.
  35080. *
  35081. * @constructor
  35082. * @param {!string} geometryName Geometry name to use.
  35083. * @param {!ol.geom.Geometry} geometry Geometry.
  35084. * @param {string=} opt_srsName SRS name. No srsName attribute will be
  35085. * set on geometries when this is not provided.
  35086. * @extends {ol.format.filter.Spatial}
  35087. * @api
  35088. */
  35089. ol.format.filter.Intersects = function(geometryName, geometry, opt_srsName) {
  35090. ol.format.filter.Spatial.call(this, 'Intersects', geometryName, geometry, opt_srsName);
  35091. };
  35092. ol.inherits(ol.format.filter.Intersects, ol.format.filter.Spatial);
  35093. goog.provide('ol.format.filter.IsBetween');
  35094. goog.require('ol');
  35095. goog.require('ol.format.filter.Comparison');
  35096. /**
  35097. * @classdesc
  35098. * Represents a `<PropertyIsBetween>` comparison operator.
  35099. *
  35100. * @constructor
  35101. * @param {!string} propertyName Name of the context property to compare.
  35102. * @param {!number} lowerBoundary The lower bound of the range.
  35103. * @param {!number} upperBoundary The upper bound of the range.
  35104. * @extends {ol.format.filter.Comparison}
  35105. * @api
  35106. */
  35107. ol.format.filter.IsBetween = function(propertyName, lowerBoundary, upperBoundary) {
  35108. ol.format.filter.Comparison.call(this, 'PropertyIsBetween', propertyName);
  35109. /**
  35110. * @public
  35111. * @type {!number}
  35112. */
  35113. this.lowerBoundary = lowerBoundary;
  35114. /**
  35115. * @public
  35116. * @type {!number}
  35117. */
  35118. this.upperBoundary = upperBoundary;
  35119. };
  35120. ol.inherits(ol.format.filter.IsBetween, ol.format.filter.Comparison);
  35121. goog.provide('ol.format.filter.IsLike');
  35122. goog.require('ol');
  35123. goog.require('ol.format.filter.Comparison');
  35124. /**
  35125. * @classdesc
  35126. * Represents a `<PropertyIsLike>` comparison operator.
  35127. *
  35128. * @constructor
  35129. * @param {!string} propertyName Name of the context property to compare.
  35130. * @param {!string} pattern Text pattern.
  35131. * @param {string=} opt_wildCard Pattern character which matches any sequence of
  35132. * zero or more string characters. Default is '*'.
  35133. * @param {string=} opt_singleChar pattern character which matches any single
  35134. * string character. Default is '.'.
  35135. * @param {string=} opt_escapeChar Escape character which can be used to escape
  35136. * the pattern characters. Default is '!'.
  35137. * @param {boolean=} opt_matchCase Case-sensitive?
  35138. * @extends {ol.format.filter.Comparison}
  35139. * @api
  35140. */
  35141. ol.format.filter.IsLike = function(propertyName, pattern,
  35142. opt_wildCard, opt_singleChar, opt_escapeChar, opt_matchCase) {
  35143. ol.format.filter.Comparison.call(this, 'PropertyIsLike', propertyName);
  35144. /**
  35145. * @public
  35146. * @type {!string}
  35147. */
  35148. this.pattern = pattern;
  35149. /**
  35150. * @public
  35151. * @type {!string}
  35152. */
  35153. this.wildCard = (opt_wildCard !== undefined) ? opt_wildCard : '*';
  35154. /**
  35155. * @public
  35156. * @type {!string}
  35157. */
  35158. this.singleChar = (opt_singleChar !== undefined) ? opt_singleChar : '.';
  35159. /**
  35160. * @public
  35161. * @type {!string}
  35162. */
  35163. this.escapeChar = (opt_escapeChar !== undefined) ? opt_escapeChar : '!';
  35164. /**
  35165. * @public
  35166. * @type {boolean|undefined}
  35167. */
  35168. this.matchCase = opt_matchCase;
  35169. };
  35170. ol.inherits(ol.format.filter.IsLike, ol.format.filter.Comparison);
  35171. goog.provide('ol.format.filter.IsNull');
  35172. goog.require('ol');
  35173. goog.require('ol.format.filter.Comparison');
  35174. /**
  35175. * @classdesc
  35176. * Represents a `<PropertyIsNull>` comparison operator.
  35177. *
  35178. * @constructor
  35179. * @param {!string} propertyName Name of the context property to compare.
  35180. * @extends {ol.format.filter.Comparison}
  35181. * @api
  35182. */
  35183. ol.format.filter.IsNull = function(propertyName) {
  35184. ol.format.filter.Comparison.call(this, 'PropertyIsNull', propertyName);
  35185. };
  35186. ol.inherits(ol.format.filter.IsNull, ol.format.filter.Comparison);
  35187. goog.provide('ol.format.filter.LessThan');
  35188. goog.require('ol');
  35189. goog.require('ol.format.filter.ComparisonBinary');
  35190. /**
  35191. * @classdesc
  35192. * Represents a `<PropertyIsLessThan>` comparison operator.
  35193. *
  35194. * @constructor
  35195. * @param {!string} propertyName Name of the context property to compare.
  35196. * @param {!number} expression The value to compare.
  35197. * @extends {ol.format.filter.ComparisonBinary}
  35198. * @api
  35199. */
  35200. ol.format.filter.LessThan = function(propertyName, expression) {
  35201. ol.format.filter.ComparisonBinary.call(this, 'PropertyIsLessThan', propertyName, expression);
  35202. };
  35203. ol.inherits(ol.format.filter.LessThan, ol.format.filter.ComparisonBinary);
  35204. goog.provide('ol.format.filter.LessThanOrEqualTo');
  35205. goog.require('ol');
  35206. goog.require('ol.format.filter.ComparisonBinary');
  35207. /**
  35208. * @classdesc
  35209. * Represents a `<PropertyIsLessThanOrEqualTo>` comparison operator.
  35210. *
  35211. * @constructor
  35212. * @param {!string} propertyName Name of the context property to compare.
  35213. * @param {!number} expression The value to compare.
  35214. * @extends {ol.format.filter.ComparisonBinary}
  35215. * @api
  35216. */
  35217. ol.format.filter.LessThanOrEqualTo = function(propertyName, expression) {
  35218. ol.format.filter.ComparisonBinary.call(this, 'PropertyIsLessThanOrEqualTo', propertyName, expression);
  35219. };
  35220. ol.inherits(ol.format.filter.LessThanOrEqualTo, ol.format.filter.ComparisonBinary);
  35221. goog.provide('ol.format.filter.Not');
  35222. goog.require('ol');
  35223. goog.require('ol.format.filter.Filter');
  35224. /**
  35225. * @classdesc
  35226. * Represents a logical `<Not>` operator for a filter condition.
  35227. *
  35228. * @constructor
  35229. * @param {!ol.format.filter.Filter} condition Filter condition.
  35230. * @extends {ol.format.filter.Filter}
  35231. * @api
  35232. */
  35233. ol.format.filter.Not = function(condition) {
  35234. ol.format.filter.Filter.call(this, 'Not');
  35235. /**
  35236. * @public
  35237. * @type {!ol.format.filter.Filter}
  35238. */
  35239. this.condition = condition;
  35240. };
  35241. ol.inherits(ol.format.filter.Not, ol.format.filter.Filter);
  35242. goog.provide('ol.format.filter.NotEqualTo');
  35243. goog.require('ol');
  35244. goog.require('ol.format.filter.ComparisonBinary');
  35245. /**
  35246. * @classdesc
  35247. * Represents a `<PropertyIsNotEqualTo>` comparison operator.
  35248. *
  35249. * @constructor
  35250. * @param {!string} propertyName Name of the context property to compare.
  35251. * @param {!(string|number)} expression The value to compare.
  35252. * @param {boolean=} opt_matchCase Case-sensitive?
  35253. * @extends {ol.format.filter.ComparisonBinary}
  35254. * @api
  35255. */
  35256. ol.format.filter.NotEqualTo = function(propertyName, expression, opt_matchCase) {
  35257. ol.format.filter.ComparisonBinary.call(this, 'PropertyIsNotEqualTo', propertyName, expression, opt_matchCase);
  35258. };
  35259. ol.inherits(ol.format.filter.NotEqualTo, ol.format.filter.ComparisonBinary);
  35260. goog.provide('ol.format.filter.Or');
  35261. goog.require('ol');
  35262. goog.require('ol.format.filter.LogicalNary');
  35263. /**
  35264. * @classdesc
  35265. * Represents a logical `<Or>` operator between two ore more filter conditions.
  35266. *
  35267. * @constructor
  35268. * @param {...ol.format.filter.Filter} conditions Conditions.
  35269. * @extends {ol.format.filter.LogicalNary}
  35270. * @api
  35271. */
  35272. ol.format.filter.Or = function(conditions) {
  35273. var params = ['Or'].concat(Array.prototype.slice.call(arguments));
  35274. ol.format.filter.LogicalNary.apply(this, params);
  35275. };
  35276. ol.inherits(ol.format.filter.Or, ol.format.filter.LogicalNary);
  35277. goog.provide('ol.format.filter.Within');
  35278. goog.require('ol');
  35279. goog.require('ol.format.filter.Spatial');
  35280. /**
  35281. * @classdesc
  35282. * Represents a `<Within>` operator to test whether a geometry-valued property
  35283. * is within a given geometry.
  35284. *
  35285. * @constructor
  35286. * @param {!string} geometryName Geometry name to use.
  35287. * @param {!ol.geom.Geometry} geometry Geometry.
  35288. * @param {string=} opt_srsName SRS name. No srsName attribute will be
  35289. * set on geometries when this is not provided.
  35290. * @extends {ol.format.filter.Spatial}
  35291. * @api
  35292. */
  35293. ol.format.filter.Within = function(geometryName, geometry, opt_srsName) {
  35294. ol.format.filter.Spatial.call(this, 'Within', geometryName, geometry, opt_srsName);
  35295. };
  35296. ol.inherits(ol.format.filter.Within, ol.format.filter.Spatial);
  35297. goog.provide('ol.format.filter');
  35298. goog.require('ol.format.filter.And');
  35299. goog.require('ol.format.filter.Bbox');
  35300. goog.require('ol.format.filter.During');
  35301. goog.require('ol.format.filter.EqualTo');
  35302. goog.require('ol.format.filter.GreaterThan');
  35303. goog.require('ol.format.filter.GreaterThanOrEqualTo');
  35304. goog.require('ol.format.filter.Intersects');
  35305. goog.require('ol.format.filter.IsBetween');
  35306. goog.require('ol.format.filter.IsLike');
  35307. goog.require('ol.format.filter.IsNull');
  35308. goog.require('ol.format.filter.LessThan');
  35309. goog.require('ol.format.filter.LessThanOrEqualTo');
  35310. goog.require('ol.format.filter.Not');
  35311. goog.require('ol.format.filter.NotEqualTo');
  35312. goog.require('ol.format.filter.Or');
  35313. goog.require('ol.format.filter.Within');
  35314. /**
  35315. * Create a logical `<And>` operator between two or more filter conditions.
  35316. *
  35317. * @param {...ol.format.filter.Filter} conditions Filter conditions.
  35318. * @returns {!ol.format.filter.And} `<And>` operator.
  35319. * @api
  35320. */
  35321. ol.format.filter.and = function(conditions) {
  35322. var params = [null].concat(Array.prototype.slice.call(arguments));
  35323. return new (Function.prototype.bind.apply(ol.format.filter.And, params));
  35324. };
  35325. /**
  35326. * Create a logical `<Or>` operator between two or more filter conditions.
  35327. *
  35328. * @param {...ol.format.filter.Filter} conditions Filter conditions.
  35329. * @returns {!ol.format.filter.Or} `<Or>` operator.
  35330. * @api
  35331. */
  35332. ol.format.filter.or = function(conditions) {
  35333. var params = [null].concat(Array.prototype.slice.call(arguments));
  35334. return new (Function.prototype.bind.apply(ol.format.filter.Or, params));
  35335. };
  35336. /**
  35337. * Represents a logical `<Not>` operator for a filter condition.
  35338. *
  35339. * @param {!ol.format.filter.Filter} condition Filter condition.
  35340. * @returns {!ol.format.filter.Not} `<Not>` operator.
  35341. * @api
  35342. */
  35343. ol.format.filter.not = function(condition) {
  35344. return new ol.format.filter.Not(condition);
  35345. };
  35346. /**
  35347. * Create a `<BBOX>` operator to test whether a geometry-valued property
  35348. * intersects a fixed bounding box
  35349. *
  35350. * @param {!string} geometryName Geometry name to use.
  35351. * @param {!ol.Extent} extent Extent.
  35352. * @param {string=} opt_srsName SRS name. No srsName attribute will be
  35353. * set on geometries when this is not provided.
  35354. * @returns {!ol.format.filter.Bbox} `<BBOX>` operator.
  35355. * @api
  35356. */
  35357. ol.format.filter.bbox = function(geometryName, extent, opt_srsName) {
  35358. return new ol.format.filter.Bbox(geometryName, extent, opt_srsName);
  35359. };
  35360. /**
  35361. * Create a `<Intersects>` operator to test whether a geometry-valued property
  35362. * intersects a given geometry.
  35363. *
  35364. * @param {!string} geometryName Geometry name to use.
  35365. * @param {!ol.geom.Geometry} geometry Geometry.
  35366. * @param {string=} opt_srsName SRS name. No srsName attribute will be
  35367. * set on geometries when this is not provided.
  35368. * @returns {!ol.format.filter.Intersects} `<Intersects>` operator.
  35369. * @api
  35370. */
  35371. ol.format.filter.intersects = function(geometryName, geometry, opt_srsName) {
  35372. return new ol.format.filter.Intersects(geometryName, geometry, opt_srsName);
  35373. };
  35374. /**
  35375. * Create a `<Within>` operator to test whether a geometry-valued property
  35376. * is within a given geometry.
  35377. *
  35378. * @param {!string} geometryName Geometry name to use.
  35379. * @param {!ol.geom.Geometry} geometry Geometry.
  35380. * @param {string=} opt_srsName SRS name. No srsName attribute will be
  35381. * set on geometries when this is not provided.
  35382. * @returns {!ol.format.filter.Within} `<Within>` operator.
  35383. * @api
  35384. */
  35385. ol.format.filter.within = function(geometryName, geometry, opt_srsName) {
  35386. return new ol.format.filter.Within(geometryName, geometry, opt_srsName);
  35387. };
  35388. /**
  35389. * Creates a `<PropertyIsEqualTo>` comparison operator.
  35390. *
  35391. * @param {!string} propertyName Name of the context property to compare.
  35392. * @param {!(string|number)} expression The value to compare.
  35393. * @param {boolean=} opt_matchCase Case-sensitive?
  35394. * @returns {!ol.format.filter.EqualTo} `<PropertyIsEqualTo>` operator.
  35395. * @api
  35396. */
  35397. ol.format.filter.equalTo = function(propertyName, expression, opt_matchCase) {
  35398. return new ol.format.filter.EqualTo(propertyName, expression, opt_matchCase);
  35399. };
  35400. /**
  35401. * Creates a `<PropertyIsNotEqualTo>` comparison operator.
  35402. *
  35403. * @param {!string} propertyName Name of the context property to compare.
  35404. * @param {!(string|number)} expression The value to compare.
  35405. * @param {boolean=} opt_matchCase Case-sensitive?
  35406. * @returns {!ol.format.filter.NotEqualTo} `<PropertyIsNotEqualTo>` operator.
  35407. * @api
  35408. */
  35409. ol.format.filter.notEqualTo = function(propertyName, expression, opt_matchCase) {
  35410. return new ol.format.filter.NotEqualTo(propertyName, expression, opt_matchCase);
  35411. };
  35412. /**
  35413. * Creates a `<PropertyIsLessThan>` comparison operator.
  35414. *
  35415. * @param {!string} propertyName Name of the context property to compare.
  35416. * @param {!number} expression The value to compare.
  35417. * @returns {!ol.format.filter.LessThan} `<PropertyIsLessThan>` operator.
  35418. * @api
  35419. */
  35420. ol.format.filter.lessThan = function(propertyName, expression) {
  35421. return new ol.format.filter.LessThan(propertyName, expression);
  35422. };
  35423. /**
  35424. * Creates a `<PropertyIsLessThanOrEqualTo>` comparison operator.
  35425. *
  35426. * @param {!string} propertyName Name of the context property to compare.
  35427. * @param {!number} expression The value to compare.
  35428. * @returns {!ol.format.filter.LessThanOrEqualTo} `<PropertyIsLessThanOrEqualTo>` operator.
  35429. * @api
  35430. */
  35431. ol.format.filter.lessThanOrEqualTo = function(propertyName, expression) {
  35432. return new ol.format.filter.LessThanOrEqualTo(propertyName, expression);
  35433. };
  35434. /**
  35435. * Creates a `<PropertyIsGreaterThan>` comparison operator.
  35436. *
  35437. * @param {!string} propertyName Name of the context property to compare.
  35438. * @param {!number} expression The value to compare.
  35439. * @returns {!ol.format.filter.GreaterThan} `<PropertyIsGreaterThan>` operator.
  35440. * @api
  35441. */
  35442. ol.format.filter.greaterThan = function(propertyName, expression) {
  35443. return new ol.format.filter.GreaterThan(propertyName, expression);
  35444. };
  35445. /**
  35446. * Creates a `<PropertyIsGreaterThanOrEqualTo>` comparison operator.
  35447. *
  35448. * @param {!string} propertyName Name of the context property to compare.
  35449. * @param {!number} expression The value to compare.
  35450. * @returns {!ol.format.filter.GreaterThanOrEqualTo} `<PropertyIsGreaterThanOrEqualTo>` operator.
  35451. * @api
  35452. */
  35453. ol.format.filter.greaterThanOrEqualTo = function(propertyName, expression) {
  35454. return new ol.format.filter.GreaterThanOrEqualTo(propertyName, expression);
  35455. };
  35456. /**
  35457. * Creates a `<PropertyIsNull>` comparison operator to test whether a property value
  35458. * is null.
  35459. *
  35460. * @param {!string} propertyName Name of the context property to compare.
  35461. * @returns {!ol.format.filter.IsNull} `<PropertyIsNull>` operator.
  35462. * @api
  35463. */
  35464. ol.format.filter.isNull = function(propertyName) {
  35465. return new ol.format.filter.IsNull(propertyName);
  35466. };
  35467. /**
  35468. * Creates a `<PropertyIsBetween>` comparison operator to test whether an expression
  35469. * value lies within a range given by a lower and upper bound (inclusive).
  35470. *
  35471. * @param {!string} propertyName Name of the context property to compare.
  35472. * @param {!number} lowerBoundary The lower bound of the range.
  35473. * @param {!number} upperBoundary The upper bound of the range.
  35474. * @returns {!ol.format.filter.IsBetween} `<PropertyIsBetween>` operator.
  35475. * @api
  35476. */
  35477. ol.format.filter.between = function(propertyName, lowerBoundary, upperBoundary) {
  35478. return new ol.format.filter.IsBetween(propertyName, lowerBoundary, upperBoundary);
  35479. };
  35480. /**
  35481. * Represents a `<PropertyIsLike>` comparison operator that matches a string property
  35482. * value against a text pattern.
  35483. *
  35484. * @param {!string} propertyName Name of the context property to compare.
  35485. * @param {!string} pattern Text pattern.
  35486. * @param {string=} opt_wildCard Pattern character which matches any sequence of
  35487. * zero or more string characters. Default is '*'.
  35488. * @param {string=} opt_singleChar pattern character which matches any single
  35489. * string character. Default is '.'.
  35490. * @param {string=} opt_escapeChar Escape character which can be used to escape
  35491. * the pattern characters. Default is '!'.
  35492. * @param {boolean=} opt_matchCase Case-sensitive?
  35493. * @returns {!ol.format.filter.IsLike} `<PropertyIsLike>` operator.
  35494. * @api
  35495. */
  35496. ol.format.filter.like = function(propertyName, pattern,
  35497. opt_wildCard, opt_singleChar, opt_escapeChar, opt_matchCase) {
  35498. return new ol.format.filter.IsLike(propertyName, pattern,
  35499. opt_wildCard, opt_singleChar, opt_escapeChar, opt_matchCase);
  35500. };
  35501. /**
  35502. * Create a `<During>` temporal operator.
  35503. *
  35504. * @param {!string} propertyName Name of the context property to compare.
  35505. * @param {!string} begin The begin date in ISO-8601 format.
  35506. * @param {!string} end The end date in ISO-8601 format.
  35507. * @returns {!ol.format.filter.During} `<During>` operator.
  35508. * @api
  35509. */
  35510. ol.format.filter.during = function(propertyName, begin, end) {
  35511. return new ol.format.filter.During(propertyName, begin, end);
  35512. };
  35513. goog.provide('ol.geom.GeometryCollection');
  35514. goog.require('ol');
  35515. goog.require('ol.events');
  35516. goog.require('ol.events.EventType');
  35517. goog.require('ol.extent');
  35518. goog.require('ol.geom.Geometry');
  35519. goog.require('ol.geom.GeometryType');
  35520. goog.require('ol.obj');
  35521. /**
  35522. * @classdesc
  35523. * An array of {@link ol.geom.Geometry} objects.
  35524. *
  35525. * @constructor
  35526. * @extends {ol.geom.Geometry}
  35527. * @param {Array.<ol.geom.Geometry>=} opt_geometries Geometries.
  35528. * @api
  35529. */
  35530. ol.geom.GeometryCollection = function(opt_geometries) {
  35531. ol.geom.Geometry.call(this);
  35532. /**
  35533. * @private
  35534. * @type {Array.<ol.geom.Geometry>}
  35535. */
  35536. this.geometries_ = opt_geometries ? opt_geometries : null;
  35537. this.listenGeometriesChange_();
  35538. };
  35539. ol.inherits(ol.geom.GeometryCollection, ol.geom.Geometry);
  35540. /**
  35541. * @param {Array.<ol.geom.Geometry>} geometries Geometries.
  35542. * @private
  35543. * @return {Array.<ol.geom.Geometry>} Cloned geometries.
  35544. */
  35545. ol.geom.GeometryCollection.cloneGeometries_ = function(geometries) {
  35546. var clonedGeometries = [];
  35547. var i, ii;
  35548. for (i = 0, ii = geometries.length; i < ii; ++i) {
  35549. clonedGeometries.push(geometries[i].clone());
  35550. }
  35551. return clonedGeometries;
  35552. };
  35553. /**
  35554. * @private
  35555. */
  35556. ol.geom.GeometryCollection.prototype.unlistenGeometriesChange_ = function() {
  35557. var i, ii;
  35558. if (!this.geometries_) {
  35559. return;
  35560. }
  35561. for (i = 0, ii = this.geometries_.length; i < ii; ++i) {
  35562. ol.events.unlisten(
  35563. this.geometries_[i], ol.events.EventType.CHANGE,
  35564. this.changed, this);
  35565. }
  35566. };
  35567. /**
  35568. * @private
  35569. */
  35570. ol.geom.GeometryCollection.prototype.listenGeometriesChange_ = function() {
  35571. var i, ii;
  35572. if (!this.geometries_) {
  35573. return;
  35574. }
  35575. for (i = 0, ii = this.geometries_.length; i < ii; ++i) {
  35576. ol.events.listen(
  35577. this.geometries_[i], ol.events.EventType.CHANGE,
  35578. this.changed, this);
  35579. }
  35580. };
  35581. /**
  35582. * Make a complete copy of the geometry.
  35583. * @return {!ol.geom.GeometryCollection} Clone.
  35584. * @override
  35585. * @api
  35586. */
  35587. ol.geom.GeometryCollection.prototype.clone = function() {
  35588. var geometryCollection = new ol.geom.GeometryCollection(null);
  35589. geometryCollection.setGeometries(this.geometries_);
  35590. return geometryCollection;
  35591. };
  35592. /**
  35593. * @inheritDoc
  35594. */
  35595. ol.geom.GeometryCollection.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  35596. if (minSquaredDistance <
  35597. ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
  35598. return minSquaredDistance;
  35599. }
  35600. var geometries = this.geometries_;
  35601. var i, ii;
  35602. for (i = 0, ii = geometries.length; i < ii; ++i) {
  35603. minSquaredDistance = geometries[i].closestPointXY(
  35604. x, y, closestPoint, minSquaredDistance);
  35605. }
  35606. return minSquaredDistance;
  35607. };
  35608. /**
  35609. * @inheritDoc
  35610. */
  35611. ol.geom.GeometryCollection.prototype.containsXY = function(x, y) {
  35612. var geometries = this.geometries_;
  35613. var i, ii;
  35614. for (i = 0, ii = geometries.length; i < ii; ++i) {
  35615. if (geometries[i].containsXY(x, y)) {
  35616. return true;
  35617. }
  35618. }
  35619. return false;
  35620. };
  35621. /**
  35622. * @inheritDoc
  35623. */
  35624. ol.geom.GeometryCollection.prototype.computeExtent = function(extent) {
  35625. ol.extent.createOrUpdateEmpty(extent);
  35626. var geometries = this.geometries_;
  35627. for (var i = 0, ii = geometries.length; i < ii; ++i) {
  35628. ol.extent.extend(extent, geometries[i].getExtent());
  35629. }
  35630. return extent;
  35631. };
  35632. /**
  35633. * Return the geometries that make up this geometry collection.
  35634. * @return {Array.<ol.geom.Geometry>} Geometries.
  35635. * @api
  35636. */
  35637. ol.geom.GeometryCollection.prototype.getGeometries = function() {
  35638. return ol.geom.GeometryCollection.cloneGeometries_(this.geometries_);
  35639. };
  35640. /**
  35641. * @return {Array.<ol.geom.Geometry>} Geometries.
  35642. */
  35643. ol.geom.GeometryCollection.prototype.getGeometriesArray = function() {
  35644. return this.geometries_;
  35645. };
  35646. /**
  35647. * @inheritDoc
  35648. */
  35649. ol.geom.GeometryCollection.prototype.getSimplifiedGeometry = function(squaredTolerance) {
  35650. if (this.simplifiedGeometryRevision != this.getRevision()) {
  35651. ol.obj.clear(this.simplifiedGeometryCache);
  35652. this.simplifiedGeometryMaxMinSquaredTolerance = 0;
  35653. this.simplifiedGeometryRevision = this.getRevision();
  35654. }
  35655. if (squaredTolerance < 0 ||
  35656. (this.simplifiedGeometryMaxMinSquaredTolerance !== 0 &&
  35657. squaredTolerance < this.simplifiedGeometryMaxMinSquaredTolerance)) {
  35658. return this;
  35659. }
  35660. var key = squaredTolerance.toString();
  35661. if (this.simplifiedGeometryCache.hasOwnProperty(key)) {
  35662. return this.simplifiedGeometryCache[key];
  35663. } else {
  35664. var simplifiedGeometries = [];
  35665. var geometries = this.geometries_;
  35666. var simplified = false;
  35667. var i, ii;
  35668. for (i = 0, ii = geometries.length; i < ii; ++i) {
  35669. var geometry = geometries[i];
  35670. var simplifiedGeometry = geometry.getSimplifiedGeometry(squaredTolerance);
  35671. simplifiedGeometries.push(simplifiedGeometry);
  35672. if (simplifiedGeometry !== geometry) {
  35673. simplified = true;
  35674. }
  35675. }
  35676. if (simplified) {
  35677. var simplifiedGeometryCollection = new ol.geom.GeometryCollection(null);
  35678. simplifiedGeometryCollection.setGeometriesArray(simplifiedGeometries);
  35679. this.simplifiedGeometryCache[key] = simplifiedGeometryCollection;
  35680. return simplifiedGeometryCollection;
  35681. } else {
  35682. this.simplifiedGeometryMaxMinSquaredTolerance = squaredTolerance;
  35683. return this;
  35684. }
  35685. }
  35686. };
  35687. /**
  35688. * @inheritDoc
  35689. * @api
  35690. */
  35691. ol.geom.GeometryCollection.prototype.getType = function() {
  35692. return ol.geom.GeometryType.GEOMETRY_COLLECTION;
  35693. };
  35694. /**
  35695. * @inheritDoc
  35696. * @api
  35697. */
  35698. ol.geom.GeometryCollection.prototype.intersectsExtent = function(extent) {
  35699. var geometries = this.geometries_;
  35700. var i, ii;
  35701. for (i = 0, ii = geometries.length; i < ii; ++i) {
  35702. if (geometries[i].intersectsExtent(extent)) {
  35703. return true;
  35704. }
  35705. }
  35706. return false;
  35707. };
  35708. /**
  35709. * @return {boolean} Is empty.
  35710. */
  35711. ol.geom.GeometryCollection.prototype.isEmpty = function() {
  35712. return this.geometries_.length === 0;
  35713. };
  35714. /**
  35715. * @inheritDoc
  35716. * @api
  35717. */
  35718. ol.geom.GeometryCollection.prototype.rotate = function(angle, anchor) {
  35719. var geometries = this.geometries_;
  35720. for (var i = 0, ii = geometries.length; i < ii; ++i) {
  35721. geometries[i].rotate(angle, anchor);
  35722. }
  35723. this.changed();
  35724. };
  35725. /**
  35726. * @inheritDoc
  35727. * @api
  35728. */
  35729. ol.geom.GeometryCollection.prototype.scale = function(sx, opt_sy, opt_anchor) {
  35730. var anchor = opt_anchor;
  35731. if (!anchor) {
  35732. anchor = ol.extent.getCenter(this.getExtent());
  35733. }
  35734. var geometries = this.geometries_;
  35735. for (var i = 0, ii = geometries.length; i < ii; ++i) {
  35736. geometries[i].scale(sx, opt_sy, anchor);
  35737. }
  35738. this.changed();
  35739. };
  35740. /**
  35741. * Set the geometries that make up this geometry collection.
  35742. * @param {Array.<ol.geom.Geometry>} geometries Geometries.
  35743. * @api
  35744. */
  35745. ol.geom.GeometryCollection.prototype.setGeometries = function(geometries) {
  35746. this.setGeometriesArray(
  35747. ol.geom.GeometryCollection.cloneGeometries_(geometries));
  35748. };
  35749. /**
  35750. * @param {Array.<ol.geom.Geometry>} geometries Geometries.
  35751. */
  35752. ol.geom.GeometryCollection.prototype.setGeometriesArray = function(geometries) {
  35753. this.unlistenGeometriesChange_();
  35754. this.geometries_ = geometries;
  35755. this.listenGeometriesChange_();
  35756. this.changed();
  35757. };
  35758. /**
  35759. * @inheritDoc
  35760. * @api
  35761. */
  35762. ol.geom.GeometryCollection.prototype.applyTransform = function(transformFn) {
  35763. var geometries = this.geometries_;
  35764. var i, ii;
  35765. for (i = 0, ii = geometries.length; i < ii; ++i) {
  35766. geometries[i].applyTransform(transformFn);
  35767. }
  35768. this.changed();
  35769. };
  35770. /**
  35771. * Translate the geometry.
  35772. * @param {number} deltaX Delta X.
  35773. * @param {number} deltaY Delta Y.
  35774. * @override
  35775. * @api
  35776. */
  35777. ol.geom.GeometryCollection.prototype.translate = function(deltaX, deltaY) {
  35778. var geometries = this.geometries_;
  35779. var i, ii;
  35780. for (i = 0, ii = geometries.length; i < ii; ++i) {
  35781. geometries[i].translate(deltaX, deltaY);
  35782. }
  35783. this.changed();
  35784. };
  35785. /**
  35786. * @inheritDoc
  35787. */
  35788. ol.geom.GeometryCollection.prototype.disposeInternal = function() {
  35789. this.unlistenGeometriesChange_();
  35790. ol.geom.Geometry.prototype.disposeInternal.call(this);
  35791. };
  35792. // TODO: serialize dataProjection as crs member when writing
  35793. // see https://github.com/openlayers/openlayers/issues/2078
  35794. goog.provide('ol.format.GeoJSON');
  35795. goog.require('ol');
  35796. goog.require('ol.asserts');
  35797. goog.require('ol.Feature');
  35798. goog.require('ol.format.Feature');
  35799. goog.require('ol.format.JSONFeature');
  35800. goog.require('ol.geom.GeometryCollection');
  35801. goog.require('ol.geom.LineString');
  35802. goog.require('ol.geom.MultiLineString');
  35803. goog.require('ol.geom.MultiPoint');
  35804. goog.require('ol.geom.MultiPolygon');
  35805. goog.require('ol.geom.Point');
  35806. goog.require('ol.geom.Polygon');
  35807. goog.require('ol.obj');
  35808. goog.require('ol.proj');
  35809. /**
  35810. * @classdesc
  35811. * Feature format for reading and writing data in the GeoJSON format.
  35812. *
  35813. * @constructor
  35814. * @extends {ol.format.JSONFeature}
  35815. * @param {olx.format.GeoJSONOptions=} opt_options Options.
  35816. * @api
  35817. */
  35818. ol.format.GeoJSON = function(opt_options) {
  35819. var options = opt_options ? opt_options : {};
  35820. ol.format.JSONFeature.call(this);
  35821. /**
  35822. * @inheritDoc
  35823. */
  35824. this.defaultDataProjection = ol.proj.get(
  35825. options.defaultDataProjection ?
  35826. options.defaultDataProjection : 'EPSG:4326');
  35827. if (options.featureProjection) {
  35828. this.defaultFeatureProjection = ol.proj.get(options.featureProjection);
  35829. }
  35830. /**
  35831. * Name of the geometry attribute for features.
  35832. * @type {string|undefined}
  35833. * @private
  35834. */
  35835. this.geometryName_ = options.geometryName;
  35836. };
  35837. ol.inherits(ol.format.GeoJSON, ol.format.JSONFeature);
  35838. /**
  35839. * @param {GeoJSONGeometry|GeoJSONGeometryCollection} object Object.
  35840. * @param {olx.format.ReadOptions=} opt_options Read options.
  35841. * @private
  35842. * @return {ol.geom.Geometry} Geometry.
  35843. */
  35844. ol.format.GeoJSON.readGeometry_ = function(object, opt_options) {
  35845. if (!object) {
  35846. return null;
  35847. }
  35848. var geometryReader = ol.format.GeoJSON.GEOMETRY_READERS_[object.type];
  35849. return /** @type {ol.geom.Geometry} */ (
  35850. ol.format.Feature.transformWithOptions(
  35851. geometryReader(object), false, opt_options));
  35852. };
  35853. /**
  35854. * @param {GeoJSONGeometryCollection} object Object.
  35855. * @param {olx.format.ReadOptions=} opt_options Read options.
  35856. * @private
  35857. * @return {ol.geom.GeometryCollection} Geometry collection.
  35858. */
  35859. ol.format.GeoJSON.readGeometryCollectionGeometry_ = function(
  35860. object, opt_options) {
  35861. var geometries = object.geometries.map(
  35862. /**
  35863. * @param {GeoJSONGeometry} geometry Geometry.
  35864. * @return {ol.geom.Geometry} geometry Geometry.
  35865. */
  35866. function(geometry) {
  35867. return ol.format.GeoJSON.readGeometry_(geometry, opt_options);
  35868. });
  35869. return new ol.geom.GeometryCollection(geometries);
  35870. };
  35871. /**
  35872. * @param {GeoJSONGeometry} object Object.
  35873. * @private
  35874. * @return {ol.geom.Point} Point.
  35875. */
  35876. ol.format.GeoJSON.readPointGeometry_ = function(object) {
  35877. return new ol.geom.Point(object.coordinates);
  35878. };
  35879. /**
  35880. * @param {GeoJSONGeometry} object Object.
  35881. * @private
  35882. * @return {ol.geom.LineString} LineString.
  35883. */
  35884. ol.format.GeoJSON.readLineStringGeometry_ = function(object) {
  35885. return new ol.geom.LineString(object.coordinates);
  35886. };
  35887. /**
  35888. * @param {GeoJSONGeometry} object Object.
  35889. * @private
  35890. * @return {ol.geom.MultiLineString} MultiLineString.
  35891. */
  35892. ol.format.GeoJSON.readMultiLineStringGeometry_ = function(object) {
  35893. return new ol.geom.MultiLineString(object.coordinates);
  35894. };
  35895. /**
  35896. * @param {GeoJSONGeometry} object Object.
  35897. * @private
  35898. * @return {ol.geom.MultiPoint} MultiPoint.
  35899. */
  35900. ol.format.GeoJSON.readMultiPointGeometry_ = function(object) {
  35901. return new ol.geom.MultiPoint(object.coordinates);
  35902. };
  35903. /**
  35904. * @param {GeoJSONGeometry} object Object.
  35905. * @private
  35906. * @return {ol.geom.MultiPolygon} MultiPolygon.
  35907. */
  35908. ol.format.GeoJSON.readMultiPolygonGeometry_ = function(object) {
  35909. return new ol.geom.MultiPolygon(object.coordinates);
  35910. };
  35911. /**
  35912. * @param {GeoJSONGeometry} object Object.
  35913. * @private
  35914. * @return {ol.geom.Polygon} Polygon.
  35915. */
  35916. ol.format.GeoJSON.readPolygonGeometry_ = function(object) {
  35917. return new ol.geom.Polygon(object.coordinates);
  35918. };
  35919. /**
  35920. * @param {ol.geom.Geometry} geometry Geometry.
  35921. * @param {olx.format.WriteOptions=} opt_options Write options.
  35922. * @private
  35923. * @return {GeoJSONGeometry|GeoJSONGeometryCollection} GeoJSON geometry.
  35924. */
  35925. ol.format.GeoJSON.writeGeometry_ = function(geometry, opt_options) {
  35926. var geometryWriter = ol.format.GeoJSON.GEOMETRY_WRITERS_[geometry.getType()];
  35927. return geometryWriter(/** @type {ol.geom.Geometry} */ (
  35928. ol.format.Feature.transformWithOptions(geometry, true, opt_options)),
  35929. opt_options);
  35930. };
  35931. /**
  35932. * @param {ol.geom.Geometry} geometry Geometry.
  35933. * @private
  35934. * @return {GeoJSONGeometryCollection} Empty GeoJSON geometry collection.
  35935. */
  35936. ol.format.GeoJSON.writeEmptyGeometryCollectionGeometry_ = function(geometry) {
  35937. return /** @type {GeoJSONGeometryCollection} */ ({
  35938. type: 'GeometryCollection',
  35939. geometries: []
  35940. });
  35941. };
  35942. /**
  35943. * @param {ol.geom.GeometryCollection} geometry Geometry.
  35944. * @param {olx.format.WriteOptions=} opt_options Write options.
  35945. * @private
  35946. * @return {GeoJSONGeometryCollection} GeoJSON geometry collection.
  35947. */
  35948. ol.format.GeoJSON.writeGeometryCollectionGeometry_ = function(
  35949. geometry, opt_options) {
  35950. var geometries = geometry.getGeometriesArray().map(function(geometry) {
  35951. var options = ol.obj.assign({}, opt_options);
  35952. delete options.featureProjection;
  35953. return ol.format.GeoJSON.writeGeometry_(geometry, options);
  35954. });
  35955. return /** @type {GeoJSONGeometryCollection} */ ({
  35956. type: 'GeometryCollection',
  35957. geometries: geometries
  35958. });
  35959. };
  35960. /**
  35961. * @param {ol.geom.LineString} geometry Geometry.
  35962. * @param {olx.format.WriteOptions=} opt_options Write options.
  35963. * @private
  35964. * @return {GeoJSONGeometry} GeoJSON geometry.
  35965. */
  35966. ol.format.GeoJSON.writeLineStringGeometry_ = function(geometry, opt_options) {
  35967. return /** @type {GeoJSONGeometry} */ ({
  35968. type: 'LineString',
  35969. coordinates: geometry.getCoordinates()
  35970. });
  35971. };
  35972. /**
  35973. * @param {ol.geom.MultiLineString} geometry Geometry.
  35974. * @param {olx.format.WriteOptions=} opt_options Write options.
  35975. * @private
  35976. * @return {GeoJSONGeometry} GeoJSON geometry.
  35977. */
  35978. ol.format.GeoJSON.writeMultiLineStringGeometry_ = function(geometry, opt_options) {
  35979. return /** @type {GeoJSONGeometry} */ ({
  35980. type: 'MultiLineString',
  35981. coordinates: geometry.getCoordinates()
  35982. });
  35983. };
  35984. /**
  35985. * @param {ol.geom.MultiPoint} geometry Geometry.
  35986. * @param {olx.format.WriteOptions=} opt_options Write options.
  35987. * @private
  35988. * @return {GeoJSONGeometry} GeoJSON geometry.
  35989. */
  35990. ol.format.GeoJSON.writeMultiPointGeometry_ = function(geometry, opt_options) {
  35991. return /** @type {GeoJSONGeometry} */ ({
  35992. type: 'MultiPoint',
  35993. coordinates: geometry.getCoordinates()
  35994. });
  35995. };
  35996. /**
  35997. * @param {ol.geom.MultiPolygon} geometry Geometry.
  35998. * @param {olx.format.WriteOptions=} opt_options Write options.
  35999. * @private
  36000. * @return {GeoJSONGeometry} GeoJSON geometry.
  36001. */
  36002. ol.format.GeoJSON.writeMultiPolygonGeometry_ = function(geometry, opt_options) {
  36003. var right;
  36004. if (opt_options) {
  36005. right = opt_options.rightHanded;
  36006. }
  36007. return /** @type {GeoJSONGeometry} */ ({
  36008. type: 'MultiPolygon',
  36009. coordinates: geometry.getCoordinates(right)
  36010. });
  36011. };
  36012. /**
  36013. * @param {ol.geom.Point} geometry Geometry.
  36014. * @param {olx.format.WriteOptions=} opt_options Write options.
  36015. * @private
  36016. * @return {GeoJSONGeometry} GeoJSON geometry.
  36017. */
  36018. ol.format.GeoJSON.writePointGeometry_ = function(geometry, opt_options) {
  36019. return /** @type {GeoJSONGeometry} */ ({
  36020. type: 'Point',
  36021. coordinates: geometry.getCoordinates()
  36022. });
  36023. };
  36024. /**
  36025. * @param {ol.geom.Polygon} geometry Geometry.
  36026. * @param {olx.format.WriteOptions=} opt_options Write options.
  36027. * @private
  36028. * @return {GeoJSONGeometry} GeoJSON geometry.
  36029. */
  36030. ol.format.GeoJSON.writePolygonGeometry_ = function(geometry, opt_options) {
  36031. var right;
  36032. if (opt_options) {
  36033. right = opt_options.rightHanded;
  36034. }
  36035. return /** @type {GeoJSONGeometry} */ ({
  36036. type: 'Polygon',
  36037. coordinates: geometry.getCoordinates(right)
  36038. });
  36039. };
  36040. /**
  36041. * @const
  36042. * @private
  36043. * @type {Object.<string, function(GeoJSONObject): ol.geom.Geometry>}
  36044. */
  36045. ol.format.GeoJSON.GEOMETRY_READERS_ = {
  36046. 'Point': ol.format.GeoJSON.readPointGeometry_,
  36047. 'LineString': ol.format.GeoJSON.readLineStringGeometry_,
  36048. 'Polygon': ol.format.GeoJSON.readPolygonGeometry_,
  36049. 'MultiPoint': ol.format.GeoJSON.readMultiPointGeometry_,
  36050. 'MultiLineString': ol.format.GeoJSON.readMultiLineStringGeometry_,
  36051. 'MultiPolygon': ol.format.GeoJSON.readMultiPolygonGeometry_,
  36052. 'GeometryCollection': ol.format.GeoJSON.readGeometryCollectionGeometry_
  36053. };
  36054. /**
  36055. * @const
  36056. * @private
  36057. * @type {Object.<string, function(ol.geom.Geometry, olx.format.WriteOptions=): (GeoJSONGeometry|GeoJSONGeometryCollection)>}
  36058. */
  36059. ol.format.GeoJSON.GEOMETRY_WRITERS_ = {
  36060. 'Point': ol.format.GeoJSON.writePointGeometry_,
  36061. 'LineString': ol.format.GeoJSON.writeLineStringGeometry_,
  36062. 'Polygon': ol.format.GeoJSON.writePolygonGeometry_,
  36063. 'MultiPoint': ol.format.GeoJSON.writeMultiPointGeometry_,
  36064. 'MultiLineString': ol.format.GeoJSON.writeMultiLineStringGeometry_,
  36065. 'MultiPolygon': ol.format.GeoJSON.writeMultiPolygonGeometry_,
  36066. 'GeometryCollection': ol.format.GeoJSON.writeGeometryCollectionGeometry_,
  36067. 'Circle': ol.format.GeoJSON.writeEmptyGeometryCollectionGeometry_
  36068. };
  36069. /**
  36070. * Read a feature from a GeoJSON Feature source. Only works for Feature or
  36071. * geometry types. Use {@link ol.format.GeoJSON#readFeatures} to read
  36072. * FeatureCollection source. If feature at source has an id, it will be used
  36073. * as Feature id by calling {@link ol.Feature#setId} internally.
  36074. *
  36075. * @function
  36076. * @param {Document|Node|Object|string} source Source.
  36077. * @param {olx.format.ReadOptions=} opt_options Read options.
  36078. * @return {ol.Feature} Feature.
  36079. * @api
  36080. */
  36081. ol.format.GeoJSON.prototype.readFeature;
  36082. /**
  36083. * Read all features from a GeoJSON source. Works for all GeoJSON types.
  36084. * If the source includes only geometries, features will be created with those
  36085. * geometries.
  36086. *
  36087. * @function
  36088. * @param {Document|Node|Object|string} source Source.
  36089. * @param {olx.format.ReadOptions=} opt_options Read options.
  36090. * @return {Array.<ol.Feature>} Features.
  36091. * @api
  36092. */
  36093. ol.format.GeoJSON.prototype.readFeatures;
  36094. /**
  36095. * @inheritDoc
  36096. */
  36097. ol.format.GeoJSON.prototype.readFeatureFromObject = function(
  36098. object, opt_options) {
  36099. /**
  36100. * @type {GeoJSONFeature}
  36101. */
  36102. var geoJSONFeature = null;
  36103. if (object.type === 'Feature') {
  36104. geoJSONFeature = /** @type {GeoJSONFeature} */ (object);
  36105. } else {
  36106. geoJSONFeature = /** @type {GeoJSONFeature} */ ({
  36107. type: 'Feature',
  36108. geometry: /** @type {GeoJSONGeometry|GeoJSONGeometryCollection} */ (object)
  36109. });
  36110. }
  36111. var geometry = ol.format.GeoJSON.readGeometry_(geoJSONFeature.geometry, opt_options);
  36112. var feature = new ol.Feature();
  36113. if (this.geometryName_) {
  36114. feature.setGeometryName(this.geometryName_);
  36115. }
  36116. feature.setGeometry(geometry);
  36117. if (geoJSONFeature.id !== undefined) {
  36118. feature.setId(geoJSONFeature.id);
  36119. }
  36120. if (geoJSONFeature.properties) {
  36121. feature.setProperties(geoJSONFeature.properties);
  36122. }
  36123. return feature;
  36124. };
  36125. /**
  36126. * @inheritDoc
  36127. */
  36128. ol.format.GeoJSON.prototype.readFeaturesFromObject = function(
  36129. object, opt_options) {
  36130. var geoJSONObject = /** @type {GeoJSONObject} */ (object);
  36131. /** @type {Array.<ol.Feature>} */
  36132. var features = null;
  36133. if (geoJSONObject.type === 'FeatureCollection') {
  36134. var geoJSONFeatureCollection = /** @type {GeoJSONFeatureCollection} */
  36135. (object);
  36136. features = [];
  36137. var geoJSONFeatures = geoJSONFeatureCollection.features;
  36138. var i, ii;
  36139. for (i = 0, ii = geoJSONFeatures.length; i < ii; ++i) {
  36140. features.push(this.readFeatureFromObject(geoJSONFeatures[i],
  36141. opt_options));
  36142. }
  36143. } else {
  36144. features = [this.readFeatureFromObject(object, opt_options)];
  36145. }
  36146. return features;
  36147. };
  36148. /**
  36149. * Read a geometry from a GeoJSON source.
  36150. *
  36151. * @function
  36152. * @param {Document|Node|Object|string} source Source.
  36153. * @param {olx.format.ReadOptions=} opt_options Read options.
  36154. * @return {ol.geom.Geometry} Geometry.
  36155. * @api
  36156. */
  36157. ol.format.GeoJSON.prototype.readGeometry;
  36158. /**
  36159. * @inheritDoc
  36160. */
  36161. ol.format.GeoJSON.prototype.readGeometryFromObject = function(
  36162. object, opt_options) {
  36163. return ol.format.GeoJSON.readGeometry_(
  36164. /** @type {GeoJSONGeometry} */ (object), opt_options);
  36165. };
  36166. /**
  36167. * Read the projection from a GeoJSON source.
  36168. *
  36169. * @function
  36170. * @param {Document|Node|Object|string} source Source.
  36171. * @return {ol.proj.Projection} Projection.
  36172. * @api
  36173. */
  36174. ol.format.GeoJSON.prototype.readProjection;
  36175. /**
  36176. * @inheritDoc
  36177. */
  36178. ol.format.GeoJSON.prototype.readProjectionFromObject = function(object) {
  36179. var geoJSONObject = /** @type {GeoJSONObject} */ (object);
  36180. var crs = geoJSONObject.crs;
  36181. var projection;
  36182. if (crs) {
  36183. if (crs.type == 'name') {
  36184. projection = ol.proj.get(crs.properties.name);
  36185. } else if (crs.type == 'EPSG') {
  36186. // 'EPSG' is not part of the GeoJSON specification, but is generated by
  36187. // GeoServer.
  36188. // TODO: remove this when http://jira.codehaus.org/browse/GEOS-5996
  36189. // is fixed and widely deployed.
  36190. projection = ol.proj.get('EPSG:' + crs.properties.code);
  36191. } else {
  36192. ol.asserts.assert(false, 36); // Unknown SRS type
  36193. }
  36194. } else {
  36195. projection = this.defaultDataProjection;
  36196. }
  36197. return /** @type {ol.proj.Projection} */ (projection);
  36198. };
  36199. /**
  36200. * Encode a feature as a GeoJSON Feature string.
  36201. *
  36202. * @function
  36203. * @param {ol.Feature} feature Feature.
  36204. * @param {olx.format.WriteOptions=} opt_options Write options.
  36205. * @return {string} GeoJSON.
  36206. * @override
  36207. * @api
  36208. */
  36209. ol.format.GeoJSON.prototype.writeFeature;
  36210. /**
  36211. * Encode a feature as a GeoJSON Feature object.
  36212. *
  36213. * @param {ol.Feature} feature Feature.
  36214. * @param {olx.format.WriteOptions=} opt_options Write options.
  36215. * @return {GeoJSONFeature} Object.
  36216. * @override
  36217. * @api
  36218. */
  36219. ol.format.GeoJSON.prototype.writeFeatureObject = function(feature, opt_options) {
  36220. opt_options = this.adaptOptions(opt_options);
  36221. var object = /** @type {GeoJSONFeature} */ ({
  36222. 'type': 'Feature'
  36223. });
  36224. var id = feature.getId();
  36225. if (id !== undefined) {
  36226. object.id = id;
  36227. }
  36228. var geometry = feature.getGeometry();
  36229. if (geometry) {
  36230. object.geometry =
  36231. ol.format.GeoJSON.writeGeometry_(geometry, opt_options);
  36232. } else {
  36233. object.geometry = null;
  36234. }
  36235. var properties = feature.getProperties();
  36236. delete properties[feature.getGeometryName()];
  36237. if (!ol.obj.isEmpty(properties)) {
  36238. object.properties = properties;
  36239. } else {
  36240. object.properties = null;
  36241. }
  36242. return object;
  36243. };
  36244. /**
  36245. * Encode an array of features as GeoJSON.
  36246. *
  36247. * @function
  36248. * @param {Array.<ol.Feature>} features Features.
  36249. * @param {olx.format.WriteOptions=} opt_options Write options.
  36250. * @return {string} GeoJSON.
  36251. * @api
  36252. */
  36253. ol.format.GeoJSON.prototype.writeFeatures;
  36254. /**
  36255. * Encode an array of features as a GeoJSON object.
  36256. *
  36257. * @param {Array.<ol.Feature>} features Features.
  36258. * @param {olx.format.WriteOptions=} opt_options Write options.
  36259. * @return {GeoJSONFeatureCollection} GeoJSON Object.
  36260. * @override
  36261. * @api
  36262. */
  36263. ol.format.GeoJSON.prototype.writeFeaturesObject = function(features, opt_options) {
  36264. opt_options = this.adaptOptions(opt_options);
  36265. var objects = [];
  36266. var i, ii;
  36267. for (i = 0, ii = features.length; i < ii; ++i) {
  36268. objects.push(this.writeFeatureObject(features[i], opt_options));
  36269. }
  36270. return /** @type {GeoJSONFeatureCollection} */ ({
  36271. type: 'FeatureCollection',
  36272. features: objects
  36273. });
  36274. };
  36275. /**
  36276. * Encode a geometry as a GeoJSON string.
  36277. *
  36278. * @function
  36279. * @param {ol.geom.Geometry} geometry Geometry.
  36280. * @param {olx.format.WriteOptions=} opt_options Write options.
  36281. * @return {string} GeoJSON.
  36282. * @api
  36283. */
  36284. ol.format.GeoJSON.prototype.writeGeometry;
  36285. /**
  36286. * Encode a geometry as a GeoJSON object.
  36287. *
  36288. * @param {ol.geom.Geometry} geometry Geometry.
  36289. * @param {olx.format.WriteOptions=} opt_options Write options.
  36290. * @return {GeoJSONGeometry|GeoJSONGeometryCollection} Object.
  36291. * @override
  36292. * @api
  36293. */
  36294. ol.format.GeoJSON.prototype.writeGeometryObject = function(geometry,
  36295. opt_options) {
  36296. return ol.format.GeoJSON.writeGeometry_(geometry,
  36297. this.adaptOptions(opt_options));
  36298. };
  36299. goog.provide('ol.format.XMLFeature');
  36300. goog.require('ol');
  36301. goog.require('ol.array');
  36302. goog.require('ol.format.Feature');
  36303. goog.require('ol.format.FormatType');
  36304. goog.require('ol.xml');
  36305. /**
  36306. * @classdesc
  36307. * Abstract base class; normally only used for creating subclasses and not
  36308. * instantiated in apps.
  36309. * Base class for XML feature formats.
  36310. *
  36311. * @constructor
  36312. * @abstract
  36313. * @extends {ol.format.Feature}
  36314. */
  36315. ol.format.XMLFeature = function() {
  36316. /**
  36317. * @type {XMLSerializer}
  36318. * @private
  36319. */
  36320. this.xmlSerializer_ = new XMLSerializer();
  36321. ol.format.Feature.call(this);
  36322. };
  36323. ol.inherits(ol.format.XMLFeature, ol.format.Feature);
  36324. /**
  36325. * @inheritDoc
  36326. */
  36327. ol.format.XMLFeature.prototype.getType = function() {
  36328. return ol.format.FormatType.XML;
  36329. };
  36330. /**
  36331. * @inheritDoc
  36332. */
  36333. ol.format.XMLFeature.prototype.readFeature = function(source, opt_options) {
  36334. if (ol.xml.isDocument(source)) {
  36335. return this.readFeatureFromDocument(
  36336. /** @type {Document} */ (source), opt_options);
  36337. } else if (ol.xml.isNode(source)) {
  36338. return this.readFeatureFromNode(/** @type {Node} */ (source), opt_options);
  36339. } else if (typeof source === 'string') {
  36340. var doc = ol.xml.parse(source);
  36341. return this.readFeatureFromDocument(doc, opt_options);
  36342. } else {
  36343. return null;
  36344. }
  36345. };
  36346. /**
  36347. * @param {Document} doc Document.
  36348. * @param {olx.format.ReadOptions=} opt_options Options.
  36349. * @return {ol.Feature} Feature.
  36350. */
  36351. ol.format.XMLFeature.prototype.readFeatureFromDocument = function(
  36352. doc, opt_options) {
  36353. var features = this.readFeaturesFromDocument(doc, opt_options);
  36354. if (features.length > 0) {
  36355. return features[0];
  36356. } else {
  36357. return null;
  36358. }
  36359. };
  36360. /**
  36361. * @param {Node} node Node.
  36362. * @param {olx.format.ReadOptions=} opt_options Options.
  36363. * @return {ol.Feature} Feature.
  36364. */
  36365. ol.format.XMLFeature.prototype.readFeatureFromNode = function(node, opt_options) {
  36366. return null; // not implemented
  36367. };
  36368. /**
  36369. * @inheritDoc
  36370. */
  36371. ol.format.XMLFeature.prototype.readFeatures = function(source, opt_options) {
  36372. if (ol.xml.isDocument(source)) {
  36373. return this.readFeaturesFromDocument(
  36374. /** @type {Document} */ (source), opt_options);
  36375. } else if (ol.xml.isNode(source)) {
  36376. return this.readFeaturesFromNode(/** @type {Node} */ (source), opt_options);
  36377. } else if (typeof source === 'string') {
  36378. var doc = ol.xml.parse(source);
  36379. return this.readFeaturesFromDocument(doc, opt_options);
  36380. } else {
  36381. return [];
  36382. }
  36383. };
  36384. /**
  36385. * @param {Document} doc Document.
  36386. * @param {olx.format.ReadOptions=} opt_options Options.
  36387. * @protected
  36388. * @return {Array.<ol.Feature>} Features.
  36389. */
  36390. ol.format.XMLFeature.prototype.readFeaturesFromDocument = function(
  36391. doc, opt_options) {
  36392. /** @type {Array.<ol.Feature>} */
  36393. var features = [];
  36394. var n;
  36395. for (n = doc.firstChild; n; n = n.nextSibling) {
  36396. if (n.nodeType == Node.ELEMENT_NODE) {
  36397. ol.array.extend(features, this.readFeaturesFromNode(n, opt_options));
  36398. }
  36399. }
  36400. return features;
  36401. };
  36402. /**
  36403. * @abstract
  36404. * @param {Node} node Node.
  36405. * @param {olx.format.ReadOptions=} opt_options Options.
  36406. * @protected
  36407. * @return {Array.<ol.Feature>} Features.
  36408. */
  36409. ol.format.XMLFeature.prototype.readFeaturesFromNode = function(node, opt_options) {};
  36410. /**
  36411. * @inheritDoc
  36412. */
  36413. ol.format.XMLFeature.prototype.readGeometry = function(source, opt_options) {
  36414. if (ol.xml.isDocument(source)) {
  36415. return this.readGeometryFromDocument(
  36416. /** @type {Document} */ (source), opt_options);
  36417. } else if (ol.xml.isNode(source)) {
  36418. return this.readGeometryFromNode(/** @type {Node} */ (source), opt_options);
  36419. } else if (typeof source === 'string') {
  36420. var doc = ol.xml.parse(source);
  36421. return this.readGeometryFromDocument(doc, opt_options);
  36422. } else {
  36423. return null;
  36424. }
  36425. };
  36426. /**
  36427. * @param {Document} doc Document.
  36428. * @param {olx.format.ReadOptions=} opt_options Options.
  36429. * @protected
  36430. * @return {ol.geom.Geometry} Geometry.
  36431. */
  36432. ol.format.XMLFeature.prototype.readGeometryFromDocument = function(doc, opt_options) {
  36433. return null; // not implemented
  36434. };
  36435. /**
  36436. * @param {Node} node Node.
  36437. * @param {olx.format.ReadOptions=} opt_options Options.
  36438. * @protected
  36439. * @return {ol.geom.Geometry} Geometry.
  36440. */
  36441. ol.format.XMLFeature.prototype.readGeometryFromNode = function(node, opt_options) {
  36442. return null; // not implemented
  36443. };
  36444. /**
  36445. * @inheritDoc
  36446. */
  36447. ol.format.XMLFeature.prototype.readProjection = function(source) {
  36448. if (ol.xml.isDocument(source)) {
  36449. return this.readProjectionFromDocument(/** @type {Document} */ (source));
  36450. } else if (ol.xml.isNode(source)) {
  36451. return this.readProjectionFromNode(/** @type {Node} */ (source));
  36452. } else if (typeof source === 'string') {
  36453. var doc = ol.xml.parse(source);
  36454. return this.readProjectionFromDocument(doc);
  36455. } else {
  36456. return null;
  36457. }
  36458. };
  36459. /**
  36460. * @param {Document} doc Document.
  36461. * @protected
  36462. * @return {ol.proj.Projection} Projection.
  36463. */
  36464. ol.format.XMLFeature.prototype.readProjectionFromDocument = function(doc) {
  36465. return this.defaultDataProjection;
  36466. };
  36467. /**
  36468. * @param {Node} node Node.
  36469. * @protected
  36470. * @return {ol.proj.Projection} Projection.
  36471. */
  36472. ol.format.XMLFeature.prototype.readProjectionFromNode = function(node) {
  36473. return this.defaultDataProjection;
  36474. };
  36475. /**
  36476. * @inheritDoc
  36477. */
  36478. ol.format.XMLFeature.prototype.writeFeature = function(feature, opt_options) {
  36479. var node = this.writeFeatureNode(feature, opt_options);
  36480. return this.xmlSerializer_.serializeToString(node);
  36481. };
  36482. /**
  36483. * @param {ol.Feature} feature Feature.
  36484. * @param {olx.format.WriteOptions=} opt_options Options.
  36485. * @protected
  36486. * @return {Node} Node.
  36487. */
  36488. ol.format.XMLFeature.prototype.writeFeatureNode = function(feature, opt_options) {
  36489. return null; // not implemented
  36490. };
  36491. /**
  36492. * @inheritDoc
  36493. */
  36494. ol.format.XMLFeature.prototype.writeFeatures = function(features, opt_options) {
  36495. var node = this.writeFeaturesNode(features, opt_options);
  36496. return this.xmlSerializer_.serializeToString(node);
  36497. };
  36498. /**
  36499. * @param {Array.<ol.Feature>} features Features.
  36500. * @param {olx.format.WriteOptions=} opt_options Options.
  36501. * @return {Node} Node.
  36502. */
  36503. ol.format.XMLFeature.prototype.writeFeaturesNode = function(features, opt_options) {
  36504. return null; // not implemented
  36505. };
  36506. /**
  36507. * @inheritDoc
  36508. */
  36509. ol.format.XMLFeature.prototype.writeGeometry = function(geometry, opt_options) {
  36510. var node = this.writeGeometryNode(geometry, opt_options);
  36511. return this.xmlSerializer_.serializeToString(node);
  36512. };
  36513. /**
  36514. * @param {ol.geom.Geometry} geometry Geometry.
  36515. * @param {olx.format.WriteOptions=} opt_options Options.
  36516. * @return {Node} Node.
  36517. */
  36518. ol.format.XMLFeature.prototype.writeGeometryNode = function(geometry, opt_options) {
  36519. return null; // not implemented
  36520. };
  36521. // FIXME Envelopes should not be treated as geometries! readEnvelope_ is part
  36522. // of GEOMETRY_PARSERS_ and methods using GEOMETRY_PARSERS_ do not expect
  36523. // envelopes/extents, only geometries!
  36524. goog.provide('ol.format.GMLBase');
  36525. goog.require('ol');
  36526. goog.require('ol.array');
  36527. goog.require('ol.Feature');
  36528. goog.require('ol.format.Feature');
  36529. goog.require('ol.format.XMLFeature');
  36530. goog.require('ol.geom.GeometryLayout');
  36531. goog.require('ol.geom.LineString');
  36532. goog.require('ol.geom.LinearRing');
  36533. goog.require('ol.geom.MultiLineString');
  36534. goog.require('ol.geom.MultiPoint');
  36535. goog.require('ol.geom.MultiPolygon');
  36536. goog.require('ol.geom.Point');
  36537. goog.require('ol.geom.Polygon');
  36538. goog.require('ol.obj');
  36539. goog.require('ol.proj');
  36540. goog.require('ol.xml');
  36541. /**
  36542. * @classdesc
  36543. * Abstract base class; normally only used for creating subclasses and not
  36544. * instantiated in apps.
  36545. * Feature base format for reading and writing data in the GML format.
  36546. * This class cannot be instantiated, it contains only base content that
  36547. * is shared with versioned format classes ol.format.GML2 and
  36548. * ol.format.GML3.
  36549. *
  36550. * @constructor
  36551. * @abstract
  36552. * @param {olx.format.GMLOptions=} opt_options
  36553. * Optional configuration object.
  36554. * @extends {ol.format.XMLFeature}
  36555. */
  36556. ol.format.GMLBase = function(opt_options) {
  36557. var options = /** @type {olx.format.GMLOptions} */
  36558. (opt_options ? opt_options : {});
  36559. /**
  36560. * @protected
  36561. * @type {Array.<string>|string|undefined}
  36562. */
  36563. this.featureType = options.featureType;
  36564. /**
  36565. * @protected
  36566. * @type {Object.<string, string>|string|undefined}
  36567. */
  36568. this.featureNS = options.featureNS;
  36569. /**
  36570. * @protected
  36571. * @type {string}
  36572. */
  36573. this.srsName = options.srsName;
  36574. /**
  36575. * @protected
  36576. * @type {string}
  36577. */
  36578. this.schemaLocation = '';
  36579. /**
  36580. * @type {Object.<string, Object.<string, Object>>}
  36581. */
  36582. this.FEATURE_COLLECTION_PARSERS = {};
  36583. this.FEATURE_COLLECTION_PARSERS[ol.format.GMLBase.GMLNS] = {
  36584. 'featureMember': ol.xml.makeReplacer(
  36585. ol.format.GMLBase.prototype.readFeaturesInternal),
  36586. 'featureMembers': ol.xml.makeReplacer(
  36587. ol.format.GMLBase.prototype.readFeaturesInternal)
  36588. };
  36589. ol.format.XMLFeature.call(this);
  36590. };
  36591. ol.inherits(ol.format.GMLBase, ol.format.XMLFeature);
  36592. /**
  36593. * @const
  36594. * @type {string}
  36595. */
  36596. ol.format.GMLBase.GMLNS = 'http://www.opengis.net/gml';
  36597. /**
  36598. * A regular expression that matches if a string only contains whitespace
  36599. * characters. It will e.g. match `''`, `' '`, `'\n'` etc. The non-breaking
  36600. * space (0xa0) is explicitly included as IE doesn't include it in its
  36601. * definition of `\s`.
  36602. *
  36603. * Information from `goog.string.isEmptyOrWhitespace`: https://github.com/google/closure-library/blob/e877b1e/closure/goog/string/string.js#L156-L160
  36604. *
  36605. * @const
  36606. * @type {RegExp}
  36607. * @private
  36608. */
  36609. ol.format.GMLBase.ONLY_WHITESPACE_RE_ = /^[\s\xa0]*$/;
  36610. /**
  36611. * @param {Node} node Node.
  36612. * @param {Array.<*>} objectStack Object stack.
  36613. * @return {Array.<ol.Feature> | undefined} Features.
  36614. */
  36615. ol.format.GMLBase.prototype.readFeaturesInternal = function(node, objectStack) {
  36616. var localName = node.localName;
  36617. var features = null;
  36618. if (localName == 'FeatureCollection') {
  36619. if (node.namespaceURI === 'http://www.opengis.net/wfs') {
  36620. features = ol.xml.pushParseAndPop([],
  36621. this.FEATURE_COLLECTION_PARSERS, node,
  36622. objectStack, this);
  36623. } else {
  36624. features = ol.xml.pushParseAndPop(null,
  36625. this.FEATURE_COLLECTION_PARSERS, node,
  36626. objectStack, this);
  36627. }
  36628. } else if (localName == 'featureMembers' || localName == 'featureMember') {
  36629. var context = objectStack[0];
  36630. var featureType = context['featureType'];
  36631. var featureNS = context['featureNS'];
  36632. var i, ii, prefix = 'p', defaultPrefix = 'p0';
  36633. if (!featureType && node.childNodes) {
  36634. featureType = [], featureNS = {};
  36635. for (i = 0, ii = node.childNodes.length; i < ii; ++i) {
  36636. var child = node.childNodes[i];
  36637. if (child.nodeType === 1) {
  36638. var ft = child.nodeName.split(':').pop();
  36639. if (featureType.indexOf(ft) === -1) {
  36640. var key = '';
  36641. var count = 0;
  36642. var uri = child.namespaceURI;
  36643. for (var candidate in featureNS) {
  36644. if (featureNS[candidate] === uri) {
  36645. key = candidate;
  36646. break;
  36647. }
  36648. ++count;
  36649. }
  36650. if (!key) {
  36651. key = prefix + count;
  36652. featureNS[key] = uri;
  36653. }
  36654. featureType.push(key + ':' + ft);
  36655. }
  36656. }
  36657. }
  36658. if (localName != 'featureMember') {
  36659. // recheck featureType for each featureMember
  36660. context['featureType'] = featureType;
  36661. context['featureNS'] = featureNS;
  36662. }
  36663. }
  36664. if (typeof featureNS === 'string') {
  36665. var ns = featureNS;
  36666. featureNS = {};
  36667. featureNS[defaultPrefix] = ns;
  36668. }
  36669. var parsersNS = {};
  36670. var featureTypes = Array.isArray(featureType) ? featureType : [featureType];
  36671. for (var p in featureNS) {
  36672. var parsers = {};
  36673. for (i = 0, ii = featureTypes.length; i < ii; ++i) {
  36674. var featurePrefix = featureTypes[i].indexOf(':') === -1 ?
  36675. defaultPrefix : featureTypes[i].split(':')[0];
  36676. if (featurePrefix === p) {
  36677. parsers[featureTypes[i].split(':').pop()] =
  36678. (localName == 'featureMembers') ?
  36679. ol.xml.makeArrayPusher(this.readFeatureElement, this) :
  36680. ol.xml.makeReplacer(this.readFeatureElement, this);
  36681. }
  36682. }
  36683. parsersNS[featureNS[p]] = parsers;
  36684. }
  36685. if (localName == 'featureMember') {
  36686. features = ol.xml.pushParseAndPop(undefined, parsersNS, node, objectStack);
  36687. } else {
  36688. features = ol.xml.pushParseAndPop([], parsersNS, node, objectStack);
  36689. }
  36690. }
  36691. if (features === null) {
  36692. features = [];
  36693. }
  36694. return features;
  36695. };
  36696. /**
  36697. * @param {Node} node Node.
  36698. * @param {Array.<*>} objectStack Object stack.
  36699. * @return {ol.geom.Geometry|undefined} Geometry.
  36700. */
  36701. ol.format.GMLBase.prototype.readGeometryElement = function(node, objectStack) {
  36702. var context = /** @type {Object} */ (objectStack[0]);
  36703. context['srsName'] = node.firstElementChild.getAttribute('srsName');
  36704. /** @type {ol.geom.Geometry} */
  36705. var geometry = ol.xml.pushParseAndPop(null,
  36706. this.GEOMETRY_PARSERS_, node, objectStack, this);
  36707. if (geometry) {
  36708. return /** @type {ol.geom.Geometry} */ (
  36709. ol.format.Feature.transformWithOptions(geometry, false, context));
  36710. } else {
  36711. return undefined;
  36712. }
  36713. };
  36714. /**
  36715. * @param {Node} node Node.
  36716. * @param {Array.<*>} objectStack Object stack.
  36717. * @return {ol.Feature} Feature.
  36718. */
  36719. ol.format.GMLBase.prototype.readFeatureElement = function(node, objectStack) {
  36720. var n;
  36721. var fid = node.getAttribute('fid') ||
  36722. ol.xml.getAttributeNS(node, ol.format.GMLBase.GMLNS, 'id');
  36723. var values = {}, geometryName;
  36724. for (n = node.firstElementChild; n; n = n.nextElementSibling) {
  36725. var localName = n.localName;
  36726. // Assume attribute elements have one child node and that the child
  36727. // is a text or CDATA node (to be treated as text).
  36728. // Otherwise assume it is a geometry node.
  36729. if (n.childNodes.length === 0 ||
  36730. (n.childNodes.length === 1 &&
  36731. (n.firstChild.nodeType === 3 || n.firstChild.nodeType === 4))) {
  36732. var value = ol.xml.getAllTextContent(n, false);
  36733. if (ol.format.GMLBase.ONLY_WHITESPACE_RE_.test(value)) {
  36734. value = undefined;
  36735. }
  36736. values[localName] = value;
  36737. } else {
  36738. // boundedBy is an extent and must not be considered as a geometry
  36739. if (localName !== 'boundedBy') {
  36740. geometryName = localName;
  36741. }
  36742. values[localName] = this.readGeometryElement(n, objectStack);
  36743. }
  36744. }
  36745. var feature = new ol.Feature(values);
  36746. if (geometryName) {
  36747. feature.setGeometryName(geometryName);
  36748. }
  36749. if (fid) {
  36750. feature.setId(fid);
  36751. }
  36752. return feature;
  36753. };
  36754. /**
  36755. * @param {Node} node Node.
  36756. * @param {Array.<*>} objectStack Object stack.
  36757. * @return {ol.geom.Point|undefined} Point.
  36758. */
  36759. ol.format.GMLBase.prototype.readPoint = function(node, objectStack) {
  36760. var flatCoordinates =
  36761. this.readFlatCoordinatesFromNode_(node, objectStack);
  36762. if (flatCoordinates) {
  36763. var point = new ol.geom.Point(null);
  36764. point.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates);
  36765. return point;
  36766. }
  36767. };
  36768. /**
  36769. * @param {Node} node Node.
  36770. * @param {Array.<*>} objectStack Object stack.
  36771. * @return {ol.geom.MultiPoint|undefined} MultiPoint.
  36772. */
  36773. ol.format.GMLBase.prototype.readMultiPoint = function(node, objectStack) {
  36774. /** @type {Array.<Array.<number>>} */
  36775. var coordinates = ol.xml.pushParseAndPop([],
  36776. this.MULTIPOINT_PARSERS_, node, objectStack, this);
  36777. if (coordinates) {
  36778. return new ol.geom.MultiPoint(coordinates);
  36779. } else {
  36780. return undefined;
  36781. }
  36782. };
  36783. /**
  36784. * @param {Node} node Node.
  36785. * @param {Array.<*>} objectStack Object stack.
  36786. * @return {ol.geom.MultiLineString|undefined} MultiLineString.
  36787. */
  36788. ol.format.GMLBase.prototype.readMultiLineString = function(node, objectStack) {
  36789. /** @type {Array.<ol.geom.LineString>} */
  36790. var lineStrings = ol.xml.pushParseAndPop([],
  36791. this.MULTILINESTRING_PARSERS_, node, objectStack, this);
  36792. if (lineStrings) {
  36793. var multiLineString = new ol.geom.MultiLineString(null);
  36794. multiLineString.setLineStrings(lineStrings);
  36795. return multiLineString;
  36796. } else {
  36797. return undefined;
  36798. }
  36799. };
  36800. /**
  36801. * @param {Node} node Node.
  36802. * @param {Array.<*>} objectStack Object stack.
  36803. * @return {ol.geom.MultiPolygon|undefined} MultiPolygon.
  36804. */
  36805. ol.format.GMLBase.prototype.readMultiPolygon = function(node, objectStack) {
  36806. /** @type {Array.<ol.geom.Polygon>} */
  36807. var polygons = ol.xml.pushParseAndPop([],
  36808. this.MULTIPOLYGON_PARSERS_, node, objectStack, this);
  36809. if (polygons) {
  36810. var multiPolygon = new ol.geom.MultiPolygon(null);
  36811. multiPolygon.setPolygons(polygons);
  36812. return multiPolygon;
  36813. } else {
  36814. return undefined;
  36815. }
  36816. };
  36817. /**
  36818. * @param {Node} node Node.
  36819. * @param {Array.<*>} objectStack Object stack.
  36820. * @private
  36821. */
  36822. ol.format.GMLBase.prototype.pointMemberParser_ = function(node, objectStack) {
  36823. ol.xml.parseNode(this.POINTMEMBER_PARSERS_,
  36824. node, objectStack, this);
  36825. };
  36826. /**
  36827. * @param {Node} node Node.
  36828. * @param {Array.<*>} objectStack Object stack.
  36829. * @private
  36830. */
  36831. ol.format.GMLBase.prototype.lineStringMemberParser_ = function(node, objectStack) {
  36832. ol.xml.parseNode(this.LINESTRINGMEMBER_PARSERS_,
  36833. node, objectStack, this);
  36834. };
  36835. /**
  36836. * @param {Node} node Node.
  36837. * @param {Array.<*>} objectStack Object stack.
  36838. * @private
  36839. */
  36840. ol.format.GMLBase.prototype.polygonMemberParser_ = function(node, objectStack) {
  36841. ol.xml.parseNode(this.POLYGONMEMBER_PARSERS_, node,
  36842. objectStack, this);
  36843. };
  36844. /**
  36845. * @param {Node} node Node.
  36846. * @param {Array.<*>} objectStack Object stack.
  36847. * @return {ol.geom.LineString|undefined} LineString.
  36848. */
  36849. ol.format.GMLBase.prototype.readLineString = function(node, objectStack) {
  36850. var flatCoordinates =
  36851. this.readFlatCoordinatesFromNode_(node, objectStack);
  36852. if (flatCoordinates) {
  36853. var lineString = new ol.geom.LineString(null);
  36854. lineString.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates);
  36855. return lineString;
  36856. } else {
  36857. return undefined;
  36858. }
  36859. };
  36860. /**
  36861. * @param {Node} node Node.
  36862. * @param {Array.<*>} objectStack Object stack.
  36863. * @private
  36864. * @return {Array.<number>|undefined} LinearRing flat coordinates.
  36865. */
  36866. ol.format.GMLBase.prototype.readFlatLinearRing_ = function(node, objectStack) {
  36867. var ring = ol.xml.pushParseAndPop(null,
  36868. this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node,
  36869. objectStack, this);
  36870. if (ring) {
  36871. return ring;
  36872. } else {
  36873. return undefined;
  36874. }
  36875. };
  36876. /**
  36877. * @param {Node} node Node.
  36878. * @param {Array.<*>} objectStack Object stack.
  36879. * @return {ol.geom.LinearRing|undefined} LinearRing.
  36880. */
  36881. ol.format.GMLBase.prototype.readLinearRing = function(node, objectStack) {
  36882. var flatCoordinates =
  36883. this.readFlatCoordinatesFromNode_(node, objectStack);
  36884. if (flatCoordinates) {
  36885. var ring = new ol.geom.LinearRing(null);
  36886. ring.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates);
  36887. return ring;
  36888. } else {
  36889. return undefined;
  36890. }
  36891. };
  36892. /**
  36893. * @param {Node} node Node.
  36894. * @param {Array.<*>} objectStack Object stack.
  36895. * @return {ol.geom.Polygon|undefined} Polygon.
  36896. */
  36897. ol.format.GMLBase.prototype.readPolygon = function(node, objectStack) {
  36898. /** @type {Array.<Array.<number>>} */
  36899. var flatLinearRings = ol.xml.pushParseAndPop([null],
  36900. this.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack, this);
  36901. if (flatLinearRings && flatLinearRings[0]) {
  36902. var polygon = new ol.geom.Polygon(null);
  36903. var flatCoordinates = flatLinearRings[0];
  36904. var ends = [flatCoordinates.length];
  36905. var i, ii;
  36906. for (i = 1, ii = flatLinearRings.length; i < ii; ++i) {
  36907. ol.array.extend(flatCoordinates, flatLinearRings[i]);
  36908. ends.push(flatCoordinates.length);
  36909. }
  36910. polygon.setFlatCoordinates(
  36911. ol.geom.GeometryLayout.XYZ, flatCoordinates, ends);
  36912. return polygon;
  36913. } else {
  36914. return undefined;
  36915. }
  36916. };
  36917. /**
  36918. * @param {Node} node Node.
  36919. * @param {Array.<*>} objectStack Object stack.
  36920. * @private
  36921. * @return {Array.<number>} Flat coordinates.
  36922. */
  36923. ol.format.GMLBase.prototype.readFlatCoordinatesFromNode_ = function(node, objectStack) {
  36924. return ol.xml.pushParseAndPop(null,
  36925. this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node,
  36926. objectStack, this);
  36927. };
  36928. /**
  36929. * @const
  36930. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  36931. * @private
  36932. */
  36933. ol.format.GMLBase.prototype.MULTIPOINT_PARSERS_ = {
  36934. 'http://www.opengis.net/gml': {
  36935. 'pointMember': ol.xml.makeArrayPusher(
  36936. ol.format.GMLBase.prototype.pointMemberParser_),
  36937. 'pointMembers': ol.xml.makeArrayPusher(
  36938. ol.format.GMLBase.prototype.pointMemberParser_)
  36939. }
  36940. };
  36941. /**
  36942. * @const
  36943. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  36944. * @private
  36945. */
  36946. ol.format.GMLBase.prototype.MULTILINESTRING_PARSERS_ = {
  36947. 'http://www.opengis.net/gml': {
  36948. 'lineStringMember': ol.xml.makeArrayPusher(
  36949. ol.format.GMLBase.prototype.lineStringMemberParser_),
  36950. 'lineStringMembers': ol.xml.makeArrayPusher(
  36951. ol.format.GMLBase.prototype.lineStringMemberParser_)
  36952. }
  36953. };
  36954. /**
  36955. * @const
  36956. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  36957. * @private
  36958. */
  36959. ol.format.GMLBase.prototype.MULTIPOLYGON_PARSERS_ = {
  36960. 'http://www.opengis.net/gml': {
  36961. 'polygonMember': ol.xml.makeArrayPusher(
  36962. ol.format.GMLBase.prototype.polygonMemberParser_),
  36963. 'polygonMembers': ol.xml.makeArrayPusher(
  36964. ol.format.GMLBase.prototype.polygonMemberParser_)
  36965. }
  36966. };
  36967. /**
  36968. * @const
  36969. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  36970. * @private
  36971. */
  36972. ol.format.GMLBase.prototype.POINTMEMBER_PARSERS_ = {
  36973. 'http://www.opengis.net/gml': {
  36974. 'Point': ol.xml.makeArrayPusher(
  36975. ol.format.GMLBase.prototype.readFlatCoordinatesFromNode_)
  36976. }
  36977. };
  36978. /**
  36979. * @const
  36980. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  36981. * @private
  36982. */
  36983. ol.format.GMLBase.prototype.LINESTRINGMEMBER_PARSERS_ = {
  36984. 'http://www.opengis.net/gml': {
  36985. 'LineString': ol.xml.makeArrayPusher(
  36986. ol.format.GMLBase.prototype.readLineString)
  36987. }
  36988. };
  36989. /**
  36990. * @const
  36991. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  36992. * @private
  36993. */
  36994. ol.format.GMLBase.prototype.POLYGONMEMBER_PARSERS_ = {
  36995. 'http://www.opengis.net/gml': {
  36996. 'Polygon': ol.xml.makeArrayPusher(
  36997. ol.format.GMLBase.prototype.readPolygon)
  36998. }
  36999. };
  37000. /**
  37001. * @const
  37002. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  37003. * @protected
  37004. */
  37005. ol.format.GMLBase.prototype.RING_PARSERS = {
  37006. 'http://www.opengis.net/gml': {
  37007. 'LinearRing': ol.xml.makeReplacer(
  37008. ol.format.GMLBase.prototype.readFlatLinearRing_)
  37009. }
  37010. };
  37011. /**
  37012. * @inheritDoc
  37013. */
  37014. ol.format.GMLBase.prototype.readGeometryFromNode = function(node, opt_options) {
  37015. var geometry = this.readGeometryElement(node,
  37016. [this.getReadOptions(node, opt_options ? opt_options : {})]);
  37017. return geometry ? geometry : null;
  37018. };
  37019. /**
  37020. * Read all features from a GML FeatureCollection.
  37021. *
  37022. * @function
  37023. * @param {Document|Node|Object|string} source Source.
  37024. * @param {olx.format.ReadOptions=} opt_options Options.
  37025. * @return {Array.<ol.Feature>} Features.
  37026. * @api
  37027. */
  37028. ol.format.GMLBase.prototype.readFeatures;
  37029. /**
  37030. * @inheritDoc
  37031. */
  37032. ol.format.GMLBase.prototype.readFeaturesFromNode = function(node, opt_options) {
  37033. var options = {
  37034. featureType: this.featureType,
  37035. featureNS: this.featureNS
  37036. };
  37037. if (opt_options) {
  37038. ol.obj.assign(options, this.getReadOptions(node, opt_options));
  37039. }
  37040. var features = this.readFeaturesInternal(node, [options]);
  37041. return features || [];
  37042. };
  37043. /**
  37044. * @inheritDoc
  37045. */
  37046. ol.format.GMLBase.prototype.readProjectionFromNode = function(node) {
  37047. return ol.proj.get(this.srsName ? this.srsName :
  37048. node.firstElementChild.getAttribute('srsName'));
  37049. };
  37050. goog.provide('ol.format.XSD');
  37051. goog.require('ol.xml');
  37052. goog.require('ol.string');
  37053. /**
  37054. * @const
  37055. * @type {string}
  37056. */
  37057. ol.format.XSD.NAMESPACE_URI = 'http://www.w3.org/2001/XMLSchema';
  37058. /**
  37059. * @param {Node} node Node.
  37060. * @return {boolean|undefined} Boolean.
  37061. */
  37062. ol.format.XSD.readBoolean = function(node) {
  37063. var s = ol.xml.getAllTextContent(node, false);
  37064. return ol.format.XSD.readBooleanString(s);
  37065. };
  37066. /**
  37067. * @param {string} string String.
  37068. * @return {boolean|undefined} Boolean.
  37069. */
  37070. ol.format.XSD.readBooleanString = function(string) {
  37071. var m = /^\s*(true|1)|(false|0)\s*$/.exec(string);
  37072. if (m) {
  37073. return m[1] !== undefined || false;
  37074. } else {
  37075. return undefined;
  37076. }
  37077. };
  37078. /**
  37079. * @param {Node} node Node.
  37080. * @return {number|undefined} DateTime in seconds.
  37081. */
  37082. ol.format.XSD.readDateTime = function(node) {
  37083. var s = ol.xml.getAllTextContent(node, false);
  37084. var dateTime = Date.parse(s);
  37085. return isNaN(dateTime) ? undefined : dateTime / 1000;
  37086. };
  37087. /**
  37088. * @param {Node} node Node.
  37089. * @return {number|undefined} Decimal.
  37090. */
  37091. ol.format.XSD.readDecimal = function(node) {
  37092. var s = ol.xml.getAllTextContent(node, false);
  37093. return ol.format.XSD.readDecimalString(s);
  37094. };
  37095. /**
  37096. * @param {string} string String.
  37097. * @return {number|undefined} Decimal.
  37098. */
  37099. ol.format.XSD.readDecimalString = function(string) {
  37100. // FIXME check spec
  37101. var m = /^\s*([+\-]?\d*\.?\d+(?:e[+\-]?\d+)?)\s*$/i.exec(string);
  37102. if (m) {
  37103. return parseFloat(m[1]);
  37104. } else {
  37105. return undefined;
  37106. }
  37107. };
  37108. /**
  37109. * @param {Node} node Node.
  37110. * @return {number|undefined} Non negative integer.
  37111. */
  37112. ol.format.XSD.readNonNegativeInteger = function(node) {
  37113. var s = ol.xml.getAllTextContent(node, false);
  37114. return ol.format.XSD.readNonNegativeIntegerString(s);
  37115. };
  37116. /**
  37117. * @param {string} string String.
  37118. * @return {number|undefined} Non negative integer.
  37119. */
  37120. ol.format.XSD.readNonNegativeIntegerString = function(string) {
  37121. var m = /^\s*(\d+)\s*$/.exec(string);
  37122. if (m) {
  37123. return parseInt(m[1], 10);
  37124. } else {
  37125. return undefined;
  37126. }
  37127. };
  37128. /**
  37129. * @param {Node} node Node.
  37130. * @return {string|undefined} String.
  37131. */
  37132. ol.format.XSD.readString = function(node) {
  37133. return ol.xml.getAllTextContent(node, false).trim();
  37134. };
  37135. /**
  37136. * @param {Node} node Node to append a TextNode with the boolean to.
  37137. * @param {boolean} bool Boolean.
  37138. */
  37139. ol.format.XSD.writeBooleanTextNode = function(node, bool) {
  37140. ol.format.XSD.writeStringTextNode(node, (bool) ? '1' : '0');
  37141. };
  37142. /**
  37143. * @param {Node} node Node to append a CDATA Section with the string to.
  37144. * @param {string} string String.
  37145. */
  37146. ol.format.XSD.writeCDATASection = function(node, string) {
  37147. node.appendChild(ol.xml.DOCUMENT.createCDATASection(string));
  37148. };
  37149. /**
  37150. * @param {Node} node Node to append a TextNode with the dateTime to.
  37151. * @param {number} dateTime DateTime in seconds.
  37152. */
  37153. ol.format.XSD.writeDateTimeTextNode = function(node, dateTime) {
  37154. var date = new Date(dateTime * 1000);
  37155. var string = date.getUTCFullYear() + '-' +
  37156. ol.string.padNumber(date.getUTCMonth() + 1, 2) + '-' +
  37157. ol.string.padNumber(date.getUTCDate(), 2) + 'T' +
  37158. ol.string.padNumber(date.getUTCHours(), 2) + ':' +
  37159. ol.string.padNumber(date.getUTCMinutes(), 2) + ':' +
  37160. ol.string.padNumber(date.getUTCSeconds(), 2) + 'Z';
  37161. node.appendChild(ol.xml.DOCUMENT.createTextNode(string));
  37162. };
  37163. /**
  37164. * @param {Node} node Node to append a TextNode with the decimal to.
  37165. * @param {number} decimal Decimal.
  37166. */
  37167. ol.format.XSD.writeDecimalTextNode = function(node, decimal) {
  37168. var string = decimal.toPrecision();
  37169. node.appendChild(ol.xml.DOCUMENT.createTextNode(string));
  37170. };
  37171. /**
  37172. * @param {Node} node Node to append a TextNode with the decimal to.
  37173. * @param {number} nonNegativeInteger Non negative integer.
  37174. */
  37175. ol.format.XSD.writeNonNegativeIntegerTextNode = function(node, nonNegativeInteger) {
  37176. var string = nonNegativeInteger.toString();
  37177. node.appendChild(ol.xml.DOCUMENT.createTextNode(string));
  37178. };
  37179. /**
  37180. * @param {Node} node Node to append a TextNode with the string to.
  37181. * @param {string} string String.
  37182. */
  37183. ol.format.XSD.writeStringTextNode = function(node, string) {
  37184. node.appendChild(ol.xml.DOCUMENT.createTextNode(string));
  37185. };
  37186. goog.provide('ol.format.GML3');
  37187. goog.require('ol');
  37188. goog.require('ol.array');
  37189. goog.require('ol.extent');
  37190. goog.require('ol.format.Feature');
  37191. goog.require('ol.format.GMLBase');
  37192. goog.require('ol.format.XSD');
  37193. goog.require('ol.geom.Geometry');
  37194. goog.require('ol.geom.GeometryLayout');
  37195. goog.require('ol.geom.LineString');
  37196. goog.require('ol.geom.MultiLineString');
  37197. goog.require('ol.geom.MultiPolygon');
  37198. goog.require('ol.geom.Polygon');
  37199. goog.require('ol.obj');
  37200. goog.require('ol.proj');
  37201. goog.require('ol.xml');
  37202. /**
  37203. * @classdesc
  37204. * Feature format for reading and writing data in the GML format
  37205. * version 3.1.1.
  37206. * Currently only supports GML 3.1.1 Simple Features profile.
  37207. *
  37208. * @constructor
  37209. * @param {olx.format.GMLOptions=} opt_options
  37210. * Optional configuration object.
  37211. * @extends {ol.format.GMLBase}
  37212. * @api
  37213. */
  37214. ol.format.GML3 = function(opt_options) {
  37215. var options = /** @type {olx.format.GMLOptions} */
  37216. (opt_options ? opt_options : {});
  37217. ol.format.GMLBase.call(this, options);
  37218. /**
  37219. * @private
  37220. * @type {boolean}
  37221. */
  37222. this.surface_ = options.surface !== undefined ? options.surface : false;
  37223. /**
  37224. * @private
  37225. * @type {boolean}
  37226. */
  37227. this.curve_ = options.curve !== undefined ? options.curve : false;
  37228. /**
  37229. * @private
  37230. * @type {boolean}
  37231. */
  37232. this.multiCurve_ = options.multiCurve !== undefined ?
  37233. options.multiCurve : true;
  37234. /**
  37235. * @private
  37236. * @type {boolean}
  37237. */
  37238. this.multiSurface_ = options.multiSurface !== undefined ?
  37239. options.multiSurface : true;
  37240. /**
  37241. * @inheritDoc
  37242. */
  37243. this.schemaLocation = options.schemaLocation ?
  37244. options.schemaLocation : ol.format.GML3.schemaLocation_;
  37245. /**
  37246. * @private
  37247. * @type {boolean}
  37248. */
  37249. this.hasZ = options.hasZ !== undefined ?
  37250. options.hasZ : false;
  37251. };
  37252. ol.inherits(ol.format.GML3, ol.format.GMLBase);
  37253. /**
  37254. * @const
  37255. * @type {string}
  37256. * @private
  37257. */
  37258. ol.format.GML3.schemaLocation_ = ol.format.GMLBase.GMLNS +
  37259. ' http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/' +
  37260. '1.0.0/gmlsf.xsd';
  37261. /**
  37262. * @param {Node} node Node.
  37263. * @param {Array.<*>} objectStack Object stack.
  37264. * @private
  37265. * @return {ol.geom.MultiLineString|undefined} MultiLineString.
  37266. */
  37267. ol.format.GML3.prototype.readMultiCurve_ = function(node, objectStack) {
  37268. /** @type {Array.<ol.geom.LineString>} */
  37269. var lineStrings = ol.xml.pushParseAndPop([],
  37270. this.MULTICURVE_PARSERS_, node, objectStack, this);
  37271. if (lineStrings) {
  37272. var multiLineString = new ol.geom.MultiLineString(null);
  37273. multiLineString.setLineStrings(lineStrings);
  37274. return multiLineString;
  37275. } else {
  37276. return undefined;
  37277. }
  37278. };
  37279. /**
  37280. * @param {Node} node Node.
  37281. * @param {Array.<*>} objectStack Object stack.
  37282. * @private
  37283. * @return {ol.geom.MultiPolygon|undefined} MultiPolygon.
  37284. */
  37285. ol.format.GML3.prototype.readMultiSurface_ = function(node, objectStack) {
  37286. /** @type {Array.<ol.geom.Polygon>} */
  37287. var polygons = ol.xml.pushParseAndPop([],
  37288. this.MULTISURFACE_PARSERS_, node, objectStack, this);
  37289. if (polygons) {
  37290. var multiPolygon = new ol.geom.MultiPolygon(null);
  37291. multiPolygon.setPolygons(polygons);
  37292. return multiPolygon;
  37293. } else {
  37294. return undefined;
  37295. }
  37296. };
  37297. /**
  37298. * @param {Node} node Node.
  37299. * @param {Array.<*>} objectStack Object stack.
  37300. * @private
  37301. */
  37302. ol.format.GML3.prototype.curveMemberParser_ = function(node, objectStack) {
  37303. ol.xml.parseNode(this.CURVEMEMBER_PARSERS_, node, objectStack, this);
  37304. };
  37305. /**
  37306. * @param {Node} node Node.
  37307. * @param {Array.<*>} objectStack Object stack.
  37308. * @private
  37309. */
  37310. ol.format.GML3.prototype.surfaceMemberParser_ = function(node, objectStack) {
  37311. ol.xml.parseNode(this.SURFACEMEMBER_PARSERS_,
  37312. node, objectStack, this);
  37313. };
  37314. /**
  37315. * @param {Node} node Node.
  37316. * @param {Array.<*>} objectStack Object stack.
  37317. * @private
  37318. * @return {Array.<(Array.<number>)>|undefined} flat coordinates.
  37319. */
  37320. ol.format.GML3.prototype.readPatch_ = function(node, objectStack) {
  37321. return ol.xml.pushParseAndPop([null],
  37322. this.PATCHES_PARSERS_, node, objectStack, this);
  37323. };
  37324. /**
  37325. * @param {Node} node Node.
  37326. * @param {Array.<*>} objectStack Object stack.
  37327. * @private
  37328. * @return {Array.<number>|undefined} flat coordinates.
  37329. */
  37330. ol.format.GML3.prototype.readSegment_ = function(node, objectStack) {
  37331. return ol.xml.pushParseAndPop([null],
  37332. this.SEGMENTS_PARSERS_, node, objectStack, this);
  37333. };
  37334. /**
  37335. * @param {Node} node Node.
  37336. * @param {Array.<*>} objectStack Object stack.
  37337. * @private
  37338. * @return {Array.<(Array.<number>)>|undefined} flat coordinates.
  37339. */
  37340. ol.format.GML3.prototype.readPolygonPatch_ = function(node, objectStack) {
  37341. return ol.xml.pushParseAndPop([null],
  37342. this.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack, this);
  37343. };
  37344. /**
  37345. * @param {Node} node Node.
  37346. * @param {Array.<*>} objectStack Object stack.
  37347. * @private
  37348. * @return {Array.<number>|undefined} flat coordinates.
  37349. */
  37350. ol.format.GML3.prototype.readLineStringSegment_ = function(node, objectStack) {
  37351. return ol.xml.pushParseAndPop([null],
  37352. this.GEOMETRY_FLAT_COORDINATES_PARSERS_,
  37353. node, objectStack, this);
  37354. };
  37355. /**
  37356. * @param {Node} node Node.
  37357. * @param {Array.<*>} objectStack Object stack.
  37358. * @private
  37359. */
  37360. ol.format.GML3.prototype.interiorParser_ = function(node, objectStack) {
  37361. /** @type {Array.<number>|undefined} */
  37362. var flatLinearRing = ol.xml.pushParseAndPop(undefined,
  37363. this.RING_PARSERS, node, objectStack, this);
  37364. if (flatLinearRing) {
  37365. var flatLinearRings = /** @type {Array.<Array.<number>>} */
  37366. (objectStack[objectStack.length - 1]);
  37367. flatLinearRings.push(flatLinearRing);
  37368. }
  37369. };
  37370. /**
  37371. * @param {Node} node Node.
  37372. * @param {Array.<*>} objectStack Object stack.
  37373. * @private
  37374. */
  37375. ol.format.GML3.prototype.exteriorParser_ = function(node, objectStack) {
  37376. /** @type {Array.<number>|undefined} */
  37377. var flatLinearRing = ol.xml.pushParseAndPop(undefined,
  37378. this.RING_PARSERS, node, objectStack, this);
  37379. if (flatLinearRing) {
  37380. var flatLinearRings = /** @type {Array.<Array.<number>>} */
  37381. (objectStack[objectStack.length - 1]);
  37382. flatLinearRings[0] = flatLinearRing;
  37383. }
  37384. };
  37385. /**
  37386. * @param {Node} node Node.
  37387. * @param {Array.<*>} objectStack Object stack.
  37388. * @private
  37389. * @return {ol.geom.Polygon|undefined} Polygon.
  37390. */
  37391. ol.format.GML3.prototype.readSurface_ = function(node, objectStack) {
  37392. /** @type {Array.<Array.<number>>} */
  37393. var flatLinearRings = ol.xml.pushParseAndPop([null],
  37394. this.SURFACE_PARSERS_, node, objectStack, this);
  37395. if (flatLinearRings && flatLinearRings[0]) {
  37396. var polygon = new ol.geom.Polygon(null);
  37397. var flatCoordinates = flatLinearRings[0];
  37398. var ends = [flatCoordinates.length];
  37399. var i, ii;
  37400. for (i = 1, ii = flatLinearRings.length; i < ii; ++i) {
  37401. ol.array.extend(flatCoordinates, flatLinearRings[i]);
  37402. ends.push(flatCoordinates.length);
  37403. }
  37404. polygon.setFlatCoordinates(
  37405. ol.geom.GeometryLayout.XYZ, flatCoordinates, ends);
  37406. return polygon;
  37407. } else {
  37408. return undefined;
  37409. }
  37410. };
  37411. /**
  37412. * @param {Node} node Node.
  37413. * @param {Array.<*>} objectStack Object stack.
  37414. * @private
  37415. * @return {ol.geom.LineString|undefined} LineString.
  37416. */
  37417. ol.format.GML3.prototype.readCurve_ = function(node, objectStack) {
  37418. /** @type {Array.<number>} */
  37419. var flatCoordinates = ol.xml.pushParseAndPop([null],
  37420. this.CURVE_PARSERS_, node, objectStack, this);
  37421. if (flatCoordinates) {
  37422. var lineString = new ol.geom.LineString(null);
  37423. lineString.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates);
  37424. return lineString;
  37425. } else {
  37426. return undefined;
  37427. }
  37428. };
  37429. /**
  37430. * @param {Node} node Node.
  37431. * @param {Array.<*>} objectStack Object stack.
  37432. * @private
  37433. * @return {ol.Extent|undefined} Envelope.
  37434. */
  37435. ol.format.GML3.prototype.readEnvelope_ = function(node, objectStack) {
  37436. /** @type {Array.<number>} */
  37437. var flatCoordinates = ol.xml.pushParseAndPop([null],
  37438. this.ENVELOPE_PARSERS_, node, objectStack, this);
  37439. return ol.extent.createOrUpdate(flatCoordinates[1][0],
  37440. flatCoordinates[1][1], flatCoordinates[2][0],
  37441. flatCoordinates[2][1]);
  37442. };
  37443. /**
  37444. * @param {Node} node Node.
  37445. * @param {Array.<*>} objectStack Object stack.
  37446. * @private
  37447. * @return {Array.<number>|undefined} Flat coordinates.
  37448. */
  37449. ol.format.GML3.prototype.readFlatPos_ = function(node, objectStack) {
  37450. var s = ol.xml.getAllTextContent(node, false);
  37451. var re = /^\s*([+\-]?\d*\.?\d+(?:[eE][+\-]?\d+)?)\s*/;
  37452. /** @type {Array.<number>} */
  37453. var flatCoordinates = [];
  37454. var m;
  37455. while ((m = re.exec(s))) {
  37456. flatCoordinates.push(parseFloat(m[1]));
  37457. s = s.substr(m[0].length);
  37458. }
  37459. if (s !== '') {
  37460. return undefined;
  37461. }
  37462. var context = objectStack[0];
  37463. var containerSrs = context['srsName'];
  37464. var axisOrientation = 'enu';
  37465. if (containerSrs) {
  37466. var proj = ol.proj.get(containerSrs);
  37467. axisOrientation = proj.getAxisOrientation();
  37468. }
  37469. if (axisOrientation === 'neu') {
  37470. var i, ii;
  37471. for (i = 0, ii = flatCoordinates.length; i < ii; i += 3) {
  37472. var y = flatCoordinates[i];
  37473. var x = flatCoordinates[i + 1];
  37474. flatCoordinates[i] = x;
  37475. flatCoordinates[i + 1] = y;
  37476. }
  37477. }
  37478. var len = flatCoordinates.length;
  37479. if (len == 2) {
  37480. flatCoordinates.push(0);
  37481. }
  37482. if (len === 0) {
  37483. return undefined;
  37484. }
  37485. return flatCoordinates;
  37486. };
  37487. /**
  37488. * @param {Node} node Node.
  37489. * @param {Array.<*>} objectStack Object stack.
  37490. * @private
  37491. * @return {Array.<number>|undefined} Flat coordinates.
  37492. */
  37493. ol.format.GML3.prototype.readFlatPosList_ = function(node, objectStack) {
  37494. var s = ol.xml.getAllTextContent(node, false).replace(/^\s*|\s*$/g, '');
  37495. var context = objectStack[0];
  37496. var containerSrs = context['srsName'];
  37497. var containerDimension = node.parentNode.getAttribute('srsDimension');
  37498. var axisOrientation = 'enu';
  37499. if (containerSrs) {
  37500. var proj = ol.proj.get(containerSrs);
  37501. axisOrientation = proj.getAxisOrientation();
  37502. }
  37503. var coords = s.split(/\s+/);
  37504. // The "dimension" attribute is from the GML 3.0.1 spec.
  37505. var dim = 2;
  37506. if (node.getAttribute('srsDimension')) {
  37507. dim = ol.format.XSD.readNonNegativeIntegerString(
  37508. node.getAttribute('srsDimension'));
  37509. } else if (node.getAttribute('dimension')) {
  37510. dim = ol.format.XSD.readNonNegativeIntegerString(
  37511. node.getAttribute('dimension'));
  37512. } else if (containerDimension) {
  37513. dim = ol.format.XSD.readNonNegativeIntegerString(containerDimension);
  37514. }
  37515. var x, y, z;
  37516. var flatCoordinates = [];
  37517. for (var i = 0, ii = coords.length; i < ii; i += dim) {
  37518. x = parseFloat(coords[i]);
  37519. y = parseFloat(coords[i + 1]);
  37520. z = (dim === 3) ? parseFloat(coords[i + 2]) : 0;
  37521. if (axisOrientation.substr(0, 2) === 'en') {
  37522. flatCoordinates.push(x, y, z);
  37523. } else {
  37524. flatCoordinates.push(y, x, z);
  37525. }
  37526. }
  37527. return flatCoordinates;
  37528. };
  37529. /**
  37530. * @const
  37531. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  37532. * @private
  37533. */
  37534. ol.format.GML3.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = {
  37535. 'http://www.opengis.net/gml': {
  37536. 'pos': ol.xml.makeReplacer(ol.format.GML3.prototype.readFlatPos_),
  37537. 'posList': ol.xml.makeReplacer(ol.format.GML3.prototype.readFlatPosList_)
  37538. }
  37539. };
  37540. /**
  37541. * @const
  37542. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  37543. * @private
  37544. */
  37545. ol.format.GML3.prototype.FLAT_LINEAR_RINGS_PARSERS_ = {
  37546. 'http://www.opengis.net/gml': {
  37547. 'interior': ol.format.GML3.prototype.interiorParser_,
  37548. 'exterior': ol.format.GML3.prototype.exteriorParser_
  37549. }
  37550. };
  37551. /**
  37552. * @const
  37553. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  37554. * @private
  37555. */
  37556. ol.format.GML3.prototype.GEOMETRY_PARSERS_ = {
  37557. 'http://www.opengis.net/gml': {
  37558. 'Point': ol.xml.makeReplacer(ol.format.GMLBase.prototype.readPoint),
  37559. 'MultiPoint': ol.xml.makeReplacer(
  37560. ol.format.GMLBase.prototype.readMultiPoint),
  37561. 'LineString': ol.xml.makeReplacer(
  37562. ol.format.GMLBase.prototype.readLineString),
  37563. 'MultiLineString': ol.xml.makeReplacer(
  37564. ol.format.GMLBase.prototype.readMultiLineString),
  37565. 'LinearRing': ol.xml.makeReplacer(
  37566. ol.format.GMLBase.prototype.readLinearRing),
  37567. 'Polygon': ol.xml.makeReplacer(ol.format.GMLBase.prototype.readPolygon),
  37568. 'MultiPolygon': ol.xml.makeReplacer(
  37569. ol.format.GMLBase.prototype.readMultiPolygon),
  37570. 'Surface': ol.xml.makeReplacer(ol.format.GML3.prototype.readSurface_),
  37571. 'MultiSurface': ol.xml.makeReplacer(
  37572. ol.format.GML3.prototype.readMultiSurface_),
  37573. 'Curve': ol.xml.makeReplacer(ol.format.GML3.prototype.readCurve_),
  37574. 'MultiCurve': ol.xml.makeReplacer(
  37575. ol.format.GML3.prototype.readMultiCurve_),
  37576. 'Envelope': ol.xml.makeReplacer(ol.format.GML3.prototype.readEnvelope_)
  37577. }
  37578. };
  37579. /**
  37580. * @const
  37581. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  37582. * @private
  37583. */
  37584. ol.format.GML3.prototype.MULTICURVE_PARSERS_ = {
  37585. 'http://www.opengis.net/gml': {
  37586. 'curveMember': ol.xml.makeArrayPusher(
  37587. ol.format.GML3.prototype.curveMemberParser_),
  37588. 'curveMembers': ol.xml.makeArrayPusher(
  37589. ol.format.GML3.prototype.curveMemberParser_)
  37590. }
  37591. };
  37592. /**
  37593. * @const
  37594. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  37595. * @private
  37596. */
  37597. ol.format.GML3.prototype.MULTISURFACE_PARSERS_ = {
  37598. 'http://www.opengis.net/gml': {
  37599. 'surfaceMember': ol.xml.makeArrayPusher(
  37600. ol.format.GML3.prototype.surfaceMemberParser_),
  37601. 'surfaceMembers': ol.xml.makeArrayPusher(
  37602. ol.format.GML3.prototype.surfaceMemberParser_)
  37603. }
  37604. };
  37605. /**
  37606. * @const
  37607. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  37608. * @private
  37609. */
  37610. ol.format.GML3.prototype.CURVEMEMBER_PARSERS_ = {
  37611. 'http://www.opengis.net/gml': {
  37612. 'LineString': ol.xml.makeArrayPusher(
  37613. ol.format.GMLBase.prototype.readLineString),
  37614. 'Curve': ol.xml.makeArrayPusher(ol.format.GML3.prototype.readCurve_)
  37615. }
  37616. };
  37617. /**
  37618. * @const
  37619. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  37620. * @private
  37621. */
  37622. ol.format.GML3.prototype.SURFACEMEMBER_PARSERS_ = {
  37623. 'http://www.opengis.net/gml': {
  37624. 'Polygon': ol.xml.makeArrayPusher(ol.format.GMLBase.prototype.readPolygon),
  37625. 'Surface': ol.xml.makeArrayPusher(ol.format.GML3.prototype.readSurface_)
  37626. }
  37627. };
  37628. /**
  37629. * @const
  37630. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  37631. * @private
  37632. */
  37633. ol.format.GML3.prototype.SURFACE_PARSERS_ = {
  37634. 'http://www.opengis.net/gml': {
  37635. 'patches': ol.xml.makeReplacer(ol.format.GML3.prototype.readPatch_)
  37636. }
  37637. };
  37638. /**
  37639. * @const
  37640. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  37641. * @private
  37642. */
  37643. ol.format.GML3.prototype.CURVE_PARSERS_ = {
  37644. 'http://www.opengis.net/gml': {
  37645. 'segments': ol.xml.makeReplacer(ol.format.GML3.prototype.readSegment_)
  37646. }
  37647. };
  37648. /**
  37649. * @const
  37650. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  37651. * @private
  37652. */
  37653. ol.format.GML3.prototype.ENVELOPE_PARSERS_ = {
  37654. 'http://www.opengis.net/gml': {
  37655. 'lowerCorner': ol.xml.makeArrayPusher(
  37656. ol.format.GML3.prototype.readFlatPosList_),
  37657. 'upperCorner': ol.xml.makeArrayPusher(
  37658. ol.format.GML3.prototype.readFlatPosList_)
  37659. }
  37660. };
  37661. /**
  37662. * @const
  37663. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  37664. * @private
  37665. */
  37666. ol.format.GML3.prototype.PATCHES_PARSERS_ = {
  37667. 'http://www.opengis.net/gml': {
  37668. 'PolygonPatch': ol.xml.makeReplacer(
  37669. ol.format.GML3.prototype.readPolygonPatch_)
  37670. }
  37671. };
  37672. /**
  37673. * @const
  37674. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  37675. * @private
  37676. */
  37677. ol.format.GML3.prototype.SEGMENTS_PARSERS_ = {
  37678. 'http://www.opengis.net/gml': {
  37679. 'LineStringSegment': ol.xml.makeReplacer(
  37680. ol.format.GML3.prototype.readLineStringSegment_)
  37681. }
  37682. };
  37683. /**
  37684. * @param {Node} node Node.
  37685. * @param {ol.geom.Point} value Point geometry.
  37686. * @param {Array.<*>} objectStack Node stack.
  37687. * @private
  37688. */
  37689. ol.format.GML3.prototype.writePos_ = function(node, value, objectStack) {
  37690. var context = objectStack[objectStack.length - 1];
  37691. var hasZ = context['hasZ'];
  37692. var srsName = context['srsName'];
  37693. var axisOrientation = 'enu';
  37694. if (srsName) {
  37695. axisOrientation = ol.proj.get(srsName).getAxisOrientation();
  37696. }
  37697. var point = value.getCoordinates();
  37698. var coords;
  37699. // only 2d for simple features profile
  37700. if (axisOrientation.substr(0, 2) === 'en') {
  37701. coords = (point[0] + ' ' + point[1]);
  37702. } else {
  37703. coords = (point[1] + ' ' + point[0]);
  37704. }
  37705. if (hasZ) {
  37706. // For newly created points, Z can be undefined.
  37707. var z = point[2] || 0;
  37708. coords += ' ' + z;
  37709. }
  37710. ol.format.XSD.writeStringTextNode(node, coords);
  37711. };
  37712. /**
  37713. * @param {Array.<number>} point Point geometry.
  37714. * @param {string=} opt_srsName Optional srsName
  37715. * @param {boolean=} opt_hasZ whether the geometry has a Z coordinate (is 3D) or not.
  37716. * @return {string} The coords string.
  37717. * @private
  37718. */
  37719. ol.format.GML3.prototype.getCoords_ = function(point, opt_srsName, opt_hasZ) {
  37720. var axisOrientation = 'enu';
  37721. if (opt_srsName) {
  37722. axisOrientation = ol.proj.get(opt_srsName).getAxisOrientation();
  37723. }
  37724. var coords = ((axisOrientation.substr(0, 2) === 'en') ?
  37725. point[0] + ' ' + point[1] :
  37726. point[1] + ' ' + point[0]);
  37727. if (opt_hasZ) {
  37728. // For newly created points, Z can be undefined.
  37729. var z = point[2] || 0;
  37730. coords += ' ' + z;
  37731. }
  37732. return coords;
  37733. };
  37734. /**
  37735. * @param {Node} node Node.
  37736. * @param {ol.geom.LineString|ol.geom.LinearRing} value Geometry.
  37737. * @param {Array.<*>} objectStack Node stack.
  37738. * @private
  37739. */
  37740. ol.format.GML3.prototype.writePosList_ = function(node, value, objectStack) {
  37741. var context = objectStack[objectStack.length - 1];
  37742. var hasZ = context['hasZ'];
  37743. var srsName = context['srsName'];
  37744. // only 2d for simple features profile
  37745. var points = value.getCoordinates();
  37746. var len = points.length;
  37747. var parts = new Array(len);
  37748. var point;
  37749. for (var i = 0; i < len; ++i) {
  37750. point = points[i];
  37751. parts[i] = this.getCoords_(point, srsName, hasZ);
  37752. }
  37753. ol.format.XSD.writeStringTextNode(node, parts.join(' '));
  37754. };
  37755. /**
  37756. * @param {Node} node Node.
  37757. * @param {ol.geom.Point} geometry Point geometry.
  37758. * @param {Array.<*>} objectStack Node stack.
  37759. * @private
  37760. */
  37761. ol.format.GML3.prototype.writePoint_ = function(node, geometry, objectStack) {
  37762. var context = objectStack[objectStack.length - 1];
  37763. var srsName = context['srsName'];
  37764. if (srsName) {
  37765. node.setAttribute('srsName', srsName);
  37766. }
  37767. var pos = ol.xml.createElementNS(node.namespaceURI, 'pos');
  37768. node.appendChild(pos);
  37769. this.writePos_(pos, geometry, objectStack);
  37770. };
  37771. /**
  37772. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  37773. * @private
  37774. */
  37775. ol.format.GML3.ENVELOPE_SERIALIZERS_ = {
  37776. 'http://www.opengis.net/gml': {
  37777. 'lowerCorner': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  37778. 'upperCorner': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode)
  37779. }
  37780. };
  37781. /**
  37782. * @param {Node} node Node.
  37783. * @param {ol.Extent} extent Extent.
  37784. * @param {Array.<*>} objectStack Node stack.
  37785. */
  37786. ol.format.GML3.prototype.writeEnvelope = function(node, extent, objectStack) {
  37787. var context = objectStack[objectStack.length - 1];
  37788. var srsName = context['srsName'];
  37789. if (srsName) {
  37790. node.setAttribute('srsName', srsName);
  37791. }
  37792. var keys = ['lowerCorner', 'upperCorner'];
  37793. var values = [extent[0] + ' ' + extent[1], extent[2] + ' ' + extent[3]];
  37794. ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
  37795. ({node: node}), ol.format.GML3.ENVELOPE_SERIALIZERS_,
  37796. ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
  37797. values,
  37798. objectStack, keys, this);
  37799. };
  37800. /**
  37801. * @param {Node} node Node.
  37802. * @param {ol.geom.LinearRing} geometry LinearRing geometry.
  37803. * @param {Array.<*>} objectStack Node stack.
  37804. * @private
  37805. */
  37806. ol.format.GML3.prototype.writeLinearRing_ = function(node, geometry, objectStack) {
  37807. var context = objectStack[objectStack.length - 1];
  37808. var srsName = context['srsName'];
  37809. if (srsName) {
  37810. node.setAttribute('srsName', srsName);
  37811. }
  37812. var posList = ol.xml.createElementNS(node.namespaceURI, 'posList');
  37813. node.appendChild(posList);
  37814. this.writePosList_(posList, geometry, objectStack);
  37815. };
  37816. /**
  37817. * @param {*} value Value.
  37818. * @param {Array.<*>} objectStack Object stack.
  37819. * @param {string=} opt_nodeName Node name.
  37820. * @return {Node} Node.
  37821. * @private
  37822. */
  37823. ol.format.GML3.prototype.RING_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
  37824. var context = objectStack[objectStack.length - 1];
  37825. var parentNode = context.node;
  37826. var exteriorWritten = context['exteriorWritten'];
  37827. if (exteriorWritten === undefined) {
  37828. context['exteriorWritten'] = true;
  37829. }
  37830. return ol.xml.createElementNS(parentNode.namespaceURI,
  37831. exteriorWritten !== undefined ? 'interior' : 'exterior');
  37832. };
  37833. /**
  37834. * @param {Node} node Node.
  37835. * @param {ol.geom.Polygon} geometry Polygon geometry.
  37836. * @param {Array.<*>} objectStack Node stack.
  37837. * @private
  37838. */
  37839. ol.format.GML3.prototype.writeSurfaceOrPolygon_ = function(node, geometry, objectStack) {
  37840. var context = objectStack[objectStack.length - 1];
  37841. var hasZ = context['hasZ'];
  37842. var srsName = context['srsName'];
  37843. if (node.nodeName !== 'PolygonPatch' && srsName) {
  37844. node.setAttribute('srsName', srsName);
  37845. }
  37846. if (node.nodeName === 'Polygon' || node.nodeName === 'PolygonPatch') {
  37847. var rings = geometry.getLinearRings();
  37848. ol.xml.pushSerializeAndPop(
  37849. {node: node, hasZ: hasZ, srsName: srsName},
  37850. ol.format.GML3.RING_SERIALIZERS_,
  37851. this.RING_NODE_FACTORY_,
  37852. rings, objectStack, undefined, this);
  37853. } else if (node.nodeName === 'Surface') {
  37854. var patches = ol.xml.createElementNS(node.namespaceURI, 'patches');
  37855. node.appendChild(patches);
  37856. this.writeSurfacePatches_(
  37857. patches, geometry, objectStack);
  37858. }
  37859. };
  37860. /**
  37861. * @param {Node} node Node.
  37862. * @param {ol.geom.LineString} geometry LineString geometry.
  37863. * @param {Array.<*>} objectStack Node stack.
  37864. * @private
  37865. */
  37866. ol.format.GML3.prototype.writeCurveOrLineString_ = function(node, geometry, objectStack) {
  37867. var context = objectStack[objectStack.length - 1];
  37868. var srsName = context['srsName'];
  37869. if (node.nodeName !== 'LineStringSegment' && srsName) {
  37870. node.setAttribute('srsName', srsName);
  37871. }
  37872. if (node.nodeName === 'LineString' ||
  37873. node.nodeName === 'LineStringSegment') {
  37874. var posList = ol.xml.createElementNS(node.namespaceURI, 'posList');
  37875. node.appendChild(posList);
  37876. this.writePosList_(posList, geometry, objectStack);
  37877. } else if (node.nodeName === 'Curve') {
  37878. var segments = ol.xml.createElementNS(node.namespaceURI, 'segments');
  37879. node.appendChild(segments);
  37880. this.writeCurveSegments_(segments,
  37881. geometry, objectStack);
  37882. }
  37883. };
  37884. /**
  37885. * @param {Node} node Node.
  37886. * @param {ol.geom.MultiPolygon} geometry MultiPolygon geometry.
  37887. * @param {Array.<*>} objectStack Node stack.
  37888. * @private
  37889. */
  37890. ol.format.GML3.prototype.writeMultiSurfaceOrPolygon_ = function(node, geometry, objectStack) {
  37891. var context = objectStack[objectStack.length - 1];
  37892. var hasZ = context['hasZ'];
  37893. var srsName = context['srsName'];
  37894. var surface = context['surface'];
  37895. if (srsName) {
  37896. node.setAttribute('srsName', srsName);
  37897. }
  37898. var polygons = geometry.getPolygons();
  37899. ol.xml.pushSerializeAndPop({node: node, hasZ: hasZ, srsName: srsName, surface: surface},
  37900. ol.format.GML3.SURFACEORPOLYGONMEMBER_SERIALIZERS_,
  37901. this.MULTIGEOMETRY_MEMBER_NODE_FACTORY_, polygons,
  37902. objectStack, undefined, this);
  37903. };
  37904. /**
  37905. * @param {Node} node Node.
  37906. * @param {ol.geom.MultiPoint} geometry MultiPoint geometry.
  37907. * @param {Array.<*>} objectStack Node stack.
  37908. * @private
  37909. */
  37910. ol.format.GML3.prototype.writeMultiPoint_ = function(node, geometry,
  37911. objectStack) {
  37912. var context = objectStack[objectStack.length - 1];
  37913. var srsName = context['srsName'];
  37914. var hasZ = context['hasZ'];
  37915. if (srsName) {
  37916. node.setAttribute('srsName', srsName);
  37917. }
  37918. var points = geometry.getPoints();
  37919. ol.xml.pushSerializeAndPop({node: node, hasZ: hasZ, srsName: srsName},
  37920. ol.format.GML3.POINTMEMBER_SERIALIZERS_,
  37921. ol.xml.makeSimpleNodeFactory('pointMember'), points,
  37922. objectStack, undefined, this);
  37923. };
  37924. /**
  37925. * @param {Node} node Node.
  37926. * @param {ol.geom.MultiLineString} geometry MultiLineString geometry.
  37927. * @param {Array.<*>} objectStack Node stack.
  37928. * @private
  37929. */
  37930. ol.format.GML3.prototype.writeMultiCurveOrLineString_ = function(node, geometry, objectStack) {
  37931. var context = objectStack[objectStack.length - 1];
  37932. var hasZ = context['hasZ'];
  37933. var srsName = context['srsName'];
  37934. var curve = context['curve'];
  37935. if (srsName) {
  37936. node.setAttribute('srsName', srsName);
  37937. }
  37938. var lines = geometry.getLineStrings();
  37939. ol.xml.pushSerializeAndPop({node: node, hasZ: hasZ, srsName: srsName, curve: curve},
  37940. ol.format.GML3.LINESTRINGORCURVEMEMBER_SERIALIZERS_,
  37941. this.MULTIGEOMETRY_MEMBER_NODE_FACTORY_, lines,
  37942. objectStack, undefined, this);
  37943. };
  37944. /**
  37945. * @param {Node} node Node.
  37946. * @param {ol.geom.LinearRing} ring LinearRing geometry.
  37947. * @param {Array.<*>} objectStack Node stack.
  37948. * @private
  37949. */
  37950. ol.format.GML3.prototype.writeRing_ = function(node, ring, objectStack) {
  37951. var linearRing = ol.xml.createElementNS(node.namespaceURI, 'LinearRing');
  37952. node.appendChild(linearRing);
  37953. this.writeLinearRing_(linearRing, ring, objectStack);
  37954. };
  37955. /**
  37956. * @param {Node} node Node.
  37957. * @param {ol.geom.Polygon} polygon Polygon geometry.
  37958. * @param {Array.<*>} objectStack Node stack.
  37959. * @private
  37960. */
  37961. ol.format.GML3.prototype.writeSurfaceOrPolygonMember_ = function(node, polygon, objectStack) {
  37962. var child = this.GEOMETRY_NODE_FACTORY_(
  37963. polygon, objectStack);
  37964. if (child) {
  37965. node.appendChild(child);
  37966. this.writeSurfaceOrPolygon_(child, polygon, objectStack);
  37967. }
  37968. };
  37969. /**
  37970. * @param {Node} node Node.
  37971. * @param {ol.geom.Point} point Point geometry.
  37972. * @param {Array.<*>} objectStack Node stack.
  37973. * @private
  37974. */
  37975. ol.format.GML3.prototype.writePointMember_ = function(node, point, objectStack) {
  37976. var child = ol.xml.createElementNS(node.namespaceURI, 'Point');
  37977. node.appendChild(child);
  37978. this.writePoint_(child, point, objectStack);
  37979. };
  37980. /**
  37981. * @param {Node} node Node.
  37982. * @param {ol.geom.LineString} line LineString geometry.
  37983. * @param {Array.<*>} objectStack Node stack.
  37984. * @private
  37985. */
  37986. ol.format.GML3.prototype.writeLineStringOrCurveMember_ = function(node, line, objectStack) {
  37987. var child = this.GEOMETRY_NODE_FACTORY_(line, objectStack);
  37988. if (child) {
  37989. node.appendChild(child);
  37990. this.writeCurveOrLineString_(child, line, objectStack);
  37991. }
  37992. };
  37993. /**
  37994. * @param {Node} node Node.
  37995. * @param {ol.geom.Polygon} polygon Polygon geometry.
  37996. * @param {Array.<*>} objectStack Node stack.
  37997. * @private
  37998. */
  37999. ol.format.GML3.prototype.writeSurfacePatches_ = function(node, polygon, objectStack) {
  38000. var child = ol.xml.createElementNS(node.namespaceURI, 'PolygonPatch');
  38001. node.appendChild(child);
  38002. this.writeSurfaceOrPolygon_(child, polygon, objectStack);
  38003. };
  38004. /**
  38005. * @param {Node} node Node.
  38006. * @param {ol.geom.LineString} line LineString geometry.
  38007. * @param {Array.<*>} objectStack Node stack.
  38008. * @private
  38009. */
  38010. ol.format.GML3.prototype.writeCurveSegments_ = function(node, line, objectStack) {
  38011. var child = ol.xml.createElementNS(node.namespaceURI,
  38012. 'LineStringSegment');
  38013. node.appendChild(child);
  38014. this.writeCurveOrLineString_(child, line, objectStack);
  38015. };
  38016. /**
  38017. * @param {Node} node Node.
  38018. * @param {ol.geom.Geometry|ol.Extent} geometry Geometry.
  38019. * @param {Array.<*>} objectStack Node stack.
  38020. */
  38021. ol.format.GML3.prototype.writeGeometryElement = function(node, geometry, objectStack) {
  38022. var context = /** @type {olx.format.WriteOptions} */ (objectStack[objectStack.length - 1]);
  38023. var item = ol.obj.assign({}, context);
  38024. item.node = node;
  38025. var value;
  38026. if (Array.isArray(geometry)) {
  38027. if (context.dataProjection) {
  38028. value = ol.proj.transformExtent(
  38029. geometry, context.featureProjection, context.dataProjection);
  38030. } else {
  38031. value = geometry;
  38032. }
  38033. } else {
  38034. value =
  38035. ol.format.Feature.transformWithOptions(/** @type {ol.geom.Geometry} */ (geometry), true, context);
  38036. }
  38037. ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
  38038. (item), ol.format.GML3.GEOMETRY_SERIALIZERS_,
  38039. this.GEOMETRY_NODE_FACTORY_, [value],
  38040. objectStack, undefined, this);
  38041. };
  38042. /**
  38043. * @param {Node} node Node.
  38044. * @param {ol.Feature} feature Feature.
  38045. * @param {Array.<*>} objectStack Node stack.
  38046. */
  38047. ol.format.GML3.prototype.writeFeatureElement = function(node, feature, objectStack) {
  38048. var fid = feature.getId();
  38049. if (fid) {
  38050. node.setAttribute('fid', fid);
  38051. }
  38052. var context = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  38053. var featureNS = context['featureNS'];
  38054. var geometryName = feature.getGeometryName();
  38055. if (!context.serializers) {
  38056. context.serializers = {};
  38057. context.serializers[featureNS] = {};
  38058. }
  38059. var properties = feature.getProperties();
  38060. var keys = [], values = [];
  38061. for (var key in properties) {
  38062. var value = properties[key];
  38063. if (value !== null) {
  38064. keys.push(key);
  38065. values.push(value);
  38066. if (key == geometryName || value instanceof ol.geom.Geometry) {
  38067. if (!(key in context.serializers[featureNS])) {
  38068. context.serializers[featureNS][key] = ol.xml.makeChildAppender(
  38069. this.writeGeometryElement, this);
  38070. }
  38071. } else {
  38072. if (!(key in context.serializers[featureNS])) {
  38073. context.serializers[featureNS][key] = ol.xml.makeChildAppender(
  38074. ol.format.XSD.writeStringTextNode);
  38075. }
  38076. }
  38077. }
  38078. }
  38079. var item = ol.obj.assign({}, context);
  38080. item.node = node;
  38081. ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
  38082. (item), context.serializers,
  38083. ol.xml.makeSimpleNodeFactory(undefined, featureNS),
  38084. values,
  38085. objectStack, keys);
  38086. };
  38087. /**
  38088. * @param {Node} node Node.
  38089. * @param {Array.<ol.Feature>} features Features.
  38090. * @param {Array.<*>} objectStack Node stack.
  38091. * @private
  38092. */
  38093. ol.format.GML3.prototype.writeFeatureMembers_ = function(node, features, objectStack) {
  38094. var context = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  38095. var featureType = context['featureType'];
  38096. var featureNS = context['featureNS'];
  38097. var serializers = {};
  38098. serializers[featureNS] = {};
  38099. serializers[featureNS][featureType] = ol.xml.makeChildAppender(
  38100. this.writeFeatureElement, this);
  38101. var item = ol.obj.assign({}, context);
  38102. item.node = node;
  38103. ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
  38104. (item),
  38105. serializers,
  38106. ol.xml.makeSimpleNodeFactory(featureType, featureNS), features,
  38107. objectStack);
  38108. };
  38109. /**
  38110. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  38111. * @private
  38112. */
  38113. ol.format.GML3.SURFACEORPOLYGONMEMBER_SERIALIZERS_ = {
  38114. 'http://www.opengis.net/gml': {
  38115. 'surfaceMember': ol.xml.makeChildAppender(
  38116. ol.format.GML3.prototype.writeSurfaceOrPolygonMember_),
  38117. 'polygonMember': ol.xml.makeChildAppender(
  38118. ol.format.GML3.prototype.writeSurfaceOrPolygonMember_)
  38119. }
  38120. };
  38121. /**
  38122. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  38123. * @private
  38124. */
  38125. ol.format.GML3.POINTMEMBER_SERIALIZERS_ = {
  38126. 'http://www.opengis.net/gml': {
  38127. 'pointMember': ol.xml.makeChildAppender(
  38128. ol.format.GML3.prototype.writePointMember_)
  38129. }
  38130. };
  38131. /**
  38132. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  38133. * @private
  38134. */
  38135. ol.format.GML3.LINESTRINGORCURVEMEMBER_SERIALIZERS_ = {
  38136. 'http://www.opengis.net/gml': {
  38137. 'lineStringMember': ol.xml.makeChildAppender(
  38138. ol.format.GML3.prototype.writeLineStringOrCurveMember_),
  38139. 'curveMember': ol.xml.makeChildAppender(
  38140. ol.format.GML3.prototype.writeLineStringOrCurveMember_)
  38141. }
  38142. };
  38143. /**
  38144. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  38145. * @private
  38146. */
  38147. ol.format.GML3.RING_SERIALIZERS_ = {
  38148. 'http://www.opengis.net/gml': {
  38149. 'exterior': ol.xml.makeChildAppender(ol.format.GML3.prototype.writeRing_),
  38150. 'interior': ol.xml.makeChildAppender(ol.format.GML3.prototype.writeRing_)
  38151. }
  38152. };
  38153. /**
  38154. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  38155. * @private
  38156. */
  38157. ol.format.GML3.GEOMETRY_SERIALIZERS_ = {
  38158. 'http://www.opengis.net/gml': {
  38159. 'Curve': ol.xml.makeChildAppender(
  38160. ol.format.GML3.prototype.writeCurveOrLineString_),
  38161. 'MultiCurve': ol.xml.makeChildAppender(
  38162. ol.format.GML3.prototype.writeMultiCurveOrLineString_),
  38163. 'Point': ol.xml.makeChildAppender(ol.format.GML3.prototype.writePoint_),
  38164. 'MultiPoint': ol.xml.makeChildAppender(
  38165. ol.format.GML3.prototype.writeMultiPoint_),
  38166. 'LineString': ol.xml.makeChildAppender(
  38167. ol.format.GML3.prototype.writeCurveOrLineString_),
  38168. 'MultiLineString': ol.xml.makeChildAppender(
  38169. ol.format.GML3.prototype.writeMultiCurveOrLineString_),
  38170. 'LinearRing': ol.xml.makeChildAppender(
  38171. ol.format.GML3.prototype.writeLinearRing_),
  38172. 'Polygon': ol.xml.makeChildAppender(
  38173. ol.format.GML3.prototype.writeSurfaceOrPolygon_),
  38174. 'MultiPolygon': ol.xml.makeChildAppender(
  38175. ol.format.GML3.prototype.writeMultiSurfaceOrPolygon_),
  38176. 'Surface': ol.xml.makeChildAppender(
  38177. ol.format.GML3.prototype.writeSurfaceOrPolygon_),
  38178. 'MultiSurface': ol.xml.makeChildAppender(
  38179. ol.format.GML3.prototype.writeMultiSurfaceOrPolygon_),
  38180. 'Envelope': ol.xml.makeChildAppender(
  38181. ol.format.GML3.prototype.writeEnvelope)
  38182. }
  38183. };
  38184. /**
  38185. * @const
  38186. * @type {Object.<string, string>}
  38187. * @private
  38188. */
  38189. ol.format.GML3.MULTIGEOMETRY_TO_MEMBER_NODENAME_ = {
  38190. 'MultiLineString': 'lineStringMember',
  38191. 'MultiCurve': 'curveMember',
  38192. 'MultiPolygon': 'polygonMember',
  38193. 'MultiSurface': 'surfaceMember'
  38194. };
  38195. /**
  38196. * @const
  38197. * @param {*} value Value.
  38198. * @param {Array.<*>} objectStack Object stack.
  38199. * @param {string=} opt_nodeName Node name.
  38200. * @return {Node|undefined} Node.
  38201. * @private
  38202. */
  38203. ol.format.GML3.prototype.MULTIGEOMETRY_MEMBER_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
  38204. var parentNode = objectStack[objectStack.length - 1].node;
  38205. return ol.xml.createElementNS('http://www.opengis.net/gml',
  38206. ol.format.GML3.MULTIGEOMETRY_TO_MEMBER_NODENAME_[parentNode.nodeName]);
  38207. };
  38208. /**
  38209. * @const
  38210. * @param {*} value Value.
  38211. * @param {Array.<*>} objectStack Object stack.
  38212. * @param {string=} opt_nodeName Node name.
  38213. * @return {Node|undefined} Node.
  38214. * @private
  38215. */
  38216. ol.format.GML3.prototype.GEOMETRY_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
  38217. var context = objectStack[objectStack.length - 1];
  38218. var multiSurface = context['multiSurface'];
  38219. var surface = context['surface'];
  38220. var curve = context['curve'];
  38221. var multiCurve = context['multiCurve'];
  38222. var nodeName;
  38223. if (!Array.isArray(value)) {
  38224. nodeName = /** @type {ol.geom.Geometry} */ (value).getType();
  38225. if (nodeName === 'MultiPolygon' && multiSurface === true) {
  38226. nodeName = 'MultiSurface';
  38227. } else if (nodeName === 'Polygon' && surface === true) {
  38228. nodeName = 'Surface';
  38229. } else if (nodeName === 'LineString' && curve === true) {
  38230. nodeName = 'Curve';
  38231. } else if (nodeName === 'MultiLineString' && multiCurve === true) {
  38232. nodeName = 'MultiCurve';
  38233. }
  38234. } else {
  38235. nodeName = 'Envelope';
  38236. }
  38237. return ol.xml.createElementNS('http://www.opengis.net/gml',
  38238. nodeName);
  38239. };
  38240. /**
  38241. * Encode a geometry in GML 3.1.1 Simple Features.
  38242. *
  38243. * @param {ol.geom.Geometry} geometry Geometry.
  38244. * @param {olx.format.WriteOptions=} opt_options Options.
  38245. * @return {Node} Node.
  38246. * @override
  38247. * @api
  38248. */
  38249. ol.format.GML3.prototype.writeGeometryNode = function(geometry, opt_options) {
  38250. opt_options = this.adaptOptions(opt_options);
  38251. var geom = ol.xml.createElementNS('http://www.opengis.net/gml', 'geom');
  38252. var context = {node: geom, hasZ: this.hasZ, srsName: this.srsName,
  38253. curve: this.curve_, surface: this.surface_,
  38254. multiSurface: this.multiSurface_, multiCurve: this.multiCurve_};
  38255. if (opt_options) {
  38256. ol.obj.assign(context, opt_options);
  38257. }
  38258. this.writeGeometryElement(geom, geometry, [context]);
  38259. return geom;
  38260. };
  38261. /**
  38262. * Encode an array of features in GML 3.1.1 Simple Features.
  38263. *
  38264. * @function
  38265. * @param {Array.<ol.Feature>} features Features.
  38266. * @param {olx.format.WriteOptions=} opt_options Options.
  38267. * @return {string} Result.
  38268. * @api
  38269. */
  38270. ol.format.GML3.prototype.writeFeatures;
  38271. /**
  38272. * Encode an array of features in the GML 3.1.1 format as an XML node.
  38273. *
  38274. * @param {Array.<ol.Feature>} features Features.
  38275. * @param {olx.format.WriteOptions=} opt_options Options.
  38276. * @return {Node} Node.
  38277. * @override
  38278. * @api
  38279. */
  38280. ol.format.GML3.prototype.writeFeaturesNode = function(features, opt_options) {
  38281. opt_options = this.adaptOptions(opt_options);
  38282. var node = ol.xml.createElementNS('http://www.opengis.net/gml',
  38283. 'featureMembers');
  38284. ol.xml.setAttributeNS(node, 'http://www.w3.org/2001/XMLSchema-instance',
  38285. 'xsi:schemaLocation', this.schemaLocation);
  38286. var context = {
  38287. srsName: this.srsName,
  38288. hasZ: this.hasZ,
  38289. curve: this.curve_,
  38290. surface: this.surface_,
  38291. multiSurface: this.multiSurface_,
  38292. multiCurve: this.multiCurve_,
  38293. featureNS: this.featureNS,
  38294. featureType: this.featureType
  38295. };
  38296. if (opt_options) {
  38297. ol.obj.assign(context, opt_options);
  38298. }
  38299. this.writeFeatureMembers_(node, features, [context]);
  38300. return node;
  38301. };
  38302. goog.provide('ol.format.GML');
  38303. goog.require('ol.format.GML3');
  38304. /**
  38305. * @classdesc
  38306. * Feature format for reading and writing data in the GML format
  38307. * version 3.1.1.
  38308. * Currently only supports GML 3.1.1 Simple Features profile.
  38309. *
  38310. * @constructor
  38311. * @param {olx.format.GMLOptions=} opt_options
  38312. * Optional configuration object.
  38313. * @extends {ol.format.GMLBase}
  38314. * @api
  38315. */
  38316. ol.format.GML = ol.format.GML3;
  38317. /**
  38318. * Encode an array of features in GML 3.1.1 Simple Features.
  38319. *
  38320. * @function
  38321. * @param {Array.<ol.Feature>} features Features.
  38322. * @param {olx.format.WriteOptions=} opt_options Options.
  38323. * @return {string} Result.
  38324. * @api
  38325. */
  38326. ol.format.GML.prototype.writeFeatures;
  38327. /**
  38328. * Encode an array of features in the GML 3.1.1 format as an XML node.
  38329. *
  38330. * @function
  38331. * @param {Array.<ol.Feature>} features Features.
  38332. * @param {olx.format.WriteOptions=} opt_options Options.
  38333. * @return {Node} Node.
  38334. * @api
  38335. */
  38336. ol.format.GML.prototype.writeFeaturesNode;
  38337. goog.provide('ol.format.GML2');
  38338. goog.require('ol');
  38339. goog.require('ol.extent');
  38340. goog.require('ol.format.Feature');
  38341. goog.require('ol.format.GMLBase');
  38342. goog.require('ol.format.XSD');
  38343. goog.require('ol.geom.Geometry');
  38344. goog.require('ol.obj');
  38345. goog.require('ol.proj');
  38346. goog.require('ol.xml');
  38347. /**
  38348. * @classdesc
  38349. * Feature format for reading and writing data in the GML format,
  38350. * version 2.1.2.
  38351. *
  38352. * @constructor
  38353. * @param {olx.format.GMLOptions=} opt_options Optional configuration object.
  38354. * @extends {ol.format.GMLBase}
  38355. * @api
  38356. */
  38357. ol.format.GML2 = function(opt_options) {
  38358. var options = /** @type {olx.format.GMLOptions} */
  38359. (opt_options ? opt_options : {});
  38360. ol.format.GMLBase.call(this, options);
  38361. this.FEATURE_COLLECTION_PARSERS[ol.format.GMLBase.GMLNS][
  38362. 'featureMember'] =
  38363. ol.xml.makeArrayPusher(ol.format.GMLBase.prototype.readFeaturesInternal);
  38364. /**
  38365. * @inheritDoc
  38366. */
  38367. this.schemaLocation = options.schemaLocation ?
  38368. options.schemaLocation : ol.format.GML2.schemaLocation_;
  38369. };
  38370. ol.inherits(ol.format.GML2, ol.format.GMLBase);
  38371. /**
  38372. * @const
  38373. * @type {string}
  38374. * @private
  38375. */
  38376. ol.format.GML2.schemaLocation_ = ol.format.GMLBase.GMLNS +
  38377. ' http://schemas.opengis.net/gml/2.1.2/feature.xsd';
  38378. /**
  38379. * @param {Node} node Node.
  38380. * @param {Array.<*>} objectStack Object stack.
  38381. * @private
  38382. * @return {Array.<number>|undefined} Flat coordinates.
  38383. */
  38384. ol.format.GML2.prototype.readFlatCoordinates_ = function(node, objectStack) {
  38385. var s = ol.xml.getAllTextContent(node, false).replace(/^\s*|\s*$/g, '');
  38386. var context = /** @type {ol.XmlNodeStackItem} */ (objectStack[0]);
  38387. var containerSrs = context['srsName'];
  38388. var axisOrientation = 'enu';
  38389. if (containerSrs) {
  38390. var proj = ol.proj.get(containerSrs);
  38391. if (proj) {
  38392. axisOrientation = proj.getAxisOrientation();
  38393. }
  38394. }
  38395. var coordsGroups = s.trim().split(/\s+/);
  38396. var x, y, z;
  38397. var flatCoordinates = [];
  38398. for (var i = 0, ii = coordsGroups.length; i < ii; i++) {
  38399. var coords = coordsGroups[i].split(/,+/);
  38400. x = parseFloat(coords[0]);
  38401. y = parseFloat(coords[1]);
  38402. z = (coords.length === 3) ? parseFloat(coords[2]) : 0;
  38403. if (axisOrientation.substr(0, 2) === 'en') {
  38404. flatCoordinates.push(x, y, z);
  38405. } else {
  38406. flatCoordinates.push(y, x, z);
  38407. }
  38408. }
  38409. return flatCoordinates;
  38410. };
  38411. /**
  38412. * @param {Node} node Node.
  38413. * @param {Array.<*>} objectStack Object stack.
  38414. * @private
  38415. * @return {ol.Extent|undefined} Envelope.
  38416. */
  38417. ol.format.GML2.prototype.readBox_ = function(node, objectStack) {
  38418. /** @type {Array.<number>} */
  38419. var flatCoordinates = ol.xml.pushParseAndPop([null],
  38420. this.BOX_PARSERS_, node, objectStack, this);
  38421. return ol.extent.createOrUpdate(flatCoordinates[1][0],
  38422. flatCoordinates[1][1], flatCoordinates[1][3],
  38423. flatCoordinates[1][4]);
  38424. };
  38425. /**
  38426. * @param {Node} node Node.
  38427. * @param {Array.<*>} objectStack Object stack.
  38428. * @private
  38429. */
  38430. ol.format.GML2.prototype.innerBoundaryIsParser_ = function(node, objectStack) {
  38431. /** @type {Array.<number>|undefined} */
  38432. var flatLinearRing = ol.xml.pushParseAndPop(undefined,
  38433. this.RING_PARSERS, node, objectStack, this);
  38434. if (flatLinearRing) {
  38435. var flatLinearRings = /** @type {Array.<Array.<number>>} */
  38436. (objectStack[objectStack.length - 1]);
  38437. flatLinearRings.push(flatLinearRing);
  38438. }
  38439. };
  38440. /**
  38441. * @param {Node} node Node.
  38442. * @param {Array.<*>} objectStack Object stack.
  38443. * @private
  38444. */
  38445. ol.format.GML2.prototype.outerBoundaryIsParser_ = function(node, objectStack) {
  38446. /** @type {Array.<number>|undefined} */
  38447. var flatLinearRing = ol.xml.pushParseAndPop(undefined,
  38448. this.RING_PARSERS, node, objectStack, this);
  38449. if (flatLinearRing) {
  38450. var flatLinearRings = /** @type {Array.<Array.<number>>} */
  38451. (objectStack[objectStack.length - 1]);
  38452. flatLinearRings[0] = flatLinearRing;
  38453. }
  38454. };
  38455. /**
  38456. * @const
  38457. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  38458. * @private
  38459. */
  38460. ol.format.GML2.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = {
  38461. 'http://www.opengis.net/gml': {
  38462. 'coordinates': ol.xml.makeReplacer(
  38463. ol.format.GML2.prototype.readFlatCoordinates_)
  38464. }
  38465. };
  38466. /**
  38467. * @const
  38468. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  38469. * @private
  38470. */
  38471. ol.format.GML2.prototype.FLAT_LINEAR_RINGS_PARSERS_ = {
  38472. 'http://www.opengis.net/gml': {
  38473. 'innerBoundaryIs': ol.format.GML2.prototype.innerBoundaryIsParser_,
  38474. 'outerBoundaryIs': ol.format.GML2.prototype.outerBoundaryIsParser_
  38475. }
  38476. };
  38477. /**
  38478. * @const
  38479. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  38480. * @private
  38481. */
  38482. ol.format.GML2.prototype.BOX_PARSERS_ = {
  38483. 'http://www.opengis.net/gml': {
  38484. 'coordinates': ol.xml.makeArrayPusher(
  38485. ol.format.GML2.prototype.readFlatCoordinates_)
  38486. }
  38487. };
  38488. /**
  38489. * @const
  38490. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  38491. * @private
  38492. */
  38493. ol.format.GML2.prototype.GEOMETRY_PARSERS_ = {
  38494. 'http://www.opengis.net/gml': {
  38495. 'Point': ol.xml.makeReplacer(ol.format.GMLBase.prototype.readPoint),
  38496. 'MultiPoint': ol.xml.makeReplacer(
  38497. ol.format.GMLBase.prototype.readMultiPoint),
  38498. 'LineString': ol.xml.makeReplacer(
  38499. ol.format.GMLBase.prototype.readLineString),
  38500. 'MultiLineString': ol.xml.makeReplacer(
  38501. ol.format.GMLBase.prototype.readMultiLineString),
  38502. 'LinearRing': ol.xml.makeReplacer(
  38503. ol.format.GMLBase.prototype.readLinearRing),
  38504. 'Polygon': ol.xml.makeReplacer(ol.format.GMLBase.prototype.readPolygon),
  38505. 'MultiPolygon': ol.xml.makeReplacer(
  38506. ol.format.GMLBase.prototype.readMultiPolygon),
  38507. 'Box': ol.xml.makeReplacer(ol.format.GML2.prototype.readBox_)
  38508. }
  38509. };
  38510. /**
  38511. * @const
  38512. * @param {*} value Value.
  38513. * @param {Array.<*>} objectStack Object stack.
  38514. * @param {string=} opt_nodeName Node name.
  38515. * @return {Node|undefined} Node.
  38516. * @private
  38517. */
  38518. ol.format.GML2.prototype.GEOMETRY_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
  38519. var context = objectStack[objectStack.length - 1];
  38520. var multiSurface = context['multiSurface'];
  38521. var surface = context['surface'];
  38522. var multiCurve = context['multiCurve'];
  38523. var nodeName;
  38524. if (!Array.isArray(value)) {
  38525. nodeName = /** @type {ol.geom.Geometry} */ (value).getType();
  38526. if (nodeName === 'MultiPolygon' && multiSurface === true) {
  38527. nodeName = 'MultiSurface';
  38528. } else if (nodeName === 'Polygon' && surface === true) {
  38529. nodeName = 'Surface';
  38530. } else if (nodeName === 'MultiLineString' && multiCurve === true) {
  38531. nodeName = 'MultiCurve';
  38532. }
  38533. } else {
  38534. nodeName = 'Envelope';
  38535. }
  38536. return ol.xml.createElementNS('http://www.opengis.net/gml',
  38537. nodeName);
  38538. };
  38539. /**
  38540. * @param {Node} node Node.
  38541. * @param {ol.Feature} feature Feature.
  38542. * @param {Array.<*>} objectStack Node stack.
  38543. */
  38544. ol.format.GML2.prototype.writeFeatureElement = function(node, feature, objectStack) {
  38545. var fid = feature.getId();
  38546. if (fid) {
  38547. node.setAttribute('fid', fid);
  38548. }
  38549. var context = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  38550. var featureNS = context['featureNS'];
  38551. var geometryName = feature.getGeometryName();
  38552. if (!context.serializers) {
  38553. context.serializers = {};
  38554. context.serializers[featureNS] = {};
  38555. }
  38556. var properties = feature.getProperties();
  38557. var keys = [], values = [];
  38558. for (var key in properties) {
  38559. var value = properties[key];
  38560. if (value !== null) {
  38561. keys.push(key);
  38562. values.push(value);
  38563. if (key == geometryName || value instanceof ol.geom.Geometry) {
  38564. if (!(key in context.serializers[featureNS])) {
  38565. context.serializers[featureNS][key] = ol.xml.makeChildAppender(
  38566. this.writeGeometryElement, this);
  38567. }
  38568. } else {
  38569. if (!(key in context.serializers[featureNS])) {
  38570. context.serializers[featureNS][key] = ol.xml.makeChildAppender(
  38571. ol.format.XSD.writeStringTextNode);
  38572. }
  38573. }
  38574. }
  38575. }
  38576. var item = ol.obj.assign({}, context);
  38577. item.node = node;
  38578. ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
  38579. (item), context.serializers,
  38580. ol.xml.makeSimpleNodeFactory(undefined, featureNS),
  38581. values,
  38582. objectStack, keys);
  38583. };
  38584. /**
  38585. * @param {Node} node Node.
  38586. * @param {ol.geom.Geometry|ol.Extent} geometry Geometry.
  38587. * @param {Array.<*>} objectStack Node stack.
  38588. */
  38589. ol.format.GML2.prototype.writeGeometryElement = function(node, geometry, objectStack) {
  38590. var context = /** @type {olx.format.WriteOptions} */ (objectStack[objectStack.length - 1]);
  38591. var item = ol.obj.assign({}, context);
  38592. item.node = node;
  38593. var value;
  38594. if (Array.isArray(geometry)) {
  38595. if (context.dataProjection) {
  38596. value = ol.proj.transformExtent(
  38597. geometry, context.featureProjection, context.dataProjection);
  38598. } else {
  38599. value = geometry;
  38600. }
  38601. } else {
  38602. value =
  38603. ol.format.Feature.transformWithOptions(/** @type {ol.geom.Geometry} */ (geometry), true, context);
  38604. }
  38605. ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
  38606. (item), ol.format.GML2.GEOMETRY_SERIALIZERS_,
  38607. this.GEOMETRY_NODE_FACTORY_, [value],
  38608. objectStack, undefined, this);
  38609. };
  38610. /**
  38611. * @param {Node} node Node.
  38612. * @param {ol.geom.LineString} geometry LineString geometry.
  38613. * @param {Array.<*>} objectStack Node stack.
  38614. * @private
  38615. */
  38616. ol.format.GML2.prototype.writeCurveOrLineString_ = function(node, geometry, objectStack) {
  38617. var context = objectStack[objectStack.length - 1];
  38618. var srsName = context['srsName'];
  38619. if (node.nodeName !== 'LineStringSegment' && srsName) {
  38620. node.setAttribute('srsName', srsName);
  38621. }
  38622. if (node.nodeName === 'LineString' ||
  38623. node.nodeName === 'LineStringSegment') {
  38624. var coordinates = this.createCoordinatesNode_(node.namespaceURI);
  38625. node.appendChild(coordinates);
  38626. this.writeCoordinates_(coordinates, geometry, objectStack);
  38627. } else if (node.nodeName === 'Curve') {
  38628. var segments = ol.xml.createElementNS(node.namespaceURI, 'segments');
  38629. node.appendChild(segments);
  38630. this.writeCurveSegments_(segments,
  38631. geometry, objectStack);
  38632. }
  38633. };
  38634. /**
  38635. * @param {string} namespaceURI XML namespace.
  38636. * @returns {Node} coordinates node.
  38637. * @private
  38638. */
  38639. ol.format.GML2.prototype.createCoordinatesNode_ = function(namespaceURI) {
  38640. var coordinates = ol.xml.createElementNS(namespaceURI, 'coordinates');
  38641. coordinates.setAttribute('decimal', '.');
  38642. coordinates.setAttribute('cs', ',');
  38643. coordinates.setAttribute('ts', ' ');
  38644. return coordinates;
  38645. };
  38646. /**
  38647. * @param {Node} node Node.
  38648. * @param {ol.geom.LineString|ol.geom.LinearRing} value Geometry.
  38649. * @param {Array.<*>} objectStack Node stack.
  38650. * @private
  38651. */
  38652. ol.format.GML2.prototype.writeCoordinates_ = function(node, value, objectStack) {
  38653. var context = objectStack[objectStack.length - 1];
  38654. var hasZ = context['hasZ'];
  38655. var srsName = context['srsName'];
  38656. // only 2d for simple features profile
  38657. var points = value.getCoordinates();
  38658. var len = points.length;
  38659. var parts = new Array(len);
  38660. var point;
  38661. for (var i = 0; i < len; ++i) {
  38662. point = points[i];
  38663. parts[i] = this.getCoords_(point, srsName, hasZ);
  38664. }
  38665. ol.format.XSD.writeStringTextNode(node, parts.join(' '));
  38666. };
  38667. /**
  38668. * @param {Node} node Node.
  38669. * @param {ol.geom.LineString} line LineString geometry.
  38670. * @param {Array.<*>} objectStack Node stack.
  38671. * @private
  38672. */
  38673. ol.format.GML2.prototype.writeCurveSegments_ = function(node, line, objectStack) {
  38674. var child = ol.xml.createElementNS(node.namespaceURI,
  38675. 'LineStringSegment');
  38676. node.appendChild(child);
  38677. this.writeCurveOrLineString_(child, line, objectStack);
  38678. };
  38679. /**
  38680. * @param {Node} node Node.
  38681. * @param {ol.geom.Polygon} geometry Polygon geometry.
  38682. * @param {Array.<*>} objectStack Node stack.
  38683. * @private
  38684. */
  38685. ol.format.GML2.prototype.writeSurfaceOrPolygon_ = function(node, geometry, objectStack) {
  38686. var context = objectStack[objectStack.length - 1];
  38687. var hasZ = context['hasZ'];
  38688. var srsName = context['srsName'];
  38689. if (node.nodeName !== 'PolygonPatch' && srsName) {
  38690. node.setAttribute('srsName', srsName);
  38691. }
  38692. if (node.nodeName === 'Polygon' || node.nodeName === 'PolygonPatch') {
  38693. var rings = geometry.getLinearRings();
  38694. ol.xml.pushSerializeAndPop(
  38695. {node: node, hasZ: hasZ, srsName: srsName},
  38696. ol.format.GML2.RING_SERIALIZERS_,
  38697. this.RING_NODE_FACTORY_,
  38698. rings, objectStack, undefined, this);
  38699. } else if (node.nodeName === 'Surface') {
  38700. var patches = ol.xml.createElementNS(node.namespaceURI, 'patches');
  38701. node.appendChild(patches);
  38702. this.writeSurfacePatches_(
  38703. patches, geometry, objectStack);
  38704. }
  38705. };
  38706. /**
  38707. * @param {*} value Value.
  38708. * @param {Array.<*>} objectStack Object stack.
  38709. * @param {string=} opt_nodeName Node name.
  38710. * @return {Node} Node.
  38711. * @private
  38712. */
  38713. ol.format.GML2.prototype.RING_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
  38714. var context = objectStack[objectStack.length - 1];
  38715. var parentNode = context.node;
  38716. var exteriorWritten = context['exteriorWritten'];
  38717. if (exteriorWritten === undefined) {
  38718. context['exteriorWritten'] = true;
  38719. }
  38720. return ol.xml.createElementNS(parentNode.namespaceURI,
  38721. exteriorWritten !== undefined ? 'innerBoundaryIs' : 'outerBoundaryIs');
  38722. };
  38723. /**
  38724. * @param {Node} node Node.
  38725. * @param {ol.geom.Polygon} polygon Polygon geometry.
  38726. * @param {Array.<*>} objectStack Node stack.
  38727. * @private
  38728. */
  38729. ol.format.GML2.prototype.writeSurfacePatches_ = function(node, polygon, objectStack) {
  38730. var child = ol.xml.createElementNS(node.namespaceURI, 'PolygonPatch');
  38731. node.appendChild(child);
  38732. this.writeSurfaceOrPolygon_(child, polygon, objectStack);
  38733. };
  38734. /**
  38735. * @param {Node} node Node.
  38736. * @param {ol.geom.LinearRing} ring LinearRing geometry.
  38737. * @param {Array.<*>} objectStack Node stack.
  38738. * @private
  38739. */
  38740. ol.format.GML2.prototype.writeRing_ = function(node, ring, objectStack) {
  38741. var linearRing = ol.xml.createElementNS(node.namespaceURI, 'LinearRing');
  38742. node.appendChild(linearRing);
  38743. this.writeLinearRing_(linearRing, ring, objectStack);
  38744. };
  38745. /**
  38746. * @param {Array.<number>} point Point geometry.
  38747. * @param {string=} opt_srsName Optional srsName
  38748. * @param {boolean=} opt_hasZ whether the geometry has a Z coordinate (is 3D) or not.
  38749. * @return {string} The coords string.
  38750. * @private
  38751. */
  38752. ol.format.GML2.prototype.getCoords_ = function(point, opt_srsName, opt_hasZ) {
  38753. var axisOrientation = 'enu';
  38754. if (opt_srsName) {
  38755. axisOrientation = ol.proj.get(opt_srsName).getAxisOrientation();
  38756. }
  38757. var coords = ((axisOrientation.substr(0, 2) === 'en') ?
  38758. point[0] + ',' + point[1] :
  38759. point[1] + ',' + point[0]);
  38760. if (opt_hasZ) {
  38761. // For newly created points, Z can be undefined.
  38762. var z = point[2] || 0;
  38763. coords += ',' + z;
  38764. }
  38765. return coords;
  38766. };
  38767. /**
  38768. * @param {Node} node Node.
  38769. * @param {ol.geom.MultiLineString} geometry MultiLineString geometry.
  38770. * @param {Array.<*>} objectStack Node stack.
  38771. * @private
  38772. */
  38773. ol.format.GML2.prototype.writeMultiCurveOrLineString_ = function(node, geometry, objectStack) {
  38774. var context = objectStack[objectStack.length - 1];
  38775. var hasZ = context['hasZ'];
  38776. var srsName = context['srsName'];
  38777. var curve = context['curve'];
  38778. if (srsName) {
  38779. node.setAttribute('srsName', srsName);
  38780. }
  38781. var lines = geometry.getLineStrings();
  38782. ol.xml.pushSerializeAndPop({node: node, hasZ: hasZ, srsName: srsName, curve: curve},
  38783. ol.format.GML2.LINESTRINGORCURVEMEMBER_SERIALIZERS_,
  38784. this.MULTIGEOMETRY_MEMBER_NODE_FACTORY_, lines,
  38785. objectStack, undefined, this);
  38786. };
  38787. /**
  38788. * @param {Node} node Node.
  38789. * @param {ol.geom.Point} geometry Point geometry.
  38790. * @param {Array.<*>} objectStack Node stack.
  38791. * @private
  38792. */
  38793. ol.format.GML2.prototype.writePoint_ = function(node, geometry, objectStack) {
  38794. var context = objectStack[objectStack.length - 1];
  38795. var hasZ = context['hasZ'];
  38796. var srsName = context['srsName'];
  38797. if (srsName) {
  38798. node.setAttribute('srsName', srsName);
  38799. }
  38800. var coordinates = this.createCoordinatesNode_(node.namespaceURI);
  38801. node.appendChild(coordinates);
  38802. var point = geometry.getCoordinates();
  38803. var coord = this.getCoords_(point, srsName, hasZ);
  38804. ol.format.XSD.writeStringTextNode(coordinates, coord);
  38805. };
  38806. /**
  38807. * @param {Node} node Node.
  38808. * @param {ol.geom.MultiPoint} geometry MultiPoint geometry.
  38809. * @param {Array.<*>} objectStack Node stack.
  38810. * @private
  38811. */
  38812. ol.format.GML2.prototype.writeMultiPoint_ = function(node, geometry,
  38813. objectStack) {
  38814. var context = objectStack[objectStack.length - 1];
  38815. var hasZ = context['hasZ'];
  38816. var srsName = context['srsName'];
  38817. if (srsName) {
  38818. node.setAttribute('srsName', srsName);
  38819. }
  38820. var points = geometry.getPoints();
  38821. ol.xml.pushSerializeAndPop({node: node, hasZ: hasZ, srsName: srsName},
  38822. ol.format.GML2.POINTMEMBER_SERIALIZERS_,
  38823. ol.xml.makeSimpleNodeFactory('pointMember'), points,
  38824. objectStack, undefined, this);
  38825. };
  38826. /**
  38827. * @param {Node} node Node.
  38828. * @param {ol.geom.Point} point Point geometry.
  38829. * @param {Array.<*>} objectStack Node stack.
  38830. * @private
  38831. */
  38832. ol.format.GML2.prototype.writePointMember_ = function(node, point, objectStack) {
  38833. var child = ol.xml.createElementNS(node.namespaceURI, 'Point');
  38834. node.appendChild(child);
  38835. this.writePoint_(child, point, objectStack);
  38836. };
  38837. /**
  38838. * @param {Node} node Node.
  38839. * @param {ol.geom.LineString} line LineString geometry.
  38840. * @param {Array.<*>} objectStack Node stack.
  38841. * @private
  38842. */
  38843. ol.format.GML2.prototype.writeLineStringOrCurveMember_ = function(node, line, objectStack) {
  38844. var child = this.GEOMETRY_NODE_FACTORY_(line, objectStack);
  38845. if (child) {
  38846. node.appendChild(child);
  38847. this.writeCurveOrLineString_(child, line, objectStack);
  38848. }
  38849. };
  38850. /**
  38851. * @param {Node} node Node.
  38852. * @param {ol.geom.LinearRing} geometry LinearRing geometry.
  38853. * @param {Array.<*>} objectStack Node stack.
  38854. * @private
  38855. */
  38856. ol.format.GML2.prototype.writeLinearRing_ = function(node, geometry, objectStack) {
  38857. var context = objectStack[objectStack.length - 1];
  38858. var srsName = context['srsName'];
  38859. if (srsName) {
  38860. node.setAttribute('srsName', srsName);
  38861. }
  38862. var coordinates = this.createCoordinatesNode_(node.namespaceURI);
  38863. node.appendChild(coordinates);
  38864. this.writeCoordinates_(coordinates, geometry, objectStack);
  38865. };
  38866. /**
  38867. * @param {Node} node Node.
  38868. * @param {ol.geom.MultiPolygon} geometry MultiPolygon geometry.
  38869. * @param {Array.<*>} objectStack Node stack.
  38870. * @private
  38871. */
  38872. ol.format.GML2.prototype.writeMultiSurfaceOrPolygon_ = function(node, geometry, objectStack) {
  38873. var context = objectStack[objectStack.length - 1];
  38874. var hasZ = context['hasZ'];
  38875. var srsName = context['srsName'];
  38876. var surface = context['surface'];
  38877. if (srsName) {
  38878. node.setAttribute('srsName', srsName);
  38879. }
  38880. var polygons = geometry.getPolygons();
  38881. ol.xml.pushSerializeAndPop({node: node, hasZ: hasZ, srsName: srsName, surface: surface},
  38882. ol.format.GML2.SURFACEORPOLYGONMEMBER_SERIALIZERS_,
  38883. this.MULTIGEOMETRY_MEMBER_NODE_FACTORY_, polygons,
  38884. objectStack, undefined, this);
  38885. };
  38886. /**
  38887. * @param {Node} node Node.
  38888. * @param {ol.geom.Polygon} polygon Polygon geometry.
  38889. * @param {Array.<*>} objectStack Node stack.
  38890. * @private
  38891. */
  38892. ol.format.GML2.prototype.writeSurfaceOrPolygonMember_ = function(node, polygon, objectStack) {
  38893. var child = this.GEOMETRY_NODE_FACTORY_(
  38894. polygon, objectStack);
  38895. if (child) {
  38896. node.appendChild(child);
  38897. this.writeSurfaceOrPolygon_(child, polygon, objectStack);
  38898. }
  38899. };
  38900. /**
  38901. * @param {Node} node Node.
  38902. * @param {ol.Extent} extent Extent.
  38903. * @param {Array.<*>} objectStack Node stack.
  38904. * @private
  38905. */
  38906. ol.format.GML2.prototype.writeEnvelope = function(node, extent, objectStack) {
  38907. var context = objectStack[objectStack.length - 1];
  38908. var srsName = context['srsName'];
  38909. if (srsName) {
  38910. node.setAttribute('srsName', srsName);
  38911. }
  38912. var keys = ['lowerCorner', 'upperCorner'];
  38913. var values = [extent[0] + ' ' + extent[1], extent[2] + ' ' + extent[3]];
  38914. ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
  38915. ({node: node}), ol.format.GML2.ENVELOPE_SERIALIZERS_,
  38916. ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
  38917. values,
  38918. objectStack, keys, this);
  38919. };
  38920. /**
  38921. * @const
  38922. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  38923. * @private
  38924. */
  38925. ol.format.GML2.GEOMETRY_SERIALIZERS_ = {
  38926. 'http://www.opengis.net/gml': {
  38927. 'Curve': ol.xml.makeChildAppender(
  38928. ol.format.GML2.prototype.writeCurveOrLineString_),
  38929. 'MultiCurve': ol.xml.makeChildAppender(
  38930. ol.format.GML2.prototype.writeMultiCurveOrLineString_),
  38931. 'Point': ol.xml.makeChildAppender(ol.format.GML2.prototype.writePoint_),
  38932. 'MultiPoint': ol.xml.makeChildAppender(
  38933. ol.format.GML2.prototype.writeMultiPoint_),
  38934. 'LineString': ol.xml.makeChildAppender(
  38935. ol.format.GML2.prototype.writeCurveOrLineString_),
  38936. 'MultiLineString': ol.xml.makeChildAppender(
  38937. ol.format.GML2.prototype.writeMultiCurveOrLineString_),
  38938. 'LinearRing': ol.xml.makeChildAppender(
  38939. ol.format.GML2.prototype.writeLinearRing_),
  38940. 'Polygon': ol.xml.makeChildAppender(
  38941. ol.format.GML2.prototype.writeSurfaceOrPolygon_),
  38942. 'MultiPolygon': ol.xml.makeChildAppender(
  38943. ol.format.GML2.prototype.writeMultiSurfaceOrPolygon_),
  38944. 'Surface': ol.xml.makeChildAppender(
  38945. ol.format.GML2.prototype.writeSurfaceOrPolygon_),
  38946. 'MultiSurface': ol.xml.makeChildAppender(
  38947. ol.format.GML2.prototype.writeMultiSurfaceOrPolygon_),
  38948. 'Envelope': ol.xml.makeChildAppender(
  38949. ol.format.GML2.prototype.writeEnvelope)
  38950. }
  38951. };
  38952. /**
  38953. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  38954. * @private
  38955. */
  38956. ol.format.GML2.RING_SERIALIZERS_ = {
  38957. 'http://www.opengis.net/gml': {
  38958. 'outerBoundaryIs': ol.xml.makeChildAppender(ol.format.GML2.prototype.writeRing_),
  38959. 'innerBoundaryIs': ol.xml.makeChildAppender(ol.format.GML2.prototype.writeRing_)
  38960. }
  38961. };
  38962. /**
  38963. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  38964. * @private
  38965. */
  38966. ol.format.GML2.POINTMEMBER_SERIALIZERS_ = {
  38967. 'http://www.opengis.net/gml': {
  38968. 'pointMember': ol.xml.makeChildAppender(
  38969. ol.format.GML2.prototype.writePointMember_)
  38970. }
  38971. };
  38972. /**
  38973. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  38974. * @private
  38975. */
  38976. ol.format.GML2.LINESTRINGORCURVEMEMBER_SERIALIZERS_ = {
  38977. 'http://www.opengis.net/gml': {
  38978. 'lineStringMember': ol.xml.makeChildAppender(
  38979. ol.format.GML2.prototype.writeLineStringOrCurveMember_),
  38980. 'curveMember': ol.xml.makeChildAppender(
  38981. ol.format.GML2.prototype.writeLineStringOrCurveMember_)
  38982. }
  38983. };
  38984. /**
  38985. * @const
  38986. * @param {*} value Value.
  38987. * @param {Array.<*>} objectStack Object stack.
  38988. * @param {string=} opt_nodeName Node name.
  38989. * @return {Node|undefined} Node.
  38990. * @private
  38991. */
  38992. ol.format.GML2.prototype.MULTIGEOMETRY_MEMBER_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
  38993. var parentNode = objectStack[objectStack.length - 1].node;
  38994. return ol.xml.createElementNS('http://www.opengis.net/gml',
  38995. ol.format.GML2.MULTIGEOMETRY_TO_MEMBER_NODENAME_[parentNode.nodeName]);
  38996. };
  38997. /**
  38998. * @const
  38999. * @type {Object.<string, string>}
  39000. * @private
  39001. */
  39002. ol.format.GML2.MULTIGEOMETRY_TO_MEMBER_NODENAME_ = {
  39003. 'MultiLineString': 'lineStringMember',
  39004. 'MultiCurve': 'curveMember',
  39005. 'MultiPolygon': 'polygonMember',
  39006. 'MultiSurface': 'surfaceMember'
  39007. };
  39008. /**
  39009. * @const
  39010. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  39011. * @private
  39012. */
  39013. ol.format.GML2.SURFACEORPOLYGONMEMBER_SERIALIZERS_ = {
  39014. 'http://www.opengis.net/gml': {
  39015. 'surfaceMember': ol.xml.makeChildAppender(
  39016. ol.format.GML2.prototype.writeSurfaceOrPolygonMember_),
  39017. 'polygonMember': ol.xml.makeChildAppender(
  39018. ol.format.GML2.prototype.writeSurfaceOrPolygonMember_)
  39019. }
  39020. };
  39021. /**
  39022. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  39023. * @private
  39024. */
  39025. ol.format.GML2.ENVELOPE_SERIALIZERS_ = {
  39026. 'http://www.opengis.net/gml': {
  39027. 'lowerCorner': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39028. 'upperCorner': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode)
  39029. }
  39030. };
  39031. goog.provide('ol.format.GPX');
  39032. goog.require('ol');
  39033. goog.require('ol.Feature');
  39034. goog.require('ol.array');
  39035. goog.require('ol.format.Feature');
  39036. goog.require('ol.format.XMLFeature');
  39037. goog.require('ol.format.XSD');
  39038. goog.require('ol.geom.GeometryLayout');
  39039. goog.require('ol.geom.LineString');
  39040. goog.require('ol.geom.MultiLineString');
  39041. goog.require('ol.geom.Point');
  39042. goog.require('ol.proj');
  39043. goog.require('ol.xml');
  39044. /**
  39045. * @classdesc
  39046. * Feature format for reading and writing data in the GPX format.
  39047. *
  39048. * @constructor
  39049. * @extends {ol.format.XMLFeature}
  39050. * @param {olx.format.GPXOptions=} opt_options Options.
  39051. * @api
  39052. */
  39053. ol.format.GPX = function(opt_options) {
  39054. var options = opt_options ? opt_options : {};
  39055. ol.format.XMLFeature.call(this);
  39056. /**
  39057. * @inheritDoc
  39058. */
  39059. this.defaultDataProjection = ol.proj.get('EPSG:4326');
  39060. /**
  39061. * @type {function(ol.Feature, Node)|undefined}
  39062. * @private
  39063. */
  39064. this.readExtensions_ = options.readExtensions;
  39065. };
  39066. ol.inherits(ol.format.GPX, ol.format.XMLFeature);
  39067. /**
  39068. * @const
  39069. * @private
  39070. * @type {Array.<string>}
  39071. */
  39072. ol.format.GPX.NAMESPACE_URIS_ = [
  39073. null,
  39074. 'http://www.topografix.com/GPX/1/0',
  39075. 'http://www.topografix.com/GPX/1/1'
  39076. ];
  39077. /**
  39078. * @const
  39079. * @type {string}
  39080. * @private
  39081. */
  39082. ol.format.GPX.SCHEMA_LOCATION_ = 'http://www.topografix.com/GPX/1/1 ' +
  39083. 'http://www.topografix.com/GPX/1/1/gpx.xsd';
  39084. /**
  39085. * @param {Array.<number>} flatCoordinates Flat coordinates.
  39086. * @param {ol.LayoutOptions} layoutOptions Layout options.
  39087. * @param {Node} node Node.
  39088. * @param {Object} values Values.
  39089. * @private
  39090. * @return {Array.<number>} Flat coordinates.
  39091. */
  39092. ol.format.GPX.appendCoordinate_ = function(flatCoordinates, layoutOptions, node, values) {
  39093. flatCoordinates.push(
  39094. parseFloat(node.getAttribute('lon')),
  39095. parseFloat(node.getAttribute('lat')));
  39096. if ('ele' in values) {
  39097. flatCoordinates.push(/** @type {number} */ (values['ele']));
  39098. delete values['ele'];
  39099. layoutOptions.hasZ = true;
  39100. } else {
  39101. flatCoordinates.push(0);
  39102. }
  39103. if ('time' in values) {
  39104. flatCoordinates.push(/** @type {number} */ (values['time']));
  39105. delete values['time'];
  39106. layoutOptions.hasM = true;
  39107. } else {
  39108. flatCoordinates.push(0);
  39109. }
  39110. return flatCoordinates;
  39111. };
  39112. /**
  39113. * Choose GeometryLayout based on flags in layoutOptions and adjust flatCoordinates
  39114. * and ends arrays by shrinking them accordingly (removing unused zero entries).
  39115. *
  39116. * @param {ol.LayoutOptions} layoutOptions Layout options.
  39117. * @param {Array.<number>} flatCoordinates Flat coordinates.
  39118. * @param {Array.<number>=} ends Ends.
  39119. * @return {ol.geom.GeometryLayout} Layout.
  39120. */
  39121. ol.format.GPX.applyLayoutOptions_ = function(layoutOptions, flatCoordinates, ends) {
  39122. var layout = ol.geom.GeometryLayout.XY;
  39123. var stride = 2;
  39124. if (layoutOptions.hasZ && layoutOptions.hasM) {
  39125. layout = ol.geom.GeometryLayout.XYZM;
  39126. stride = 4;
  39127. } else if (layoutOptions.hasZ) {
  39128. layout = ol.geom.GeometryLayout.XYZ;
  39129. stride = 3;
  39130. } else if (layoutOptions.hasM) {
  39131. layout = ol.geom.GeometryLayout.XYM;
  39132. stride = 3;
  39133. }
  39134. if (stride !== 4) {
  39135. var i, ii;
  39136. for (i = 0, ii = flatCoordinates.length / 4; i < ii; i++) {
  39137. flatCoordinates[i * stride] = flatCoordinates[i * 4];
  39138. flatCoordinates[i * stride + 1] = flatCoordinates[i * 4 + 1];
  39139. if (layoutOptions.hasZ) {
  39140. flatCoordinates[i * stride + 2] = flatCoordinates[i * 4 + 2];
  39141. }
  39142. if (layoutOptions.hasM) {
  39143. flatCoordinates[i * stride + 2] = flatCoordinates[i * 4 + 3];
  39144. }
  39145. }
  39146. flatCoordinates.length = flatCoordinates.length / 4 * stride;
  39147. if (ends) {
  39148. for (i = 0, ii = ends.length; i < ii; i++) {
  39149. ends[i] = ends[i] / 4 * stride;
  39150. }
  39151. }
  39152. }
  39153. return layout;
  39154. };
  39155. /**
  39156. * @param {Node} node Node.
  39157. * @param {Array.<*>} objectStack Object stack.
  39158. * @private
  39159. */
  39160. ol.format.GPX.parseLink_ = function(node, objectStack) {
  39161. var values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  39162. var href = node.getAttribute('href');
  39163. if (href !== null) {
  39164. values['link'] = href;
  39165. }
  39166. ol.xml.parseNode(ol.format.GPX.LINK_PARSERS_, node, objectStack);
  39167. };
  39168. /**
  39169. * @param {Node} node Node.
  39170. * @param {Array.<*>} objectStack Object stack.
  39171. * @private
  39172. */
  39173. ol.format.GPX.parseExtensions_ = function(node, objectStack) {
  39174. var values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  39175. values['extensionsNode_'] = node;
  39176. };
  39177. /**
  39178. * @param {Node} node Node.
  39179. * @param {Array.<*>} objectStack Object stack.
  39180. * @private
  39181. */
  39182. ol.format.GPX.parseRtePt_ = function(node, objectStack) {
  39183. var values = ol.xml.pushParseAndPop(
  39184. {}, ol.format.GPX.RTEPT_PARSERS_, node, objectStack);
  39185. if (values) {
  39186. var rteValues = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  39187. var flatCoordinates = /** @type {Array.<number>} */
  39188. (rteValues['flatCoordinates']);
  39189. var layoutOptions = /** @type {ol.LayoutOptions} */
  39190. (rteValues['layoutOptions']);
  39191. ol.format.GPX.appendCoordinate_(flatCoordinates, layoutOptions, node, values);
  39192. }
  39193. };
  39194. /**
  39195. * @param {Node} node Node.
  39196. * @param {Array.<*>} objectStack Object stack.
  39197. * @private
  39198. */
  39199. ol.format.GPX.parseTrkPt_ = function(node, objectStack) {
  39200. var values = ol.xml.pushParseAndPop(
  39201. {}, ol.format.GPX.TRKPT_PARSERS_, node, objectStack);
  39202. if (values) {
  39203. var trkValues = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  39204. var flatCoordinates = /** @type {Array.<number>} */
  39205. (trkValues['flatCoordinates']);
  39206. var layoutOptions = /** @type {ol.LayoutOptions} */
  39207. (trkValues['layoutOptions']);
  39208. ol.format.GPX.appendCoordinate_(flatCoordinates, layoutOptions, node, values);
  39209. }
  39210. };
  39211. /**
  39212. * @param {Node} node Node.
  39213. * @param {Array.<*>} objectStack Object stack.
  39214. * @private
  39215. */
  39216. ol.format.GPX.parseTrkSeg_ = function(node, objectStack) {
  39217. var values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  39218. ol.xml.parseNode(ol.format.GPX.TRKSEG_PARSERS_, node, objectStack);
  39219. var flatCoordinates = /** @type {Array.<number>} */
  39220. (values['flatCoordinates']);
  39221. var ends = /** @type {Array.<number>} */ (values['ends']);
  39222. ends.push(flatCoordinates.length);
  39223. };
  39224. /**
  39225. * @param {Node} node Node.
  39226. * @param {Array.<*>} objectStack Object stack.
  39227. * @private
  39228. * @return {ol.Feature|undefined} Track.
  39229. */
  39230. ol.format.GPX.readRte_ = function(node, objectStack) {
  39231. var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]);
  39232. var values = ol.xml.pushParseAndPop({
  39233. 'flatCoordinates': [],
  39234. 'layoutOptions': {}
  39235. }, ol.format.GPX.RTE_PARSERS_, node, objectStack);
  39236. if (!values) {
  39237. return undefined;
  39238. }
  39239. var flatCoordinates = /** @type {Array.<number>} */
  39240. (values['flatCoordinates']);
  39241. delete values['flatCoordinates'];
  39242. var layoutOptions = /** @type {ol.LayoutOptions} */ (values['layoutOptions']);
  39243. delete values['layoutOptions'];
  39244. var layout = ol.format.GPX.applyLayoutOptions_(layoutOptions, flatCoordinates);
  39245. var geometry = new ol.geom.LineString(null);
  39246. geometry.setFlatCoordinates(layout, flatCoordinates);
  39247. ol.format.Feature.transformWithOptions(geometry, false, options);
  39248. var feature = new ol.Feature(geometry);
  39249. feature.setProperties(values);
  39250. return feature;
  39251. };
  39252. /**
  39253. * @param {Node} node Node.
  39254. * @param {Array.<*>} objectStack Object stack.
  39255. * @private
  39256. * @return {ol.Feature|undefined} Track.
  39257. */
  39258. ol.format.GPX.readTrk_ = function(node, objectStack) {
  39259. var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]);
  39260. var values = ol.xml.pushParseAndPop({
  39261. 'flatCoordinates': [],
  39262. 'ends': [],
  39263. 'layoutOptions': {}
  39264. }, ol.format.GPX.TRK_PARSERS_, node, objectStack);
  39265. if (!values) {
  39266. return undefined;
  39267. }
  39268. var flatCoordinates = /** @type {Array.<number>} */
  39269. (values['flatCoordinates']);
  39270. delete values['flatCoordinates'];
  39271. var ends = /** @type {Array.<number>} */ (values['ends']);
  39272. delete values['ends'];
  39273. var layoutOptions = /** @type {ol.LayoutOptions} */ (values['layoutOptions']);
  39274. delete values['layoutOptions'];
  39275. var layout = ol.format.GPX.applyLayoutOptions_(layoutOptions, flatCoordinates, ends);
  39276. var geometry = new ol.geom.MultiLineString(null);
  39277. geometry.setFlatCoordinates(layout, flatCoordinates, ends);
  39278. ol.format.Feature.transformWithOptions(geometry, false, options);
  39279. var feature = new ol.Feature(geometry);
  39280. feature.setProperties(values);
  39281. return feature;
  39282. };
  39283. /**
  39284. * @param {Node} node Node.
  39285. * @param {Array.<*>} objectStack Object stack.
  39286. * @private
  39287. * @return {ol.Feature|undefined} Waypoint.
  39288. */
  39289. ol.format.GPX.readWpt_ = function(node, objectStack) {
  39290. var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]);
  39291. var values = ol.xml.pushParseAndPop(
  39292. {}, ol.format.GPX.WPT_PARSERS_, node, objectStack);
  39293. if (!values) {
  39294. return undefined;
  39295. }
  39296. var layoutOptions = /** @type {ol.LayoutOptions} */ ({});
  39297. var coordinates = ol.format.GPX.appendCoordinate_([], layoutOptions, node, values);
  39298. var layout = ol.format.GPX.applyLayoutOptions_(layoutOptions, coordinates);
  39299. var geometry = new ol.geom.Point(coordinates, layout);
  39300. ol.format.Feature.transformWithOptions(geometry, false, options);
  39301. var feature = new ol.Feature(geometry);
  39302. feature.setProperties(values);
  39303. return feature;
  39304. };
  39305. /**
  39306. * @const
  39307. * @type {Object.<string, function(Node, Array.<*>): (ol.Feature|undefined)>}
  39308. * @private
  39309. */
  39310. ol.format.GPX.FEATURE_READER_ = {
  39311. 'rte': ol.format.GPX.readRte_,
  39312. 'trk': ol.format.GPX.readTrk_,
  39313. 'wpt': ol.format.GPX.readWpt_
  39314. };
  39315. /**
  39316. * @const
  39317. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  39318. * @private
  39319. */
  39320. ol.format.GPX.GPX_PARSERS_ = ol.xml.makeStructureNS(
  39321. ol.format.GPX.NAMESPACE_URIS_, {
  39322. 'rte': ol.xml.makeArrayPusher(ol.format.GPX.readRte_),
  39323. 'trk': ol.xml.makeArrayPusher(ol.format.GPX.readTrk_),
  39324. 'wpt': ol.xml.makeArrayPusher(ol.format.GPX.readWpt_)
  39325. });
  39326. /**
  39327. * @const
  39328. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  39329. * @private
  39330. */
  39331. ol.format.GPX.LINK_PARSERS_ = ol.xml.makeStructureNS(
  39332. ol.format.GPX.NAMESPACE_URIS_, {
  39333. 'text':
  39334. ol.xml.makeObjectPropertySetter(ol.format.XSD.readString, 'linkText'),
  39335. 'type':
  39336. ol.xml.makeObjectPropertySetter(ol.format.XSD.readString, 'linkType')
  39337. });
  39338. /**
  39339. * @const
  39340. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  39341. * @private
  39342. */
  39343. ol.format.GPX.RTE_PARSERS_ = ol.xml.makeStructureNS(
  39344. ol.format.GPX.NAMESPACE_URIS_, {
  39345. 'name': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39346. 'cmt': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39347. 'desc': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39348. 'src': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39349. 'link': ol.format.GPX.parseLink_,
  39350. 'number':
  39351. ol.xml.makeObjectPropertySetter(ol.format.XSD.readNonNegativeInteger),
  39352. 'extensions': ol.format.GPX.parseExtensions_,
  39353. 'type': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39354. 'rtept': ol.format.GPX.parseRtePt_
  39355. });
  39356. /**
  39357. * @const
  39358. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  39359. * @private
  39360. */
  39361. ol.format.GPX.RTEPT_PARSERS_ = ol.xml.makeStructureNS(
  39362. ol.format.GPX.NAMESPACE_URIS_, {
  39363. 'ele': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  39364. 'time': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDateTime)
  39365. });
  39366. /**
  39367. * @const
  39368. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  39369. * @private
  39370. */
  39371. ol.format.GPX.TRK_PARSERS_ = ol.xml.makeStructureNS(
  39372. ol.format.GPX.NAMESPACE_URIS_, {
  39373. 'name': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39374. 'cmt': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39375. 'desc': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39376. 'src': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39377. 'link': ol.format.GPX.parseLink_,
  39378. 'number':
  39379. ol.xml.makeObjectPropertySetter(ol.format.XSD.readNonNegativeInteger),
  39380. 'type': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39381. 'extensions': ol.format.GPX.parseExtensions_,
  39382. 'trkseg': ol.format.GPX.parseTrkSeg_
  39383. });
  39384. /**
  39385. * @const
  39386. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  39387. * @private
  39388. */
  39389. ol.format.GPX.TRKSEG_PARSERS_ = ol.xml.makeStructureNS(
  39390. ol.format.GPX.NAMESPACE_URIS_, {
  39391. 'trkpt': ol.format.GPX.parseTrkPt_
  39392. });
  39393. /**
  39394. * @const
  39395. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  39396. * @private
  39397. */
  39398. ol.format.GPX.TRKPT_PARSERS_ = ol.xml.makeStructureNS(
  39399. ol.format.GPX.NAMESPACE_URIS_, {
  39400. 'ele': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  39401. 'time': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDateTime)
  39402. });
  39403. /**
  39404. * @const
  39405. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  39406. * @private
  39407. */
  39408. ol.format.GPX.WPT_PARSERS_ = ol.xml.makeStructureNS(
  39409. ol.format.GPX.NAMESPACE_URIS_, {
  39410. 'ele': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  39411. 'time': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDateTime),
  39412. 'magvar': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  39413. 'geoidheight': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  39414. 'name': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39415. 'cmt': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39416. 'desc': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39417. 'src': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39418. 'link': ol.format.GPX.parseLink_,
  39419. 'sym': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39420. 'type': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39421. 'fix': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  39422. 'sat': ol.xml.makeObjectPropertySetter(
  39423. ol.format.XSD.readNonNegativeInteger),
  39424. 'hdop': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  39425. 'vdop': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  39426. 'pdop': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  39427. 'ageofdgpsdata':
  39428. ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  39429. 'dgpsid':
  39430. ol.xml.makeObjectPropertySetter(ol.format.XSD.readNonNegativeInteger),
  39431. 'extensions': ol.format.GPX.parseExtensions_
  39432. });
  39433. /**
  39434. * @param {Array.<ol.Feature>} features List of features.
  39435. * @private
  39436. */
  39437. ol.format.GPX.prototype.handleReadExtensions_ = function(features) {
  39438. if (!features) {
  39439. features = [];
  39440. }
  39441. for (var i = 0, ii = features.length; i < ii; ++i) {
  39442. var feature = features[i];
  39443. if (this.readExtensions_) {
  39444. var extensionsNode = feature.get('extensionsNode_') || null;
  39445. this.readExtensions_(feature, extensionsNode);
  39446. }
  39447. feature.set('extensionsNode_', undefined);
  39448. }
  39449. };
  39450. /**
  39451. * Read the first feature from a GPX source.
  39452. * Routes (`<rte>`) are converted into LineString geometries, and tracks (`<trk>`)
  39453. * into MultiLineString. Any properties on route and track waypoints are ignored.
  39454. *
  39455. * @function
  39456. * @param {Document|Node|Object|string} source Source.
  39457. * @param {olx.format.ReadOptions=} opt_options Read options.
  39458. * @return {ol.Feature} Feature.
  39459. * @api
  39460. */
  39461. ol.format.GPX.prototype.readFeature;
  39462. /**
  39463. * @inheritDoc
  39464. */
  39465. ol.format.GPX.prototype.readFeatureFromNode = function(node, opt_options) {
  39466. if (!ol.array.includes(ol.format.GPX.NAMESPACE_URIS_, node.namespaceURI)) {
  39467. return null;
  39468. }
  39469. var featureReader = ol.format.GPX.FEATURE_READER_[node.localName];
  39470. if (!featureReader) {
  39471. return null;
  39472. }
  39473. var feature = featureReader(node, [this.getReadOptions(node, opt_options)]);
  39474. if (!feature) {
  39475. return null;
  39476. }
  39477. this.handleReadExtensions_([feature]);
  39478. return feature;
  39479. };
  39480. /**
  39481. * Read all features from a GPX source.
  39482. * Routes (`<rte>`) are converted into LineString geometries, and tracks (`<trk>`)
  39483. * into MultiLineString. Any properties on route and track waypoints are ignored.
  39484. *
  39485. * @function
  39486. * @param {Document|Node|Object|string} source Source.
  39487. * @param {olx.format.ReadOptions=} opt_options Read options.
  39488. * @return {Array.<ol.Feature>} Features.
  39489. * @api
  39490. */
  39491. ol.format.GPX.prototype.readFeatures;
  39492. /**
  39493. * @inheritDoc
  39494. */
  39495. ol.format.GPX.prototype.readFeaturesFromNode = function(node, opt_options) {
  39496. if (!ol.array.includes(ol.format.GPX.NAMESPACE_URIS_, node.namespaceURI)) {
  39497. return [];
  39498. }
  39499. if (node.localName == 'gpx') {
  39500. /** @type {Array.<ol.Feature>} */
  39501. var features = ol.xml.pushParseAndPop([], ol.format.GPX.GPX_PARSERS_,
  39502. node, [this.getReadOptions(node, opt_options)]);
  39503. if (features) {
  39504. this.handleReadExtensions_(features);
  39505. return features;
  39506. } else {
  39507. return [];
  39508. }
  39509. }
  39510. return [];
  39511. };
  39512. /**
  39513. * Read the projection from a GPX source.
  39514. *
  39515. * @function
  39516. * @param {Document|Node|Object|string} source Source.
  39517. * @return {ol.proj.Projection} Projection.
  39518. * @api
  39519. */
  39520. ol.format.GPX.prototype.readProjection;
  39521. /**
  39522. * @param {Node} node Node.
  39523. * @param {string} value Value for the link's `href` attribute.
  39524. * @param {Array.<*>} objectStack Node stack.
  39525. * @private
  39526. */
  39527. ol.format.GPX.writeLink_ = function(node, value, objectStack) {
  39528. node.setAttribute('href', value);
  39529. var context = objectStack[objectStack.length - 1];
  39530. var properties = context['properties'];
  39531. var link = [
  39532. properties['linkText'],
  39533. properties['linkType']
  39534. ];
  39535. ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */ ({node: node}),
  39536. ol.format.GPX.LINK_SERIALIZERS_, ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
  39537. link, objectStack, ol.format.GPX.LINK_SEQUENCE_);
  39538. };
  39539. /**
  39540. * @param {Node} node Node.
  39541. * @param {ol.Coordinate} coordinate Coordinate.
  39542. * @param {Array.<*>} objectStack Object stack.
  39543. * @private
  39544. */
  39545. ol.format.GPX.writeWptType_ = function(node, coordinate, objectStack) {
  39546. var context = objectStack[objectStack.length - 1];
  39547. var parentNode = context.node;
  39548. var namespaceURI = parentNode.namespaceURI;
  39549. var properties = context['properties'];
  39550. //FIXME Projection handling
  39551. ol.xml.setAttributeNS(node, null, 'lat', coordinate[1]);
  39552. ol.xml.setAttributeNS(node, null, 'lon', coordinate[0]);
  39553. var geometryLayout = context['geometryLayout'];
  39554. switch (geometryLayout) {
  39555. case ol.geom.GeometryLayout.XYZM:
  39556. if (coordinate[3] !== 0) {
  39557. properties['time'] = coordinate[3];
  39558. }
  39559. // fall through
  39560. case ol.geom.GeometryLayout.XYZ:
  39561. if (coordinate[2] !== 0) {
  39562. properties['ele'] = coordinate[2];
  39563. }
  39564. break;
  39565. case ol.geom.GeometryLayout.XYM:
  39566. if (coordinate[2] !== 0) {
  39567. properties['time'] = coordinate[2];
  39568. }
  39569. break;
  39570. default:
  39571. // pass
  39572. }
  39573. var orderedKeys = (node.nodeName == 'rtept') ?
  39574. ol.format.GPX.RTEPT_TYPE_SEQUENCE_[namespaceURI] :
  39575. ol.format.GPX.WPT_TYPE_SEQUENCE_[namespaceURI];
  39576. var values = ol.xml.makeSequence(properties, orderedKeys);
  39577. ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
  39578. ({node: node, 'properties': properties}),
  39579. ol.format.GPX.WPT_TYPE_SERIALIZERS_, ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
  39580. values, objectStack, orderedKeys);
  39581. };
  39582. /**
  39583. * @param {Node} node Node.
  39584. * @param {ol.Feature} feature Feature.
  39585. * @param {Array.<*>} objectStack Object stack.
  39586. * @private
  39587. */
  39588. ol.format.GPX.writeRte_ = function(node, feature, objectStack) {
  39589. var options = /** @type {olx.format.WriteOptions} */ (objectStack[0]);
  39590. var properties = feature.getProperties();
  39591. var context = {node: node, 'properties': properties};
  39592. var geometry = feature.getGeometry();
  39593. if (geometry) {
  39594. geometry = /** @type {ol.geom.LineString} */
  39595. (ol.format.Feature.transformWithOptions(geometry, true, options));
  39596. context['geometryLayout'] = geometry.getLayout();
  39597. properties['rtept'] = geometry.getCoordinates();
  39598. }
  39599. var parentNode = objectStack[objectStack.length - 1].node;
  39600. var orderedKeys = ol.format.GPX.RTE_SEQUENCE_[parentNode.namespaceURI];
  39601. var values = ol.xml.makeSequence(properties, orderedKeys);
  39602. ol.xml.pushSerializeAndPop(context,
  39603. ol.format.GPX.RTE_SERIALIZERS_, ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
  39604. values, objectStack, orderedKeys);
  39605. };
  39606. /**
  39607. * @param {Node} node Node.
  39608. * @param {ol.Feature} feature Feature.
  39609. * @param {Array.<*>} objectStack Object stack.
  39610. * @private
  39611. */
  39612. ol.format.GPX.writeTrk_ = function(node, feature, objectStack) {
  39613. var options = /** @type {olx.format.WriteOptions} */ (objectStack[0]);
  39614. var properties = feature.getProperties();
  39615. /** @type {ol.XmlNodeStackItem} */
  39616. var context = {node: node, 'properties': properties};
  39617. var geometry = feature.getGeometry();
  39618. if (geometry) {
  39619. geometry = /** @type {ol.geom.MultiLineString} */
  39620. (ol.format.Feature.transformWithOptions(geometry, true, options));
  39621. properties['trkseg'] = geometry.getLineStrings();
  39622. }
  39623. var parentNode = objectStack[objectStack.length - 1].node;
  39624. var orderedKeys = ol.format.GPX.TRK_SEQUENCE_[parentNode.namespaceURI];
  39625. var values = ol.xml.makeSequence(properties, orderedKeys);
  39626. ol.xml.pushSerializeAndPop(context,
  39627. ol.format.GPX.TRK_SERIALIZERS_, ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
  39628. values, objectStack, orderedKeys);
  39629. };
  39630. /**
  39631. * @param {Node} node Node.
  39632. * @param {ol.geom.LineString} lineString LineString.
  39633. * @param {Array.<*>} objectStack Object stack.
  39634. * @private
  39635. */
  39636. ol.format.GPX.writeTrkSeg_ = function(node, lineString, objectStack) {
  39637. /** @type {ol.XmlNodeStackItem} */
  39638. var context = {node: node, 'geometryLayout': lineString.getLayout(),
  39639. 'properties': {}};
  39640. ol.xml.pushSerializeAndPop(context,
  39641. ol.format.GPX.TRKSEG_SERIALIZERS_, ol.format.GPX.TRKSEG_NODE_FACTORY_,
  39642. lineString.getCoordinates(), objectStack);
  39643. };
  39644. /**
  39645. * @param {Node} node Node.
  39646. * @param {ol.Feature} feature Feature.
  39647. * @param {Array.<*>} objectStack Object stack.
  39648. * @private
  39649. */
  39650. ol.format.GPX.writeWpt_ = function(node, feature, objectStack) {
  39651. var options = /** @type {olx.format.WriteOptions} */ (objectStack[0]);
  39652. var context = objectStack[objectStack.length - 1];
  39653. context['properties'] = feature.getProperties();
  39654. var geometry = feature.getGeometry();
  39655. if (geometry) {
  39656. geometry = /** @type {ol.geom.Point} */
  39657. (ol.format.Feature.transformWithOptions(geometry, true, options));
  39658. context['geometryLayout'] = geometry.getLayout();
  39659. ol.format.GPX.writeWptType_(node, geometry.getCoordinates(), objectStack);
  39660. }
  39661. };
  39662. /**
  39663. * @const
  39664. * @type {Array.<string>}
  39665. * @private
  39666. */
  39667. ol.format.GPX.LINK_SEQUENCE_ = ['text', 'type'];
  39668. /**
  39669. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  39670. * @private
  39671. */
  39672. ol.format.GPX.LINK_SERIALIZERS_ = ol.xml.makeStructureNS(
  39673. ol.format.GPX.NAMESPACE_URIS_, {
  39674. 'text': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39675. 'type': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode)
  39676. });
  39677. /**
  39678. * @const
  39679. * @type {Object.<string, Array.<string>>}
  39680. * @private
  39681. */
  39682. ol.format.GPX.RTE_SEQUENCE_ = ol.xml.makeStructureNS(
  39683. ol.format.GPX.NAMESPACE_URIS_, [
  39684. 'name', 'cmt', 'desc', 'src', 'link', 'number', 'type', 'rtept'
  39685. ]);
  39686. /**
  39687. * @const
  39688. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  39689. * @private
  39690. */
  39691. ol.format.GPX.RTE_SERIALIZERS_ = ol.xml.makeStructureNS(
  39692. ol.format.GPX.NAMESPACE_URIS_, {
  39693. 'name': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39694. 'cmt': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39695. 'desc': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39696. 'src': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39697. 'link': ol.xml.makeChildAppender(ol.format.GPX.writeLink_),
  39698. 'number': ol.xml.makeChildAppender(
  39699. ol.format.XSD.writeNonNegativeIntegerTextNode),
  39700. 'type': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39701. 'rtept': ol.xml.makeArraySerializer(ol.xml.makeChildAppender(
  39702. ol.format.GPX.writeWptType_))
  39703. });
  39704. /**
  39705. * @const
  39706. * @type {Object.<string, Array.<string>>}
  39707. * @private
  39708. */
  39709. ol.format.GPX.RTEPT_TYPE_SEQUENCE_ = ol.xml.makeStructureNS(
  39710. ol.format.GPX.NAMESPACE_URIS_, [
  39711. 'ele', 'time'
  39712. ]);
  39713. /**
  39714. * @const
  39715. * @type {Object.<string, Array.<string>>}
  39716. * @private
  39717. */
  39718. ol.format.GPX.TRK_SEQUENCE_ = ol.xml.makeStructureNS(
  39719. ol.format.GPX.NAMESPACE_URIS_, [
  39720. 'name', 'cmt', 'desc', 'src', 'link', 'number', 'type', 'trkseg'
  39721. ]);
  39722. /**
  39723. * @const
  39724. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  39725. * @private
  39726. */
  39727. ol.format.GPX.TRK_SERIALIZERS_ = ol.xml.makeStructureNS(
  39728. ol.format.GPX.NAMESPACE_URIS_, {
  39729. 'name': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39730. 'cmt': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39731. 'desc': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39732. 'src': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39733. 'link': ol.xml.makeChildAppender(ol.format.GPX.writeLink_),
  39734. 'number': ol.xml.makeChildAppender(
  39735. ol.format.XSD.writeNonNegativeIntegerTextNode),
  39736. 'type': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39737. 'trkseg': ol.xml.makeArraySerializer(ol.xml.makeChildAppender(
  39738. ol.format.GPX.writeTrkSeg_))
  39739. });
  39740. /**
  39741. * @const
  39742. * @type {function(*, Array.<*>, string=): (Node|undefined)}
  39743. * @private
  39744. */
  39745. ol.format.GPX.TRKSEG_NODE_FACTORY_ = ol.xml.makeSimpleNodeFactory('trkpt');
  39746. /**
  39747. * @const
  39748. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  39749. * @private
  39750. */
  39751. ol.format.GPX.TRKSEG_SERIALIZERS_ = ol.xml.makeStructureNS(
  39752. ol.format.GPX.NAMESPACE_URIS_, {
  39753. 'trkpt': ol.xml.makeChildAppender(ol.format.GPX.writeWptType_)
  39754. });
  39755. /**
  39756. * @const
  39757. * @type {Object.<string, Array.<string>>}
  39758. * @private
  39759. */
  39760. ol.format.GPX.WPT_TYPE_SEQUENCE_ = ol.xml.makeStructureNS(
  39761. ol.format.GPX.NAMESPACE_URIS_, [
  39762. 'ele', 'time', 'magvar', 'geoidheight', 'name', 'cmt', 'desc', 'src',
  39763. 'link', 'sym', 'type', 'fix', 'sat', 'hdop', 'vdop', 'pdop',
  39764. 'ageofdgpsdata', 'dgpsid'
  39765. ]);
  39766. /**
  39767. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  39768. * @private
  39769. */
  39770. ol.format.GPX.WPT_TYPE_SERIALIZERS_ = ol.xml.makeStructureNS(
  39771. ol.format.GPX.NAMESPACE_URIS_, {
  39772. 'ele': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
  39773. 'time': ol.xml.makeChildAppender(ol.format.XSD.writeDateTimeTextNode),
  39774. 'magvar': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
  39775. 'geoidheight': ol.xml.makeChildAppender(
  39776. ol.format.XSD.writeDecimalTextNode),
  39777. 'name': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39778. 'cmt': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39779. 'desc': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39780. 'src': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39781. 'link': ol.xml.makeChildAppender(ol.format.GPX.writeLink_),
  39782. 'sym': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39783. 'type': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39784. 'fix': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  39785. 'sat': ol.xml.makeChildAppender(
  39786. ol.format.XSD.writeNonNegativeIntegerTextNode),
  39787. 'hdop': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
  39788. 'vdop': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
  39789. 'pdop': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
  39790. 'ageofdgpsdata': ol.xml.makeChildAppender(
  39791. ol.format.XSD.writeDecimalTextNode),
  39792. 'dgpsid': ol.xml.makeChildAppender(
  39793. ol.format.XSD.writeNonNegativeIntegerTextNode)
  39794. });
  39795. /**
  39796. * @const
  39797. * @type {Object.<string, string>}
  39798. * @private
  39799. */
  39800. ol.format.GPX.GEOMETRY_TYPE_TO_NODENAME_ = {
  39801. 'Point': 'wpt',
  39802. 'LineString': 'rte',
  39803. 'MultiLineString': 'trk'
  39804. };
  39805. /**
  39806. * @const
  39807. * @param {*} value Value.
  39808. * @param {Array.<*>} objectStack Object stack.
  39809. * @param {string=} opt_nodeName Node name.
  39810. * @return {Node|undefined} Node.
  39811. * @private
  39812. */
  39813. ol.format.GPX.GPX_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
  39814. var geometry = /** @type {ol.Feature} */ (value).getGeometry();
  39815. if (geometry) {
  39816. var nodeName = ol.format.GPX.GEOMETRY_TYPE_TO_NODENAME_[geometry.getType()];
  39817. if (nodeName) {
  39818. var parentNode = objectStack[objectStack.length - 1].node;
  39819. return ol.xml.createElementNS(parentNode.namespaceURI, nodeName);
  39820. }
  39821. }
  39822. };
  39823. /**
  39824. * @const
  39825. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  39826. * @private
  39827. */
  39828. ol.format.GPX.GPX_SERIALIZERS_ = ol.xml.makeStructureNS(
  39829. ol.format.GPX.NAMESPACE_URIS_, {
  39830. 'rte': ol.xml.makeChildAppender(ol.format.GPX.writeRte_),
  39831. 'trk': ol.xml.makeChildAppender(ol.format.GPX.writeTrk_),
  39832. 'wpt': ol.xml.makeChildAppender(ol.format.GPX.writeWpt_)
  39833. });
  39834. /**
  39835. * Encode an array of features in the GPX format.
  39836. * LineString geometries are output as routes (`<rte>`), and MultiLineString
  39837. * as tracks (`<trk>`).
  39838. *
  39839. * @function
  39840. * @param {Array.<ol.Feature>} features Features.
  39841. * @param {olx.format.WriteOptions=} opt_options Write options.
  39842. * @return {string} Result.
  39843. * @api
  39844. */
  39845. ol.format.GPX.prototype.writeFeatures;
  39846. /**
  39847. * Encode an array of features in the GPX format as an XML node.
  39848. * LineString geometries are output as routes (`<rte>`), and MultiLineString
  39849. * as tracks (`<trk>`).
  39850. *
  39851. * @param {Array.<ol.Feature>} features Features.
  39852. * @param {olx.format.WriteOptions=} opt_options Options.
  39853. * @return {Node} Node.
  39854. * @override
  39855. * @api
  39856. */
  39857. ol.format.GPX.prototype.writeFeaturesNode = function(features, opt_options) {
  39858. opt_options = this.adaptOptions(opt_options);
  39859. //FIXME Serialize metadata
  39860. var gpx = ol.xml.createElementNS('http://www.topografix.com/GPX/1/1', 'gpx');
  39861. var xmlnsUri = 'http://www.w3.org/2000/xmlns/';
  39862. var xmlSchemaInstanceUri = 'http://www.w3.org/2001/XMLSchema-instance';
  39863. ol.xml.setAttributeNS(gpx, xmlnsUri, 'xmlns:xsi', xmlSchemaInstanceUri);
  39864. ol.xml.setAttributeNS(gpx, xmlSchemaInstanceUri, 'xsi:schemaLocation',
  39865. ol.format.GPX.SCHEMA_LOCATION_);
  39866. gpx.setAttribute('version', '1.1');
  39867. gpx.setAttribute('creator', 'OpenLayers');
  39868. ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */
  39869. ({node: gpx}), ol.format.GPX.GPX_SERIALIZERS_,
  39870. ol.format.GPX.GPX_NODE_FACTORY_, features, [opt_options]);
  39871. return gpx;
  39872. };
  39873. goog.provide('ol.format.IGCZ');
  39874. /**
  39875. * IGC altitude/z. One of 'barometric', 'gps', 'none'.
  39876. * @enum {string}
  39877. */
  39878. ol.format.IGCZ = {
  39879. BAROMETRIC: 'barometric',
  39880. GPS: 'gps',
  39881. NONE: 'none'
  39882. };
  39883. goog.provide('ol.format.TextFeature');
  39884. goog.require('ol');
  39885. goog.require('ol.format.Feature');
  39886. goog.require('ol.format.FormatType');
  39887. /**
  39888. * @classdesc
  39889. * Abstract base class; normally only used for creating subclasses and not
  39890. * instantiated in apps.
  39891. * Base class for text feature formats.
  39892. *
  39893. * @constructor
  39894. * @abstract
  39895. * @extends {ol.format.Feature}
  39896. */
  39897. ol.format.TextFeature = function() {
  39898. ol.format.Feature.call(this);
  39899. };
  39900. ol.inherits(ol.format.TextFeature, ol.format.Feature);
  39901. /**
  39902. * @param {Document|Node|Object|string} source Source.
  39903. * @private
  39904. * @return {string} Text.
  39905. */
  39906. ol.format.TextFeature.prototype.getText_ = function(source) {
  39907. if (typeof source === 'string') {
  39908. return source;
  39909. } else {
  39910. return '';
  39911. }
  39912. };
  39913. /**
  39914. * @inheritDoc
  39915. */
  39916. ol.format.TextFeature.prototype.getType = function() {
  39917. return ol.format.FormatType.TEXT;
  39918. };
  39919. /**
  39920. * @inheritDoc
  39921. */
  39922. ol.format.TextFeature.prototype.readFeature = function(source, opt_options) {
  39923. return this.readFeatureFromText(
  39924. this.getText_(source), this.adaptOptions(opt_options));
  39925. };
  39926. /**
  39927. * @abstract
  39928. * @param {string} text Text.
  39929. * @param {olx.format.ReadOptions=} opt_options Read options.
  39930. * @protected
  39931. * @return {ol.Feature} Feature.
  39932. */
  39933. ol.format.TextFeature.prototype.readFeatureFromText = function(text, opt_options) {};
  39934. /**
  39935. * @inheritDoc
  39936. */
  39937. ol.format.TextFeature.prototype.readFeatures = function(source, opt_options) {
  39938. return this.readFeaturesFromText(
  39939. this.getText_(source), this.adaptOptions(opt_options));
  39940. };
  39941. /**
  39942. * @abstract
  39943. * @param {string} text Text.
  39944. * @param {olx.format.ReadOptions=} opt_options Read options.
  39945. * @protected
  39946. * @return {Array.<ol.Feature>} Features.
  39947. */
  39948. ol.format.TextFeature.prototype.readFeaturesFromText = function(text, opt_options) {};
  39949. /**
  39950. * @inheritDoc
  39951. */
  39952. ol.format.TextFeature.prototype.readGeometry = function(source, opt_options) {
  39953. return this.readGeometryFromText(
  39954. this.getText_(source), this.adaptOptions(opt_options));
  39955. };
  39956. /**
  39957. * @abstract
  39958. * @param {string} text Text.
  39959. * @param {olx.format.ReadOptions=} opt_options Read options.
  39960. * @protected
  39961. * @return {ol.geom.Geometry} Geometry.
  39962. */
  39963. ol.format.TextFeature.prototype.readGeometryFromText = function(text, opt_options) {};
  39964. /**
  39965. * @inheritDoc
  39966. */
  39967. ol.format.TextFeature.prototype.readProjection = function(source) {
  39968. return this.readProjectionFromText(this.getText_(source));
  39969. };
  39970. /**
  39971. * @param {string} text Text.
  39972. * @protected
  39973. * @return {ol.proj.Projection} Projection.
  39974. */
  39975. ol.format.TextFeature.prototype.readProjectionFromText = function(text) {
  39976. return this.defaultDataProjection;
  39977. };
  39978. /**
  39979. * @inheritDoc
  39980. */
  39981. ol.format.TextFeature.prototype.writeFeature = function(feature, opt_options) {
  39982. return this.writeFeatureText(feature, this.adaptOptions(opt_options));
  39983. };
  39984. /**
  39985. * @abstract
  39986. * @param {ol.Feature} feature Features.
  39987. * @param {olx.format.WriteOptions=} opt_options Write options.
  39988. * @protected
  39989. * @return {string} Text.
  39990. */
  39991. ol.format.TextFeature.prototype.writeFeatureText = function(feature, opt_options) {};
  39992. /**
  39993. * @inheritDoc
  39994. */
  39995. ol.format.TextFeature.prototype.writeFeatures = function(
  39996. features, opt_options) {
  39997. return this.writeFeaturesText(features, this.adaptOptions(opt_options));
  39998. };
  39999. /**
  40000. * @abstract
  40001. * @param {Array.<ol.Feature>} features Features.
  40002. * @param {olx.format.WriteOptions=} opt_options Write options.
  40003. * @protected
  40004. * @return {string} Text.
  40005. */
  40006. ol.format.TextFeature.prototype.writeFeaturesText = function(features, opt_options) {};
  40007. /**
  40008. * @inheritDoc
  40009. */
  40010. ol.format.TextFeature.prototype.writeGeometry = function(
  40011. geometry, opt_options) {
  40012. return this.writeGeometryText(geometry, this.adaptOptions(opt_options));
  40013. };
  40014. /**
  40015. * @abstract
  40016. * @param {ol.geom.Geometry} geometry Geometry.
  40017. * @param {olx.format.WriteOptions=} opt_options Write options.
  40018. * @protected
  40019. * @return {string} Text.
  40020. */
  40021. ol.format.TextFeature.prototype.writeGeometryText = function(geometry, opt_options) {};
  40022. goog.provide('ol.format.IGC');
  40023. goog.require('ol');
  40024. goog.require('ol.Feature');
  40025. goog.require('ol.format.Feature');
  40026. goog.require('ol.format.IGCZ');
  40027. goog.require('ol.format.TextFeature');
  40028. goog.require('ol.geom.GeometryLayout');
  40029. goog.require('ol.geom.LineString');
  40030. goog.require('ol.proj');
  40031. /**
  40032. * @classdesc
  40033. * Feature format for `*.igc` flight recording files.
  40034. *
  40035. * @constructor
  40036. * @extends {ol.format.TextFeature}
  40037. * @param {olx.format.IGCOptions=} opt_options Options.
  40038. * @api
  40039. */
  40040. ol.format.IGC = function(opt_options) {
  40041. var options = opt_options ? opt_options : {};
  40042. ol.format.TextFeature.call(this);
  40043. /**
  40044. * @inheritDoc
  40045. */
  40046. this.defaultDataProjection = ol.proj.get('EPSG:4326');
  40047. /**
  40048. * @private
  40049. * @type {ol.format.IGCZ}
  40050. */
  40051. this.altitudeMode_ = options.altitudeMode ?
  40052. options.altitudeMode : ol.format.IGCZ.NONE;
  40053. };
  40054. ol.inherits(ol.format.IGC, ol.format.TextFeature);
  40055. /**
  40056. * @const
  40057. * @type {RegExp}
  40058. * @private
  40059. */
  40060. ol.format.IGC.B_RECORD_RE_ =
  40061. /^B(\d{2})(\d{2})(\d{2})(\d{2})(\d{5})([NS])(\d{3})(\d{5})([EW])([AV])(\d{5})(\d{5})/;
  40062. /**
  40063. * @const
  40064. * @type {RegExp}
  40065. * @private
  40066. */
  40067. ol.format.IGC.H_RECORD_RE_ = /^H.([A-Z]{3}).*?:(.*)/;
  40068. /**
  40069. * @const
  40070. * @type {RegExp}
  40071. * @private
  40072. */
  40073. ol.format.IGC.HFDTE_RECORD_RE_ = /^HFDTE(\d{2})(\d{2})(\d{2})/;
  40074. /**
  40075. * A regular expression matching the newline characters `\r\n`, `\r` and `\n`.
  40076. *
  40077. * @const
  40078. * @type {RegExp}
  40079. * @private
  40080. */
  40081. ol.format.IGC.NEWLINE_RE_ = /\r\n|\r|\n/;
  40082. /**
  40083. * Read the feature from the IGC source.
  40084. *
  40085. * @function
  40086. * @param {Document|Node|Object|string} source Source.
  40087. * @param {olx.format.ReadOptions=} opt_options Read options.
  40088. * @return {ol.Feature} Feature.
  40089. * @api
  40090. */
  40091. ol.format.IGC.prototype.readFeature;
  40092. /**
  40093. * @inheritDoc
  40094. */
  40095. ol.format.IGC.prototype.readFeatureFromText = function(text, opt_options) {
  40096. var altitudeMode = this.altitudeMode_;
  40097. var lines = text.split(ol.format.IGC.NEWLINE_RE_);
  40098. /** @type {Object.<string, string>} */
  40099. var properties = {};
  40100. var flatCoordinates = [];
  40101. var year = 2000;
  40102. var month = 0;
  40103. var day = 1;
  40104. var lastDateTime = -1;
  40105. var i, ii;
  40106. for (i = 0, ii = lines.length; i < ii; ++i) {
  40107. var line = lines[i];
  40108. var m;
  40109. if (line.charAt(0) == 'B') {
  40110. m = ol.format.IGC.B_RECORD_RE_.exec(line);
  40111. if (m) {
  40112. var hour = parseInt(m[1], 10);
  40113. var minute = parseInt(m[2], 10);
  40114. var second = parseInt(m[3], 10);
  40115. var y = parseInt(m[4], 10) + parseInt(m[5], 10) / 60000;
  40116. if (m[6] == 'S') {
  40117. y = -y;
  40118. }
  40119. var x = parseInt(m[7], 10) + parseInt(m[8], 10) / 60000;
  40120. if (m[9] == 'W') {
  40121. x = -x;
  40122. }
  40123. flatCoordinates.push(x, y);
  40124. if (altitudeMode != ol.format.IGCZ.NONE) {
  40125. var z;
  40126. if (altitudeMode == ol.format.IGCZ.GPS) {
  40127. z = parseInt(m[11], 10);
  40128. } else if (altitudeMode == ol.format.IGCZ.BAROMETRIC) {
  40129. z = parseInt(m[12], 10);
  40130. } else {
  40131. z = 0;
  40132. }
  40133. flatCoordinates.push(z);
  40134. }
  40135. var dateTime = Date.UTC(year, month, day, hour, minute, second);
  40136. // Detect UTC midnight wrap around.
  40137. if (dateTime < lastDateTime) {
  40138. dateTime = Date.UTC(year, month, day + 1, hour, minute, second);
  40139. }
  40140. flatCoordinates.push(dateTime / 1000);
  40141. lastDateTime = dateTime;
  40142. }
  40143. } else if (line.charAt(0) == 'H') {
  40144. m = ol.format.IGC.HFDTE_RECORD_RE_.exec(line);
  40145. if (m) {
  40146. day = parseInt(m[1], 10);
  40147. month = parseInt(m[2], 10) - 1;
  40148. year = 2000 + parseInt(m[3], 10);
  40149. } else {
  40150. m = ol.format.IGC.H_RECORD_RE_.exec(line);
  40151. if (m) {
  40152. properties[m[1]] = m[2].trim();
  40153. }
  40154. }
  40155. }
  40156. }
  40157. if (flatCoordinates.length === 0) {
  40158. return null;
  40159. }
  40160. var lineString = new ol.geom.LineString(null);
  40161. var layout = altitudeMode == ol.format.IGCZ.NONE ?
  40162. ol.geom.GeometryLayout.XYM : ol.geom.GeometryLayout.XYZM;
  40163. lineString.setFlatCoordinates(layout, flatCoordinates);
  40164. var feature = new ol.Feature(ol.format.Feature.transformWithOptions(
  40165. lineString, false, opt_options));
  40166. feature.setProperties(properties);
  40167. return feature;
  40168. };
  40169. /**
  40170. * Read the feature from the source. As IGC sources contain a single
  40171. * feature, this will return the feature in an array.
  40172. *
  40173. * @function
  40174. * @param {Document|Node|Object|string} source Source.
  40175. * @param {olx.format.ReadOptions=} opt_options Read options.
  40176. * @return {Array.<ol.Feature>} Features.
  40177. * @api
  40178. */
  40179. ol.format.IGC.prototype.readFeatures;
  40180. /**
  40181. * @inheritDoc
  40182. */
  40183. ol.format.IGC.prototype.readFeaturesFromText = function(text, opt_options) {
  40184. var feature = this.readFeatureFromText(text, opt_options);
  40185. if (feature) {
  40186. return [feature];
  40187. } else {
  40188. return [];
  40189. }
  40190. };
  40191. /**
  40192. * Read the projection from the IGC source.
  40193. *
  40194. * @function
  40195. * @param {Document|Node|Object|string} source Source.
  40196. * @return {ol.proj.Projection} Projection.
  40197. * @api
  40198. */
  40199. ol.format.IGC.prototype.readProjection;
  40200. /**
  40201. * Not implemented.
  40202. * @inheritDoc
  40203. */
  40204. ol.format.IGC.prototype.writeFeatureText = function(feature, opt_options) {};
  40205. /**
  40206. * Not implemented.
  40207. * @inheritDoc
  40208. */
  40209. ol.format.IGC.prototype.writeFeaturesText = function(features, opt_options) {};
  40210. /**
  40211. * Not implemented.
  40212. * @inheritDoc
  40213. */
  40214. ol.format.IGC.prototype.writeGeometryText = function(geometry, opt_options) {};
  40215. /**
  40216. * Not implemented.
  40217. * @inheritDoc
  40218. */
  40219. ol.format.IGC.prototype.readGeometryFromText = function(text, opt_options) {};
  40220. goog.provide('ol.style.IconAnchorUnits');
  40221. /**
  40222. * Icon anchor units. One of 'fraction', 'pixels'.
  40223. * @enum {string}
  40224. */
  40225. ol.style.IconAnchorUnits = {
  40226. FRACTION: 'fraction',
  40227. PIXELS: 'pixels'
  40228. };
  40229. goog.provide('ol.style.IconImage');
  40230. goog.require('ol');
  40231. goog.require('ol.dom');
  40232. goog.require('ol.events');
  40233. goog.require('ol.events.EventTarget');
  40234. goog.require('ol.events.EventType');
  40235. goog.require('ol.ImageState');
  40236. goog.require('ol.style');
  40237. /**
  40238. * @constructor
  40239. * @param {Image|HTMLCanvasElement} image Image.
  40240. * @param {string|undefined} src Src.
  40241. * @param {ol.Size} size Size.
  40242. * @param {?string} crossOrigin Cross origin.
  40243. * @param {ol.ImageState} imageState Image state.
  40244. * @param {ol.Color} color Color.
  40245. * @extends {ol.events.EventTarget}
  40246. */
  40247. ol.style.IconImage = function(image, src, size, crossOrigin, imageState,
  40248. color) {
  40249. ol.events.EventTarget.call(this);
  40250. /**
  40251. * @private
  40252. * @type {Image|HTMLCanvasElement}
  40253. */
  40254. this.hitDetectionImage_ = null;
  40255. /**
  40256. * @private
  40257. * @type {Image|HTMLCanvasElement}
  40258. */
  40259. this.image_ = !image ? new Image() : image;
  40260. if (crossOrigin !== null) {
  40261. this.image_.crossOrigin = crossOrigin;
  40262. }
  40263. /**
  40264. * @private
  40265. * @type {HTMLCanvasElement}
  40266. */
  40267. this.canvas_ = color ?
  40268. /** @type {HTMLCanvasElement} */ (document.createElement('CANVAS')) :
  40269. null;
  40270. /**
  40271. * @private
  40272. * @type {ol.Color}
  40273. */
  40274. this.color_ = color;
  40275. /**
  40276. * @private
  40277. * @type {Array.<ol.EventsKey>}
  40278. */
  40279. this.imageListenerKeys_ = null;
  40280. /**
  40281. * @private
  40282. * @type {ol.ImageState}
  40283. */
  40284. this.imageState_ = imageState;
  40285. /**
  40286. * @private
  40287. * @type {ol.Size}
  40288. */
  40289. this.size_ = size;
  40290. /**
  40291. * @private
  40292. * @type {string|undefined}
  40293. */
  40294. this.src_ = src;
  40295. /**
  40296. * @private
  40297. * @type {boolean}
  40298. */
  40299. this.tainting_ = false;
  40300. if (this.imageState_ == ol.ImageState.LOADED) {
  40301. this.determineTainting_();
  40302. }
  40303. };
  40304. ol.inherits(ol.style.IconImage, ol.events.EventTarget);
  40305. /**
  40306. * @param {Image|HTMLCanvasElement} image Image.
  40307. * @param {string} src Src.
  40308. * @param {ol.Size} size Size.
  40309. * @param {?string} crossOrigin Cross origin.
  40310. * @param {ol.ImageState} imageState Image state.
  40311. * @param {ol.Color} color Color.
  40312. * @return {ol.style.IconImage} Icon image.
  40313. */
  40314. ol.style.IconImage.get = function(image, src, size, crossOrigin, imageState,
  40315. color) {
  40316. var iconImageCache = ol.style.iconImageCache;
  40317. var iconImage = iconImageCache.get(src, crossOrigin, color);
  40318. if (!iconImage) {
  40319. iconImage = new ol.style.IconImage(
  40320. image, src, size, crossOrigin, imageState, color);
  40321. iconImageCache.set(src, crossOrigin, color, iconImage);
  40322. }
  40323. return iconImage;
  40324. };
  40325. /**
  40326. * @private
  40327. */
  40328. ol.style.IconImage.prototype.determineTainting_ = function() {
  40329. var context = ol.dom.createCanvasContext2D(1, 1);
  40330. try {
  40331. context.drawImage(this.image_, 0, 0);
  40332. context.getImageData(0, 0, 1, 1);
  40333. } catch (e) {
  40334. this.tainting_ = true;
  40335. }
  40336. };
  40337. /**
  40338. * @private
  40339. */
  40340. ol.style.IconImage.prototype.dispatchChangeEvent_ = function() {
  40341. this.dispatchEvent(ol.events.EventType.CHANGE);
  40342. };
  40343. /**
  40344. * @private
  40345. */
  40346. ol.style.IconImage.prototype.handleImageError_ = function() {
  40347. this.imageState_ = ol.ImageState.ERROR;
  40348. this.unlistenImage_();
  40349. this.dispatchChangeEvent_();
  40350. };
  40351. /**
  40352. * @private
  40353. */
  40354. ol.style.IconImage.prototype.handleImageLoad_ = function() {
  40355. this.imageState_ = ol.ImageState.LOADED;
  40356. if (this.size_) {
  40357. this.image_.width = this.size_[0];
  40358. this.image_.height = this.size_[1];
  40359. }
  40360. this.size_ = [this.image_.width, this.image_.height];
  40361. this.unlistenImage_();
  40362. this.determineTainting_();
  40363. this.replaceColor_();
  40364. this.dispatchChangeEvent_();
  40365. };
  40366. /**
  40367. * @param {number} pixelRatio Pixel ratio.
  40368. * @return {Image|HTMLCanvasElement} Image or Canvas element.
  40369. */
  40370. ol.style.IconImage.prototype.getImage = function(pixelRatio) {
  40371. return this.canvas_ ? this.canvas_ : this.image_;
  40372. };
  40373. /**
  40374. * @return {ol.ImageState} Image state.
  40375. */
  40376. ol.style.IconImage.prototype.getImageState = function() {
  40377. return this.imageState_;
  40378. };
  40379. /**
  40380. * @param {number} pixelRatio Pixel ratio.
  40381. * @return {Image|HTMLCanvasElement} Image element.
  40382. */
  40383. ol.style.IconImage.prototype.getHitDetectionImage = function(pixelRatio) {
  40384. if (!this.hitDetectionImage_) {
  40385. if (this.tainting_) {
  40386. var width = this.size_[0];
  40387. var height = this.size_[1];
  40388. var context = ol.dom.createCanvasContext2D(width, height);
  40389. context.fillRect(0, 0, width, height);
  40390. this.hitDetectionImage_ = context.canvas;
  40391. } else {
  40392. this.hitDetectionImage_ = this.image_;
  40393. }
  40394. }
  40395. return this.hitDetectionImage_;
  40396. };
  40397. /**
  40398. * @return {ol.Size} Image size.
  40399. */
  40400. ol.style.IconImage.prototype.getSize = function() {
  40401. return this.size_;
  40402. };
  40403. /**
  40404. * @return {string|undefined} Image src.
  40405. */
  40406. ol.style.IconImage.prototype.getSrc = function() {
  40407. return this.src_;
  40408. };
  40409. /**
  40410. * Load not yet loaded URI.
  40411. */
  40412. ol.style.IconImage.prototype.load = function() {
  40413. if (this.imageState_ == ol.ImageState.IDLE) {
  40414. this.imageState_ = ol.ImageState.LOADING;
  40415. this.imageListenerKeys_ = [
  40416. ol.events.listenOnce(this.image_, ol.events.EventType.ERROR,
  40417. this.handleImageError_, this),
  40418. ol.events.listenOnce(this.image_, ol.events.EventType.LOAD,
  40419. this.handleImageLoad_, this)
  40420. ];
  40421. try {
  40422. this.image_.src = this.src_;
  40423. } catch (e) {
  40424. this.handleImageError_();
  40425. }
  40426. }
  40427. };
  40428. /**
  40429. * @private
  40430. */
  40431. ol.style.IconImage.prototype.replaceColor_ = function() {
  40432. if (this.tainting_ || this.color_ === null) {
  40433. return;
  40434. }
  40435. this.canvas_.width = this.image_.width;
  40436. this.canvas_.height = this.image_.height;
  40437. var ctx = this.canvas_.getContext('2d');
  40438. ctx.drawImage(this.image_, 0, 0);
  40439. var imgData = ctx.getImageData(0, 0, this.image_.width, this.image_.height);
  40440. var data = imgData.data;
  40441. var r = this.color_[0] / 255.0;
  40442. var g = this.color_[1] / 255.0;
  40443. var b = this.color_[2] / 255.0;
  40444. for (var i = 0, ii = data.length; i < ii; i += 4) {
  40445. data[i] *= r;
  40446. data[i + 1] *= g;
  40447. data[i + 2] *= b;
  40448. }
  40449. ctx.putImageData(imgData, 0, 0);
  40450. };
  40451. /**
  40452. * Discards event handlers which listen for load completion or errors.
  40453. *
  40454. * @private
  40455. */
  40456. ol.style.IconImage.prototype.unlistenImage_ = function() {
  40457. this.imageListenerKeys_.forEach(ol.events.unlistenByKey);
  40458. this.imageListenerKeys_ = null;
  40459. };
  40460. goog.provide('ol.style.IconOrigin');
  40461. /**
  40462. * Icon origin. One of 'bottom-left', 'bottom-right', 'top-left', 'top-right'.
  40463. * @enum {string}
  40464. */
  40465. ol.style.IconOrigin = {
  40466. BOTTOM_LEFT: 'bottom-left',
  40467. BOTTOM_RIGHT: 'bottom-right',
  40468. TOP_LEFT: 'top-left',
  40469. TOP_RIGHT: 'top-right'
  40470. };
  40471. goog.provide('ol.style.Icon');
  40472. goog.require('ol');
  40473. goog.require('ol.ImageState');
  40474. goog.require('ol.asserts');
  40475. goog.require('ol.color');
  40476. goog.require('ol.events');
  40477. goog.require('ol.events.EventType');
  40478. goog.require('ol.style.IconAnchorUnits');
  40479. goog.require('ol.style.IconImage');
  40480. goog.require('ol.style.IconOrigin');
  40481. goog.require('ol.style.Image');
  40482. /**
  40483. * @classdesc
  40484. * Set icon style for vector features.
  40485. *
  40486. * @constructor
  40487. * @param {olx.style.IconOptions=} opt_options Options.
  40488. * @extends {ol.style.Image}
  40489. * @api
  40490. */
  40491. ol.style.Icon = function(opt_options) {
  40492. var options = opt_options || {};
  40493. /**
  40494. * @private
  40495. * @type {Array.<number>}
  40496. */
  40497. this.anchor_ = options.anchor !== undefined ? options.anchor : [0.5, 0.5];
  40498. /**
  40499. * @private
  40500. * @type {Array.<number>}
  40501. */
  40502. this.normalizedAnchor_ = null;
  40503. /**
  40504. * @private
  40505. * @type {ol.style.IconOrigin}
  40506. */
  40507. this.anchorOrigin_ = options.anchorOrigin !== undefined ?
  40508. options.anchorOrigin : ol.style.IconOrigin.TOP_LEFT;
  40509. /**
  40510. * @private
  40511. * @type {ol.style.IconAnchorUnits}
  40512. */
  40513. this.anchorXUnits_ = options.anchorXUnits !== undefined ?
  40514. options.anchorXUnits : ol.style.IconAnchorUnits.FRACTION;
  40515. /**
  40516. * @private
  40517. * @type {ol.style.IconAnchorUnits}
  40518. */
  40519. this.anchorYUnits_ = options.anchorYUnits !== undefined ?
  40520. options.anchorYUnits : ol.style.IconAnchorUnits.FRACTION;
  40521. /**
  40522. * @private
  40523. * @type {?string}
  40524. */
  40525. this.crossOrigin_ =
  40526. options.crossOrigin !== undefined ? options.crossOrigin : null;
  40527. /**
  40528. * @type {Image|HTMLCanvasElement}
  40529. */
  40530. var image = options.img !== undefined ? options.img : null;
  40531. /**
  40532. * @type {ol.Size}
  40533. */
  40534. var imgSize = options.imgSize !== undefined ? options.imgSize : null;
  40535. /**
  40536. * @type {string|undefined}
  40537. */
  40538. var src = options.src;
  40539. ol.asserts.assert(!(src !== undefined && image),
  40540. 4); // `image` and `src` cannot be provided at the same time
  40541. ol.asserts.assert(!image || (image && imgSize),
  40542. 5); // `imgSize` must be set when `image` is provided
  40543. if ((src === undefined || src.length === 0) && image) {
  40544. src = image.src || ol.getUid(image).toString();
  40545. }
  40546. ol.asserts.assert(src !== undefined && src.length > 0,
  40547. 6); // A defined and non-empty `src` or `image` must be provided
  40548. /**
  40549. * @type {ol.ImageState}
  40550. */
  40551. var imageState = options.src !== undefined ?
  40552. ol.ImageState.IDLE : ol.ImageState.LOADED;
  40553. /**
  40554. * @private
  40555. * @type {ol.Color}
  40556. */
  40557. this.color_ = options.color !== undefined ? ol.color.asArray(options.color) :
  40558. null;
  40559. /**
  40560. * @private
  40561. * @type {ol.style.IconImage}
  40562. */
  40563. this.iconImage_ = ol.style.IconImage.get(
  40564. image, /** @type {string} */ (src), imgSize, this.crossOrigin_, imageState, this.color_);
  40565. /**
  40566. * @private
  40567. * @type {Array.<number>}
  40568. */
  40569. this.offset_ = options.offset !== undefined ? options.offset : [0, 0];
  40570. /**
  40571. * @private
  40572. * @type {ol.style.IconOrigin}
  40573. */
  40574. this.offsetOrigin_ = options.offsetOrigin !== undefined ?
  40575. options.offsetOrigin : ol.style.IconOrigin.TOP_LEFT;
  40576. /**
  40577. * @private
  40578. * @type {Array.<number>}
  40579. */
  40580. this.origin_ = null;
  40581. /**
  40582. * @private
  40583. * @type {ol.Size}
  40584. */
  40585. this.size_ = options.size !== undefined ? options.size : null;
  40586. /**
  40587. * @type {number}
  40588. */
  40589. var opacity = options.opacity !== undefined ? options.opacity : 1;
  40590. /**
  40591. * @type {boolean}
  40592. */
  40593. var rotateWithView = options.rotateWithView !== undefined ?
  40594. options.rotateWithView : false;
  40595. /**
  40596. * @type {number}
  40597. */
  40598. var rotation = options.rotation !== undefined ? options.rotation : 0;
  40599. /**
  40600. * @type {number}
  40601. */
  40602. var scale = options.scale !== undefined ? options.scale : 1;
  40603. /**
  40604. * @type {boolean}
  40605. */
  40606. var snapToPixel = options.snapToPixel !== undefined ?
  40607. options.snapToPixel : true;
  40608. ol.style.Image.call(this, {
  40609. opacity: opacity,
  40610. rotation: rotation,
  40611. scale: scale,
  40612. snapToPixel: snapToPixel,
  40613. rotateWithView: rotateWithView
  40614. });
  40615. };
  40616. ol.inherits(ol.style.Icon, ol.style.Image);
  40617. /**
  40618. * Clones the style.
  40619. * @return {ol.style.Icon} The cloned style.
  40620. * @api
  40621. */
  40622. ol.style.Icon.prototype.clone = function() {
  40623. var oldImage = this.getImage(1);
  40624. var newImage;
  40625. if (this.iconImage_.getImageState() === ol.ImageState.LOADED) {
  40626. if (oldImage.tagName.toUpperCase() === 'IMG') {
  40627. newImage = /** @type {Image} */ (oldImage.cloneNode(true));
  40628. } else {
  40629. newImage = /** @type {HTMLCanvasElement} */ (document.createElement('canvas'));
  40630. var context = newImage.getContext('2d');
  40631. newImage.width = oldImage.width;
  40632. newImage.height = oldImage.height;
  40633. context.drawImage(oldImage, 0, 0);
  40634. }
  40635. }
  40636. return new ol.style.Icon({
  40637. anchor: this.anchor_.slice(),
  40638. anchorOrigin: this.anchorOrigin_,
  40639. anchorXUnits: this.anchorXUnits_,
  40640. anchorYUnits: this.anchorYUnits_,
  40641. crossOrigin: this.crossOrigin_,
  40642. color: (this.color_ && this.color_.slice) ? this.color_.slice() : this.color_ || undefined,
  40643. img: newImage ? newImage : undefined,
  40644. imgSize: newImage ? this.iconImage_.getSize().slice() : undefined,
  40645. src: newImage ? undefined : this.getSrc(),
  40646. offset: this.offset_.slice(),
  40647. offsetOrigin: this.offsetOrigin_,
  40648. size: this.size_ !== null ? this.size_.slice() : undefined,
  40649. opacity: this.getOpacity(),
  40650. scale: this.getScale(),
  40651. snapToPixel: this.getSnapToPixel(),
  40652. rotation: this.getRotation(),
  40653. rotateWithView: this.getRotateWithView()
  40654. });
  40655. };
  40656. /**
  40657. * @inheritDoc
  40658. * @api
  40659. */
  40660. ol.style.Icon.prototype.getAnchor = function() {
  40661. if (this.normalizedAnchor_) {
  40662. return this.normalizedAnchor_;
  40663. }
  40664. var anchor = this.anchor_;
  40665. var size = this.getSize();
  40666. if (this.anchorXUnits_ == ol.style.IconAnchorUnits.FRACTION ||
  40667. this.anchorYUnits_ == ol.style.IconAnchorUnits.FRACTION) {
  40668. if (!size) {
  40669. return null;
  40670. }
  40671. anchor = this.anchor_.slice();
  40672. if (this.anchorXUnits_ == ol.style.IconAnchorUnits.FRACTION) {
  40673. anchor[0] *= size[0];
  40674. }
  40675. if (this.anchorYUnits_ == ol.style.IconAnchorUnits.FRACTION) {
  40676. anchor[1] *= size[1];
  40677. }
  40678. }
  40679. if (this.anchorOrigin_ != ol.style.IconOrigin.TOP_LEFT) {
  40680. if (!size) {
  40681. return null;
  40682. }
  40683. if (anchor === this.anchor_) {
  40684. anchor = this.anchor_.slice();
  40685. }
  40686. if (this.anchorOrigin_ == ol.style.IconOrigin.TOP_RIGHT ||
  40687. this.anchorOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) {
  40688. anchor[0] = -anchor[0] + size[0];
  40689. }
  40690. if (this.anchorOrigin_ == ol.style.IconOrigin.BOTTOM_LEFT ||
  40691. this.anchorOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) {
  40692. anchor[1] = -anchor[1] + size[1];
  40693. }
  40694. }
  40695. this.normalizedAnchor_ = anchor;
  40696. return this.normalizedAnchor_;
  40697. };
  40698. /**
  40699. * Get the icon color.
  40700. * @return {ol.Color} Color.
  40701. * @api
  40702. */
  40703. ol.style.Icon.prototype.getColor = function() {
  40704. return this.color_;
  40705. };
  40706. /**
  40707. * Get the image icon.
  40708. * @param {number} pixelRatio Pixel ratio.
  40709. * @return {Image|HTMLCanvasElement} Image or Canvas element.
  40710. * @override
  40711. * @api
  40712. */
  40713. ol.style.Icon.prototype.getImage = function(pixelRatio) {
  40714. return this.iconImage_.getImage(pixelRatio);
  40715. };
  40716. /**
  40717. * @override
  40718. */
  40719. ol.style.Icon.prototype.getImageSize = function() {
  40720. return this.iconImage_.getSize();
  40721. };
  40722. /**
  40723. * @override
  40724. */
  40725. ol.style.Icon.prototype.getHitDetectionImageSize = function() {
  40726. return this.getImageSize();
  40727. };
  40728. /**
  40729. * @override
  40730. */
  40731. ol.style.Icon.prototype.getImageState = function() {
  40732. return this.iconImage_.getImageState();
  40733. };
  40734. /**
  40735. * @override
  40736. */
  40737. ol.style.Icon.prototype.getHitDetectionImage = function(pixelRatio) {
  40738. return this.iconImage_.getHitDetectionImage(pixelRatio);
  40739. };
  40740. /**
  40741. * @inheritDoc
  40742. * @api
  40743. */
  40744. ol.style.Icon.prototype.getOrigin = function() {
  40745. if (this.origin_) {
  40746. return this.origin_;
  40747. }
  40748. var offset = this.offset_;
  40749. if (this.offsetOrigin_ != ol.style.IconOrigin.TOP_LEFT) {
  40750. var size = this.getSize();
  40751. var iconImageSize = this.iconImage_.getSize();
  40752. if (!size || !iconImageSize) {
  40753. return null;
  40754. }
  40755. offset = offset.slice();
  40756. if (this.offsetOrigin_ == ol.style.IconOrigin.TOP_RIGHT ||
  40757. this.offsetOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) {
  40758. offset[0] = iconImageSize[0] - size[0] - offset[0];
  40759. }
  40760. if (this.offsetOrigin_ == ol.style.IconOrigin.BOTTOM_LEFT ||
  40761. this.offsetOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) {
  40762. offset[1] = iconImageSize[1] - size[1] - offset[1];
  40763. }
  40764. }
  40765. this.origin_ = offset;
  40766. return this.origin_;
  40767. };
  40768. /**
  40769. * Get the image URL.
  40770. * @return {string|undefined} Image src.
  40771. * @api
  40772. */
  40773. ol.style.Icon.prototype.getSrc = function() {
  40774. return this.iconImage_.getSrc();
  40775. };
  40776. /**
  40777. * @inheritDoc
  40778. * @api
  40779. */
  40780. ol.style.Icon.prototype.getSize = function() {
  40781. return !this.size_ ? this.iconImage_.getSize() : this.size_;
  40782. };
  40783. /**
  40784. * @override
  40785. */
  40786. ol.style.Icon.prototype.listenImageChange = function(listener, thisArg) {
  40787. return ol.events.listen(this.iconImage_, ol.events.EventType.CHANGE,
  40788. listener, thisArg);
  40789. };
  40790. /**
  40791. * Load not yet loaded URI.
  40792. * When rendering a feature with an icon style, the vector renderer will
  40793. * automatically call this method. However, you might want to call this
  40794. * method yourself for preloading or other purposes.
  40795. * @override
  40796. * @api
  40797. */
  40798. ol.style.Icon.prototype.load = function() {
  40799. this.iconImage_.load();
  40800. };
  40801. /**
  40802. * @override
  40803. */
  40804. ol.style.Icon.prototype.unlistenImageChange = function(listener, thisArg) {
  40805. ol.events.unlisten(this.iconImage_, ol.events.EventType.CHANGE,
  40806. listener, thisArg);
  40807. };
  40808. goog.provide('ol.style.Text');
  40809. goog.require('ol.style.Fill');
  40810. /**
  40811. * @classdesc
  40812. * Set text style for vector features.
  40813. *
  40814. * @constructor
  40815. * @param {olx.style.TextOptions=} opt_options Options.
  40816. * @api
  40817. */
  40818. ol.style.Text = function(opt_options) {
  40819. var options = opt_options || {};
  40820. /**
  40821. * @private
  40822. * @type {string|undefined}
  40823. */
  40824. this.font_ = options.font;
  40825. /**
  40826. * @private
  40827. * @type {number|undefined}
  40828. */
  40829. this.rotation_ = options.rotation;
  40830. /**
  40831. * @private
  40832. * @type {boolean|undefined}
  40833. */
  40834. this.rotateWithView_ = options.rotateWithView;
  40835. /**
  40836. * @private
  40837. * @type {number|undefined}
  40838. */
  40839. this.scale_ = options.scale;
  40840. /**
  40841. * @private
  40842. * @type {string|undefined}
  40843. */
  40844. this.text_ = options.text;
  40845. /**
  40846. * @private
  40847. * @type {string|undefined}
  40848. */
  40849. this.textAlign_ = options.textAlign;
  40850. /**
  40851. * @private
  40852. * @type {string|undefined}
  40853. */
  40854. this.textBaseline_ = options.textBaseline;
  40855. /**
  40856. * @private
  40857. * @type {ol.style.Fill}
  40858. */
  40859. this.fill_ = options.fill !== undefined ? options.fill :
  40860. new ol.style.Fill({color: ol.style.Text.DEFAULT_FILL_COLOR_});
  40861. /**
  40862. * @private
  40863. * @type {ol.style.Stroke}
  40864. */
  40865. this.stroke_ = options.stroke !== undefined ? options.stroke : null;
  40866. /**
  40867. * @private
  40868. * @type {number}
  40869. */
  40870. this.offsetX_ = options.offsetX !== undefined ? options.offsetX : 0;
  40871. /**
  40872. * @private
  40873. * @type {number}
  40874. */
  40875. this.offsetY_ = options.offsetY !== undefined ? options.offsetY : 0;
  40876. };
  40877. /**
  40878. * The default fill color to use if no fill was set at construction time; a
  40879. * blackish `#333`.
  40880. *
  40881. * @const {string}
  40882. * @private
  40883. */
  40884. ol.style.Text.DEFAULT_FILL_COLOR_ = '#333';
  40885. /**
  40886. * Clones the style.
  40887. * @return {ol.style.Text} The cloned style.
  40888. * @api
  40889. */
  40890. ol.style.Text.prototype.clone = function() {
  40891. return new ol.style.Text({
  40892. font: this.getFont(),
  40893. rotation: this.getRotation(),
  40894. rotateWithView: this.getRotateWithView(),
  40895. scale: this.getScale(),
  40896. text: this.getText(),
  40897. textAlign: this.getTextAlign(),
  40898. textBaseline: this.getTextBaseline(),
  40899. fill: this.getFill() ? this.getFill().clone() : undefined,
  40900. stroke: this.getStroke() ? this.getStroke().clone() : undefined,
  40901. offsetX: this.getOffsetX(),
  40902. offsetY: this.getOffsetY()
  40903. });
  40904. };
  40905. /**
  40906. * Get the font name.
  40907. * @return {string|undefined} Font.
  40908. * @api
  40909. */
  40910. ol.style.Text.prototype.getFont = function() {
  40911. return this.font_;
  40912. };
  40913. /**
  40914. * Get the x-offset for the text.
  40915. * @return {number} Horizontal text offset.
  40916. * @api
  40917. */
  40918. ol.style.Text.prototype.getOffsetX = function() {
  40919. return this.offsetX_;
  40920. };
  40921. /**
  40922. * Get the y-offset for the text.
  40923. * @return {number} Vertical text offset.
  40924. * @api
  40925. */
  40926. ol.style.Text.prototype.getOffsetY = function() {
  40927. return this.offsetY_;
  40928. };
  40929. /**
  40930. * Get the fill style for the text.
  40931. * @return {ol.style.Fill} Fill style.
  40932. * @api
  40933. */
  40934. ol.style.Text.prototype.getFill = function() {
  40935. return this.fill_;
  40936. };
  40937. /**
  40938. * Determine whether the text rotates with the map.
  40939. * @return {boolean|undefined} Rotate with map.
  40940. * @api
  40941. */
  40942. ol.style.Text.prototype.getRotateWithView = function() {
  40943. return this.rotateWithView_;
  40944. };
  40945. /**
  40946. * Get the text rotation.
  40947. * @return {number|undefined} Rotation.
  40948. * @api
  40949. */
  40950. ol.style.Text.prototype.getRotation = function() {
  40951. return this.rotation_;
  40952. };
  40953. /**
  40954. * Get the text scale.
  40955. * @return {number|undefined} Scale.
  40956. * @api
  40957. */
  40958. ol.style.Text.prototype.getScale = function() {
  40959. return this.scale_;
  40960. };
  40961. /**
  40962. * Get the stroke style for the text.
  40963. * @return {ol.style.Stroke} Stroke style.
  40964. * @api
  40965. */
  40966. ol.style.Text.prototype.getStroke = function() {
  40967. return this.stroke_;
  40968. };
  40969. /**
  40970. * Get the text to be rendered.
  40971. * @return {string|undefined} Text.
  40972. * @api
  40973. */
  40974. ol.style.Text.prototype.getText = function() {
  40975. return this.text_;
  40976. };
  40977. /**
  40978. * Get the text alignment.
  40979. * @return {string|undefined} Text align.
  40980. * @api
  40981. */
  40982. ol.style.Text.prototype.getTextAlign = function() {
  40983. return this.textAlign_;
  40984. };
  40985. /**
  40986. * Get the text baseline.
  40987. * @return {string|undefined} Text baseline.
  40988. * @api
  40989. */
  40990. ol.style.Text.prototype.getTextBaseline = function() {
  40991. return this.textBaseline_;
  40992. };
  40993. /**
  40994. * Set the font.
  40995. *
  40996. * @param {string|undefined} font Font.
  40997. * @api
  40998. */
  40999. ol.style.Text.prototype.setFont = function(font) {
  41000. this.font_ = font;
  41001. };
  41002. /**
  41003. * Set the x offset.
  41004. *
  41005. * @param {number} offsetX Horizontal text offset.
  41006. * @api
  41007. */
  41008. ol.style.Text.prototype.setOffsetX = function(offsetX) {
  41009. this.offsetX_ = offsetX;
  41010. };
  41011. /**
  41012. * Set the y offset.
  41013. *
  41014. * @param {number} offsetY Vertical text offset.
  41015. * @api
  41016. */
  41017. ol.style.Text.prototype.setOffsetY = function(offsetY) {
  41018. this.offsetY_ = offsetY;
  41019. };
  41020. /**
  41021. * Set the fill.
  41022. *
  41023. * @param {ol.style.Fill} fill Fill style.
  41024. * @api
  41025. */
  41026. ol.style.Text.prototype.setFill = function(fill) {
  41027. this.fill_ = fill;
  41028. };
  41029. /**
  41030. * Set the rotation.
  41031. *
  41032. * @param {number|undefined} rotation Rotation.
  41033. * @api
  41034. */
  41035. ol.style.Text.prototype.setRotation = function(rotation) {
  41036. this.rotation_ = rotation;
  41037. };
  41038. /**
  41039. * Set the scale.
  41040. *
  41041. * @param {number|undefined} scale Scale.
  41042. * @api
  41043. */
  41044. ol.style.Text.prototype.setScale = function(scale) {
  41045. this.scale_ = scale;
  41046. };
  41047. /**
  41048. * Set the stroke.
  41049. *
  41050. * @param {ol.style.Stroke} stroke Stroke style.
  41051. * @api
  41052. */
  41053. ol.style.Text.prototype.setStroke = function(stroke) {
  41054. this.stroke_ = stroke;
  41055. };
  41056. /**
  41057. * Set the text.
  41058. *
  41059. * @param {string|undefined} text Text.
  41060. * @api
  41061. */
  41062. ol.style.Text.prototype.setText = function(text) {
  41063. this.text_ = text;
  41064. };
  41065. /**
  41066. * Set the text alignment.
  41067. *
  41068. * @param {string|undefined} textAlign Text align.
  41069. * @api
  41070. */
  41071. ol.style.Text.prototype.setTextAlign = function(textAlign) {
  41072. this.textAlign_ = textAlign;
  41073. };
  41074. /**
  41075. * Set the text baseline.
  41076. *
  41077. * @param {string|undefined} textBaseline Text baseline.
  41078. * @api
  41079. */
  41080. ol.style.Text.prototype.setTextBaseline = function(textBaseline) {
  41081. this.textBaseline_ = textBaseline;
  41082. };
  41083. // FIXME http://earth.google.com/kml/1.0 namespace?
  41084. // FIXME why does node.getAttribute return an unknown type?
  41085. // FIXME serialize arbitrary feature properties
  41086. // FIXME don't parse style if extractStyles is false
  41087. goog.provide('ol.format.KML');
  41088. goog.require('ol');
  41089. goog.require('ol.Feature');
  41090. goog.require('ol.array');
  41091. goog.require('ol.asserts');
  41092. goog.require('ol.color');
  41093. goog.require('ol.format.Feature');
  41094. goog.require('ol.format.XMLFeature');
  41095. goog.require('ol.format.XSD');
  41096. goog.require('ol.geom.GeometryCollection');
  41097. goog.require('ol.geom.GeometryLayout');
  41098. goog.require('ol.geom.GeometryType');
  41099. goog.require('ol.geom.LineString');
  41100. goog.require('ol.geom.MultiLineString');
  41101. goog.require('ol.geom.MultiPoint');
  41102. goog.require('ol.geom.MultiPolygon');
  41103. goog.require('ol.geom.Point');
  41104. goog.require('ol.geom.Polygon');
  41105. goog.require('ol.math');
  41106. goog.require('ol.proj');
  41107. goog.require('ol.style.Fill');
  41108. goog.require('ol.style.Icon');
  41109. goog.require('ol.style.IconAnchorUnits');
  41110. goog.require('ol.style.IconOrigin');
  41111. goog.require('ol.style.Stroke');
  41112. goog.require('ol.style.Style');
  41113. goog.require('ol.style.Text');
  41114. goog.require('ol.xml');
  41115. /**
  41116. * @classdesc
  41117. * Feature format for reading and writing data in the KML format.
  41118. *
  41119. * Note that the KML format uses the URL() constructor. Older browsers such as IE
  41120. * which do not support this will need a URL polyfill to be loaded before use.
  41121. *
  41122. * @constructor
  41123. * @extends {ol.format.XMLFeature}
  41124. * @param {olx.format.KMLOptions=} opt_options Options.
  41125. * @api
  41126. */
  41127. ol.format.KML = function(opt_options) {
  41128. var options = opt_options ? opt_options : {};
  41129. ol.format.XMLFeature.call(this);
  41130. if (!ol.format.KML.DEFAULT_STYLE_ARRAY_) {
  41131. ol.format.KML.createStyleDefaults_();
  41132. }
  41133. /**
  41134. * @inheritDoc
  41135. */
  41136. this.defaultDataProjection = ol.proj.get('EPSG:4326');
  41137. /**
  41138. * @private
  41139. * @type {Array.<ol.style.Style>}
  41140. */
  41141. this.defaultStyle_ = options.defaultStyle ?
  41142. options.defaultStyle : ol.format.KML.DEFAULT_STYLE_ARRAY_;
  41143. /**
  41144. * @private
  41145. * @type {boolean}
  41146. */
  41147. this.extractStyles_ = options.extractStyles !== undefined ?
  41148. options.extractStyles : true;
  41149. /**
  41150. * @private
  41151. * @type {boolean}
  41152. */
  41153. this.writeStyles_ = options.writeStyles !== undefined ?
  41154. options.writeStyles : true;
  41155. /**
  41156. * @private
  41157. * @type {Object.<string, (Array.<ol.style.Style>|string)>}
  41158. */
  41159. this.sharedStyles_ = {};
  41160. /**
  41161. * @private
  41162. * @type {boolean}
  41163. */
  41164. this.showPointNames_ = options.showPointNames !== undefined ?
  41165. options.showPointNames : true;
  41166. };
  41167. ol.inherits(ol.format.KML, ol.format.XMLFeature);
  41168. /**
  41169. * @const
  41170. * @type {Array.<string>}
  41171. * @private
  41172. */
  41173. ol.format.KML.GX_NAMESPACE_URIS_ = [
  41174. 'http://www.google.com/kml/ext/2.2'
  41175. ];
  41176. /**
  41177. * @const
  41178. * @type {Array.<string>}
  41179. * @private
  41180. */
  41181. ol.format.KML.NAMESPACE_URIS_ = [
  41182. null,
  41183. 'http://earth.google.com/kml/2.0',
  41184. 'http://earth.google.com/kml/2.1',
  41185. 'http://earth.google.com/kml/2.2',
  41186. 'http://www.opengis.net/kml/2.2'
  41187. ];
  41188. /**
  41189. * @const
  41190. * @type {string}
  41191. * @private
  41192. */
  41193. ol.format.KML.SCHEMA_LOCATION_ = 'http://www.opengis.net/kml/2.2 ' +
  41194. 'https://developers.google.com/kml/schema/kml22gx.xsd';
  41195. /**
  41196. * @return {Array.<ol.style.Style>} Default style.
  41197. * @private
  41198. */
  41199. ol.format.KML.createStyleDefaults_ = function() {
  41200. /**
  41201. * @const
  41202. * @type {ol.Color}
  41203. * @private
  41204. */
  41205. ol.format.KML.DEFAULT_COLOR_ = [255, 255, 255, 1];
  41206. /**
  41207. * @const
  41208. * @type {ol.style.Fill}
  41209. * @private
  41210. */
  41211. ol.format.KML.DEFAULT_FILL_STYLE_ = new ol.style.Fill({
  41212. color: ol.format.KML.DEFAULT_COLOR_
  41213. });
  41214. /**
  41215. * @const
  41216. * @type {ol.Size}
  41217. * @private
  41218. */
  41219. ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_ = [20, 2]; // FIXME maybe [8, 32] ?
  41220. /**
  41221. * @const
  41222. * @type {ol.style.IconAnchorUnits}
  41223. * @private
  41224. */
  41225. ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_X_UNITS_ =
  41226. ol.style.IconAnchorUnits.PIXELS;
  41227. /**
  41228. * @const
  41229. * @type {ol.style.IconAnchorUnits}
  41230. * @private
  41231. */
  41232. ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_Y_UNITS_ =
  41233. ol.style.IconAnchorUnits.PIXELS;
  41234. /**
  41235. * @const
  41236. * @type {ol.Size}
  41237. * @private
  41238. */
  41239. ol.format.KML.DEFAULT_IMAGE_STYLE_SIZE_ = [64, 64];
  41240. /**
  41241. * @const
  41242. * @type {string}
  41243. * @private
  41244. */
  41245. ol.format.KML.DEFAULT_IMAGE_STYLE_SRC_ =
  41246. 'https://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png';
  41247. /**
  41248. * @const
  41249. * @type {number}
  41250. * @private
  41251. */
  41252. ol.format.KML.DEFAULT_IMAGE_SCALE_MULTIPLIER_ = 0.5;
  41253. /**
  41254. * @const
  41255. * @type {ol.style.Image}
  41256. * @private
  41257. */
  41258. ol.format.KML.DEFAULT_IMAGE_STYLE_ = new ol.style.Icon({
  41259. anchor: ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_,
  41260. anchorOrigin: ol.style.IconOrigin.BOTTOM_LEFT,
  41261. anchorXUnits: ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_X_UNITS_,
  41262. anchorYUnits: ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_Y_UNITS_,
  41263. crossOrigin: 'anonymous',
  41264. rotation: 0,
  41265. scale: ol.format.KML.DEFAULT_IMAGE_SCALE_MULTIPLIER_,
  41266. size: ol.format.KML.DEFAULT_IMAGE_STYLE_SIZE_,
  41267. src: ol.format.KML.DEFAULT_IMAGE_STYLE_SRC_
  41268. });
  41269. /**
  41270. * @const
  41271. * @type {string}
  41272. * @private
  41273. */
  41274. ol.format.KML.DEFAULT_NO_IMAGE_STYLE_ = 'NO_IMAGE';
  41275. /**
  41276. * @const
  41277. * @type {ol.style.Stroke}
  41278. * @private
  41279. */
  41280. ol.format.KML.DEFAULT_STROKE_STYLE_ = new ol.style.Stroke({
  41281. color: ol.format.KML.DEFAULT_COLOR_,
  41282. width: 1
  41283. });
  41284. /**
  41285. * @const
  41286. * @type {ol.style.Stroke}
  41287. * @private
  41288. */
  41289. ol.format.KML.DEFAULT_TEXT_STROKE_STYLE_ = new ol.style.Stroke({
  41290. color: [51, 51, 51, 1],
  41291. width: 2
  41292. });
  41293. /**
  41294. * @const
  41295. * @type {ol.style.Text}
  41296. * @private
  41297. */
  41298. ol.format.KML.DEFAULT_TEXT_STYLE_ = new ol.style.Text({
  41299. font: 'bold 16px Helvetica',
  41300. fill: ol.format.KML.DEFAULT_FILL_STYLE_,
  41301. stroke: ol.format.KML.DEFAULT_TEXT_STROKE_STYLE_,
  41302. scale: 0.8
  41303. });
  41304. /**
  41305. * @const
  41306. * @type {ol.style.Style}
  41307. * @private
  41308. */
  41309. ol.format.KML.DEFAULT_STYLE_ = new ol.style.Style({
  41310. fill: ol.format.KML.DEFAULT_FILL_STYLE_,
  41311. image: ol.format.KML.DEFAULT_IMAGE_STYLE_,
  41312. text: ol.format.KML.DEFAULT_TEXT_STYLE_,
  41313. stroke: ol.format.KML.DEFAULT_STROKE_STYLE_,
  41314. zIndex: 0
  41315. });
  41316. /**
  41317. * @const
  41318. * @type {Array.<ol.style.Style>}
  41319. * @private
  41320. */
  41321. ol.format.KML.DEFAULT_STYLE_ARRAY_ = [ol.format.KML.DEFAULT_STYLE_];
  41322. return ol.format.KML.DEFAULT_STYLE_ARRAY_;
  41323. };
  41324. /**
  41325. * @const
  41326. * @type {Object.<string, ol.style.IconAnchorUnits>}
  41327. * @private
  41328. */
  41329. ol.format.KML.ICON_ANCHOR_UNITS_MAP_ = {
  41330. 'fraction': ol.style.IconAnchorUnits.FRACTION,
  41331. 'pixels': ol.style.IconAnchorUnits.PIXELS,
  41332. 'insetPixels': ol.style.IconAnchorUnits.PIXELS
  41333. };
  41334. /**
  41335. * @param {ol.style.Style|undefined} foundStyle Style.
  41336. * @param {string} name Name.
  41337. * @return {ol.style.Style} style Style.
  41338. * @private
  41339. */
  41340. ol.format.KML.createNameStyleFunction_ = function(foundStyle, name) {
  41341. var textStyle = null;
  41342. var textOffset = [0, 0];
  41343. var textAlign = 'start';
  41344. if (foundStyle.getImage()) {
  41345. var imageSize = foundStyle.getImage().getImageSize();
  41346. if (imageSize === null) {
  41347. imageSize = ol.format.KML.DEFAULT_IMAGE_STYLE_SIZE_;
  41348. }
  41349. if (imageSize.length == 2) {
  41350. var imageScale = foundStyle.getImage().getScale();
  41351. // Offset the label to be centered to the right of the icon, if there is
  41352. // one.
  41353. textOffset[0] = imageScale * imageSize[0] / 2;
  41354. textOffset[1] = -imageScale * imageSize[1] / 2;
  41355. textAlign = 'left';
  41356. }
  41357. }
  41358. if (foundStyle.getText() !== null) {
  41359. // clone the text style, customizing it with name, alignments and offset.
  41360. // Note that kml does not support many text options that OpenLayers does (rotation, textBaseline).
  41361. var foundText = foundStyle.getText();
  41362. textStyle = foundText.clone();
  41363. textStyle.setFont(foundText.getFont() || ol.format.KML.DEFAULT_TEXT_STYLE_.getFont());
  41364. textStyle.setScale(foundText.getScale() || ol.format.KML.DEFAULT_TEXT_STYLE_.getScale());
  41365. textStyle.setFill(foundText.getFill() || ol.format.KML.DEFAULT_TEXT_STYLE_.getFill());
  41366. textStyle.setStroke(foundText.getStroke() || ol.format.KML.DEFAULT_TEXT_STROKE_STYLE_);
  41367. } else {
  41368. textStyle = ol.format.KML.DEFAULT_TEXT_STYLE_.clone();
  41369. }
  41370. textStyle.setText(name);
  41371. textStyle.setOffsetX(textOffset[0]);
  41372. textStyle.setOffsetY(textOffset[1]);
  41373. textStyle.setTextAlign(textAlign);
  41374. var nameStyle = new ol.style.Style({
  41375. text: textStyle
  41376. });
  41377. return nameStyle;
  41378. };
  41379. /**
  41380. * @param {Array.<ol.style.Style>|undefined} style Style.
  41381. * @param {string} styleUrl Style URL.
  41382. * @param {Array.<ol.style.Style>} defaultStyle Default style.
  41383. * @param {Object.<string, (Array.<ol.style.Style>|string)>} sharedStyles Shared
  41384. * styles.
  41385. * @param {boolean|undefined} showPointNames true to show names for point
  41386. * placemarks.
  41387. * @return {ol.FeatureStyleFunction} Feature style function.
  41388. * @private
  41389. */
  41390. ol.format.KML.createFeatureStyleFunction_ = function(style, styleUrl,
  41391. defaultStyle, sharedStyles, showPointNames) {
  41392. return (
  41393. /**
  41394. * @param {number} resolution Resolution.
  41395. * @return {Array.<ol.style.Style>} Style.
  41396. * @this {ol.Feature}
  41397. */
  41398. function(resolution) {
  41399. var drawName = showPointNames;
  41400. /** @type {ol.style.Style|undefined} */
  41401. var nameStyle;
  41402. var name = '';
  41403. if (drawName) {
  41404. if (this.getGeometry()) {
  41405. drawName = (this.getGeometry().getType() ===
  41406. ol.geom.GeometryType.POINT);
  41407. }
  41408. }
  41409. if (drawName) {
  41410. name = /** @type {string} */ (this.get('name'));
  41411. drawName = drawName && name;
  41412. }
  41413. if (style) {
  41414. if (drawName) {
  41415. nameStyle = ol.format.KML.createNameStyleFunction_(style[0],
  41416. name);
  41417. return style.concat(nameStyle);
  41418. }
  41419. return style;
  41420. }
  41421. if (styleUrl) {
  41422. var foundStyle = ol.format.KML.findStyle_(styleUrl, defaultStyle,
  41423. sharedStyles);
  41424. if (drawName) {
  41425. nameStyle = ol.format.KML.createNameStyleFunction_(foundStyle[0],
  41426. name);
  41427. return foundStyle.concat(nameStyle);
  41428. }
  41429. return foundStyle;
  41430. }
  41431. if (drawName) {
  41432. nameStyle = ol.format.KML.createNameStyleFunction_(defaultStyle[0],
  41433. name);
  41434. return defaultStyle.concat(nameStyle);
  41435. }
  41436. return defaultStyle;
  41437. });
  41438. };
  41439. /**
  41440. * @param {Array.<ol.style.Style>|string|undefined} styleValue Style value.
  41441. * @param {Array.<ol.style.Style>} defaultStyle Default style.
  41442. * @param {Object.<string, (Array.<ol.style.Style>|string)>} sharedStyles
  41443. * Shared styles.
  41444. * @return {Array.<ol.style.Style>} Style.
  41445. * @private
  41446. */
  41447. ol.format.KML.findStyle_ = function(styleValue, defaultStyle, sharedStyles) {
  41448. if (Array.isArray(styleValue)) {
  41449. return styleValue;
  41450. } else if (typeof styleValue === 'string') {
  41451. // KML files in the wild occasionally forget the leading `#` on styleUrls
  41452. // defined in the same document. Add a leading `#` if it enables to find
  41453. // a style.
  41454. if (!(styleValue in sharedStyles) && ('#' + styleValue in sharedStyles)) {
  41455. styleValue = '#' + styleValue;
  41456. }
  41457. return ol.format.KML.findStyle_(
  41458. sharedStyles[styleValue], defaultStyle, sharedStyles);
  41459. } else {
  41460. return defaultStyle;
  41461. }
  41462. };
  41463. /**
  41464. * @param {Node} node Node.
  41465. * @private
  41466. * @return {ol.Color|undefined} Color.
  41467. */
  41468. ol.format.KML.readColor_ = function(node) {
  41469. var s = ol.xml.getAllTextContent(node, false);
  41470. // The KML specification states that colors should not include a leading `#`
  41471. // but we tolerate them.
  41472. var m = /^\s*#?\s*([0-9A-Fa-f]{8})\s*$/.exec(s);
  41473. if (m) {
  41474. var hexColor = m[1];
  41475. return [
  41476. parseInt(hexColor.substr(6, 2), 16),
  41477. parseInt(hexColor.substr(4, 2), 16),
  41478. parseInt(hexColor.substr(2, 2), 16),
  41479. parseInt(hexColor.substr(0, 2), 16) / 255
  41480. ];
  41481. } else {
  41482. return undefined;
  41483. }
  41484. };
  41485. /**
  41486. * @param {Node} node Node.
  41487. * @private
  41488. * @return {Array.<number>|undefined} Flat coordinates.
  41489. */
  41490. ol.format.KML.readFlatCoordinates_ = function(node) {
  41491. var s = ol.xml.getAllTextContent(node, false);
  41492. var flatCoordinates = [];
  41493. // The KML specification states that coordinate tuples should not include
  41494. // spaces, but we tolerate them.
  41495. var re =
  41496. /^\s*([+\-]?\d*\.?\d+(?:e[+\-]?\d+)?)\s*,\s*([+\-]?\d*\.?\d+(?:e[+\-]?\d+)?)(?:\s*,\s*([+\-]?\d*\.?\d+(?:e[+\-]?\d+)?))?\s*/i;
  41497. var m;
  41498. while ((m = re.exec(s))) {
  41499. var x = parseFloat(m[1]);
  41500. var y = parseFloat(m[2]);
  41501. var z = m[3] ? parseFloat(m[3]) : 0;
  41502. flatCoordinates.push(x, y, z);
  41503. s = s.substr(m[0].length);
  41504. }
  41505. if (s !== '') {
  41506. return undefined;
  41507. }
  41508. return flatCoordinates;
  41509. };
  41510. /**
  41511. * @param {Node} node Node.
  41512. * @private
  41513. * @return {string} URI.
  41514. */
  41515. ol.format.KML.readURI_ = function(node) {
  41516. var s = ol.xml.getAllTextContent(node, false).trim();
  41517. if (node.baseURI && node.baseURI !== 'about:blank') {
  41518. var url = new URL(s, node.baseURI);
  41519. return url.href;
  41520. } else {
  41521. return s;
  41522. }
  41523. };
  41524. /**
  41525. * @param {Node} node Node.
  41526. * @private
  41527. * @return {ol.KMLVec2_} Vec2.
  41528. */
  41529. ol.format.KML.readVec2_ = function(node) {
  41530. var xunits = node.getAttribute('xunits');
  41531. var yunits = node.getAttribute('yunits');
  41532. var origin;
  41533. if (xunits !== 'insetPixels') {
  41534. if (yunits !== 'insetPixels') {
  41535. origin = ol.style.IconOrigin.BOTTOM_LEFT;
  41536. } else {
  41537. origin = ol.style.IconOrigin.TOP_LEFT;
  41538. }
  41539. } else {
  41540. if (yunits !== 'insetPixels') {
  41541. origin = ol.style.IconOrigin.BOTTOM_RIGHT;
  41542. } else {
  41543. origin = ol.style.IconOrigin.TOP_RIGHT;
  41544. }
  41545. }
  41546. return {
  41547. x: parseFloat(node.getAttribute('x')),
  41548. xunits: ol.format.KML.ICON_ANCHOR_UNITS_MAP_[xunits],
  41549. y: parseFloat(node.getAttribute('y')),
  41550. yunits: ol.format.KML.ICON_ANCHOR_UNITS_MAP_[yunits],
  41551. origin: origin
  41552. };
  41553. };
  41554. /**
  41555. * @param {Node} node Node.
  41556. * @private
  41557. * @return {number|undefined} Scale.
  41558. */
  41559. ol.format.KML.readScale_ = function(node) {
  41560. return ol.format.XSD.readDecimal(node);
  41561. };
  41562. /**
  41563. * @param {Node} node Node.
  41564. * @param {Array.<*>} objectStack Object stack.
  41565. * @private
  41566. * @return {Array.<ol.style.Style>|string|undefined} StyleMap.
  41567. */
  41568. ol.format.KML.readStyleMapValue_ = function(node, objectStack) {
  41569. return ol.xml.pushParseAndPop(undefined,
  41570. ol.format.KML.STYLE_MAP_PARSERS_, node, objectStack);
  41571. };
  41572. /**
  41573. * @param {Node} node Node.
  41574. * @param {Array.<*>} objectStack Object stack.
  41575. * @private
  41576. */
  41577. ol.format.KML.IconStyleParser_ = function(node, objectStack) {
  41578. // FIXME refreshMode
  41579. // FIXME refreshInterval
  41580. // FIXME viewRefreshTime
  41581. // FIXME viewBoundScale
  41582. // FIXME viewFormat
  41583. // FIXME httpQuery
  41584. var object = ol.xml.pushParseAndPop(
  41585. {}, ol.format.KML.ICON_STYLE_PARSERS_, node, objectStack);
  41586. if (!object) {
  41587. return;
  41588. }
  41589. var styleObject = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  41590. var IconObject = 'Icon' in object ? object['Icon'] : {};
  41591. var drawIcon = (!('Icon' in object) || Object.keys(IconObject).length > 0);
  41592. var src;
  41593. var href = /** @type {string|undefined} */
  41594. (IconObject['href']);
  41595. if (href) {
  41596. src = href;
  41597. } else if (drawIcon) {
  41598. src = ol.format.KML.DEFAULT_IMAGE_STYLE_SRC_;
  41599. }
  41600. var anchor, anchorXUnits, anchorYUnits;
  41601. var anchorOrigin = ol.style.IconOrigin.BOTTOM_LEFT;
  41602. var hotSpot = /** @type {ol.KMLVec2_|undefined} */
  41603. (object['hotSpot']);
  41604. if (hotSpot) {
  41605. anchor = [hotSpot.x, hotSpot.y];
  41606. anchorXUnits = hotSpot.xunits;
  41607. anchorYUnits = hotSpot.yunits;
  41608. anchorOrigin = hotSpot.origin;
  41609. } else if (src === ol.format.KML.DEFAULT_IMAGE_STYLE_SRC_) {
  41610. anchor = ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_;
  41611. anchorXUnits = ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_X_UNITS_;
  41612. anchorYUnits = ol.format.KML.DEFAULT_IMAGE_STYLE_ANCHOR_Y_UNITS_;
  41613. } else if (/^http:\/\/maps\.(?:google|gstatic)\.com\//.test(src)) {
  41614. anchor = [0.5, 0];
  41615. anchorXUnits = ol.style.IconAnchorUnits.FRACTION;
  41616. anchorYUnits = ol.style.IconAnchorUnits.FRACTION;
  41617. }
  41618. var offset;
  41619. var x = /** @type {number|undefined} */
  41620. (IconObject['x']);
  41621. var y = /** @type {number|undefined} */
  41622. (IconObject['y']);
  41623. if (x !== undefined && y !== undefined) {
  41624. offset = [x, y];
  41625. }
  41626. var size;
  41627. var w = /** @type {number|undefined} */
  41628. (IconObject['w']);
  41629. var h = /** @type {number|undefined} */
  41630. (IconObject['h']);
  41631. if (w !== undefined && h !== undefined) {
  41632. size = [w, h];
  41633. }
  41634. var rotation;
  41635. var heading = /** @type {number} */
  41636. (object['heading']);
  41637. if (heading !== undefined) {
  41638. rotation = ol.math.toRadians(heading);
  41639. }
  41640. var scale = /** @type {number|undefined} */
  41641. (object['scale']);
  41642. if (drawIcon) {
  41643. if (src == ol.format.KML.DEFAULT_IMAGE_STYLE_SRC_) {
  41644. size = ol.format.KML.DEFAULT_IMAGE_STYLE_SIZE_;
  41645. if (scale === undefined) {
  41646. scale = ol.format.KML.DEFAULT_IMAGE_SCALE_MULTIPLIER_;
  41647. }
  41648. }
  41649. var imageStyle = new ol.style.Icon({
  41650. anchor: anchor,
  41651. anchorOrigin: anchorOrigin,
  41652. anchorXUnits: anchorXUnits,
  41653. anchorYUnits: anchorYUnits,
  41654. crossOrigin: 'anonymous', // FIXME should this be configurable?
  41655. offset: offset,
  41656. offsetOrigin: ol.style.IconOrigin.BOTTOM_LEFT,
  41657. rotation: rotation,
  41658. scale: scale,
  41659. size: size,
  41660. src: src
  41661. });
  41662. styleObject['imageStyle'] = imageStyle;
  41663. } else {
  41664. // handle the case when we explicitly want to draw no icon.
  41665. styleObject['imageStyle'] = ol.format.KML.DEFAULT_NO_IMAGE_STYLE_;
  41666. }
  41667. };
  41668. /**
  41669. * @param {Node} node Node.
  41670. * @param {Array.<*>} objectStack Object stack.
  41671. * @private
  41672. */
  41673. ol.format.KML.LabelStyleParser_ = function(node, objectStack) {
  41674. // FIXME colorMode
  41675. var object = ol.xml.pushParseAndPop(
  41676. {}, ol.format.KML.LABEL_STYLE_PARSERS_, node, objectStack);
  41677. if (!object) {
  41678. return;
  41679. }
  41680. var styleObject = objectStack[objectStack.length - 1];
  41681. var textStyle = new ol.style.Text({
  41682. fill: new ol.style.Fill({
  41683. color: /** @type {ol.Color} */
  41684. ('color' in object ? object['color'] : ol.format.KML.DEFAULT_COLOR_)
  41685. }),
  41686. scale: /** @type {number|undefined} */
  41687. (object['scale'])
  41688. });
  41689. styleObject['textStyle'] = textStyle;
  41690. };
  41691. /**
  41692. * @param {Node} node Node.
  41693. * @param {Array.<*>} objectStack Object stack.
  41694. * @private
  41695. */
  41696. ol.format.KML.LineStyleParser_ = function(node, objectStack) {
  41697. // FIXME colorMode
  41698. // FIXME gx:outerColor
  41699. // FIXME gx:outerWidth
  41700. // FIXME gx:physicalWidth
  41701. // FIXME gx:labelVisibility
  41702. var object = ol.xml.pushParseAndPop(
  41703. {}, ol.format.KML.LINE_STYLE_PARSERS_, node, objectStack);
  41704. if (!object) {
  41705. return;
  41706. }
  41707. var styleObject = objectStack[objectStack.length - 1];
  41708. var strokeStyle = new ol.style.Stroke({
  41709. color: /** @type {ol.Color} */
  41710. ('color' in object ? object['color'] : ol.format.KML.DEFAULT_COLOR_),
  41711. width: /** @type {number} */ ('width' in object ? object['width'] : 1)
  41712. });
  41713. styleObject['strokeStyle'] = strokeStyle;
  41714. };
  41715. /**
  41716. * @param {Node} node Node.
  41717. * @param {Array.<*>} objectStack Object stack.
  41718. * @private
  41719. */
  41720. ol.format.KML.PolyStyleParser_ = function(node, objectStack) {
  41721. // FIXME colorMode
  41722. var object = ol.xml.pushParseAndPop(
  41723. {}, ol.format.KML.POLY_STYLE_PARSERS_, node, objectStack);
  41724. if (!object) {
  41725. return;
  41726. }
  41727. var styleObject = objectStack[objectStack.length - 1];
  41728. var fillStyle = new ol.style.Fill({
  41729. color: /** @type {ol.Color} */
  41730. ('color' in object ? object['color'] : ol.format.KML.DEFAULT_COLOR_)
  41731. });
  41732. styleObject['fillStyle'] = fillStyle;
  41733. var fill = /** @type {boolean|undefined} */ (object['fill']);
  41734. if (fill !== undefined) {
  41735. styleObject['fill'] = fill;
  41736. }
  41737. var outline =
  41738. /** @type {boolean|undefined} */ (object['outline']);
  41739. if (outline !== undefined) {
  41740. styleObject['outline'] = outline;
  41741. }
  41742. };
  41743. /**
  41744. * @param {Node} node Node.
  41745. * @param {Array.<*>} objectStack Object stack.
  41746. * @private
  41747. * @return {Array.<number>} LinearRing flat coordinates.
  41748. */
  41749. ol.format.KML.readFlatLinearRing_ = function(node, objectStack) {
  41750. return ol.xml.pushParseAndPop(null,
  41751. ol.format.KML.FLAT_LINEAR_RING_PARSERS_, node, objectStack);
  41752. };
  41753. /**
  41754. * @param {Node} node Node.
  41755. * @param {Array.<*>} objectStack Object stack.
  41756. * @private
  41757. */
  41758. ol.format.KML.gxCoordParser_ = function(node, objectStack) {
  41759. var gxTrackObject = /** @type {ol.KMLGxTrackObject_} */
  41760. (objectStack[objectStack.length - 1]);
  41761. var flatCoordinates = gxTrackObject.flatCoordinates;
  41762. var s = ol.xml.getAllTextContent(node, false);
  41763. var re =
  41764. /^\s*([+\-]?\d+(?:\.\d*)?(?:e[+\-]?\d*)?)\s+([+\-]?\d+(?:\.\d*)?(?:e[+\-]?\d*)?)\s+([+\-]?\d+(?:\.\d*)?(?:e[+\-]?\d*)?)\s*$/i;
  41765. var m = re.exec(s);
  41766. if (m) {
  41767. var x = parseFloat(m[1]);
  41768. var y = parseFloat(m[2]);
  41769. var z = parseFloat(m[3]);
  41770. flatCoordinates.push(x, y, z, 0);
  41771. } else {
  41772. flatCoordinates.push(0, 0, 0, 0);
  41773. }
  41774. };
  41775. /**
  41776. * @param {Node} node Node.
  41777. * @param {Array.<*>} objectStack Object stack.
  41778. * @private
  41779. * @return {ol.geom.MultiLineString|undefined} MultiLineString.
  41780. */
  41781. ol.format.KML.readGxMultiTrack_ = function(node, objectStack) {
  41782. var lineStrings = ol.xml.pushParseAndPop([],
  41783. ol.format.KML.GX_MULTITRACK_GEOMETRY_PARSERS_, node, objectStack);
  41784. if (!lineStrings) {
  41785. return undefined;
  41786. }
  41787. var multiLineString = new ol.geom.MultiLineString(null);
  41788. multiLineString.setLineStrings(lineStrings);
  41789. return multiLineString;
  41790. };
  41791. /**
  41792. * @param {Node} node Node.
  41793. * @param {Array.<*>} objectStack Object stack.
  41794. * @private
  41795. * @return {ol.geom.LineString|undefined} LineString.
  41796. */
  41797. ol.format.KML.readGxTrack_ = function(node, objectStack) {
  41798. var gxTrackObject = ol.xml.pushParseAndPop(
  41799. /** @type {ol.KMLGxTrackObject_} */ ({
  41800. flatCoordinates: [],
  41801. whens: []
  41802. }), ol.format.KML.GX_TRACK_PARSERS_, node, objectStack);
  41803. if (!gxTrackObject) {
  41804. return undefined;
  41805. }
  41806. var flatCoordinates = gxTrackObject.flatCoordinates;
  41807. var whens = gxTrackObject.whens;
  41808. var i, ii;
  41809. for (i = 0, ii = Math.min(flatCoordinates.length, whens.length); i < ii;
  41810. ++i) {
  41811. flatCoordinates[4 * i + 3] = whens[i];
  41812. }
  41813. var lineString = new ol.geom.LineString(null);
  41814. lineString.setFlatCoordinates(ol.geom.GeometryLayout.XYZM, flatCoordinates);
  41815. return lineString;
  41816. };
  41817. /**
  41818. * @param {Node} node Node.
  41819. * @param {Array.<*>} objectStack Object stack.
  41820. * @private
  41821. * @return {Object} Icon object.
  41822. */
  41823. ol.format.KML.readIcon_ = function(node, objectStack) {
  41824. var iconObject = ol.xml.pushParseAndPop(
  41825. {}, ol.format.KML.ICON_PARSERS_, node, objectStack);
  41826. if (iconObject) {
  41827. return iconObject;
  41828. } else {
  41829. return null;
  41830. }
  41831. };
  41832. /**
  41833. * @param {Node} node Node.
  41834. * @param {Array.<*>} objectStack Object stack.
  41835. * @private
  41836. * @return {Array.<number>} Flat coordinates.
  41837. */
  41838. ol.format.KML.readFlatCoordinatesFromNode_ = function(node, objectStack) {
  41839. return ol.xml.pushParseAndPop(null,
  41840. ol.format.KML.GEOMETRY_FLAT_COORDINATES_PARSERS_, node, objectStack);
  41841. };
  41842. /**
  41843. * @param {Node} node Node.
  41844. * @param {Array.<*>} objectStack Object stack.
  41845. * @private
  41846. * @return {ol.geom.LineString|undefined} LineString.
  41847. */
  41848. ol.format.KML.readLineString_ = function(node, objectStack) {
  41849. var properties = ol.xml.pushParseAndPop({},
  41850. ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_, node,
  41851. objectStack);
  41852. var flatCoordinates =
  41853. ol.format.KML.readFlatCoordinatesFromNode_(node, objectStack);
  41854. if (flatCoordinates) {
  41855. var lineString = new ol.geom.LineString(null);
  41856. lineString.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates);
  41857. lineString.setProperties(properties);
  41858. return lineString;
  41859. } else {
  41860. return undefined;
  41861. }
  41862. };
  41863. /**
  41864. * @param {Node} node Node.
  41865. * @param {Array.<*>} objectStack Object stack.
  41866. * @private
  41867. * @return {ol.geom.Polygon|undefined} Polygon.
  41868. */
  41869. ol.format.KML.readLinearRing_ = function(node, objectStack) {
  41870. var properties = ol.xml.pushParseAndPop({},
  41871. ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_, node,
  41872. objectStack);
  41873. var flatCoordinates =
  41874. ol.format.KML.readFlatCoordinatesFromNode_(node, objectStack);
  41875. if (flatCoordinates) {
  41876. var polygon = new ol.geom.Polygon(null);
  41877. polygon.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates,
  41878. [flatCoordinates.length]);
  41879. polygon.setProperties(properties);
  41880. return polygon;
  41881. } else {
  41882. return undefined;
  41883. }
  41884. };
  41885. /**
  41886. * @param {Node} node Node.
  41887. * @param {Array.<*>} objectStack Object stack.
  41888. * @private
  41889. * @return {ol.geom.Geometry} Geometry.
  41890. */
  41891. ol.format.KML.readMultiGeometry_ = function(node, objectStack) {
  41892. var geometries = ol.xml.pushParseAndPop([],
  41893. ol.format.KML.MULTI_GEOMETRY_PARSERS_, node, objectStack);
  41894. if (!geometries) {
  41895. return null;
  41896. }
  41897. if (geometries.length === 0) {
  41898. return new ol.geom.GeometryCollection(geometries);
  41899. }
  41900. /** @type {ol.geom.Geometry} */
  41901. var multiGeometry;
  41902. var homogeneous = true;
  41903. var type = geometries[0].getType();
  41904. var geometry, i, ii;
  41905. for (i = 1, ii = geometries.length; i < ii; ++i) {
  41906. geometry = geometries[i];
  41907. if (geometry.getType() != type) {
  41908. homogeneous = false;
  41909. break;
  41910. }
  41911. }
  41912. if (homogeneous) {
  41913. var layout;
  41914. var flatCoordinates;
  41915. if (type == ol.geom.GeometryType.POINT) {
  41916. var point = geometries[0];
  41917. layout = point.getLayout();
  41918. flatCoordinates = point.getFlatCoordinates();
  41919. for (i = 1, ii = geometries.length; i < ii; ++i) {
  41920. geometry = geometries[i];
  41921. ol.array.extend(flatCoordinates, geometry.getFlatCoordinates());
  41922. }
  41923. multiGeometry = new ol.geom.MultiPoint(null);
  41924. multiGeometry.setFlatCoordinates(layout, flatCoordinates);
  41925. ol.format.KML.setCommonGeometryProperties_(multiGeometry, geometries);
  41926. } else if (type == ol.geom.GeometryType.LINE_STRING) {
  41927. multiGeometry = new ol.geom.MultiLineString(null);
  41928. multiGeometry.setLineStrings(geometries);
  41929. ol.format.KML.setCommonGeometryProperties_(multiGeometry, geometries);
  41930. } else if (type == ol.geom.GeometryType.POLYGON) {
  41931. multiGeometry = new ol.geom.MultiPolygon(null);
  41932. multiGeometry.setPolygons(geometries);
  41933. ol.format.KML.setCommonGeometryProperties_(multiGeometry, geometries);
  41934. } else if (type == ol.geom.GeometryType.GEOMETRY_COLLECTION) {
  41935. multiGeometry = new ol.geom.GeometryCollection(geometries);
  41936. } else {
  41937. ol.asserts.assert(false, 37); // Unknown geometry type found
  41938. }
  41939. } else {
  41940. multiGeometry = new ol.geom.GeometryCollection(geometries);
  41941. }
  41942. return /** @type {ol.geom.Geometry} */ (multiGeometry);
  41943. };
  41944. /**
  41945. * @param {Node} node Node.
  41946. * @param {Array.<*>} objectStack Object stack.
  41947. * @private
  41948. * @return {ol.geom.Point|undefined} Point.
  41949. */
  41950. ol.format.KML.readPoint_ = function(node, objectStack) {
  41951. var properties = ol.xml.pushParseAndPop({},
  41952. ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_, node,
  41953. objectStack);
  41954. var flatCoordinates =
  41955. ol.format.KML.readFlatCoordinatesFromNode_(node, objectStack);
  41956. if (flatCoordinates) {
  41957. var point = new ol.geom.Point(null);
  41958. point.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates);
  41959. point.setProperties(properties);
  41960. return point;
  41961. } else {
  41962. return undefined;
  41963. }
  41964. };
  41965. /**
  41966. * @param {Node} node Node.
  41967. * @param {Array.<*>} objectStack Object stack.
  41968. * @private
  41969. * @return {ol.geom.Polygon|undefined} Polygon.
  41970. */
  41971. ol.format.KML.readPolygon_ = function(node, objectStack) {
  41972. var properties = ol.xml.pushParseAndPop(/** @type {Object<string,*>} */ ({}),
  41973. ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_, node,
  41974. objectStack);
  41975. var flatLinearRings = ol.xml.pushParseAndPop([null],
  41976. ol.format.KML.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack);
  41977. if (flatLinearRings && flatLinearRings[0]) {
  41978. var polygon = new ol.geom.Polygon(null);
  41979. var flatCoordinates = flatLinearRings[0];
  41980. var ends = [flatCoordinates.length];
  41981. var i, ii;
  41982. for (i = 1, ii = flatLinearRings.length; i < ii; ++i) {
  41983. ol.array.extend(flatCoordinates, flatLinearRings[i]);
  41984. ends.push(flatCoordinates.length);
  41985. }
  41986. polygon.setFlatCoordinates(
  41987. ol.geom.GeometryLayout.XYZ, flatCoordinates, ends);
  41988. polygon.setProperties(properties);
  41989. return polygon;
  41990. } else {
  41991. return undefined;
  41992. }
  41993. };
  41994. /**
  41995. * @param {Node} node Node.
  41996. * @param {Array.<*>} objectStack Object stack.
  41997. * @private
  41998. * @return {Array.<ol.style.Style>} Style.
  41999. */
  42000. ol.format.KML.readStyle_ = function(node, objectStack) {
  42001. var styleObject = ol.xml.pushParseAndPop(
  42002. {}, ol.format.KML.STYLE_PARSERS_, node, objectStack);
  42003. if (!styleObject) {
  42004. return null;
  42005. }
  42006. var fillStyle = /** @type {ol.style.Fill} */
  42007. ('fillStyle' in styleObject ?
  42008. styleObject['fillStyle'] : ol.format.KML.DEFAULT_FILL_STYLE_);
  42009. var fill = /** @type {boolean|undefined} */ (styleObject['fill']);
  42010. if (fill !== undefined && !fill) {
  42011. fillStyle = null;
  42012. }
  42013. var imageStyle = /** @type {ol.style.Image} */
  42014. ('imageStyle' in styleObject ?
  42015. styleObject['imageStyle'] : ol.format.KML.DEFAULT_IMAGE_STYLE_);
  42016. if (imageStyle == ol.format.KML.DEFAULT_NO_IMAGE_STYLE_) {
  42017. imageStyle = undefined;
  42018. }
  42019. var textStyle = /** @type {ol.style.Text} */
  42020. ('textStyle' in styleObject ?
  42021. styleObject['textStyle'] : ol.format.KML.DEFAULT_TEXT_STYLE_);
  42022. var strokeStyle = /** @type {ol.style.Stroke} */
  42023. ('strokeStyle' in styleObject ?
  42024. styleObject['strokeStyle'] : ol.format.KML.DEFAULT_STROKE_STYLE_);
  42025. var outline = /** @type {boolean|undefined} */
  42026. (styleObject['outline']);
  42027. if (outline !== undefined && !outline) {
  42028. strokeStyle = null;
  42029. }
  42030. return [new ol.style.Style({
  42031. fill: fillStyle,
  42032. image: imageStyle,
  42033. stroke: strokeStyle,
  42034. text: textStyle,
  42035. zIndex: undefined // FIXME
  42036. })];
  42037. };
  42038. /**
  42039. * Reads an array of geometries and creates arrays for common geometry
  42040. * properties. Then sets them to the multi geometry.
  42041. * @param {ol.geom.MultiPoint|ol.geom.MultiLineString|ol.geom.MultiPolygon}
  42042. * multiGeometry A multi-geometry.
  42043. * @param {Array.<ol.geom.Geometry>} geometries List of geometries.
  42044. * @private
  42045. */
  42046. ol.format.KML.setCommonGeometryProperties_ = function(multiGeometry,
  42047. geometries) {
  42048. var ii = geometries.length;
  42049. var extrudes = new Array(geometries.length);
  42050. var tessellates = new Array(geometries.length);
  42051. var altitudeModes = new Array(geometries.length);
  42052. var geometry, i, hasExtrude, hasTessellate, hasAltitudeMode;
  42053. hasExtrude = hasTessellate = hasAltitudeMode = false;
  42054. for (i = 0; i < ii; ++i) {
  42055. geometry = geometries[i];
  42056. extrudes[i] = geometry.get('extrude');
  42057. tessellates[i] = geometry.get('tessellate');
  42058. altitudeModes[i] = geometry.get('altitudeMode');
  42059. hasExtrude = hasExtrude || extrudes[i] !== undefined;
  42060. hasTessellate = hasTessellate || tessellates[i] !== undefined;
  42061. hasAltitudeMode = hasAltitudeMode || altitudeModes[i];
  42062. }
  42063. if (hasExtrude) {
  42064. multiGeometry.set('extrude', extrudes);
  42065. }
  42066. if (hasTessellate) {
  42067. multiGeometry.set('tessellate', tessellates);
  42068. }
  42069. if (hasAltitudeMode) {
  42070. multiGeometry.set('altitudeMode', altitudeModes);
  42071. }
  42072. };
  42073. /**
  42074. * @param {Node} node Node.
  42075. * @param {Array.<*>} objectStack Object stack.
  42076. * @private
  42077. */
  42078. ol.format.KML.DataParser_ = function(node, objectStack) {
  42079. var name = node.getAttribute('name');
  42080. ol.xml.parseNode(ol.format.KML.DATA_PARSERS_, node, objectStack);
  42081. var featureObject = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  42082. if (name !== null) {
  42083. featureObject[name] = featureObject.value;
  42084. } else if (featureObject.displayName !== null) {
  42085. featureObject[featureObject.displayName] = featureObject.value;
  42086. }
  42087. delete featureObject['value'];
  42088. };
  42089. /**
  42090. * @param {Node} node Node.
  42091. * @param {Array.<*>} objectStack Object stack.
  42092. * @private
  42093. */
  42094. ol.format.KML.ExtendedDataParser_ = function(node, objectStack) {
  42095. ol.xml.parseNode(ol.format.KML.EXTENDED_DATA_PARSERS_, node, objectStack);
  42096. };
  42097. /**
  42098. * @param {Node} node Node.
  42099. * @param {Array.<*>} objectStack Object stack.
  42100. * @private
  42101. */
  42102. ol.format.KML.RegionParser_ = function(node, objectStack) {
  42103. ol.xml.parseNode(ol.format.KML.REGION_PARSERS_, node, objectStack);
  42104. };
  42105. /**
  42106. * @param {Node} node Node.
  42107. * @param {Array.<*>} objectStack Object stack.
  42108. * @private
  42109. */
  42110. ol.format.KML.PairDataParser_ = function(node, objectStack) {
  42111. var pairObject = ol.xml.pushParseAndPop(
  42112. {}, ol.format.KML.PAIR_PARSERS_, node, objectStack);
  42113. if (!pairObject) {
  42114. return;
  42115. }
  42116. var key = /** @type {string|undefined} */
  42117. (pairObject['key']);
  42118. if (key && key == 'normal') {
  42119. var styleUrl = /** @type {string|undefined} */
  42120. (pairObject['styleUrl']);
  42121. if (styleUrl) {
  42122. objectStack[objectStack.length - 1] = styleUrl;
  42123. }
  42124. var Style = /** @type {ol.style.Style} */
  42125. (pairObject['Style']);
  42126. if (Style) {
  42127. objectStack[objectStack.length - 1] = Style;
  42128. }
  42129. }
  42130. };
  42131. /**
  42132. * @param {Node} node Node.
  42133. * @param {Array.<*>} objectStack Object stack.
  42134. * @private
  42135. */
  42136. ol.format.KML.PlacemarkStyleMapParser_ = function(node, objectStack) {
  42137. var styleMapValue = ol.format.KML.readStyleMapValue_(node, objectStack);
  42138. if (!styleMapValue) {
  42139. return;
  42140. }
  42141. var placemarkObject = objectStack[objectStack.length - 1];
  42142. if (Array.isArray(styleMapValue)) {
  42143. placemarkObject['Style'] = styleMapValue;
  42144. } else if (typeof styleMapValue === 'string') {
  42145. placemarkObject['styleUrl'] = styleMapValue;
  42146. } else {
  42147. ol.asserts.assert(false, 38); // `styleMapValue` has an unknown type
  42148. }
  42149. };
  42150. /**
  42151. * @param {Node} node Node.
  42152. * @param {Array.<*>} objectStack Object stack.
  42153. * @private
  42154. */
  42155. ol.format.KML.SchemaDataParser_ = function(node, objectStack) {
  42156. ol.xml.parseNode(ol.format.KML.SCHEMA_DATA_PARSERS_, node, objectStack);
  42157. };
  42158. /**
  42159. * @param {Node} node Node.
  42160. * @param {Array.<*>} objectStack Object stack.
  42161. * @private
  42162. */
  42163. ol.format.KML.SimpleDataParser_ = function(node, objectStack) {
  42164. var name = node.getAttribute('name');
  42165. if (name !== null) {
  42166. var data = ol.format.XSD.readString(node);
  42167. var featureObject =
  42168. /** @type {Object} */ (objectStack[objectStack.length - 1]);
  42169. featureObject[name] = data;
  42170. }
  42171. };
  42172. /**
  42173. * @param {Node} node Node.
  42174. * @param {Array.<*>} objectStack Object stack.
  42175. * @private
  42176. */
  42177. ol.format.KML.LatLonAltBoxParser_ = function(node, objectStack) {
  42178. var object = ol.xml.pushParseAndPop({}, ol.format.KML.LAT_LON_ALT_BOX_PARSERS_, node, objectStack);
  42179. if (!object) {
  42180. return;
  42181. }
  42182. var regionObject = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  42183. var extent = [
  42184. parseFloat(object['west']),
  42185. parseFloat(object['south']),
  42186. parseFloat(object['east']),
  42187. parseFloat(object['north'])
  42188. ];
  42189. regionObject['extent'] = extent;
  42190. regionObject['altitudeMode'] = object['altitudeMode'];
  42191. regionObject['minAltitude'] = parseFloat(object['minAltitude']);
  42192. regionObject['maxAltitude'] = parseFloat(object['maxAltitude']);
  42193. };
  42194. /**
  42195. * @param {Node} node Node.
  42196. * @param {Array.<*>} objectStack Object stack.
  42197. * @private
  42198. */
  42199. ol.format.KML.LodParser_ = function(node, objectStack) {
  42200. var object = ol.xml.pushParseAndPop({}, ol.format.KML.LOD_PARSERS_, node, objectStack);
  42201. if (!object) {
  42202. return;
  42203. }
  42204. var lodObject = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  42205. lodObject['minLodPixels'] = parseFloat(object['minLodPixels']);
  42206. lodObject['maxLodPixels'] = parseFloat(object['maxLodPixels']);
  42207. lodObject['minFadeExtent'] = parseFloat(object['minFadeExtent']);
  42208. lodObject['maxFadeExtent'] = parseFloat(object['maxFadeExtent']);
  42209. };
  42210. /**
  42211. * @param {Node} node Node.
  42212. * @param {Array.<*>} objectStack Object stack.
  42213. * @private
  42214. */
  42215. ol.format.KML.innerBoundaryIsParser_ = function(node, objectStack) {
  42216. /** @type {Array.<number>|undefined} */
  42217. var flatLinearRing = ol.xml.pushParseAndPop(undefined,
  42218. ol.format.KML.INNER_BOUNDARY_IS_PARSERS_, node, objectStack);
  42219. if (flatLinearRing) {
  42220. var flatLinearRings = /** @type {Array.<Array.<number>>} */
  42221. (objectStack[objectStack.length - 1]);
  42222. flatLinearRings.push(flatLinearRing);
  42223. }
  42224. };
  42225. /**
  42226. * @param {Node} node Node.
  42227. * @param {Array.<*>} objectStack Object stack.
  42228. * @private
  42229. */
  42230. ol.format.KML.outerBoundaryIsParser_ = function(node, objectStack) {
  42231. /** @type {Array.<number>|undefined} */
  42232. var flatLinearRing = ol.xml.pushParseAndPop(undefined,
  42233. ol.format.KML.OUTER_BOUNDARY_IS_PARSERS_, node, objectStack);
  42234. if (flatLinearRing) {
  42235. var flatLinearRings = /** @type {Array.<Array.<number>>} */
  42236. (objectStack[objectStack.length - 1]);
  42237. flatLinearRings[0] = flatLinearRing;
  42238. }
  42239. };
  42240. /**
  42241. * @param {Node} node Node.
  42242. * @param {Array.<*>} objectStack Object stack.
  42243. * @private
  42244. */
  42245. ol.format.KML.LinkParser_ = function(node, objectStack) {
  42246. ol.xml.parseNode(ol.format.KML.LINK_PARSERS_, node, objectStack);
  42247. };
  42248. /**
  42249. * @param {Node} node Node.
  42250. * @param {Array.<*>} objectStack Object stack.
  42251. * @private
  42252. */
  42253. ol.format.KML.whenParser_ = function(node, objectStack) {
  42254. var gxTrackObject = /** @type {ol.KMLGxTrackObject_} */
  42255. (objectStack[objectStack.length - 1]);
  42256. var whens = gxTrackObject.whens;
  42257. var s = ol.xml.getAllTextContent(node, false);
  42258. var when = Date.parse(s);
  42259. whens.push(isNaN(when) ? 0 : when);
  42260. };
  42261. /**
  42262. * @const
  42263. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42264. * @private
  42265. */
  42266. ol.format.KML.DATA_PARSERS_ = ol.xml.makeStructureNS(
  42267. ol.format.KML.NAMESPACE_URIS_, {
  42268. 'displayName': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  42269. 'value': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString)
  42270. });
  42271. /**
  42272. * @const
  42273. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42274. * @private
  42275. */
  42276. ol.format.KML.EXTENDED_DATA_PARSERS_ = ol.xml.makeStructureNS(
  42277. ol.format.KML.NAMESPACE_URIS_, {
  42278. 'Data': ol.format.KML.DataParser_,
  42279. 'SchemaData': ol.format.KML.SchemaDataParser_
  42280. });
  42281. /**
  42282. * @const
  42283. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42284. * @private
  42285. */
  42286. ol.format.KML.REGION_PARSERS_ = ol.xml.makeStructureNS(
  42287. ol.format.KML.NAMESPACE_URIS_, {
  42288. 'LatLonAltBox': ol.format.KML.LatLonAltBoxParser_,
  42289. 'Lod': ol.format.KML.LodParser_
  42290. });
  42291. /**
  42292. * @const
  42293. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42294. * @private
  42295. */
  42296. ol.format.KML.LAT_LON_ALT_BOX_PARSERS_ = ol.xml.makeStructureNS(
  42297. ol.format.KML.NAMESPACE_URIS_, {
  42298. 'altitudeMode': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  42299. 'minAltitude': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  42300. 'maxAltitude': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  42301. 'north': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  42302. 'south': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  42303. 'east': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  42304. 'west': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal)
  42305. });
  42306. /**
  42307. * @const
  42308. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42309. * @private
  42310. */
  42311. ol.format.KML.LOD_PARSERS_ = ol.xml.makeStructureNS(
  42312. ol.format.KML.NAMESPACE_URIS_, {
  42313. 'minLodPixels': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  42314. 'maxLodPixels': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  42315. 'minFadeExtent': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  42316. 'maxFadeExtent': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal)
  42317. });
  42318. /**
  42319. * @const
  42320. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42321. * @private
  42322. */
  42323. ol.format.KML.EXTRUDE_AND_ALTITUDE_MODE_PARSERS_ = ol.xml.makeStructureNS(
  42324. ol.format.KML.NAMESPACE_URIS_, {
  42325. 'extrude': ol.xml.makeObjectPropertySetter(ol.format.XSD.readBoolean),
  42326. 'tessellate': ol.xml.makeObjectPropertySetter(ol.format.XSD.readBoolean),
  42327. 'altitudeMode': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString)
  42328. });
  42329. /**
  42330. * @const
  42331. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42332. * @private
  42333. */
  42334. ol.format.KML.FLAT_LINEAR_RING_PARSERS_ = ol.xml.makeStructureNS(
  42335. ol.format.KML.NAMESPACE_URIS_, {
  42336. 'coordinates': ol.xml.makeReplacer(ol.format.KML.readFlatCoordinates_)
  42337. });
  42338. /**
  42339. * @const
  42340. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42341. * @private
  42342. */
  42343. ol.format.KML.FLAT_LINEAR_RINGS_PARSERS_ = ol.xml.makeStructureNS(
  42344. ol.format.KML.NAMESPACE_URIS_, {
  42345. 'innerBoundaryIs': ol.format.KML.innerBoundaryIsParser_,
  42346. 'outerBoundaryIs': ol.format.KML.outerBoundaryIsParser_
  42347. });
  42348. /**
  42349. * @const
  42350. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42351. * @private
  42352. */
  42353. ol.format.KML.GX_TRACK_PARSERS_ = ol.xml.makeStructureNS(
  42354. ol.format.KML.NAMESPACE_URIS_, {
  42355. 'when': ol.format.KML.whenParser_
  42356. }, ol.xml.makeStructureNS(
  42357. ol.format.KML.GX_NAMESPACE_URIS_, {
  42358. 'coord': ol.format.KML.gxCoordParser_
  42359. }));
  42360. /**
  42361. * @const
  42362. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42363. * @private
  42364. */
  42365. ol.format.KML.GEOMETRY_FLAT_COORDINATES_PARSERS_ = ol.xml.makeStructureNS(
  42366. ol.format.KML.NAMESPACE_URIS_, {
  42367. 'coordinates': ol.xml.makeReplacer(ol.format.KML.readFlatCoordinates_)
  42368. });
  42369. /**
  42370. * @const
  42371. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42372. * @private
  42373. */
  42374. ol.format.KML.ICON_PARSERS_ = ol.xml.makeStructureNS(
  42375. ol.format.KML.NAMESPACE_URIS_, {
  42376. 'href': ol.xml.makeObjectPropertySetter(ol.format.KML.readURI_)
  42377. }, ol.xml.makeStructureNS(
  42378. ol.format.KML.GX_NAMESPACE_URIS_, {
  42379. 'x': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  42380. 'y': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  42381. 'w': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  42382. 'h': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal)
  42383. }));
  42384. /**
  42385. * @const
  42386. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42387. * @private
  42388. */
  42389. ol.format.KML.ICON_STYLE_PARSERS_ = ol.xml.makeStructureNS(
  42390. ol.format.KML.NAMESPACE_URIS_, {
  42391. 'Icon': ol.xml.makeObjectPropertySetter(ol.format.KML.readIcon_),
  42392. 'heading': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal),
  42393. 'hotSpot': ol.xml.makeObjectPropertySetter(ol.format.KML.readVec2_),
  42394. 'scale': ol.xml.makeObjectPropertySetter(ol.format.KML.readScale_)
  42395. });
  42396. /**
  42397. * @const
  42398. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42399. * @private
  42400. */
  42401. ol.format.KML.INNER_BOUNDARY_IS_PARSERS_ = ol.xml.makeStructureNS(
  42402. ol.format.KML.NAMESPACE_URIS_, {
  42403. 'LinearRing': ol.xml.makeReplacer(ol.format.KML.readFlatLinearRing_)
  42404. });
  42405. /**
  42406. * @const
  42407. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42408. * @private
  42409. */
  42410. ol.format.KML.LABEL_STYLE_PARSERS_ = ol.xml.makeStructureNS(
  42411. ol.format.KML.NAMESPACE_URIS_, {
  42412. 'color': ol.xml.makeObjectPropertySetter(ol.format.KML.readColor_),
  42413. 'scale': ol.xml.makeObjectPropertySetter(ol.format.KML.readScale_)
  42414. });
  42415. /**
  42416. * @const
  42417. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42418. * @private
  42419. */
  42420. ol.format.KML.LINE_STYLE_PARSERS_ = ol.xml.makeStructureNS(
  42421. ol.format.KML.NAMESPACE_URIS_, {
  42422. 'color': ol.xml.makeObjectPropertySetter(ol.format.KML.readColor_),
  42423. 'width': ol.xml.makeObjectPropertySetter(ol.format.XSD.readDecimal)
  42424. });
  42425. /**
  42426. * @const
  42427. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42428. * @private
  42429. */
  42430. ol.format.KML.MULTI_GEOMETRY_PARSERS_ = ol.xml.makeStructureNS(
  42431. ol.format.KML.NAMESPACE_URIS_, {
  42432. 'LineString': ol.xml.makeArrayPusher(ol.format.KML.readLineString_),
  42433. 'LinearRing': ol.xml.makeArrayPusher(ol.format.KML.readLinearRing_),
  42434. 'MultiGeometry': ol.xml.makeArrayPusher(ol.format.KML.readMultiGeometry_),
  42435. 'Point': ol.xml.makeArrayPusher(ol.format.KML.readPoint_),
  42436. 'Polygon': ol.xml.makeArrayPusher(ol.format.KML.readPolygon_)
  42437. });
  42438. /**
  42439. * @const
  42440. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42441. * @private
  42442. */
  42443. ol.format.KML.GX_MULTITRACK_GEOMETRY_PARSERS_ = ol.xml.makeStructureNS(
  42444. ol.format.KML.GX_NAMESPACE_URIS_, {
  42445. 'Track': ol.xml.makeArrayPusher(ol.format.KML.readGxTrack_)
  42446. });
  42447. /**
  42448. * @const
  42449. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42450. * @private
  42451. */
  42452. ol.format.KML.NETWORK_LINK_PARSERS_ = ol.xml.makeStructureNS(
  42453. ol.format.KML.NAMESPACE_URIS_, {
  42454. 'ExtendedData': ol.format.KML.ExtendedDataParser_,
  42455. 'Region': ol.format.KML.RegionParser_,
  42456. 'Link': ol.format.KML.LinkParser_,
  42457. 'address': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  42458. 'description': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  42459. 'name': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  42460. 'open': ol.xml.makeObjectPropertySetter(ol.format.XSD.readBoolean),
  42461. 'phoneNumber': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  42462. 'visibility': ol.xml.makeObjectPropertySetter(ol.format.XSD.readBoolean)
  42463. });
  42464. /**
  42465. * @const
  42466. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42467. * @private
  42468. */
  42469. ol.format.KML.LINK_PARSERS_ = ol.xml.makeStructureNS(
  42470. ol.format.KML.NAMESPACE_URIS_, {
  42471. 'href': ol.xml.makeObjectPropertySetter(ol.format.KML.readURI_)
  42472. });
  42473. /**
  42474. * @const
  42475. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42476. * @private
  42477. */
  42478. ol.format.KML.OUTER_BOUNDARY_IS_PARSERS_ = ol.xml.makeStructureNS(
  42479. ol.format.KML.NAMESPACE_URIS_, {
  42480. 'LinearRing': ol.xml.makeReplacer(ol.format.KML.readFlatLinearRing_)
  42481. });
  42482. /**
  42483. * @const
  42484. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42485. * @private
  42486. */
  42487. ol.format.KML.PAIR_PARSERS_ = ol.xml.makeStructureNS(
  42488. ol.format.KML.NAMESPACE_URIS_, {
  42489. 'Style': ol.xml.makeObjectPropertySetter(ol.format.KML.readStyle_),
  42490. 'key': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  42491. 'styleUrl': ol.xml.makeObjectPropertySetter(ol.format.KML.readURI_)
  42492. });
  42493. /**
  42494. * @const
  42495. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42496. * @private
  42497. */
  42498. ol.format.KML.PLACEMARK_PARSERS_ = ol.xml.makeStructureNS(
  42499. ol.format.KML.NAMESPACE_URIS_, {
  42500. 'ExtendedData': ol.format.KML.ExtendedDataParser_,
  42501. 'Region': ol.format.KML.RegionParser_,
  42502. 'MultiGeometry': ol.xml.makeObjectPropertySetter(
  42503. ol.format.KML.readMultiGeometry_, 'geometry'),
  42504. 'LineString': ol.xml.makeObjectPropertySetter(
  42505. ol.format.KML.readLineString_, 'geometry'),
  42506. 'LinearRing': ol.xml.makeObjectPropertySetter(
  42507. ol.format.KML.readLinearRing_, 'geometry'),
  42508. 'Point': ol.xml.makeObjectPropertySetter(
  42509. ol.format.KML.readPoint_, 'geometry'),
  42510. 'Polygon': ol.xml.makeObjectPropertySetter(
  42511. ol.format.KML.readPolygon_, 'geometry'),
  42512. 'Style': ol.xml.makeObjectPropertySetter(ol.format.KML.readStyle_),
  42513. 'StyleMap': ol.format.KML.PlacemarkStyleMapParser_,
  42514. 'address': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  42515. 'description': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  42516. 'name': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  42517. 'open': ol.xml.makeObjectPropertySetter(ol.format.XSD.readBoolean),
  42518. 'phoneNumber': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  42519. 'styleUrl': ol.xml.makeObjectPropertySetter(ol.format.KML.readURI_),
  42520. 'visibility': ol.xml.makeObjectPropertySetter(ol.format.XSD.readBoolean)
  42521. }, ol.xml.makeStructureNS(
  42522. ol.format.KML.GX_NAMESPACE_URIS_, {
  42523. 'MultiTrack': ol.xml.makeObjectPropertySetter(
  42524. ol.format.KML.readGxMultiTrack_, 'geometry'),
  42525. 'Track': ol.xml.makeObjectPropertySetter(
  42526. ol.format.KML.readGxTrack_, 'geometry')
  42527. }
  42528. ));
  42529. /**
  42530. * @const
  42531. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42532. * @private
  42533. */
  42534. ol.format.KML.POLY_STYLE_PARSERS_ = ol.xml.makeStructureNS(
  42535. ol.format.KML.NAMESPACE_URIS_, {
  42536. 'color': ol.xml.makeObjectPropertySetter(ol.format.KML.readColor_),
  42537. 'fill': ol.xml.makeObjectPropertySetter(ol.format.XSD.readBoolean),
  42538. 'outline': ol.xml.makeObjectPropertySetter(ol.format.XSD.readBoolean)
  42539. });
  42540. /**
  42541. * @const
  42542. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42543. * @private
  42544. */
  42545. ol.format.KML.SCHEMA_DATA_PARSERS_ = ol.xml.makeStructureNS(
  42546. ol.format.KML.NAMESPACE_URIS_, {
  42547. 'SimpleData': ol.format.KML.SimpleDataParser_
  42548. });
  42549. /**
  42550. * @const
  42551. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42552. * @private
  42553. */
  42554. ol.format.KML.STYLE_PARSERS_ = ol.xml.makeStructureNS(
  42555. ol.format.KML.NAMESPACE_URIS_, {
  42556. 'IconStyle': ol.format.KML.IconStyleParser_,
  42557. 'LabelStyle': ol.format.KML.LabelStyleParser_,
  42558. 'LineStyle': ol.format.KML.LineStyleParser_,
  42559. 'PolyStyle': ol.format.KML.PolyStyleParser_
  42560. });
  42561. /**
  42562. * @const
  42563. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  42564. * @private
  42565. */
  42566. ol.format.KML.STYLE_MAP_PARSERS_ = ol.xml.makeStructureNS(
  42567. ol.format.KML.NAMESPACE_URIS_, {
  42568. 'Pair': ol.format.KML.PairDataParser_
  42569. });
  42570. /**
  42571. * @param {Node} node Node.
  42572. * @param {Array.<*>} objectStack Object stack.
  42573. * @private
  42574. * @return {Array.<ol.Feature>|undefined} Features.
  42575. */
  42576. ol.format.KML.prototype.readDocumentOrFolder_ = function(node, objectStack) {
  42577. // FIXME use scope somehow
  42578. var parsersNS = ol.xml.makeStructureNS(
  42579. ol.format.KML.NAMESPACE_URIS_, {
  42580. 'Document': ol.xml.makeArrayExtender(this.readDocumentOrFolder_, this),
  42581. 'Folder': ol.xml.makeArrayExtender(this.readDocumentOrFolder_, this),
  42582. 'Placemark': ol.xml.makeArrayPusher(this.readPlacemark_, this),
  42583. 'Style': this.readSharedStyle_.bind(this),
  42584. 'StyleMap': this.readSharedStyleMap_.bind(this)
  42585. });
  42586. /** @type {Array.<ol.Feature>} */
  42587. var features = ol.xml.pushParseAndPop([], parsersNS, node, objectStack, this);
  42588. if (features) {
  42589. return features;
  42590. } else {
  42591. return undefined;
  42592. }
  42593. };
  42594. /**
  42595. * @param {Node} node Node.
  42596. * @param {Array.<*>} objectStack Object stack.
  42597. * @private
  42598. * @return {ol.Feature|undefined} Feature.
  42599. */
  42600. ol.format.KML.prototype.readPlacemark_ = function(node, objectStack) {
  42601. var object = ol.xml.pushParseAndPop({'geometry': null},
  42602. ol.format.KML.PLACEMARK_PARSERS_, node, objectStack);
  42603. if (!object) {
  42604. return undefined;
  42605. }
  42606. var feature = new ol.Feature();
  42607. var id = node.getAttribute('id');
  42608. if (id !== null) {
  42609. feature.setId(id);
  42610. }
  42611. var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]);
  42612. var geometry = object['geometry'];
  42613. if (geometry) {
  42614. ol.format.Feature.transformWithOptions(geometry, false, options);
  42615. }
  42616. feature.setGeometry(geometry);
  42617. delete object['geometry'];
  42618. if (this.extractStyles_) {
  42619. var style = object['Style'];
  42620. var styleUrl = object['styleUrl'];
  42621. var styleFunction = ol.format.KML.createFeatureStyleFunction_(
  42622. style, styleUrl, this.defaultStyle_, this.sharedStyles_,
  42623. this.showPointNames_);
  42624. feature.setStyle(styleFunction);
  42625. }
  42626. delete object['Style'];
  42627. // we do not remove the styleUrl property from the object, so it
  42628. // gets stored on feature when setProperties is called
  42629. feature.setProperties(object);
  42630. return feature;
  42631. };
  42632. /**
  42633. * @param {Node} node Node.
  42634. * @param {Array.<*>} objectStack Object stack.
  42635. * @private
  42636. */
  42637. ol.format.KML.prototype.readSharedStyle_ = function(node, objectStack) {
  42638. var id = node.getAttribute('id');
  42639. if (id !== null) {
  42640. var style = ol.format.KML.readStyle_(node, objectStack);
  42641. if (style) {
  42642. var styleUri;
  42643. if (node.baseURI && node.baseURI !== 'about:blank') {
  42644. var url = new URL('#' + id, node.baseURI);
  42645. styleUri = url.href;
  42646. } else {
  42647. styleUri = '#' + id;
  42648. }
  42649. this.sharedStyles_[styleUri] = style;
  42650. }
  42651. }
  42652. };
  42653. /**
  42654. * @param {Node} node Node.
  42655. * @param {Array.<*>} objectStack Object stack.
  42656. * @private
  42657. */
  42658. ol.format.KML.prototype.readSharedStyleMap_ = function(node, objectStack) {
  42659. var id = node.getAttribute('id');
  42660. if (id === null) {
  42661. return;
  42662. }
  42663. var styleMapValue = ol.format.KML.readStyleMapValue_(node, objectStack);
  42664. if (!styleMapValue) {
  42665. return;
  42666. }
  42667. var styleUri;
  42668. if (node.baseURI && node.baseURI !== 'about:blank') {
  42669. var url = new URL('#' + id, node.baseURI);
  42670. styleUri = url.href;
  42671. } else {
  42672. styleUri = '#' + id;
  42673. }
  42674. this.sharedStyles_[styleUri] = styleMapValue;
  42675. };
  42676. /**
  42677. * Read the first feature from a KML source. MultiGeometries are converted into
  42678. * GeometryCollections if they are a mix of geometry types, and into MultiPoint/
  42679. * MultiLineString/MultiPolygon if they are all of the same type.
  42680. *
  42681. * @function
  42682. * @param {Document|Node|Object|string} source Source.
  42683. * @param {olx.format.ReadOptions=} opt_options Read options.
  42684. * @return {ol.Feature} Feature.
  42685. * @api
  42686. */
  42687. ol.format.KML.prototype.readFeature;
  42688. /**
  42689. * @inheritDoc
  42690. */
  42691. ol.format.KML.prototype.readFeatureFromNode = function(node, opt_options) {
  42692. if (!ol.array.includes(ol.format.KML.NAMESPACE_URIS_, node.namespaceURI)) {
  42693. return null;
  42694. }
  42695. var feature = this.readPlacemark_(
  42696. node, [this.getReadOptions(node, opt_options)]);
  42697. if (feature) {
  42698. return feature;
  42699. } else {
  42700. return null;
  42701. }
  42702. };
  42703. /**
  42704. * Read all features from a KML source. MultiGeometries are converted into
  42705. * GeometryCollections if they are a mix of geometry types, and into MultiPoint/
  42706. * MultiLineString/MultiPolygon if they are all of the same type.
  42707. *
  42708. * @function
  42709. * @param {Document|Node|Object|string} source Source.
  42710. * @param {olx.format.ReadOptions=} opt_options Read options.
  42711. * @return {Array.<ol.Feature>} Features.
  42712. * @api
  42713. */
  42714. ol.format.KML.prototype.readFeatures;
  42715. /**
  42716. * @inheritDoc
  42717. */
  42718. ol.format.KML.prototype.readFeaturesFromNode = function(node, opt_options) {
  42719. if (!ol.array.includes(ol.format.KML.NAMESPACE_URIS_, node.namespaceURI)) {
  42720. return [];
  42721. }
  42722. var features;
  42723. var localName = node.localName;
  42724. if (localName == 'Document' || localName == 'Folder') {
  42725. features = this.readDocumentOrFolder_(
  42726. node, [this.getReadOptions(node, opt_options)]);
  42727. if (features) {
  42728. return features;
  42729. } else {
  42730. return [];
  42731. }
  42732. } else if (localName == 'Placemark') {
  42733. var feature = this.readPlacemark_(
  42734. node, [this.getReadOptions(node, opt_options)]);
  42735. if (feature) {
  42736. return [feature];
  42737. } else {
  42738. return [];
  42739. }
  42740. } else if (localName == 'kml') {
  42741. features = [];
  42742. var n;
  42743. for (n = node.firstElementChild; n; n = n.nextElementSibling) {
  42744. var fs = this.readFeaturesFromNode(n, opt_options);
  42745. if (fs) {
  42746. ol.array.extend(features, fs);
  42747. }
  42748. }
  42749. return features;
  42750. } else {
  42751. return [];
  42752. }
  42753. };
  42754. /**
  42755. * Read the name of the KML.
  42756. *
  42757. * @param {Document|Node|string} source Souce.
  42758. * @return {string|undefined} Name.
  42759. * @api
  42760. */
  42761. ol.format.KML.prototype.readName = function(source) {
  42762. if (ol.xml.isDocument(source)) {
  42763. return this.readNameFromDocument(/** @type {Document} */ (source));
  42764. } else if (ol.xml.isNode(source)) {
  42765. return this.readNameFromNode(/** @type {Node} */ (source));
  42766. } else if (typeof source === 'string') {
  42767. var doc = ol.xml.parse(source);
  42768. return this.readNameFromDocument(doc);
  42769. } else {
  42770. return undefined;
  42771. }
  42772. };
  42773. /**
  42774. * @param {Document} doc Document.
  42775. * @return {string|undefined} Name.
  42776. */
  42777. ol.format.KML.prototype.readNameFromDocument = function(doc) {
  42778. var n;
  42779. for (n = doc.firstChild; n; n = n.nextSibling) {
  42780. if (n.nodeType == Node.ELEMENT_NODE) {
  42781. var name = this.readNameFromNode(n);
  42782. if (name) {
  42783. return name;
  42784. }
  42785. }
  42786. }
  42787. return undefined;
  42788. };
  42789. /**
  42790. * @param {Node} node Node.
  42791. * @return {string|undefined} Name.
  42792. */
  42793. ol.format.KML.prototype.readNameFromNode = function(node) {
  42794. var n;
  42795. for (n = node.firstElementChild; n; n = n.nextElementSibling) {
  42796. if (ol.array.includes(ol.format.KML.NAMESPACE_URIS_, n.namespaceURI) &&
  42797. n.localName == 'name') {
  42798. return ol.format.XSD.readString(n);
  42799. }
  42800. }
  42801. for (n = node.firstElementChild; n; n = n.nextElementSibling) {
  42802. var localName = n.localName;
  42803. if (ol.array.includes(ol.format.KML.NAMESPACE_URIS_, n.namespaceURI) &&
  42804. (localName == 'Document' ||
  42805. localName == 'Folder' ||
  42806. localName == 'Placemark' ||
  42807. localName == 'kml')) {
  42808. var name = this.readNameFromNode(n);
  42809. if (name) {
  42810. return name;
  42811. }
  42812. }
  42813. }
  42814. return undefined;
  42815. };
  42816. /**
  42817. * Read the network links of the KML.
  42818. *
  42819. * @param {Document|Node|string} source Source.
  42820. * @return {Array.<Object>} Network links.
  42821. * @api
  42822. */
  42823. ol.format.KML.prototype.readNetworkLinks = function(source) {
  42824. var networkLinks = [];
  42825. if (ol.xml.isDocument(source)) {
  42826. ol.array.extend(networkLinks, this.readNetworkLinksFromDocument(
  42827. /** @type {Document} */ (source)));
  42828. } else if (ol.xml.isNode(source)) {
  42829. ol.array.extend(networkLinks, this.readNetworkLinksFromNode(
  42830. /** @type {Node} */ (source)));
  42831. } else if (typeof source === 'string') {
  42832. var doc = ol.xml.parse(source);
  42833. ol.array.extend(networkLinks, this.readNetworkLinksFromDocument(doc));
  42834. }
  42835. return networkLinks;
  42836. };
  42837. /**
  42838. * @param {Document} doc Document.
  42839. * @return {Array.<Object>} Network links.
  42840. */
  42841. ol.format.KML.prototype.readNetworkLinksFromDocument = function(doc) {
  42842. var n, networkLinks = [];
  42843. for (n = doc.firstChild; n; n = n.nextSibling) {
  42844. if (n.nodeType == Node.ELEMENT_NODE) {
  42845. ol.array.extend(networkLinks, this.readNetworkLinksFromNode(n));
  42846. }
  42847. }
  42848. return networkLinks;
  42849. };
  42850. /**
  42851. * @param {Node} node Node.
  42852. * @return {Array.<Object>} Network links.
  42853. */
  42854. ol.format.KML.prototype.readNetworkLinksFromNode = function(node) {
  42855. var n, networkLinks = [];
  42856. for (n = node.firstElementChild; n; n = n.nextElementSibling) {
  42857. if (ol.array.includes(ol.format.KML.NAMESPACE_URIS_, n.namespaceURI) &&
  42858. n.localName == 'NetworkLink') {
  42859. var obj = ol.xml.pushParseAndPop({}, ol.format.KML.NETWORK_LINK_PARSERS_,
  42860. n, []);
  42861. networkLinks.push(obj);
  42862. }
  42863. }
  42864. for (n = node.firstElementChild; n; n = n.nextElementSibling) {
  42865. var localName = n.localName;
  42866. if (ol.array.includes(ol.format.KML.NAMESPACE_URIS_, n.namespaceURI) &&
  42867. (localName == 'Document' ||
  42868. localName == 'Folder' ||
  42869. localName == 'kml')) {
  42870. ol.array.extend(networkLinks, this.readNetworkLinksFromNode(n));
  42871. }
  42872. }
  42873. return networkLinks;
  42874. };
  42875. /**
  42876. * Read the regions of the KML.
  42877. *
  42878. * @param {Document|Node|string} source Source.
  42879. * @return {Array.<Object>} Regions.
  42880. * @api
  42881. */
  42882. ol.format.KML.prototype.readRegion = function(source) {
  42883. var regions = [];
  42884. if (ol.xml.isDocument(source)) {
  42885. ol.array.extend(regions, this.readRegionFromDocument(
  42886. /** @type {Document} */ (source)));
  42887. } else if (ol.xml.isNode(source)) {
  42888. ol.array.extend(regions, this.readRegionFromNode(
  42889. /** @type {Node} */ (source)));
  42890. } else if (typeof source === 'string') {
  42891. var doc = ol.xml.parse(source);
  42892. ol.array.extend(regions, this.readRegionFromDocument(doc));
  42893. }
  42894. return regions;
  42895. };
  42896. /**
  42897. * @param {Document} doc Document.
  42898. * @return {Array.<Object>} Region.
  42899. */
  42900. ol.format.KML.prototype.readRegionFromDocument = function(doc) {
  42901. var n, regions = [];
  42902. for (n = doc.firstChild; n; n = n.nextSibling) {
  42903. if (n.nodeType == Node.ELEMENT_NODE) {
  42904. ol.array.extend(regions, this.readRegionFromNode(n));
  42905. }
  42906. }
  42907. return regions;
  42908. };
  42909. /**
  42910. * @param {Node} node Node.
  42911. * @return {Array.<Object>} Region.
  42912. * @api
  42913. */
  42914. ol.format.KML.prototype.readRegionFromNode = function(node) {
  42915. var n, regions = [];
  42916. for (n = node.firstElementChild; n; n = n.nextElementSibling) {
  42917. if (ol.array.includes(ol.format.KML.NAMESPACE_URIS_, n.namespaceURI) &&
  42918. n.localName == 'Region') {
  42919. var obj = ol.xml.pushParseAndPop({}, ol.format.KML.REGION_PARSERS_,
  42920. n, []);
  42921. regions.push(obj);
  42922. }
  42923. }
  42924. for (n = node.firstElementChild; n; n = n.nextElementSibling) {
  42925. var localName = n.localName;
  42926. if (ol.array.includes(ol.format.KML.NAMESPACE_URIS_, n.namespaceURI) &&
  42927. (localName == 'Document' ||
  42928. localName == 'Folder' ||
  42929. localName == 'kml')) {
  42930. ol.array.extend(regions, this.readRegionFromNode(n));
  42931. }
  42932. }
  42933. return regions;
  42934. };
  42935. /**
  42936. * Read the projection from a KML source.
  42937. *
  42938. * @function
  42939. * @param {Document|Node|Object|string} source Source.
  42940. * @return {ol.proj.Projection} Projection.
  42941. * @api
  42942. */
  42943. ol.format.KML.prototype.readProjection;
  42944. /**
  42945. * @param {Node} node Node to append a TextNode with the color to.
  42946. * @param {ol.Color|string} color Color.
  42947. * @private
  42948. */
  42949. ol.format.KML.writeColorTextNode_ = function(node, color) {
  42950. var rgba = ol.color.asArray(color);
  42951. var opacity = (rgba.length == 4) ? rgba[3] : 1;
  42952. var abgr = [opacity * 255, rgba[2], rgba[1], rgba[0]];
  42953. var i;
  42954. for (i = 0; i < 4; ++i) {
  42955. var hex = parseInt(abgr[i], 10).toString(16);
  42956. abgr[i] = (hex.length == 1) ? '0' + hex : hex;
  42957. }
  42958. ol.format.XSD.writeStringTextNode(node, abgr.join(''));
  42959. };
  42960. /**
  42961. * @param {Node} node Node to append a TextNode with the coordinates to.
  42962. * @param {Array.<number>} coordinates Coordinates.
  42963. * @param {Array.<*>} objectStack Object stack.
  42964. * @private
  42965. */
  42966. ol.format.KML.writeCoordinatesTextNode_ = function(node, coordinates, objectStack) {
  42967. var context = objectStack[objectStack.length - 1];
  42968. var layout = context['layout'];
  42969. var stride = context['stride'];
  42970. var dimension;
  42971. if (layout == ol.geom.GeometryLayout.XY ||
  42972. layout == ol.geom.GeometryLayout.XYM) {
  42973. dimension = 2;
  42974. } else if (layout == ol.geom.GeometryLayout.XYZ ||
  42975. layout == ol.geom.GeometryLayout.XYZM) {
  42976. dimension = 3;
  42977. } else {
  42978. ol.asserts.assert(false, 34); // Invalid geometry layout
  42979. }
  42980. var d, i;
  42981. var ii = coordinates.length;
  42982. var text = '';
  42983. if (ii > 0) {
  42984. text += coordinates[0];
  42985. for (d = 1; d < dimension; ++d) {
  42986. text += ',' + coordinates[d];
  42987. }
  42988. for (i = stride; i < ii; i += stride) {
  42989. text += ' ' + coordinates[i];
  42990. for (d = 1; d < dimension; ++d) {
  42991. text += ',' + coordinates[i + d];
  42992. }
  42993. }
  42994. }
  42995. ol.format.XSD.writeStringTextNode(node, text);
  42996. };
  42997. /**
  42998. * @param {Node} node Node.
  42999. * @param {{name: *, value: *}} pair Name value pair.
  43000. * @param {Array.<*>} objectStack Object stack.
  43001. * @private
  43002. */
  43003. ol.format.KML.writeDataNode_ = function(node, pair, objectStack) {
  43004. node.setAttribute('name', pair.name);
  43005. var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
  43006. var value = pair.value;
  43007. if (typeof value == 'object') {
  43008. if (value !== null && value.displayName) {
  43009. ol.xml.pushSerializeAndPop(context, ol.format.KML.EXTENDEDDATA_NODE_SERIALIZERS_,
  43010. ol.xml.OBJECT_PROPERTY_NODE_FACTORY, [value.displayName], objectStack, ['displayName']);
  43011. }
  43012. if (value !== null && value.value) {
  43013. ol.xml.pushSerializeAndPop(context, ol.format.KML.EXTENDEDDATA_NODE_SERIALIZERS_,
  43014. ol.xml.OBJECT_PROPERTY_NODE_FACTORY, [value.value], objectStack, ['value']);
  43015. }
  43016. } else {
  43017. ol.xml.pushSerializeAndPop(context, ol.format.KML.EXTENDEDDATA_NODE_SERIALIZERS_,
  43018. ol.xml.OBJECT_PROPERTY_NODE_FACTORY, [value], objectStack, ['value']);
  43019. }
  43020. };
  43021. /**
  43022. * @param {Node} node Node to append a TextNode with the name to.
  43023. * @param {string} name DisplayName.
  43024. * @private
  43025. */
  43026. ol.format.KML.writeDataNodeName_ = function(node, name) {
  43027. ol.format.XSD.writeCDATASection(node, name);
  43028. };
  43029. /**
  43030. * @param {Node} node Node to append a CDATA Section with the value to.
  43031. * @param {string} value Value.
  43032. * @private
  43033. */
  43034. ol.format.KML.writeDataNodeValue_ = function(node, value) {
  43035. ol.format.XSD.writeStringTextNode(node, value);
  43036. };
  43037. /**
  43038. * @param {Node} node Node.
  43039. * @param {Array.<ol.Feature>} features Features.
  43040. * @param {Array.<*>} objectStack Object stack.
  43041. * @this {ol.format.KML}
  43042. * @private
  43043. */
  43044. ol.format.KML.writeDocument_ = function(node, features, objectStack) {
  43045. var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
  43046. ol.xml.pushSerializeAndPop(context, ol.format.KML.DOCUMENT_SERIALIZERS_,
  43047. ol.format.KML.DOCUMENT_NODE_FACTORY_, features, objectStack, undefined,
  43048. this);
  43049. };
  43050. /**
  43051. * @param {Node} node Node.
  43052. * @param {{names: Array<string>, values: (Array<*>)}} namesAndValues Names and values.
  43053. * @param {Array.<*>} objectStack Object stack.
  43054. * @private
  43055. */
  43056. ol.format.KML.writeExtendedData_ = function(node, namesAndValues, objectStack) {
  43057. var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
  43058. var names = namesAndValues.names, values = namesAndValues.values;
  43059. var length = names.length;
  43060. for (var i = 0; i < length; i++) {
  43061. ol.xml.pushSerializeAndPop(context, ol.format.KML.EXTENDEDDATA_NODE_SERIALIZERS_,
  43062. ol.format.KML.DATA_NODE_FACTORY_, [{name: names[i], value: values[i]}], objectStack);
  43063. }
  43064. };
  43065. /**
  43066. * @param {Node} node Node.
  43067. * @param {Object} icon Icon object.
  43068. * @param {Array.<*>} objectStack Object stack.
  43069. * @private
  43070. */
  43071. ol.format.KML.writeIcon_ = function(node, icon, objectStack) {
  43072. var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
  43073. var parentNode = objectStack[objectStack.length - 1].node;
  43074. var orderedKeys = ol.format.KML.ICON_SEQUENCE_[parentNode.namespaceURI];
  43075. var values = ol.xml.makeSequence(icon, orderedKeys);
  43076. ol.xml.pushSerializeAndPop(context,
  43077. ol.format.KML.ICON_SERIALIZERS_, ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
  43078. values, objectStack, orderedKeys);
  43079. orderedKeys =
  43080. ol.format.KML.ICON_SEQUENCE_[ol.format.KML.GX_NAMESPACE_URIS_[0]];
  43081. values = ol.xml.makeSequence(icon, orderedKeys);
  43082. ol.xml.pushSerializeAndPop(context, ol.format.KML.ICON_SERIALIZERS_,
  43083. ol.format.KML.GX_NODE_FACTORY_, values, objectStack, orderedKeys);
  43084. };
  43085. /**
  43086. * @param {Node} node Node.
  43087. * @param {ol.style.Icon} style Icon style.
  43088. * @param {Array.<*>} objectStack Object stack.
  43089. * @private
  43090. */
  43091. ol.format.KML.writeIconStyle_ = function(node, style, objectStack) {
  43092. var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
  43093. var properties = {};
  43094. var src = style.getSrc();
  43095. var size = style.getSize();
  43096. var iconImageSize = style.getImageSize();
  43097. var iconProperties = {
  43098. 'href': src
  43099. };
  43100. if (size) {
  43101. iconProperties['w'] = size[0];
  43102. iconProperties['h'] = size[1];
  43103. var anchor = style.getAnchor(); // top-left
  43104. var origin = style.getOrigin(); // top-left
  43105. if (origin && iconImageSize && origin[0] !== 0 && origin[1] !== size[1]) {
  43106. iconProperties['x'] = origin[0];
  43107. iconProperties['y'] = iconImageSize[1] - (origin[1] + size[1]);
  43108. }
  43109. if (anchor && (anchor[0] !== size[0] / 2 || anchor[1] !== size[1] / 2)) {
  43110. var /** @type {ol.KMLVec2_} */ hotSpot = {
  43111. x: anchor[0],
  43112. xunits: ol.style.IconAnchorUnits.PIXELS,
  43113. y: size[1] - anchor[1],
  43114. yunits: ol.style.IconAnchorUnits.PIXELS
  43115. };
  43116. properties['hotSpot'] = hotSpot;
  43117. }
  43118. }
  43119. properties['Icon'] = iconProperties;
  43120. var scale = style.getScale();
  43121. if (scale !== 1) {
  43122. properties['scale'] = scale;
  43123. }
  43124. var rotation = style.getRotation();
  43125. if (rotation !== 0) {
  43126. properties['heading'] = rotation; // 0-360
  43127. }
  43128. var parentNode = objectStack[objectStack.length - 1].node;
  43129. var orderedKeys = ol.format.KML.ICON_STYLE_SEQUENCE_[parentNode.namespaceURI];
  43130. var values = ol.xml.makeSequence(properties, orderedKeys);
  43131. ol.xml.pushSerializeAndPop(context, ol.format.KML.ICON_STYLE_SERIALIZERS_,
  43132. ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, objectStack, orderedKeys);
  43133. };
  43134. /**
  43135. * @param {Node} node Node.
  43136. * @param {ol.style.Text} style style.
  43137. * @param {Array.<*>} objectStack Object stack.
  43138. * @private
  43139. */
  43140. ol.format.KML.writeLabelStyle_ = function(node, style, objectStack) {
  43141. var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
  43142. var properties = {};
  43143. var fill = style.getFill();
  43144. if (fill) {
  43145. properties['color'] = fill.getColor();
  43146. }
  43147. var scale = style.getScale();
  43148. if (scale && scale !== 1) {
  43149. properties['scale'] = scale;
  43150. }
  43151. var parentNode = objectStack[objectStack.length - 1].node;
  43152. var orderedKeys =
  43153. ol.format.KML.LABEL_STYLE_SEQUENCE_[parentNode.namespaceURI];
  43154. var values = ol.xml.makeSequence(properties, orderedKeys);
  43155. ol.xml.pushSerializeAndPop(context, ol.format.KML.LABEL_STYLE_SERIALIZERS_,
  43156. ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, objectStack, orderedKeys);
  43157. };
  43158. /**
  43159. * @param {Node} node Node.
  43160. * @param {ol.style.Stroke} style style.
  43161. * @param {Array.<*>} objectStack Object stack.
  43162. * @private
  43163. */
  43164. ol.format.KML.writeLineStyle_ = function(node, style, objectStack) {
  43165. var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
  43166. var properties = {
  43167. 'color': style.getColor(),
  43168. 'width': style.getWidth()
  43169. };
  43170. var parentNode = objectStack[objectStack.length - 1].node;
  43171. var orderedKeys = ol.format.KML.LINE_STYLE_SEQUENCE_[parentNode.namespaceURI];
  43172. var values = ol.xml.makeSequence(properties, orderedKeys);
  43173. ol.xml.pushSerializeAndPop(context, ol.format.KML.LINE_STYLE_SERIALIZERS_,
  43174. ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, objectStack, orderedKeys);
  43175. };
  43176. /**
  43177. * @param {Node} node Node.
  43178. * @param {ol.geom.Geometry} geometry Geometry.
  43179. * @param {Array.<*>} objectStack Object stack.
  43180. * @private
  43181. */
  43182. ol.format.KML.writeMultiGeometry_ = function(node, geometry, objectStack) {
  43183. /** @type {ol.XmlNodeStackItem} */
  43184. var context = {node: node};
  43185. var type = geometry.getType();
  43186. /** @type {Array.<ol.geom.Geometry>} */
  43187. var geometries;
  43188. /** @type {function(*, Array.<*>, string=): (Node|undefined)} */
  43189. var factory;
  43190. if (type == ol.geom.GeometryType.GEOMETRY_COLLECTION) {
  43191. geometries = /** @type {ol.geom.GeometryCollection} */ (geometry).getGeometries();
  43192. factory = ol.format.KML.GEOMETRY_NODE_FACTORY_;
  43193. } else if (type == ol.geom.GeometryType.MULTI_POINT) {
  43194. geometries = /** @type {ol.geom.MultiPoint} */ (geometry).getPoints();
  43195. factory = ol.format.KML.POINT_NODE_FACTORY_;
  43196. } else if (type == ol.geom.GeometryType.MULTI_LINE_STRING) {
  43197. geometries =
  43198. (/** @type {ol.geom.MultiLineString} */ (geometry)).getLineStrings();
  43199. factory = ol.format.KML.LINE_STRING_NODE_FACTORY_;
  43200. } else if (type == ol.geom.GeometryType.MULTI_POLYGON) {
  43201. geometries =
  43202. (/** @type {ol.geom.MultiPolygon} */ (geometry)).getPolygons();
  43203. factory = ol.format.KML.POLYGON_NODE_FACTORY_;
  43204. } else {
  43205. ol.asserts.assert(false, 39); // Unknown geometry type
  43206. }
  43207. ol.xml.pushSerializeAndPop(context,
  43208. ol.format.KML.MULTI_GEOMETRY_SERIALIZERS_, factory,
  43209. geometries, objectStack);
  43210. };
  43211. /**
  43212. * @param {Node} node Node.
  43213. * @param {ol.geom.LinearRing} linearRing Linear ring.
  43214. * @param {Array.<*>} objectStack Object stack.
  43215. * @private
  43216. */
  43217. ol.format.KML.writeBoundaryIs_ = function(node, linearRing, objectStack) {
  43218. var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
  43219. ol.xml.pushSerializeAndPop(context,
  43220. ol.format.KML.BOUNDARY_IS_SERIALIZERS_,
  43221. ol.format.KML.LINEAR_RING_NODE_FACTORY_, [linearRing], objectStack);
  43222. };
  43223. /**
  43224. * FIXME currently we do serialize arbitrary/custom feature properties
  43225. * (ExtendedData).
  43226. * @param {Node} node Node.
  43227. * @param {ol.Feature} feature Feature.
  43228. * @param {Array.<*>} objectStack Object stack.
  43229. * @this {ol.format.KML}
  43230. * @private
  43231. */
  43232. ol.format.KML.writePlacemark_ = function(node, feature, objectStack) {
  43233. var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
  43234. // set id
  43235. if (feature.getId()) {
  43236. node.setAttribute('id', feature.getId());
  43237. }
  43238. // serialize properties (properties unknown to KML are not serialized)
  43239. var properties = feature.getProperties();
  43240. // don't export these to ExtendedData
  43241. var filter = {'address': 1, 'description': 1, 'name': 1, 'open': 1,
  43242. 'phoneNumber': 1, 'styleUrl': 1, 'visibility': 1};
  43243. filter[feature.getGeometryName()] = 1;
  43244. var keys = Object.keys(properties || {}).sort().filter(function(v) {
  43245. return !filter[v];
  43246. });
  43247. if (keys.length > 0) {
  43248. var sequence = ol.xml.makeSequence(properties, keys);
  43249. var namesAndValues = {names: keys, values: sequence};
  43250. ol.xml.pushSerializeAndPop(context, ol.format.KML.PLACEMARK_SERIALIZERS_,
  43251. ol.format.KML.EXTENDEDDATA_NODE_FACTORY_, [namesAndValues], objectStack);
  43252. }
  43253. var styleFunction = feature.getStyleFunction();
  43254. if (styleFunction) {
  43255. // FIXME the styles returned by the style function are supposed to be
  43256. // resolution-independent here
  43257. var styles = styleFunction.call(feature, 0);
  43258. if (styles) {
  43259. var style = Array.isArray(styles) ? styles[0] : styles;
  43260. if (this.writeStyles_) {
  43261. properties['Style'] = style;
  43262. }
  43263. var textStyle = style.getText();
  43264. if (textStyle) {
  43265. properties['name'] = textStyle.getText();
  43266. }
  43267. }
  43268. }
  43269. var parentNode = objectStack[objectStack.length - 1].node;
  43270. var orderedKeys = ol.format.KML.PLACEMARK_SEQUENCE_[parentNode.namespaceURI];
  43271. var values = ol.xml.makeSequence(properties, orderedKeys);
  43272. ol.xml.pushSerializeAndPop(context, ol.format.KML.PLACEMARK_SERIALIZERS_,
  43273. ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, objectStack, orderedKeys);
  43274. // serialize geometry
  43275. var options = /** @type {olx.format.WriteOptions} */ (objectStack[0]);
  43276. var geometry = feature.getGeometry();
  43277. if (geometry) {
  43278. geometry =
  43279. ol.format.Feature.transformWithOptions(geometry, true, options);
  43280. }
  43281. ol.xml.pushSerializeAndPop(context, ol.format.KML.PLACEMARK_SERIALIZERS_,
  43282. ol.format.KML.GEOMETRY_NODE_FACTORY_, [geometry], objectStack);
  43283. };
  43284. /**
  43285. * @param {Node} node Node.
  43286. * @param {ol.geom.SimpleGeometry} geometry Geometry.
  43287. * @param {Array.<*>} objectStack Object stack.
  43288. * @private
  43289. */
  43290. ol.format.KML.writePrimitiveGeometry_ = function(node, geometry, objectStack) {
  43291. var flatCoordinates = geometry.getFlatCoordinates();
  43292. var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
  43293. context['layout'] = geometry.getLayout();
  43294. context['stride'] = geometry.getStride();
  43295. // serialize properties (properties unknown to KML are not serialized)
  43296. var properties = geometry.getProperties();
  43297. properties.coordinates = flatCoordinates;
  43298. var parentNode = objectStack[objectStack.length - 1].node;
  43299. var orderedKeys = ol.format.KML.PRIMITIVE_GEOMETRY_SEQUENCE_[parentNode.namespaceURI];
  43300. var values = ol.xml.makeSequence(properties, orderedKeys);
  43301. ol.xml.pushSerializeAndPop(context, ol.format.KML.PRIMITIVE_GEOMETRY_SERIALIZERS_,
  43302. ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, objectStack, orderedKeys);
  43303. };
  43304. /**
  43305. * @param {Node} node Node.
  43306. * @param {ol.geom.Polygon} polygon Polygon.
  43307. * @param {Array.<*>} objectStack Object stack.
  43308. * @private
  43309. */
  43310. ol.format.KML.writePolygon_ = function(node, polygon, objectStack) {
  43311. var linearRings = polygon.getLinearRings();
  43312. var outerRing = linearRings.shift();
  43313. var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
  43314. // inner rings
  43315. ol.xml.pushSerializeAndPop(context,
  43316. ol.format.KML.POLYGON_SERIALIZERS_,
  43317. ol.format.KML.INNER_BOUNDARY_NODE_FACTORY_,
  43318. linearRings, objectStack);
  43319. // outer ring
  43320. ol.xml.pushSerializeAndPop(context,
  43321. ol.format.KML.POLYGON_SERIALIZERS_,
  43322. ol.format.KML.OUTER_BOUNDARY_NODE_FACTORY_,
  43323. [outerRing], objectStack);
  43324. };
  43325. /**
  43326. * @param {Node} node Node.
  43327. * @param {ol.style.Fill} style Style.
  43328. * @param {Array.<*>} objectStack Object stack.
  43329. * @private
  43330. */
  43331. ol.format.KML.writePolyStyle_ = function(node, style, objectStack) {
  43332. var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
  43333. ol.xml.pushSerializeAndPop(context, ol.format.KML.POLY_STYLE_SERIALIZERS_,
  43334. ol.format.KML.COLOR_NODE_FACTORY_, [style.getColor()], objectStack);
  43335. };
  43336. /**
  43337. * @param {Node} node Node to append a TextNode with the scale to.
  43338. * @param {number|undefined} scale Scale.
  43339. * @private
  43340. */
  43341. ol.format.KML.writeScaleTextNode_ = function(node, scale) {
  43342. // the Math is to remove any excess decimals created by float arithmetic
  43343. ol.format.XSD.writeDecimalTextNode(node,
  43344. Math.round(scale * 1e6) / 1e6);
  43345. };
  43346. /**
  43347. * @param {Node} node Node.
  43348. * @param {ol.style.Style} style Style.
  43349. * @param {Array.<*>} objectStack Object stack.
  43350. * @private
  43351. */
  43352. ol.format.KML.writeStyle_ = function(node, style, objectStack) {
  43353. var /** @type {ol.XmlNodeStackItem} */ context = {node: node};
  43354. var properties = {};
  43355. var fillStyle = style.getFill();
  43356. var strokeStyle = style.getStroke();
  43357. var imageStyle = style.getImage();
  43358. var textStyle = style.getText();
  43359. if (imageStyle instanceof ol.style.Icon) {
  43360. properties['IconStyle'] = imageStyle;
  43361. }
  43362. if (textStyle) {
  43363. properties['LabelStyle'] = textStyle;
  43364. }
  43365. if (strokeStyle) {
  43366. properties['LineStyle'] = strokeStyle;
  43367. }
  43368. if (fillStyle) {
  43369. properties['PolyStyle'] = fillStyle;
  43370. }
  43371. var parentNode = objectStack[objectStack.length - 1].node;
  43372. var orderedKeys = ol.format.KML.STYLE_SEQUENCE_[parentNode.namespaceURI];
  43373. var values = ol.xml.makeSequence(properties, orderedKeys);
  43374. ol.xml.pushSerializeAndPop(context, ol.format.KML.STYLE_SERIALIZERS_,
  43375. ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, objectStack, orderedKeys);
  43376. };
  43377. /**
  43378. * @param {Node} node Node to append a TextNode with the Vec2 to.
  43379. * @param {ol.KMLVec2_} vec2 Vec2.
  43380. * @private
  43381. */
  43382. ol.format.KML.writeVec2_ = function(node, vec2) {
  43383. node.setAttribute('x', vec2.x);
  43384. node.setAttribute('y', vec2.y);
  43385. node.setAttribute('xunits', vec2.xunits);
  43386. node.setAttribute('yunits', vec2.yunits);
  43387. };
  43388. /**
  43389. * @const
  43390. * @type {Object.<string, Array.<string>>}
  43391. * @private
  43392. */
  43393. ol.format.KML.KML_SEQUENCE_ = ol.xml.makeStructureNS(
  43394. ol.format.KML.NAMESPACE_URIS_, [
  43395. 'Document', 'Placemark'
  43396. ]);
  43397. /**
  43398. * @const
  43399. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  43400. * @private
  43401. */
  43402. ol.format.KML.KML_SERIALIZERS_ = ol.xml.makeStructureNS(
  43403. ol.format.KML.NAMESPACE_URIS_, {
  43404. 'Document': ol.xml.makeChildAppender(ol.format.KML.writeDocument_),
  43405. 'Placemark': ol.xml.makeChildAppender(ol.format.KML.writePlacemark_)
  43406. });
  43407. /**
  43408. * @const
  43409. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  43410. * @private
  43411. */
  43412. ol.format.KML.DOCUMENT_SERIALIZERS_ = ol.xml.makeStructureNS(
  43413. ol.format.KML.NAMESPACE_URIS_, {
  43414. 'Placemark': ol.xml.makeChildAppender(ol.format.KML.writePlacemark_)
  43415. });
  43416. /**
  43417. * @const
  43418. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  43419. * @private
  43420. */
  43421. ol.format.KML.EXTENDEDDATA_NODE_SERIALIZERS_ = ol.xml.makeStructureNS(
  43422. ol.format.KML.NAMESPACE_URIS_, {
  43423. 'Data': ol.xml.makeChildAppender(ol.format.KML.writeDataNode_),
  43424. 'value': ol.xml.makeChildAppender(ol.format.KML.writeDataNodeValue_),
  43425. 'displayName': ol.xml.makeChildAppender(ol.format.KML.writeDataNodeName_)
  43426. });
  43427. /**
  43428. * @const
  43429. * @type {Object.<string, string>}
  43430. * @private
  43431. */
  43432. ol.format.KML.GEOMETRY_TYPE_TO_NODENAME_ = {
  43433. 'Point': 'Point',
  43434. 'LineString': 'LineString',
  43435. 'LinearRing': 'LinearRing',
  43436. 'Polygon': 'Polygon',
  43437. 'MultiPoint': 'MultiGeometry',
  43438. 'MultiLineString': 'MultiGeometry',
  43439. 'MultiPolygon': 'MultiGeometry',
  43440. 'GeometryCollection': 'MultiGeometry'
  43441. };
  43442. /**
  43443. * @const
  43444. * @type {Object.<string, Array.<string>>}
  43445. * @private
  43446. */
  43447. ol.format.KML.ICON_SEQUENCE_ = ol.xml.makeStructureNS(
  43448. ol.format.KML.NAMESPACE_URIS_, [
  43449. 'href'
  43450. ],
  43451. ol.xml.makeStructureNS(ol.format.KML.GX_NAMESPACE_URIS_, [
  43452. 'x', 'y', 'w', 'h'
  43453. ]));
  43454. /**
  43455. * @const
  43456. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  43457. * @private
  43458. */
  43459. ol.format.KML.ICON_SERIALIZERS_ = ol.xml.makeStructureNS(
  43460. ol.format.KML.NAMESPACE_URIS_, {
  43461. 'href': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode)
  43462. }, ol.xml.makeStructureNS(
  43463. ol.format.KML.GX_NAMESPACE_URIS_, {
  43464. 'x': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
  43465. 'y': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
  43466. 'w': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
  43467. 'h': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode)
  43468. }));
  43469. /**
  43470. * @const
  43471. * @type {Object.<string, Array.<string>>}
  43472. * @private
  43473. */
  43474. ol.format.KML.ICON_STYLE_SEQUENCE_ = ol.xml.makeStructureNS(
  43475. ol.format.KML.NAMESPACE_URIS_, [
  43476. 'scale', 'heading', 'Icon', 'hotSpot'
  43477. ]);
  43478. /**
  43479. * @const
  43480. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  43481. * @private
  43482. */
  43483. ol.format.KML.ICON_STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
  43484. ol.format.KML.NAMESPACE_URIS_, {
  43485. 'Icon': ol.xml.makeChildAppender(ol.format.KML.writeIcon_),
  43486. 'heading': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
  43487. 'hotSpot': ol.xml.makeChildAppender(ol.format.KML.writeVec2_),
  43488. 'scale': ol.xml.makeChildAppender(ol.format.KML.writeScaleTextNode_)
  43489. });
  43490. /**
  43491. * @const
  43492. * @type {Object.<string, Array.<string>>}
  43493. * @private
  43494. */
  43495. ol.format.KML.LABEL_STYLE_SEQUENCE_ = ol.xml.makeStructureNS(
  43496. ol.format.KML.NAMESPACE_URIS_, [
  43497. 'color', 'scale'
  43498. ]);
  43499. /**
  43500. * @const
  43501. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  43502. * @private
  43503. */
  43504. ol.format.KML.LABEL_STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
  43505. ol.format.KML.NAMESPACE_URIS_, {
  43506. 'color': ol.xml.makeChildAppender(ol.format.KML.writeColorTextNode_),
  43507. 'scale': ol.xml.makeChildAppender(ol.format.KML.writeScaleTextNode_)
  43508. });
  43509. /**
  43510. * @const
  43511. * @type {Object.<string, Array.<string>>}
  43512. * @private
  43513. */
  43514. ol.format.KML.LINE_STYLE_SEQUENCE_ = ol.xml.makeStructureNS(
  43515. ol.format.KML.NAMESPACE_URIS_, [
  43516. 'color', 'width'
  43517. ]);
  43518. /**
  43519. * @const
  43520. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  43521. * @private
  43522. */
  43523. ol.format.KML.LINE_STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
  43524. ol.format.KML.NAMESPACE_URIS_, {
  43525. 'color': ol.xml.makeChildAppender(ol.format.KML.writeColorTextNode_),
  43526. 'width': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode)
  43527. });
  43528. /**
  43529. * @const
  43530. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  43531. * @private
  43532. */
  43533. ol.format.KML.BOUNDARY_IS_SERIALIZERS_ = ol.xml.makeStructureNS(
  43534. ol.format.KML.NAMESPACE_URIS_, {
  43535. 'LinearRing': ol.xml.makeChildAppender(
  43536. ol.format.KML.writePrimitiveGeometry_)
  43537. });
  43538. /**
  43539. * @const
  43540. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  43541. * @private
  43542. */
  43543. ol.format.KML.MULTI_GEOMETRY_SERIALIZERS_ = ol.xml.makeStructureNS(
  43544. ol.format.KML.NAMESPACE_URIS_, {
  43545. 'LineString': ol.xml.makeChildAppender(
  43546. ol.format.KML.writePrimitiveGeometry_),
  43547. 'Point': ol.xml.makeChildAppender(
  43548. ol.format.KML.writePrimitiveGeometry_),
  43549. 'Polygon': ol.xml.makeChildAppender(ol.format.KML.writePolygon_),
  43550. 'GeometryCollection': ol.xml.makeChildAppender(
  43551. ol.format.KML.writeMultiGeometry_)
  43552. });
  43553. /**
  43554. * @const
  43555. * @type {Object.<string, Array.<string>>}
  43556. * @private
  43557. */
  43558. ol.format.KML.PLACEMARK_SEQUENCE_ = ol.xml.makeStructureNS(
  43559. ol.format.KML.NAMESPACE_URIS_, [
  43560. 'name', 'open', 'visibility', 'address', 'phoneNumber', 'description',
  43561. 'styleUrl', 'Style'
  43562. ]);
  43563. /**
  43564. * @const
  43565. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  43566. * @private
  43567. */
  43568. ol.format.KML.PLACEMARK_SERIALIZERS_ = ol.xml.makeStructureNS(
  43569. ol.format.KML.NAMESPACE_URIS_, {
  43570. 'ExtendedData': ol.xml.makeChildAppender(
  43571. ol.format.KML.writeExtendedData_),
  43572. 'MultiGeometry': ol.xml.makeChildAppender(
  43573. ol.format.KML.writeMultiGeometry_),
  43574. 'LineString': ol.xml.makeChildAppender(
  43575. ol.format.KML.writePrimitiveGeometry_),
  43576. 'LinearRing': ol.xml.makeChildAppender(
  43577. ol.format.KML.writePrimitiveGeometry_),
  43578. 'Point': ol.xml.makeChildAppender(
  43579. ol.format.KML.writePrimitiveGeometry_),
  43580. 'Polygon': ol.xml.makeChildAppender(ol.format.KML.writePolygon_),
  43581. 'Style': ol.xml.makeChildAppender(ol.format.KML.writeStyle_),
  43582. 'address': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  43583. 'description': ol.xml.makeChildAppender(
  43584. ol.format.XSD.writeStringTextNode),
  43585. 'name': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  43586. 'open': ol.xml.makeChildAppender(ol.format.XSD.writeBooleanTextNode),
  43587. 'phoneNumber': ol.xml.makeChildAppender(
  43588. ol.format.XSD.writeStringTextNode),
  43589. 'styleUrl': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  43590. 'visibility': ol.xml.makeChildAppender(
  43591. ol.format.XSD.writeBooleanTextNode)
  43592. });
  43593. /**
  43594. * @const
  43595. * @type {Object.<string, Array.<string>>}
  43596. * @private
  43597. */
  43598. ol.format.KML.PRIMITIVE_GEOMETRY_SEQUENCE_ = ol.xml.makeStructureNS(
  43599. ol.format.KML.NAMESPACE_URIS_, [
  43600. 'extrude', 'tessellate', 'altitudeMode', 'coordinates'
  43601. ]);
  43602. /**
  43603. * @const
  43604. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  43605. * @private
  43606. */
  43607. ol.format.KML.PRIMITIVE_GEOMETRY_SERIALIZERS_ = ol.xml.makeStructureNS(
  43608. ol.format.KML.NAMESPACE_URIS_, {
  43609. 'extrude': ol.xml.makeChildAppender(ol.format.XSD.writeBooleanTextNode),
  43610. 'tessellate': ol.xml.makeChildAppender(ol.format.XSD.writeBooleanTextNode),
  43611. 'altitudeMode': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
  43612. 'coordinates': ol.xml.makeChildAppender(
  43613. ol.format.KML.writeCoordinatesTextNode_)
  43614. });
  43615. /**
  43616. * @const
  43617. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  43618. * @private
  43619. */
  43620. ol.format.KML.POLYGON_SERIALIZERS_ = ol.xml.makeStructureNS(
  43621. ol.format.KML.NAMESPACE_URIS_, {
  43622. 'outerBoundaryIs': ol.xml.makeChildAppender(
  43623. ol.format.KML.writeBoundaryIs_),
  43624. 'innerBoundaryIs': ol.xml.makeChildAppender(
  43625. ol.format.KML.writeBoundaryIs_)
  43626. });
  43627. /**
  43628. * @const
  43629. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  43630. * @private
  43631. */
  43632. ol.format.KML.POLY_STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
  43633. ol.format.KML.NAMESPACE_URIS_, {
  43634. 'color': ol.xml.makeChildAppender(ol.format.KML.writeColorTextNode_)
  43635. });
  43636. /**
  43637. * @const
  43638. * @type {Object.<string, Array.<string>>}
  43639. * @private
  43640. */
  43641. ol.format.KML.STYLE_SEQUENCE_ = ol.xml.makeStructureNS(
  43642. ol.format.KML.NAMESPACE_URIS_, [
  43643. 'IconStyle', 'LabelStyle', 'LineStyle', 'PolyStyle'
  43644. ]);
  43645. /**
  43646. * @const
  43647. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  43648. * @private
  43649. */
  43650. ol.format.KML.STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
  43651. ol.format.KML.NAMESPACE_URIS_, {
  43652. 'IconStyle': ol.xml.makeChildAppender(ol.format.KML.writeIconStyle_),
  43653. 'LabelStyle': ol.xml.makeChildAppender(ol.format.KML.writeLabelStyle_),
  43654. 'LineStyle': ol.xml.makeChildAppender(ol.format.KML.writeLineStyle_),
  43655. 'PolyStyle': ol.xml.makeChildAppender(ol.format.KML.writePolyStyle_)
  43656. });
  43657. /**
  43658. * @const
  43659. * @param {*} value Value.
  43660. * @param {Array.<*>} objectStack Object stack.
  43661. * @param {string=} opt_nodeName Node name.
  43662. * @return {Node|undefined} Node.
  43663. * @private
  43664. */
  43665. ol.format.KML.GX_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
  43666. return ol.xml.createElementNS(ol.format.KML.GX_NAMESPACE_URIS_[0],
  43667. 'gx:' + opt_nodeName);
  43668. };
  43669. /**
  43670. * @const
  43671. * @param {*} value Value.
  43672. * @param {Array.<*>} objectStack Object stack.
  43673. * @param {string=} opt_nodeName Node name.
  43674. * @return {Node|undefined} Node.
  43675. * @private
  43676. */
  43677. ol.format.KML.DOCUMENT_NODE_FACTORY_ = function(value, objectStack,
  43678. opt_nodeName) {
  43679. var parentNode = objectStack[objectStack.length - 1].node;
  43680. return ol.xml.createElementNS(parentNode.namespaceURI, 'Placemark');
  43681. };
  43682. /**
  43683. * @const
  43684. * @param {*} value Value.
  43685. * @param {Array.<*>} objectStack Object stack.
  43686. * @param {string=} opt_nodeName Node name.
  43687. * @return {Node|undefined} Node.
  43688. * @private
  43689. */
  43690. ol.format.KML.GEOMETRY_NODE_FACTORY_ = function(value, objectStack,
  43691. opt_nodeName) {
  43692. if (value) {
  43693. var parentNode = objectStack[objectStack.length - 1].node;
  43694. return ol.xml.createElementNS(parentNode.namespaceURI,
  43695. ol.format.KML.GEOMETRY_TYPE_TO_NODENAME_[/** @type {ol.geom.Geometry} */ (value).getType()]);
  43696. }
  43697. };
  43698. /**
  43699. * A factory for creating coordinates nodes.
  43700. * @const
  43701. * @type {function(*, Array.<*>, string=): (Node|undefined)}
  43702. * @private
  43703. */
  43704. ol.format.KML.COLOR_NODE_FACTORY_ = ol.xml.makeSimpleNodeFactory('color');
  43705. /**
  43706. * A factory for creating Data nodes.
  43707. * @const
  43708. * @type {function(*, Array.<*>): (Node|undefined)}
  43709. * @private
  43710. */
  43711. ol.format.KML.DATA_NODE_FACTORY_ =
  43712. ol.xml.makeSimpleNodeFactory('Data');
  43713. /**
  43714. * A factory for creating ExtendedData nodes.
  43715. * @const
  43716. * @type {function(*, Array.<*>): (Node|undefined)}
  43717. * @private
  43718. */
  43719. ol.format.KML.EXTENDEDDATA_NODE_FACTORY_ =
  43720. ol.xml.makeSimpleNodeFactory('ExtendedData');
  43721. /**
  43722. * A factory for creating innerBoundaryIs nodes.
  43723. * @const
  43724. * @type {function(*, Array.<*>, string=): (Node|undefined)}
  43725. * @private
  43726. */
  43727. ol.format.KML.INNER_BOUNDARY_NODE_FACTORY_ =
  43728. ol.xml.makeSimpleNodeFactory('innerBoundaryIs');
  43729. /**
  43730. * A factory for creating Point nodes.
  43731. * @const
  43732. * @type {function(*, Array.<*>, string=): (Node|undefined)}
  43733. * @private
  43734. */
  43735. ol.format.KML.POINT_NODE_FACTORY_ =
  43736. ol.xml.makeSimpleNodeFactory('Point');
  43737. /**
  43738. * A factory for creating LineString nodes.
  43739. * @const
  43740. * @type {function(*, Array.<*>, string=): (Node|undefined)}
  43741. * @private
  43742. */
  43743. ol.format.KML.LINE_STRING_NODE_FACTORY_ =
  43744. ol.xml.makeSimpleNodeFactory('LineString');
  43745. /**
  43746. * A factory for creating LinearRing nodes.
  43747. * @const
  43748. * @type {function(*, Array.<*>, string=): (Node|undefined)}
  43749. * @private
  43750. */
  43751. ol.format.KML.LINEAR_RING_NODE_FACTORY_ =
  43752. ol.xml.makeSimpleNodeFactory('LinearRing');
  43753. /**
  43754. * A factory for creating Polygon nodes.
  43755. * @const
  43756. * @type {function(*, Array.<*>, string=): (Node|undefined)}
  43757. * @private
  43758. */
  43759. ol.format.KML.POLYGON_NODE_FACTORY_ =
  43760. ol.xml.makeSimpleNodeFactory('Polygon');
  43761. /**
  43762. * A factory for creating outerBoundaryIs nodes.
  43763. * @const
  43764. * @type {function(*, Array.<*>, string=): (Node|undefined)}
  43765. * @private
  43766. */
  43767. ol.format.KML.OUTER_BOUNDARY_NODE_FACTORY_ =
  43768. ol.xml.makeSimpleNodeFactory('outerBoundaryIs');
  43769. /**
  43770. * Encode an array of features in the KML format. GeometryCollections, MultiPoints,
  43771. * MultiLineStrings, and MultiPolygons are output as MultiGeometries.
  43772. *
  43773. * @function
  43774. * @param {Array.<ol.Feature>} features Features.
  43775. * @param {olx.format.WriteOptions=} opt_options Options.
  43776. * @return {string} Result.
  43777. * @api
  43778. */
  43779. ol.format.KML.prototype.writeFeatures;
  43780. /**
  43781. * Encode an array of features in the KML format as an XML node. GeometryCollections,
  43782. * MultiPoints, MultiLineStrings, and MultiPolygons are output as MultiGeometries.
  43783. *
  43784. * @param {Array.<ol.Feature>} features Features.
  43785. * @param {olx.format.WriteOptions=} opt_options Options.
  43786. * @return {Node} Node.
  43787. * @override
  43788. * @api
  43789. */
  43790. ol.format.KML.prototype.writeFeaturesNode = function(features, opt_options) {
  43791. opt_options = this.adaptOptions(opt_options);
  43792. var kml = ol.xml.createElementNS(ol.format.KML.NAMESPACE_URIS_[4], 'kml');
  43793. var xmlnsUri = 'http://www.w3.org/2000/xmlns/';
  43794. var xmlSchemaInstanceUri = 'http://www.w3.org/2001/XMLSchema-instance';
  43795. ol.xml.setAttributeNS(kml, xmlnsUri, 'xmlns:gx',
  43796. ol.format.KML.GX_NAMESPACE_URIS_[0]);
  43797. ol.xml.setAttributeNS(kml, xmlnsUri, 'xmlns:xsi', xmlSchemaInstanceUri);
  43798. ol.xml.setAttributeNS(kml, xmlSchemaInstanceUri, 'xsi:schemaLocation',
  43799. ol.format.KML.SCHEMA_LOCATION_);
  43800. var /** @type {ol.XmlNodeStackItem} */ context = {node: kml};
  43801. var properties = {};
  43802. if (features.length > 1) {
  43803. properties['Document'] = features;
  43804. } else if (features.length == 1) {
  43805. properties['Placemark'] = features[0];
  43806. }
  43807. var orderedKeys = ol.format.KML.KML_SEQUENCE_[kml.namespaceURI];
  43808. var values = ol.xml.makeSequence(properties, orderedKeys);
  43809. ol.xml.pushSerializeAndPop(context, ol.format.KML.KML_SERIALIZERS_,
  43810. ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, [opt_options], orderedKeys,
  43811. this);
  43812. return kml;
  43813. };
  43814. /**
  43815. * @fileoverview
  43816. * @suppress {accessControls, ambiguousFunctionDecl, checkDebuggerStatement, checkRegExp, checkTypes, checkVars, const, constantProperty, deprecated, duplicate, es5Strict, fileoverviewTags, missingProperties, nonStandardJsDocs, strictModuleDepCheck, suspiciousCode, undefinedNames, undefinedVars, unknownDefines, unusedLocalVariables, uselessCode, visibility}
  43817. */
  43818. goog.provide('ol.ext.PBF');
  43819. /** @typedef {function(*)} */
  43820. ol.ext.PBF = function() {};
  43821. (function() {(function (exports) {
  43822. 'use strict';
  43823. var read = function (buffer, offset, isLE, mLen, nBytes) {
  43824. var e, m;
  43825. var eLen = nBytes * 8 - mLen - 1;
  43826. var eMax = (1 << eLen) - 1;
  43827. var eBias = eMax >> 1;
  43828. var nBits = -7;
  43829. var i = isLE ? (nBytes - 1) : 0;
  43830. var d = isLE ? -1 : 1;
  43831. var s = buffer[offset + i];
  43832. i += d;
  43833. e = s & ((1 << (-nBits)) - 1);
  43834. s >>= (-nBits);
  43835. nBits += eLen;
  43836. for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
  43837. m = e & ((1 << (-nBits)) - 1);
  43838. e >>= (-nBits);
  43839. nBits += mLen;
  43840. for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
  43841. if (e === 0) {
  43842. e = 1 - eBias;
  43843. } else if (e === eMax) {
  43844. return m ? NaN : ((s ? -1 : 1) * Infinity)
  43845. } else {
  43846. m = m + Math.pow(2, mLen);
  43847. e = e - eBias;
  43848. }
  43849. return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
  43850. };
  43851. var write = function (buffer, value, offset, isLE, mLen, nBytes) {
  43852. var e, m, c;
  43853. var eLen = nBytes * 8 - mLen - 1;
  43854. var eMax = (1 << eLen) - 1;
  43855. var eBias = eMax >> 1;
  43856. var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0);
  43857. var i = isLE ? 0 : (nBytes - 1);
  43858. var d = isLE ? 1 : -1;
  43859. var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
  43860. value = Math.abs(value);
  43861. if (isNaN(value) || value === Infinity) {
  43862. m = isNaN(value) ? 1 : 0;
  43863. e = eMax;
  43864. } else {
  43865. e = Math.floor(Math.log(value) / Math.LN2);
  43866. if (value * (c = Math.pow(2, -e)) < 1) {
  43867. e--;
  43868. c *= 2;
  43869. }
  43870. if (e + eBias >= 1) {
  43871. value += rt / c;
  43872. } else {
  43873. value += rt * Math.pow(2, 1 - eBias);
  43874. }
  43875. if (value * c >= 2) {
  43876. e++;
  43877. c /= 2;
  43878. }
  43879. if (e + eBias >= eMax) {
  43880. m = 0;
  43881. e = eMax;
  43882. } else if (e + eBias >= 1) {
  43883. m = (value * c - 1) * Math.pow(2, mLen);
  43884. e = e + eBias;
  43885. } else {
  43886. m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
  43887. e = 0;
  43888. }
  43889. }
  43890. for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
  43891. e = (e << mLen) | m;
  43892. eLen += mLen;
  43893. for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
  43894. buffer[offset + i - d] |= s * 128;
  43895. };
  43896. var ieee754 = {
  43897. read: read,
  43898. write: write
  43899. };
  43900. var pbf = Pbf;
  43901. function Pbf(buf) {
  43902. this.buf = ArrayBuffer.isView && ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf || 0);
  43903. this.pos = 0;
  43904. this.type = 0;
  43905. this.length = this.buf.length;
  43906. }
  43907. Pbf.Varint = 0;
  43908. Pbf.Fixed64 = 1;
  43909. Pbf.Bytes = 2;
  43910. Pbf.Fixed32 = 5;
  43911. var SHIFT_LEFT_32 = (1 << 16) * (1 << 16);
  43912. var SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32;
  43913. Pbf.prototype = {
  43914. destroy: function() {
  43915. this.buf = null;
  43916. },
  43917. readFields: function(readField, result, end) {
  43918. end = end || this.length;
  43919. while (this.pos < end) {
  43920. var val = this.readVarint(),
  43921. tag = val >> 3,
  43922. startPos = this.pos;
  43923. this.type = val & 0x7;
  43924. readField(tag, result, this);
  43925. if (this.pos === startPos) this.skip(val);
  43926. }
  43927. return result;
  43928. },
  43929. readMessage: function(readField, result) {
  43930. return this.readFields(readField, result, this.readVarint() + this.pos);
  43931. },
  43932. readFixed32: function() {
  43933. var val = readUInt32(this.buf, this.pos);
  43934. this.pos += 4;
  43935. return val;
  43936. },
  43937. readSFixed32: function() {
  43938. var val = readInt32(this.buf, this.pos);
  43939. this.pos += 4;
  43940. return val;
  43941. },
  43942. readFixed64: function() {
  43943. var val = readUInt32(this.buf, this.pos) + readUInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
  43944. this.pos += 8;
  43945. return val;
  43946. },
  43947. readSFixed64: function() {
  43948. var val = readUInt32(this.buf, this.pos) + readInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
  43949. this.pos += 8;
  43950. return val;
  43951. },
  43952. readFloat: function() {
  43953. var val = ieee754.read(this.buf, this.pos, true, 23, 4);
  43954. this.pos += 4;
  43955. return val;
  43956. },
  43957. readDouble: function() {
  43958. var val = ieee754.read(this.buf, this.pos, true, 52, 8);
  43959. this.pos += 8;
  43960. return val;
  43961. },
  43962. readVarint: function(isSigned) {
  43963. var buf = this.buf,
  43964. val, b;
  43965. b = buf[this.pos++]; val = b & 0x7f; if (b < 0x80) return val;
  43966. b = buf[this.pos++]; val |= (b & 0x7f) << 7; if (b < 0x80) return val;
  43967. b = buf[this.pos++]; val |= (b & 0x7f) << 14; if (b < 0x80) return val;
  43968. b = buf[this.pos++]; val |= (b & 0x7f) << 21; if (b < 0x80) return val;
  43969. b = buf[this.pos]; val |= (b & 0x0f) << 28;
  43970. return readVarintRemainder(val, isSigned, this);
  43971. },
  43972. readVarint64: function() {
  43973. return this.readVarint(true);
  43974. },
  43975. readSVarint: function() {
  43976. var num = this.readVarint();
  43977. return num % 2 === 1 ? (num + 1) / -2 : num / 2;
  43978. },
  43979. readBoolean: function() {
  43980. return Boolean(this.readVarint());
  43981. },
  43982. readString: function() {
  43983. var end = this.readVarint() + this.pos,
  43984. str = readUtf8(this.buf, this.pos, end);
  43985. this.pos = end;
  43986. return str;
  43987. },
  43988. readBytes: function() {
  43989. var end = this.readVarint() + this.pos,
  43990. buffer = this.buf.subarray(this.pos, end);
  43991. this.pos = end;
  43992. return buffer;
  43993. },
  43994. readPackedVarint: function(arr, isSigned) {
  43995. var end = readPackedEnd(this);
  43996. arr = arr || [];
  43997. while (this.pos < end) arr.push(this.readVarint(isSigned));
  43998. return arr;
  43999. },
  44000. readPackedSVarint: function(arr) {
  44001. var end = readPackedEnd(this);
  44002. arr = arr || [];
  44003. while (this.pos < end) arr.push(this.readSVarint());
  44004. return arr;
  44005. },
  44006. readPackedBoolean: function(arr) {
  44007. var end = readPackedEnd(this);
  44008. arr = arr || [];
  44009. while (this.pos < end) arr.push(this.readBoolean());
  44010. return arr;
  44011. },
  44012. readPackedFloat: function(arr) {
  44013. var end = readPackedEnd(this);
  44014. arr = arr || [];
  44015. while (this.pos < end) arr.push(this.readFloat());
  44016. return arr;
  44017. },
  44018. readPackedDouble: function(arr) {
  44019. var end = readPackedEnd(this);
  44020. arr = arr || [];
  44021. while (this.pos < end) arr.push(this.readDouble());
  44022. return arr;
  44023. },
  44024. readPackedFixed32: function(arr) {
  44025. var end = readPackedEnd(this);
  44026. arr = arr || [];
  44027. while (this.pos < end) arr.push(this.readFixed32());
  44028. return arr;
  44029. },
  44030. readPackedSFixed32: function(arr) {
  44031. var end = readPackedEnd(this);
  44032. arr = arr || [];
  44033. while (this.pos < end) arr.push(this.readSFixed32());
  44034. return arr;
  44035. },
  44036. readPackedFixed64: function(arr) {
  44037. var end = readPackedEnd(this);
  44038. arr = arr || [];
  44039. while (this.pos < end) arr.push(this.readFixed64());
  44040. return arr;
  44041. },
  44042. readPackedSFixed64: function(arr) {
  44043. var end = readPackedEnd(this);
  44044. arr = arr || [];
  44045. while (this.pos < end) arr.push(this.readSFixed64());
  44046. return arr;
  44047. },
  44048. skip: function(val) {
  44049. var type = val & 0x7;
  44050. if (type === Pbf.Varint) while (this.buf[this.pos++] > 0x7f) {}
  44051. else if (type === Pbf.Bytes) this.pos = this.readVarint() + this.pos;
  44052. else if (type === Pbf.Fixed32) this.pos += 4;
  44053. else if (type === Pbf.Fixed64) this.pos += 8;
  44054. else throw new Error('Unimplemented type: ' + type);
  44055. },
  44056. writeTag: function(tag, type) {
  44057. this.writeVarint((tag << 3) | type);
  44058. },
  44059. realloc: function(min) {
  44060. var length = this.length || 16;
  44061. while (length < this.pos + min) length *= 2;
  44062. if (length !== this.length) {
  44063. var buf = new Uint8Array(length);
  44064. buf.set(this.buf);
  44065. this.buf = buf;
  44066. this.length = length;
  44067. }
  44068. },
  44069. finish: function() {
  44070. this.length = this.pos;
  44071. this.pos = 0;
  44072. return this.buf.subarray(0, this.length);
  44073. },
  44074. writeFixed32: function(val) {
  44075. this.realloc(4);
  44076. writeInt32(this.buf, val, this.pos);
  44077. this.pos += 4;
  44078. },
  44079. writeSFixed32: function(val) {
  44080. this.realloc(4);
  44081. writeInt32(this.buf, val, this.pos);
  44082. this.pos += 4;
  44083. },
  44084. writeFixed64: function(val) {
  44085. this.realloc(8);
  44086. writeInt32(this.buf, val & -1, this.pos);
  44087. writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
  44088. this.pos += 8;
  44089. },
  44090. writeSFixed64: function(val) {
  44091. this.realloc(8);
  44092. writeInt32(this.buf, val & -1, this.pos);
  44093. writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
  44094. this.pos += 8;
  44095. },
  44096. writeVarint: function(val) {
  44097. val = +val || 0;
  44098. if (val > 0xfffffff || val < 0) {
  44099. writeBigVarint(val, this);
  44100. return;
  44101. }
  44102. this.realloc(4);
  44103. this.buf[this.pos++] = val & 0x7f | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
  44104. this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
  44105. this.buf[this.pos++] = ((val >>>= 7) & 0x7f) | (val > 0x7f ? 0x80 : 0); if (val <= 0x7f) return;
  44106. this.buf[this.pos++] = (val >>> 7) & 0x7f;
  44107. },
  44108. writeSVarint: function(val) {
  44109. this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);
  44110. },
  44111. writeBoolean: function(val) {
  44112. this.writeVarint(Boolean(val));
  44113. },
  44114. writeString: function(str) {
  44115. str = String(str);
  44116. this.realloc(str.length * 4);
  44117. this.pos++;
  44118. var startPos = this.pos;
  44119. this.pos = writeUtf8(this.buf, str, this.pos);
  44120. var len = this.pos - startPos;
  44121. if (len >= 0x80) makeRoomForExtraLength(startPos, len, this);
  44122. this.pos = startPos - 1;
  44123. this.writeVarint(len);
  44124. this.pos += len;
  44125. },
  44126. writeFloat: function(val) {
  44127. this.realloc(4);
  44128. ieee754.write(this.buf, val, this.pos, true, 23, 4);
  44129. this.pos += 4;
  44130. },
  44131. writeDouble: function(val) {
  44132. this.realloc(8);
  44133. ieee754.write(this.buf, val, this.pos, true, 52, 8);
  44134. this.pos += 8;
  44135. },
  44136. writeBytes: function(buffer) {
  44137. var len = buffer.length;
  44138. this.writeVarint(len);
  44139. this.realloc(len);
  44140. for (var i = 0; i < len; i++) this.buf[this.pos++] = buffer[i];
  44141. },
  44142. writeRawMessage: function(fn, obj) {
  44143. this.pos++;
  44144. var startPos = this.pos;
  44145. fn(obj, this);
  44146. var len = this.pos - startPos;
  44147. if (len >= 0x80) makeRoomForExtraLength(startPos, len, this);
  44148. this.pos = startPos - 1;
  44149. this.writeVarint(len);
  44150. this.pos += len;
  44151. },
  44152. writeMessage: function(tag, fn, obj) {
  44153. this.writeTag(tag, Pbf.Bytes);
  44154. this.writeRawMessage(fn, obj);
  44155. },
  44156. writePackedVarint: function(tag, arr) { this.writeMessage(tag, writePackedVarint, arr); },
  44157. writePackedSVarint: function(tag, arr) { this.writeMessage(tag, writePackedSVarint, arr); },
  44158. writePackedBoolean: function(tag, arr) { this.writeMessage(tag, writePackedBoolean, arr); },
  44159. writePackedFloat: function(tag, arr) { this.writeMessage(tag, writePackedFloat, arr); },
  44160. writePackedDouble: function(tag, arr) { this.writeMessage(tag, writePackedDouble, arr); },
  44161. writePackedFixed32: function(tag, arr) { this.writeMessage(tag, writePackedFixed32, arr); },
  44162. writePackedSFixed32: function(tag, arr) { this.writeMessage(tag, writePackedSFixed32, arr); },
  44163. writePackedFixed64: function(tag, arr) { this.writeMessage(tag, writePackedFixed64, arr); },
  44164. writePackedSFixed64: function(tag, arr) { this.writeMessage(tag, writePackedSFixed64, arr); },
  44165. writeBytesField: function(tag, buffer) {
  44166. this.writeTag(tag, Pbf.Bytes);
  44167. this.writeBytes(buffer);
  44168. },
  44169. writeFixed32Field: function(tag, val) {
  44170. this.writeTag(tag, Pbf.Fixed32);
  44171. this.writeFixed32(val);
  44172. },
  44173. writeSFixed32Field: function(tag, val) {
  44174. this.writeTag(tag, Pbf.Fixed32);
  44175. this.writeSFixed32(val);
  44176. },
  44177. writeFixed64Field: function(tag, val) {
  44178. this.writeTag(tag, Pbf.Fixed64);
  44179. this.writeFixed64(val);
  44180. },
  44181. writeSFixed64Field: function(tag, val) {
  44182. this.writeTag(tag, Pbf.Fixed64);
  44183. this.writeSFixed64(val);
  44184. },
  44185. writeVarintField: function(tag, val) {
  44186. this.writeTag(tag, Pbf.Varint);
  44187. this.writeVarint(val);
  44188. },
  44189. writeSVarintField: function(tag, val) {
  44190. this.writeTag(tag, Pbf.Varint);
  44191. this.writeSVarint(val);
  44192. },
  44193. writeStringField: function(tag, str) {
  44194. this.writeTag(tag, Pbf.Bytes);
  44195. this.writeString(str);
  44196. },
  44197. writeFloatField: function(tag, val) {
  44198. this.writeTag(tag, Pbf.Fixed32);
  44199. this.writeFloat(val);
  44200. },
  44201. writeDoubleField: function(tag, val) {
  44202. this.writeTag(tag, Pbf.Fixed64);
  44203. this.writeDouble(val);
  44204. },
  44205. writeBooleanField: function(tag, val) {
  44206. this.writeVarintField(tag, Boolean(val));
  44207. }
  44208. };
  44209. function readVarintRemainder(l, s, p) {
  44210. var buf = p.buf,
  44211. h, b;
  44212. b = buf[p.pos++]; h = (b & 0x70) >> 4; if (b < 0x80) return toNum(l, h, s);
  44213. b = buf[p.pos++]; h |= (b & 0x7f) << 3; if (b < 0x80) return toNum(l, h, s);
  44214. b = buf[p.pos++]; h |= (b & 0x7f) << 10; if (b < 0x80) return toNum(l, h, s);
  44215. b = buf[p.pos++]; h |= (b & 0x7f) << 17; if (b < 0x80) return toNum(l, h, s);
  44216. b = buf[p.pos++]; h |= (b & 0x7f) << 24; if (b < 0x80) return toNum(l, h, s);
  44217. b = buf[p.pos++]; h |= (b & 0x01) << 31; if (b < 0x80) return toNum(l, h, s);
  44218. throw new Error('Expected varint not more than 10 bytes');
  44219. }
  44220. function readPackedEnd(pbf) {
  44221. return pbf.type === Pbf.Bytes ?
  44222. pbf.readVarint() + pbf.pos : pbf.pos + 1;
  44223. }
  44224. function toNum(low, high, isSigned) {
  44225. if (isSigned) {
  44226. return high * 0x100000000 + (low >>> 0);
  44227. }
  44228. return ((high >>> 0) * 0x100000000) + (low >>> 0);
  44229. }
  44230. function writeBigVarint(val, pbf) {
  44231. var low, high;
  44232. if (val >= 0) {
  44233. low = (val % 0x100000000) | 0;
  44234. high = (val / 0x100000000) | 0;
  44235. } else {
  44236. low = ~(-val % 0x100000000);
  44237. high = ~(-val / 0x100000000);
  44238. if (low ^ 0xffffffff) {
  44239. low = (low + 1) | 0;
  44240. } else {
  44241. low = 0;
  44242. high = (high + 1) | 0;
  44243. }
  44244. }
  44245. if (val >= 0x10000000000000000 || val < -0x10000000000000000) {
  44246. throw new Error('Given varint doesn\'t fit into 10 bytes');
  44247. }
  44248. pbf.realloc(10);
  44249. writeBigVarintLow(low, high, pbf);
  44250. writeBigVarintHigh(high, pbf);
  44251. }
  44252. function writeBigVarintLow(low, high, pbf) {
  44253. pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
  44254. pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
  44255. pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
  44256. pbf.buf[pbf.pos++] = low & 0x7f | 0x80; low >>>= 7;
  44257. pbf.buf[pbf.pos] = low & 0x7f;
  44258. }
  44259. function writeBigVarintHigh(high, pbf) {
  44260. var lsb = (high & 0x07) << 4;
  44261. pbf.buf[pbf.pos++] |= lsb | ((high >>>= 3) ? 0x80 : 0); if (!high) return;
  44262. pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;
  44263. pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;
  44264. pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;
  44265. pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0); if (!high) return;
  44266. pbf.buf[pbf.pos++] = high & 0x7f;
  44267. }
  44268. function makeRoomForExtraLength(startPos, len, pbf) {
  44269. var extraLen =
  44270. len <= 0x3fff ? 1 :
  44271. len <= 0x1fffff ? 2 :
  44272. len <= 0xfffffff ? 3 : Math.ceil(Math.log(len) / (Math.LN2 * 7));
  44273. pbf.realloc(extraLen);
  44274. for (var i = pbf.pos - 1; i >= startPos; i--) pbf.buf[i + extraLen] = pbf.buf[i];
  44275. }
  44276. function writePackedVarint(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeVarint(arr[i]); }
  44277. function writePackedSVarint(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSVarint(arr[i]); }
  44278. function writePackedFloat(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFloat(arr[i]); }
  44279. function writePackedDouble(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeDouble(arr[i]); }
  44280. function writePackedBoolean(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeBoolean(arr[i]); }
  44281. function writePackedFixed32(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFixed32(arr[i]); }
  44282. function writePackedSFixed32(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed32(arr[i]); }
  44283. function writePackedFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeFixed64(arr[i]); }
  44284. function writePackedSFixed64(arr, pbf) { for (var i = 0; i < arr.length; i++) pbf.writeSFixed64(arr[i]); }
  44285. function readUInt32(buf, pos) {
  44286. return ((buf[pos]) |
  44287. (buf[pos + 1] << 8) |
  44288. (buf[pos + 2] << 16)) +
  44289. (buf[pos + 3] * 0x1000000);
  44290. }
  44291. function writeInt32(buf, val, pos) {
  44292. buf[pos] = val;
  44293. buf[pos + 1] = (val >>> 8);
  44294. buf[pos + 2] = (val >>> 16);
  44295. buf[pos + 3] = (val >>> 24);
  44296. }
  44297. function readInt32(buf, pos) {
  44298. return ((buf[pos]) |
  44299. (buf[pos + 1] << 8) |
  44300. (buf[pos + 2] << 16)) +
  44301. (buf[pos + 3] << 24);
  44302. }
  44303. function readUtf8(buf, pos, end) {
  44304. var str = '';
  44305. var i = pos;
  44306. while (i < end) {
  44307. var b0 = buf[i];
  44308. var c = null;
  44309. var bytesPerSequence =
  44310. b0 > 0xEF ? 4 :
  44311. b0 > 0xDF ? 3 :
  44312. b0 > 0xBF ? 2 : 1;
  44313. if (i + bytesPerSequence > end) break;
  44314. var b1, b2, b3;
  44315. if (bytesPerSequence === 1) {
  44316. if (b0 < 0x80) {
  44317. c = b0;
  44318. }
  44319. } else if (bytesPerSequence === 2) {
  44320. b1 = buf[i + 1];
  44321. if ((b1 & 0xC0) === 0x80) {
  44322. c = (b0 & 0x1F) << 0x6 | (b1 & 0x3F);
  44323. if (c <= 0x7F) {
  44324. c = null;
  44325. }
  44326. }
  44327. } else if (bytesPerSequence === 3) {
  44328. b1 = buf[i + 1];
  44329. b2 = buf[i + 2];
  44330. if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80) {
  44331. c = (b0 & 0xF) << 0xC | (b1 & 0x3F) << 0x6 | (b2 & 0x3F);
  44332. if (c <= 0x7FF || (c >= 0xD800 && c <= 0xDFFF)) {
  44333. c = null;
  44334. }
  44335. }
  44336. } else if (bytesPerSequence === 4) {
  44337. b1 = buf[i + 1];
  44338. b2 = buf[i + 2];
  44339. b3 = buf[i + 3];
  44340. if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80) {
  44341. c = (b0 & 0xF) << 0x12 | (b1 & 0x3F) << 0xC | (b2 & 0x3F) << 0x6 | (b3 & 0x3F);
  44342. if (c <= 0xFFFF || c >= 0x110000) {
  44343. c = null;
  44344. }
  44345. }
  44346. }
  44347. if (c === null) {
  44348. c = 0xFFFD;
  44349. bytesPerSequence = 1;
  44350. } else if (c > 0xFFFF) {
  44351. c -= 0x10000;
  44352. str += String.fromCharCode(c >>> 10 & 0x3FF | 0xD800);
  44353. c = 0xDC00 | c & 0x3FF;
  44354. }
  44355. str += String.fromCharCode(c);
  44356. i += bytesPerSequence;
  44357. }
  44358. return str;
  44359. }
  44360. function writeUtf8(buf, str, pos) {
  44361. for (var i = 0, c, lead; i < str.length; i++) {
  44362. c = str.charCodeAt(i);
  44363. if (c > 0xD7FF && c < 0xE000) {
  44364. if (lead) {
  44365. if (c < 0xDC00) {
  44366. buf[pos++] = 0xEF;
  44367. buf[pos++] = 0xBF;
  44368. buf[pos++] = 0xBD;
  44369. lead = c;
  44370. continue;
  44371. } else {
  44372. c = lead - 0xD800 << 10 | c - 0xDC00 | 0x10000;
  44373. lead = null;
  44374. }
  44375. } else {
  44376. if (c > 0xDBFF || (i + 1 === str.length)) {
  44377. buf[pos++] = 0xEF;
  44378. buf[pos++] = 0xBF;
  44379. buf[pos++] = 0xBD;
  44380. } else {
  44381. lead = c;
  44382. }
  44383. continue;
  44384. }
  44385. } else if (lead) {
  44386. buf[pos++] = 0xEF;
  44387. buf[pos++] = 0xBF;
  44388. buf[pos++] = 0xBD;
  44389. lead = null;
  44390. }
  44391. if (c < 0x80) {
  44392. buf[pos++] = c;
  44393. } else {
  44394. if (c < 0x800) {
  44395. buf[pos++] = c >> 0x6 | 0xC0;
  44396. } else {
  44397. if (c < 0x10000) {
  44398. buf[pos++] = c >> 0xC | 0xE0;
  44399. } else {
  44400. buf[pos++] = c >> 0x12 | 0xF0;
  44401. buf[pos++] = c >> 0xC & 0x3F | 0x80;
  44402. }
  44403. buf[pos++] = c >> 0x6 & 0x3F | 0x80;
  44404. }
  44405. buf[pos++] = c & 0x3F | 0x80;
  44406. }
  44407. }
  44408. return pos;
  44409. }
  44410. exports['default'] = pbf;
  44411. }((this.PBF = this.PBF || {})));}).call(ol.ext);
  44412. ol.ext.PBF = ol.ext.PBF.default;
  44413. /**
  44414. * @fileoverview
  44415. * @suppress {accessControls, ambiguousFunctionDecl, checkDebuggerStatement, checkRegExp, checkTypes, checkVars, const, constantProperty, deprecated, duplicate, es5Strict, fileoverviewTags, missingProperties, nonStandardJsDocs, strictModuleDepCheck, suspiciousCode, undefinedNames, undefinedVars, unknownDefines, unusedLocalVariables, uselessCode, visibility}
  44416. */
  44417. goog.provide('ol.ext.vectortile.VectorTile');
  44418. /** @typedef {function(*)} */
  44419. ol.ext.vectortile.VectorTile = function() {};
  44420. (function() {(function (exports) {
  44421. 'use strict';
  44422. var pointGeometry = Point;
  44423. function Point(x, y) {
  44424. this.x = x;
  44425. this.y = y;
  44426. }
  44427. Point.prototype = {
  44428. clone: function() { return new Point(this.x, this.y); },
  44429. add: function(p) { return this.clone()._add(p); },
  44430. sub: function(p) { return this.clone()._sub(p); },
  44431. multByPoint: function(p) { return this.clone()._multByPoint(p); },
  44432. divByPoint: function(p) { return this.clone()._divByPoint(p); },
  44433. mult: function(k) { return this.clone()._mult(k); },
  44434. div: function(k) { return this.clone()._div(k); },
  44435. rotate: function(a) { return this.clone()._rotate(a); },
  44436. rotateAround: function(a,p) { return this.clone()._rotateAround(a,p); },
  44437. matMult: function(m) { return this.clone()._matMult(m); },
  44438. unit: function() { return this.clone()._unit(); },
  44439. perp: function() { return this.clone()._perp(); },
  44440. round: function() { return this.clone()._round(); },
  44441. mag: function() {
  44442. return Math.sqrt(this.x * this.x + this.y * this.y);
  44443. },
  44444. equals: function(other) {
  44445. return this.x === other.x &&
  44446. this.y === other.y;
  44447. },
  44448. dist: function(p) {
  44449. return Math.sqrt(this.distSqr(p));
  44450. },
  44451. distSqr: function(p) {
  44452. var dx = p.x - this.x,
  44453. dy = p.y - this.y;
  44454. return dx * dx + dy * dy;
  44455. },
  44456. angle: function() {
  44457. return Math.atan2(this.y, this.x);
  44458. },
  44459. angleTo: function(b) {
  44460. return Math.atan2(this.y - b.y, this.x - b.x);
  44461. },
  44462. angleWith: function(b) {
  44463. return this.angleWithSep(b.x, b.y);
  44464. },
  44465. angleWithSep: function(x, y) {
  44466. return Math.atan2(
  44467. this.x * y - this.y * x,
  44468. this.x * x + this.y * y);
  44469. },
  44470. _matMult: function(m) {
  44471. var x = m[0] * this.x + m[1] * this.y,
  44472. y = m[2] * this.x + m[3] * this.y;
  44473. this.x = x;
  44474. this.y = y;
  44475. return this;
  44476. },
  44477. _add: function(p) {
  44478. this.x += p.x;
  44479. this.y += p.y;
  44480. return this;
  44481. },
  44482. _sub: function(p) {
  44483. this.x -= p.x;
  44484. this.y -= p.y;
  44485. return this;
  44486. },
  44487. _mult: function(k) {
  44488. this.x *= k;
  44489. this.y *= k;
  44490. return this;
  44491. },
  44492. _div: function(k) {
  44493. this.x /= k;
  44494. this.y /= k;
  44495. return this;
  44496. },
  44497. _multByPoint: function(p) {
  44498. this.x *= p.x;
  44499. this.y *= p.y;
  44500. return this;
  44501. },
  44502. _divByPoint: function(p) {
  44503. this.x /= p.x;
  44504. this.y /= p.y;
  44505. return this;
  44506. },
  44507. _unit: function() {
  44508. this._div(this.mag());
  44509. return this;
  44510. },
  44511. _perp: function() {
  44512. var y = this.y;
  44513. this.y = this.x;
  44514. this.x = -y;
  44515. return this;
  44516. },
  44517. _rotate: function(angle) {
  44518. var cos = Math.cos(angle),
  44519. sin = Math.sin(angle),
  44520. x = cos * this.x - sin * this.y,
  44521. y = sin * this.x + cos * this.y;
  44522. this.x = x;
  44523. this.y = y;
  44524. return this;
  44525. },
  44526. _rotateAround: function(angle, p) {
  44527. var cos = Math.cos(angle),
  44528. sin = Math.sin(angle),
  44529. x = p.x + cos * (this.x - p.x) - sin * (this.y - p.y),
  44530. y = p.y + sin * (this.x - p.x) + cos * (this.y - p.y);
  44531. this.x = x;
  44532. this.y = y;
  44533. return this;
  44534. },
  44535. _round: function() {
  44536. this.x = Math.round(this.x);
  44537. this.y = Math.round(this.y);
  44538. return this;
  44539. }
  44540. };
  44541. Point.convert = function (a) {
  44542. if (a instanceof Point) {
  44543. return a;
  44544. }
  44545. if (Array.isArray(a)) {
  44546. return new Point(a[0], a[1]);
  44547. }
  44548. return a;
  44549. };
  44550. var vectortilefeature = VectorTileFeature$1;
  44551. function VectorTileFeature$1(pbf, end, extent, keys, values) {
  44552. this.properties = {};
  44553. this.extent = extent;
  44554. this.type = 0;
  44555. this._pbf = pbf;
  44556. this._geometry = -1;
  44557. this._keys = keys;
  44558. this._values = values;
  44559. pbf.readFields(readFeature, this, end);
  44560. }
  44561. function readFeature(tag, feature, pbf) {
  44562. if (tag == 1) feature.id = pbf.readVarint();
  44563. else if (tag == 2) readTag(pbf, feature);
  44564. else if (tag == 3) feature.type = pbf.readVarint();
  44565. else if (tag == 4) feature._geometry = pbf.pos;
  44566. }
  44567. function readTag(pbf, feature) {
  44568. var end = pbf.readVarint() + pbf.pos;
  44569. while (pbf.pos < end) {
  44570. var key = feature._keys[pbf.readVarint()],
  44571. value = feature._values[pbf.readVarint()];
  44572. feature.properties[key] = value;
  44573. }
  44574. }
  44575. VectorTileFeature$1.types = ['Unknown', 'Point', 'LineString', 'Polygon'];
  44576. VectorTileFeature$1.prototype.loadGeometry = function() {
  44577. var pbf = this._pbf;
  44578. pbf.pos = this._geometry;
  44579. var end = pbf.readVarint() + pbf.pos,
  44580. cmd = 1,
  44581. length = 0,
  44582. x = 0,
  44583. y = 0,
  44584. lines = [],
  44585. line;
  44586. while (pbf.pos < end) {
  44587. if (!length) {
  44588. var cmdLen = pbf.readVarint();
  44589. cmd = cmdLen & 0x7;
  44590. length = cmdLen >> 3;
  44591. }
  44592. length--;
  44593. if (cmd === 1 || cmd === 2) {
  44594. x += pbf.readSVarint();
  44595. y += pbf.readSVarint();
  44596. if (cmd === 1) {
  44597. if (line) lines.push(line);
  44598. line = [];
  44599. }
  44600. line.push(new pointGeometry(x, y));
  44601. } else if (cmd === 7) {
  44602. if (line) {
  44603. line.push(line[0].clone());
  44604. }
  44605. } else {
  44606. throw new Error('unknown command ' + cmd);
  44607. }
  44608. }
  44609. if (line) lines.push(line);
  44610. return lines;
  44611. };
  44612. VectorTileFeature$1.prototype.bbox = function() {
  44613. var pbf = this._pbf;
  44614. pbf.pos = this._geometry;
  44615. var end = pbf.readVarint() + pbf.pos,
  44616. cmd = 1,
  44617. length = 0,
  44618. x = 0,
  44619. y = 0,
  44620. x1 = Infinity,
  44621. x2 = -Infinity,
  44622. y1 = Infinity,
  44623. y2 = -Infinity;
  44624. while (pbf.pos < end) {
  44625. if (!length) {
  44626. var cmdLen = pbf.readVarint();
  44627. cmd = cmdLen & 0x7;
  44628. length = cmdLen >> 3;
  44629. }
  44630. length--;
  44631. if (cmd === 1 || cmd === 2) {
  44632. x += pbf.readSVarint();
  44633. y += pbf.readSVarint();
  44634. if (x < x1) x1 = x;
  44635. if (x > x2) x2 = x;
  44636. if (y < y1) y1 = y;
  44637. if (y > y2) y2 = y;
  44638. } else if (cmd !== 7) {
  44639. throw new Error('unknown command ' + cmd);
  44640. }
  44641. }
  44642. return [x1, y1, x2, y2];
  44643. };
  44644. VectorTileFeature$1.prototype.toGeoJSON = function(x, y, z) {
  44645. var size = this.extent * Math.pow(2, z),
  44646. x0 = this.extent * x,
  44647. y0 = this.extent * y,
  44648. coords = this.loadGeometry(),
  44649. type = VectorTileFeature$1.types[this.type],
  44650. i, j;
  44651. function project(line) {
  44652. for (var j = 0; j < line.length; j++) {
  44653. var p = line[j], y2 = 180 - (p.y + y0) * 360 / size;
  44654. line[j] = [
  44655. (p.x + x0) * 360 / size - 180,
  44656. 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90
  44657. ];
  44658. }
  44659. }
  44660. switch (this.type) {
  44661. case 1:
  44662. var points = [];
  44663. for (i = 0; i < coords.length; i++) {
  44664. points[i] = coords[i][0];
  44665. }
  44666. coords = points;
  44667. project(coords);
  44668. break;
  44669. case 2:
  44670. for (i = 0; i < coords.length; i++) {
  44671. project(coords[i]);
  44672. }
  44673. break;
  44674. case 3:
  44675. coords = classifyRings(coords);
  44676. for (i = 0; i < coords.length; i++) {
  44677. for (j = 0; j < coords[i].length; j++) {
  44678. project(coords[i][j]);
  44679. }
  44680. }
  44681. break;
  44682. }
  44683. if (coords.length === 1) {
  44684. coords = coords[0];
  44685. } else {
  44686. type = 'Multi' + type;
  44687. }
  44688. var result = {
  44689. type: "Feature",
  44690. geometry: {
  44691. type: type,
  44692. coordinates: coords
  44693. },
  44694. properties: this.properties
  44695. };
  44696. if ('id' in this) {
  44697. result.id = this.id;
  44698. }
  44699. return result;
  44700. };
  44701. function classifyRings(rings) {
  44702. var len = rings.length;
  44703. if (len <= 1) return [rings];
  44704. var polygons = [],
  44705. polygon,
  44706. ccw;
  44707. for (var i = 0; i < len; i++) {
  44708. var area = signedArea(rings[i]);
  44709. if (area === 0) continue;
  44710. if (ccw === undefined) ccw = area < 0;
  44711. if (ccw === area < 0) {
  44712. if (polygon) polygons.push(polygon);
  44713. polygon = [rings[i]];
  44714. } else {
  44715. polygon.push(rings[i]);
  44716. }
  44717. }
  44718. if (polygon) polygons.push(polygon);
  44719. return polygons;
  44720. }
  44721. function signedArea(ring) {
  44722. var sum = 0;
  44723. for (var i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
  44724. p1 = ring[i];
  44725. p2 = ring[j];
  44726. sum += (p2.x - p1.x) * (p1.y + p2.y);
  44727. }
  44728. return sum;
  44729. }
  44730. var vectortilelayer = VectorTileLayer$1;
  44731. function VectorTileLayer$1(pbf, end) {
  44732. this.version = 1;
  44733. this.name = null;
  44734. this.extent = 4096;
  44735. this.length = 0;
  44736. this._pbf = pbf;
  44737. this._keys = [];
  44738. this._values = [];
  44739. this._features = [];
  44740. pbf.readFields(readLayer, this, end);
  44741. this.length = this._features.length;
  44742. }
  44743. function readLayer(tag, layer, pbf) {
  44744. if (tag === 15) layer.version = pbf.readVarint();
  44745. else if (tag === 1) layer.name = pbf.readString();
  44746. else if (tag === 5) layer.extent = pbf.readVarint();
  44747. else if (tag === 2) layer._features.push(pbf.pos);
  44748. else if (tag === 3) layer._keys.push(pbf.readString());
  44749. else if (tag === 4) layer._values.push(readValueMessage(pbf));
  44750. }
  44751. function readValueMessage(pbf) {
  44752. var value = null,
  44753. end = pbf.readVarint() + pbf.pos;
  44754. while (pbf.pos < end) {
  44755. var tag = pbf.readVarint() >> 3;
  44756. value = tag === 1 ? pbf.readString() :
  44757. tag === 2 ? pbf.readFloat() :
  44758. tag === 3 ? pbf.readDouble() :
  44759. tag === 4 ? pbf.readVarint64() :
  44760. tag === 5 ? pbf.readVarint() :
  44761. tag === 6 ? pbf.readSVarint() :
  44762. tag === 7 ? pbf.readBoolean() : null;
  44763. }
  44764. return value;
  44765. }
  44766. VectorTileLayer$1.prototype.feature = function(i) {
  44767. if (i < 0 || i >= this._features.length) throw new Error('feature index out of bounds');
  44768. this._pbf.pos = this._features[i];
  44769. var end = this._pbf.readVarint() + this._pbf.pos;
  44770. return new vectortilefeature(this._pbf, end, this.extent, this._keys, this._values);
  44771. };
  44772. var vectortile = VectorTile$1;
  44773. function VectorTile$1(pbf, end) {
  44774. this.layers = pbf.readFields(readTile, {}, end);
  44775. }
  44776. function readTile(tag, layers, pbf) {
  44777. if (tag === 3) {
  44778. var layer = new vectortilelayer(pbf, pbf.readVarint() + pbf.pos);
  44779. if (layer.length) layers[layer.name] = layer;
  44780. }
  44781. }
  44782. var VectorTile = vectortile;
  44783. var VectorTileFeature = vectortilefeature;
  44784. var VectorTileLayer = vectortilelayer;
  44785. var vectorTile = {
  44786. VectorTile: VectorTile,
  44787. VectorTileFeature: VectorTileFeature,
  44788. VectorTileLayer: VectorTileLayer
  44789. };
  44790. exports['default'] = vectorTile;
  44791. exports.VectorTile = VectorTile;
  44792. exports.VectorTileFeature = VectorTileFeature;
  44793. exports.VectorTileLayer = VectorTileLayer;
  44794. }((this.vectortile = this.vectortile || {})));}).call(ol.ext);
  44795. goog.provide('ol.render.Feature');
  44796. goog.require('ol');
  44797. goog.require('ol.extent');
  44798. goog.require('ol.geom.GeometryType');
  44799. /**
  44800. * Lightweight, read-only, {@link ol.Feature} and {@link ol.geom.Geometry} like
  44801. * structure, optimized for rendering and styling. Geometry access through the
  44802. * API is limited to getting the type and extent of the geometry.
  44803. *
  44804. * @constructor
  44805. * @param {ol.geom.GeometryType} type Geometry type.
  44806. * @param {Array.<number>} flatCoordinates Flat coordinates. These always need
  44807. * to be right-handed for polygons.
  44808. * @param {Array.<number>|Array.<Array.<number>>} ends Ends or Endss.
  44809. * @param {Object.<string, *>} properties Properties.
  44810. * @param {number|string|undefined} id Feature id.
  44811. */
  44812. ol.render.Feature = function(type, flatCoordinates, ends, properties, id) {
  44813. /**
  44814. * @private
  44815. * @type {ol.Extent|undefined}
  44816. */
  44817. this.extent_;
  44818. /**
  44819. * @private
  44820. * @type {number|string|undefined}
  44821. */
  44822. this.id_ = id;
  44823. /**
  44824. * @private
  44825. * @type {ol.geom.GeometryType}
  44826. */
  44827. this.type_ = type;
  44828. /**
  44829. * @private
  44830. * @type {Array.<number>}
  44831. */
  44832. this.flatCoordinates_ = flatCoordinates;
  44833. /**
  44834. * @private
  44835. * @type {Array.<number>|Array.<Array.<number>>}
  44836. */
  44837. this.ends_ = ends;
  44838. /**
  44839. * @private
  44840. * @type {Object.<string, *>}
  44841. */
  44842. this.properties_ = properties;
  44843. };
  44844. /**
  44845. * Get a feature property by its key.
  44846. * @param {string} key Key
  44847. * @return {*} Value for the requested key.
  44848. * @api
  44849. */
  44850. ol.render.Feature.prototype.get = function(key) {
  44851. return this.properties_[key];
  44852. };
  44853. /**
  44854. * @return {Array.<number>|Array.<Array.<number>>} Ends or endss.
  44855. */
  44856. ol.render.Feature.prototype.getEnds = function() {
  44857. return this.ends_;
  44858. };
  44859. /**
  44860. * Get the extent of this feature's geometry.
  44861. * @return {ol.Extent} Extent.
  44862. * @api
  44863. */
  44864. ol.render.Feature.prototype.getExtent = function() {
  44865. if (!this.extent_) {
  44866. this.extent_ = this.type_ === ol.geom.GeometryType.POINT ?
  44867. ol.extent.createOrUpdateFromCoordinate(this.flatCoordinates_) :
  44868. ol.extent.createOrUpdateFromFlatCoordinates(
  44869. this.flatCoordinates_, 0, this.flatCoordinates_.length, 2);
  44870. }
  44871. return this.extent_;
  44872. };
  44873. /**
  44874. * Get the feature identifier. This is a stable identifier for the feature and
  44875. * is set when reading data from a remote source.
  44876. * @return {number|string|undefined} Id.
  44877. * @api
  44878. */
  44879. ol.render.Feature.prototype.getId = function() {
  44880. return this.id_;
  44881. };
  44882. /**
  44883. * @return {Array.<number>} Flat coordinates.
  44884. */
  44885. ol.render.Feature.prototype.getOrientedFlatCoordinates = function() {
  44886. return this.flatCoordinates_;
  44887. };
  44888. /**
  44889. * @return {Array.<number>} Flat coordinates.
  44890. */
  44891. ol.render.Feature.prototype.getFlatCoordinates =
  44892. ol.render.Feature.prototype.getOrientedFlatCoordinates;
  44893. /**
  44894. * For API compatibility with {@link ol.Feature}, this method is useful when
  44895. * determining the geometry type in style function (see {@link #getType}).
  44896. * @return {ol.render.Feature} Feature.
  44897. * @api
  44898. */
  44899. ol.render.Feature.prototype.getGeometry = function() {
  44900. return this;
  44901. };
  44902. /**
  44903. * Get the feature properties.
  44904. * @return {Object.<string, *>} Feature properties.
  44905. * @api
  44906. */
  44907. ol.render.Feature.prototype.getProperties = function() {
  44908. return this.properties_;
  44909. };
  44910. /**
  44911. * Get the feature for working with its geometry.
  44912. * @return {ol.render.Feature} Feature.
  44913. */
  44914. ol.render.Feature.prototype.getSimplifiedGeometry =
  44915. ol.render.Feature.prototype.getGeometry;
  44916. /**
  44917. * @return {number} Stride.
  44918. */
  44919. ol.render.Feature.prototype.getStride = function() {
  44920. return 2;
  44921. };
  44922. /**
  44923. * @return {undefined}
  44924. */
  44925. ol.render.Feature.prototype.getStyleFunction = ol.nullFunction;
  44926. /**
  44927. * Get the type of this feature's geometry.
  44928. * @return {ol.geom.GeometryType} Geometry type.
  44929. * @api
  44930. */
  44931. ol.render.Feature.prototype.getType = function() {
  44932. return this.type_;
  44933. };
  44934. //FIXME Implement projection handling
  44935. goog.provide('ol.format.MVT');
  44936. goog.require('ol');
  44937. goog.require('ol.ext.PBF');
  44938. goog.require('ol.ext.vectortile.VectorTile');
  44939. goog.require('ol.format.Feature');
  44940. goog.require('ol.format.FormatType');
  44941. goog.require('ol.geom.GeometryLayout');
  44942. goog.require('ol.geom.GeometryType');
  44943. goog.require('ol.geom.LineString');
  44944. goog.require('ol.geom.MultiLineString');
  44945. goog.require('ol.geom.MultiPoint');
  44946. goog.require('ol.geom.Point');
  44947. goog.require('ol.geom.Polygon');
  44948. goog.require('ol.proj.Projection');
  44949. goog.require('ol.proj.Units');
  44950. goog.require('ol.render.Feature');
  44951. /**
  44952. * @classdesc
  44953. * Feature format for reading data in the Mapbox MVT format.
  44954. *
  44955. * @constructor
  44956. * @extends {ol.format.Feature}
  44957. * @param {olx.format.MVTOptions=} opt_options Options.
  44958. * @api
  44959. */
  44960. ol.format.MVT = function(opt_options) {
  44961. ol.format.Feature.call(this);
  44962. var options = opt_options ? opt_options : {};
  44963. /**
  44964. * @type {ol.proj.Projection}
  44965. */
  44966. this.defaultDataProjection = new ol.proj.Projection({
  44967. code: '',
  44968. units: ol.proj.Units.TILE_PIXELS
  44969. });
  44970. /**
  44971. * @private
  44972. * @type {function((ol.geom.Geometry|Object.<string,*>)=)|
  44973. * function(ol.geom.GeometryType,Array.<number>,
  44974. * (Array.<number>|Array.<Array.<number>>),Object.<string,*>,number)}
  44975. */
  44976. this.featureClass_ = options.featureClass ?
  44977. options.featureClass : ol.render.Feature;
  44978. /**
  44979. * @private
  44980. * @type {string|undefined}
  44981. */
  44982. this.geometryName_ = options.geometryName;
  44983. /**
  44984. * @private
  44985. * @type {string}
  44986. */
  44987. this.layerName_ = options.layerName ? options.layerName : 'layer';
  44988. /**
  44989. * @private
  44990. * @type {Array.<string>}
  44991. */
  44992. this.layers_ = options.layers ? options.layers : null;
  44993. /**
  44994. * @private
  44995. * @type {ol.Extent}
  44996. */
  44997. this.extent_ = null;
  44998. };
  44999. ol.inherits(ol.format.MVT, ol.format.Feature);
  45000. /**
  45001. * @inheritDoc
  45002. * @api
  45003. */
  45004. ol.format.MVT.prototype.getLastExtent = function() {
  45005. return this.extent_;
  45006. };
  45007. /**
  45008. * @inheritDoc
  45009. */
  45010. ol.format.MVT.prototype.getType = function() {
  45011. return ol.format.FormatType.ARRAY_BUFFER;
  45012. };
  45013. /**
  45014. * @private
  45015. * @param {Object} rawFeature Raw Mapbox feature.
  45016. * @param {string} layer Layer.
  45017. * @param {olx.format.ReadOptions=} opt_options Read options.
  45018. * @return {ol.Feature} Feature.
  45019. */
  45020. ol.format.MVT.prototype.readFeature_ = function(
  45021. rawFeature, layer, opt_options) {
  45022. var feature = new this.featureClass_();
  45023. var id = rawFeature.id;
  45024. var values = rawFeature.properties;
  45025. values[this.layerName_] = layer;
  45026. if (this.geometryName_) {
  45027. feature.setGeometryName(this.geometryName_);
  45028. }
  45029. var geometry = ol.format.Feature.transformWithOptions(
  45030. ol.format.MVT.readGeometry_(rawFeature), false,
  45031. this.adaptOptions(opt_options));
  45032. feature.setGeometry(geometry);
  45033. feature.setId(id);
  45034. feature.setProperties(values);
  45035. return feature;
  45036. };
  45037. /**
  45038. * @private
  45039. * @param {Object} rawFeature Raw Mapbox feature.
  45040. * @param {string} layer Layer.
  45041. * @return {ol.render.Feature} Feature.
  45042. */
  45043. ol.format.MVT.prototype.readRenderFeature_ = function(rawFeature, layer) {
  45044. var coords = rawFeature.loadGeometry();
  45045. var ends = [];
  45046. var flatCoordinates = [];
  45047. ol.format.MVT.calculateFlatCoordinates_(coords, flatCoordinates, ends);
  45048. var type = rawFeature.type;
  45049. /** @type {ol.geom.GeometryType} */
  45050. var geometryType;
  45051. if (type === 1) {
  45052. geometryType = coords.length === 1 ?
  45053. ol.geom.GeometryType.POINT : ol.geom.GeometryType.MULTI_POINT;
  45054. } else if (type === 2) {
  45055. if (coords.length === 1) {
  45056. geometryType = ol.geom.GeometryType.LINE_STRING;
  45057. } else {
  45058. geometryType = ol.geom.GeometryType.MULTI_LINE_STRING;
  45059. }
  45060. } else if (type === 3) {
  45061. geometryType = ol.geom.GeometryType.POLYGON;
  45062. }
  45063. var values = rawFeature.properties;
  45064. values[this.layerName_] = layer;
  45065. var id = rawFeature.id;
  45066. return new this.featureClass_(geometryType, flatCoordinates, ends, values, id);
  45067. };
  45068. /**
  45069. * @inheritDoc
  45070. * @api
  45071. */
  45072. ol.format.MVT.prototype.readFeatures = function(source, opt_options) {
  45073. var layers = this.layers_;
  45074. var pbf = new ol.ext.PBF(/** @type {ArrayBuffer} */ (source));
  45075. var tile = new ol.ext.vectortile.VectorTile(pbf);
  45076. var features = [];
  45077. var featureClass = this.featureClass_;
  45078. var layer, feature;
  45079. for (var name in tile.layers) {
  45080. if (layers && layers.indexOf(name) == -1) {
  45081. continue;
  45082. }
  45083. layer = tile.layers[name];
  45084. var rawFeature;
  45085. for (var i = 0, ii = layer.length; i < ii; ++i) {
  45086. rawFeature = layer.feature(i);
  45087. if (featureClass === ol.render.Feature) {
  45088. feature = this.readRenderFeature_(rawFeature, name);
  45089. } else {
  45090. feature = this.readFeature_(rawFeature, name, opt_options);
  45091. }
  45092. features.push(feature);
  45093. }
  45094. this.extent_ = layer ? [0, 0, layer.extent, layer.extent] : null;
  45095. }
  45096. return features;
  45097. };
  45098. /**
  45099. * @inheritDoc
  45100. * @api
  45101. */
  45102. ol.format.MVT.prototype.readProjection = function(source) {
  45103. return this.defaultDataProjection;
  45104. };
  45105. /**
  45106. * Sets the layers that features will be read from.
  45107. * @param {Array.<string>} layers Layers.
  45108. * @api
  45109. */
  45110. ol.format.MVT.prototype.setLayers = function(layers) {
  45111. this.layers_ = layers;
  45112. };
  45113. /**
  45114. * @private
  45115. * @param {Object} coords Raw feature coordinates.
  45116. * @param {Array.<number>} flatCoordinates Flat coordinates to be populated by
  45117. * this function.
  45118. * @param {Array.<number>} ends Ends to be populated by this function.
  45119. */
  45120. ol.format.MVT.calculateFlatCoordinates_ = function(
  45121. coords, flatCoordinates, ends) {
  45122. var end = 0;
  45123. for (var i = 0, ii = coords.length; i < ii; ++i) {
  45124. var line = coords[i];
  45125. var j, jj;
  45126. for (j = 0, jj = line.length; j < jj; ++j) {
  45127. var coord = line[j];
  45128. // Non-tilespace coords can be calculated here when a TileGrid and
  45129. // TileCoord are known.
  45130. flatCoordinates.push(coord.x, coord.y);
  45131. }
  45132. end += 2 * j;
  45133. ends.push(end);
  45134. }
  45135. };
  45136. /**
  45137. * @private
  45138. * @param {Object} rawFeature Raw Mapbox feature.
  45139. * @return {ol.geom.Geometry} Geometry.
  45140. */
  45141. ol.format.MVT.readGeometry_ = function(rawFeature) {
  45142. var type = rawFeature.type;
  45143. if (type === 0) {
  45144. return null;
  45145. }
  45146. var coords = rawFeature.loadGeometry();
  45147. var ends = [];
  45148. var flatCoordinates = [];
  45149. ol.format.MVT.calculateFlatCoordinates_(coords, flatCoordinates, ends);
  45150. var geom;
  45151. if (type === 1) {
  45152. geom = coords.length === 1 ?
  45153. new ol.geom.Point(null) : new ol.geom.MultiPoint(null);
  45154. } else if (type === 2) {
  45155. if (coords.length === 1) {
  45156. geom = new ol.geom.LineString(null);
  45157. } else {
  45158. geom = new ol.geom.MultiLineString(null);
  45159. }
  45160. } else if (type === 3) {
  45161. geom = new ol.geom.Polygon(null);
  45162. }
  45163. geom.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates,
  45164. ends);
  45165. return geom;
  45166. };
  45167. /**
  45168. * Not implemented.
  45169. * @override
  45170. */
  45171. ol.format.MVT.prototype.readFeature = function() {};
  45172. /**
  45173. * Not implemented.
  45174. * @override
  45175. */
  45176. ol.format.MVT.prototype.readGeometry = function() {};
  45177. /**
  45178. * Not implemented.
  45179. * @override
  45180. */
  45181. ol.format.MVT.prototype.writeFeature = function() {};
  45182. /**
  45183. * Not implemented.
  45184. * @override
  45185. */
  45186. ol.format.MVT.prototype.writeGeometry = function() {};
  45187. /**
  45188. * Not implemented.
  45189. * @override
  45190. */
  45191. ol.format.MVT.prototype.writeFeatures = function() {};
  45192. // FIXME add typedef for stack state objects
  45193. goog.provide('ol.format.OSMXML');
  45194. goog.require('ol');
  45195. goog.require('ol.array');
  45196. goog.require('ol.Feature');
  45197. goog.require('ol.format.Feature');
  45198. goog.require('ol.format.XMLFeature');
  45199. goog.require('ol.geom.GeometryLayout');
  45200. goog.require('ol.geom.LineString');
  45201. goog.require('ol.geom.Point');
  45202. goog.require('ol.geom.Polygon');
  45203. goog.require('ol.obj');
  45204. goog.require('ol.proj');
  45205. goog.require('ol.xml');
  45206. /**
  45207. * @classdesc
  45208. * Feature format for reading data in the
  45209. * [OSMXML format](http://wiki.openstreetmap.org/wiki/OSM_XML).
  45210. *
  45211. * @constructor
  45212. * @extends {ol.format.XMLFeature}
  45213. * @api
  45214. */
  45215. ol.format.OSMXML = function() {
  45216. ol.format.XMLFeature.call(this);
  45217. /**
  45218. * @inheritDoc
  45219. */
  45220. this.defaultDataProjection = ol.proj.get('EPSG:4326');
  45221. };
  45222. ol.inherits(ol.format.OSMXML, ol.format.XMLFeature);
  45223. /**
  45224. * @param {Node} node Node.
  45225. * @param {Array.<*>} objectStack Object stack.
  45226. * @private
  45227. */
  45228. ol.format.OSMXML.readNode_ = function(node, objectStack) {
  45229. var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]);
  45230. var state = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  45231. var id = node.getAttribute('id');
  45232. /** @type {ol.Coordinate} */
  45233. var coordinates = [
  45234. parseFloat(node.getAttribute('lon')),
  45235. parseFloat(node.getAttribute('lat'))
  45236. ];
  45237. state.nodes[id] = coordinates;
  45238. var values = ol.xml.pushParseAndPop({
  45239. tags: {}
  45240. }, ol.format.OSMXML.NODE_PARSERS_, node, objectStack);
  45241. if (!ol.obj.isEmpty(values.tags)) {
  45242. var geometry = new ol.geom.Point(coordinates);
  45243. ol.format.Feature.transformWithOptions(geometry, false, options);
  45244. var feature = new ol.Feature(geometry);
  45245. feature.setId(id);
  45246. feature.setProperties(values.tags);
  45247. state.features.push(feature);
  45248. }
  45249. };
  45250. /**
  45251. * @param {Node} node Node.
  45252. * @param {Array.<*>} objectStack Object stack.
  45253. * @private
  45254. */
  45255. ol.format.OSMXML.readWay_ = function(node, objectStack) {
  45256. var options = /** @type {olx.format.ReadOptions} */ (objectStack[0]);
  45257. var id = node.getAttribute('id');
  45258. var values = ol.xml.pushParseAndPop({
  45259. ndrefs: [],
  45260. tags: {}
  45261. }, ol.format.OSMXML.WAY_PARSERS_, node, objectStack);
  45262. var state = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  45263. /** @type {Array.<number>} */
  45264. var flatCoordinates = [];
  45265. for (var i = 0, ii = values.ndrefs.length; i < ii; i++) {
  45266. var point = state.nodes[values.ndrefs[i]];
  45267. ol.array.extend(flatCoordinates, point);
  45268. }
  45269. var geometry;
  45270. if (values.ndrefs[0] == values.ndrefs[values.ndrefs.length - 1]) {
  45271. // closed way
  45272. geometry = new ol.geom.Polygon(null);
  45273. geometry.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates,
  45274. [flatCoordinates.length]);
  45275. } else {
  45276. geometry = new ol.geom.LineString(null);
  45277. geometry.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates);
  45278. }
  45279. ol.format.Feature.transformWithOptions(geometry, false, options);
  45280. var feature = new ol.Feature(geometry);
  45281. feature.setId(id);
  45282. feature.setProperties(values.tags);
  45283. state.features.push(feature);
  45284. };
  45285. /**
  45286. * @param {Node} node Node.
  45287. * @param {Array.<*>} objectStack Object stack.
  45288. * @private
  45289. */
  45290. ol.format.OSMXML.readNd_ = function(node, objectStack) {
  45291. var values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  45292. values.ndrefs.push(node.getAttribute('ref'));
  45293. };
  45294. /**
  45295. * @param {Node} node Node.
  45296. * @param {Array.<*>} objectStack Object stack.
  45297. * @private
  45298. */
  45299. ol.format.OSMXML.readTag_ = function(node, objectStack) {
  45300. var values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  45301. values.tags[node.getAttribute('k')] = node.getAttribute('v');
  45302. };
  45303. /**
  45304. * @const
  45305. * @private
  45306. * @type {Array.<string>}
  45307. */
  45308. ol.format.OSMXML.NAMESPACE_URIS_ = [
  45309. null
  45310. ];
  45311. /**
  45312. * @const
  45313. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45314. * @private
  45315. */
  45316. ol.format.OSMXML.WAY_PARSERS_ = ol.xml.makeStructureNS(
  45317. ol.format.OSMXML.NAMESPACE_URIS_, {
  45318. 'nd': ol.format.OSMXML.readNd_,
  45319. 'tag': ol.format.OSMXML.readTag_
  45320. });
  45321. /**
  45322. * @const
  45323. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45324. * @private
  45325. */
  45326. ol.format.OSMXML.PARSERS_ = ol.xml.makeStructureNS(
  45327. ol.format.OSMXML.NAMESPACE_URIS_, {
  45328. 'node': ol.format.OSMXML.readNode_,
  45329. 'way': ol.format.OSMXML.readWay_
  45330. });
  45331. /**
  45332. * @const
  45333. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45334. * @private
  45335. */
  45336. ol.format.OSMXML.NODE_PARSERS_ = ol.xml.makeStructureNS(
  45337. ol.format.OSMXML.NAMESPACE_URIS_, {
  45338. 'tag': ol.format.OSMXML.readTag_
  45339. });
  45340. /**
  45341. * Read all features from an OSM source.
  45342. *
  45343. * @function
  45344. * @param {Document|Node|Object|string} source Source.
  45345. * @param {olx.format.ReadOptions=} opt_options Read options.
  45346. * @return {Array.<ol.Feature>} Features.
  45347. * @api
  45348. */
  45349. ol.format.OSMXML.prototype.readFeatures;
  45350. /**
  45351. * @inheritDoc
  45352. */
  45353. ol.format.OSMXML.prototype.readFeaturesFromNode = function(node, opt_options) {
  45354. var options = this.getReadOptions(node, opt_options);
  45355. if (node.localName == 'osm') {
  45356. var state = ol.xml.pushParseAndPop({
  45357. nodes: {},
  45358. features: []
  45359. }, ol.format.OSMXML.PARSERS_, node, [options]);
  45360. if (state.features) {
  45361. return state.features;
  45362. }
  45363. }
  45364. return [];
  45365. };
  45366. /**
  45367. * Read the projection from an OSM source.
  45368. *
  45369. * @function
  45370. * @param {Document|Node|Object|string} source Source.
  45371. * @return {ol.proj.Projection} Projection.
  45372. * @api
  45373. */
  45374. ol.format.OSMXML.prototype.readProjection;
  45375. /**
  45376. * Not implemented.
  45377. * @inheritDoc
  45378. */
  45379. ol.format.OSMXML.prototype.writeFeatureNode = function(feature, opt_options) {};
  45380. /**
  45381. * Not implemented.
  45382. * @inheritDoc
  45383. */
  45384. ol.format.OSMXML.prototype.writeFeaturesNode = function(features, opt_options) {};
  45385. /**
  45386. * Not implemented.
  45387. * @inheritDoc
  45388. */
  45389. ol.format.OSMXML.prototype.writeGeometryNode = function(geometry, opt_options) {};
  45390. goog.provide('ol.format.XLink');
  45391. /**
  45392. * @const
  45393. * @type {string}
  45394. */
  45395. ol.format.XLink.NAMESPACE_URI = 'http://www.w3.org/1999/xlink';
  45396. /**
  45397. * @param {Node} node Node.
  45398. * @return {boolean|undefined} Boolean.
  45399. */
  45400. ol.format.XLink.readHref = function(node) {
  45401. return node.getAttributeNS(ol.format.XLink.NAMESPACE_URI, 'href');
  45402. };
  45403. goog.provide('ol.format.XML');
  45404. goog.require('ol.xml');
  45405. /**
  45406. * @classdesc
  45407. * Generic format for reading non-feature XML data
  45408. *
  45409. * @constructor
  45410. * @abstract
  45411. * @struct
  45412. */
  45413. ol.format.XML = function() {
  45414. };
  45415. /**
  45416. * @param {Document|Node|string} source Source.
  45417. * @return {Object} The parsed result.
  45418. */
  45419. ol.format.XML.prototype.read = function(source) {
  45420. if (ol.xml.isDocument(source)) {
  45421. return this.readFromDocument(/** @type {Document} */ (source));
  45422. } else if (ol.xml.isNode(source)) {
  45423. return this.readFromNode(/** @type {Node} */ (source));
  45424. } else if (typeof source === 'string') {
  45425. var doc = ol.xml.parse(source);
  45426. return this.readFromDocument(doc);
  45427. } else {
  45428. return null;
  45429. }
  45430. };
  45431. /**
  45432. * @abstract
  45433. * @param {Document} doc Document.
  45434. * @return {Object} Object
  45435. */
  45436. ol.format.XML.prototype.readFromDocument = function(doc) {};
  45437. /**
  45438. * @abstract
  45439. * @param {Node} node Node.
  45440. * @return {Object} Object
  45441. */
  45442. ol.format.XML.prototype.readFromNode = function(node) {};
  45443. goog.provide('ol.format.OWS');
  45444. goog.require('ol');
  45445. goog.require('ol.format.XLink');
  45446. goog.require('ol.format.XML');
  45447. goog.require('ol.format.XSD');
  45448. goog.require('ol.xml');
  45449. /**
  45450. * @constructor
  45451. * @extends {ol.format.XML}
  45452. */
  45453. ol.format.OWS = function() {
  45454. ol.format.XML.call(this);
  45455. };
  45456. ol.inherits(ol.format.OWS, ol.format.XML);
  45457. /**
  45458. * @inheritDoc
  45459. */
  45460. ol.format.OWS.prototype.readFromDocument = function(doc) {
  45461. for (var n = doc.firstChild; n; n = n.nextSibling) {
  45462. if (n.nodeType == Node.ELEMENT_NODE) {
  45463. return this.readFromNode(n);
  45464. }
  45465. }
  45466. return null;
  45467. };
  45468. /**
  45469. * @inheritDoc
  45470. */
  45471. ol.format.OWS.prototype.readFromNode = function(node) {
  45472. var owsObject = ol.xml.pushParseAndPop({},
  45473. ol.format.OWS.PARSERS_, node, []);
  45474. return owsObject ? owsObject : null;
  45475. };
  45476. /**
  45477. * @param {Node} node Node.
  45478. * @param {Array.<*>} objectStack Object stack.
  45479. * @private
  45480. * @return {Object|undefined} The address.
  45481. */
  45482. ol.format.OWS.readAddress_ = function(node, objectStack) {
  45483. return ol.xml.pushParseAndPop({},
  45484. ol.format.OWS.ADDRESS_PARSERS_, node, objectStack);
  45485. };
  45486. /**
  45487. * @param {Node} node Node.
  45488. * @param {Array.<*>} objectStack Object stack.
  45489. * @private
  45490. * @return {Object|undefined} The values.
  45491. */
  45492. ol.format.OWS.readAllowedValues_ = function(node, objectStack) {
  45493. return ol.xml.pushParseAndPop({},
  45494. ol.format.OWS.ALLOWED_VALUES_PARSERS_, node, objectStack);
  45495. };
  45496. /**
  45497. * @param {Node} node Node.
  45498. * @param {Array.<*>} objectStack Object stack.
  45499. * @private
  45500. * @return {Object|undefined} The constraint.
  45501. */
  45502. ol.format.OWS.readConstraint_ = function(node, objectStack) {
  45503. var name = node.getAttribute('name');
  45504. if (!name) {
  45505. return undefined;
  45506. }
  45507. return ol.xml.pushParseAndPop({'name': name},
  45508. ol.format.OWS.CONSTRAINT_PARSERS_, node,
  45509. objectStack);
  45510. };
  45511. /**
  45512. * @param {Node} node Node.
  45513. * @param {Array.<*>} objectStack Object stack.
  45514. * @private
  45515. * @return {Object|undefined} The contact info.
  45516. */
  45517. ol.format.OWS.readContactInfo_ = function(node, objectStack) {
  45518. return ol.xml.pushParseAndPop({},
  45519. ol.format.OWS.CONTACT_INFO_PARSERS_, node, objectStack);
  45520. };
  45521. /**
  45522. * @param {Node} node Node.
  45523. * @param {Array.<*>} objectStack Object stack.
  45524. * @private
  45525. * @return {Object|undefined} The DCP.
  45526. */
  45527. ol.format.OWS.readDcp_ = function(node, objectStack) {
  45528. return ol.xml.pushParseAndPop({},
  45529. ol.format.OWS.DCP_PARSERS_, node, objectStack);
  45530. };
  45531. /**
  45532. * @param {Node} node Node.
  45533. * @param {Array.<*>} objectStack Object stack.
  45534. * @private
  45535. * @return {Object|undefined} The GET object.
  45536. */
  45537. ol.format.OWS.readGet_ = function(node, objectStack) {
  45538. var href = ol.format.XLink.readHref(node);
  45539. if (!href) {
  45540. return undefined;
  45541. }
  45542. return ol.xml.pushParseAndPop({'href': href},
  45543. ol.format.OWS.REQUEST_METHOD_PARSERS_, node, objectStack);
  45544. };
  45545. /**
  45546. * @param {Node} node Node.
  45547. * @param {Array.<*>} objectStack Object stack.
  45548. * @private
  45549. * @return {Object|undefined} The HTTP object.
  45550. */
  45551. ol.format.OWS.readHttp_ = function(node, objectStack) {
  45552. return ol.xml.pushParseAndPop({}, ol.format.OWS.HTTP_PARSERS_,
  45553. node, objectStack);
  45554. };
  45555. /**
  45556. * @param {Node} node Node.
  45557. * @param {Array.<*>} objectStack Object stack.
  45558. * @private
  45559. * @return {Object|undefined} The operation.
  45560. */
  45561. ol.format.OWS.readOperation_ = function(node, objectStack) {
  45562. var name = node.getAttribute('name');
  45563. var value = ol.xml.pushParseAndPop({},
  45564. ol.format.OWS.OPERATION_PARSERS_, node, objectStack);
  45565. if (!value) {
  45566. return undefined;
  45567. }
  45568. var object = /** @type {Object} */
  45569. (objectStack[objectStack.length - 1]);
  45570. object[name] = value;
  45571. };
  45572. /**
  45573. * @param {Node} node Node.
  45574. * @param {Array.<*>} objectStack Object stack.
  45575. * @private
  45576. * @return {Object|undefined} The operations metadata.
  45577. */
  45578. ol.format.OWS.readOperationsMetadata_ = function(node,
  45579. objectStack) {
  45580. return ol.xml.pushParseAndPop({},
  45581. ol.format.OWS.OPERATIONS_METADATA_PARSERS_, node,
  45582. objectStack);
  45583. };
  45584. /**
  45585. * @param {Node} node Node.
  45586. * @param {Array.<*>} objectStack Object stack.
  45587. * @private
  45588. * @return {Object|undefined} The phone.
  45589. */
  45590. ol.format.OWS.readPhone_ = function(node, objectStack) {
  45591. return ol.xml.pushParseAndPop({},
  45592. ol.format.OWS.PHONE_PARSERS_, node, objectStack);
  45593. };
  45594. /**
  45595. * @param {Node} node Node.
  45596. * @param {Array.<*>} objectStack Object stack.
  45597. * @private
  45598. * @return {Object|undefined} The service identification.
  45599. */
  45600. ol.format.OWS.readServiceIdentification_ = function(node,
  45601. objectStack) {
  45602. return ol.xml.pushParseAndPop(
  45603. {}, ol.format.OWS.SERVICE_IDENTIFICATION_PARSERS_, node,
  45604. objectStack);
  45605. };
  45606. /**
  45607. * @param {Node} node Node.
  45608. * @param {Array.<*>} objectStack Object stack.
  45609. * @private
  45610. * @return {Object|undefined} The service contact.
  45611. */
  45612. ol.format.OWS.readServiceContact_ = function(node, objectStack) {
  45613. return ol.xml.pushParseAndPop(
  45614. {}, ol.format.OWS.SERVICE_CONTACT_PARSERS_, node,
  45615. objectStack);
  45616. };
  45617. /**
  45618. * @param {Node} node Node.
  45619. * @param {Array.<*>} objectStack Object stack.
  45620. * @private
  45621. * @return {Object|undefined} The service provider.
  45622. */
  45623. ol.format.OWS.readServiceProvider_ = function(node, objectStack) {
  45624. return ol.xml.pushParseAndPop(
  45625. {}, ol.format.OWS.SERVICE_PROVIDER_PARSERS_, node,
  45626. objectStack);
  45627. };
  45628. /**
  45629. * @param {Node} node Node.
  45630. * @param {Array.<*>} objectStack Object stack.
  45631. * @private
  45632. * @return {string|undefined} The value.
  45633. */
  45634. ol.format.OWS.readValue_ = function(node, objectStack) {
  45635. return ol.format.XSD.readString(node);
  45636. };
  45637. /**
  45638. * @const
  45639. * @type {Array.<string>}
  45640. * @private
  45641. */
  45642. ol.format.OWS.NAMESPACE_URIS_ = [
  45643. null,
  45644. 'http://www.opengis.net/ows/1.1'
  45645. ];
  45646. /**
  45647. * @const
  45648. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45649. * @private
  45650. */
  45651. ol.format.OWS.PARSERS_ = ol.xml.makeStructureNS(
  45652. ol.format.OWS.NAMESPACE_URIS_, {
  45653. 'ServiceIdentification': ol.xml.makeObjectPropertySetter(
  45654. ol.format.OWS.readServiceIdentification_),
  45655. 'ServiceProvider': ol.xml.makeObjectPropertySetter(
  45656. ol.format.OWS.readServiceProvider_),
  45657. 'OperationsMetadata': ol.xml.makeObjectPropertySetter(
  45658. ol.format.OWS.readOperationsMetadata_)
  45659. });
  45660. /**
  45661. * @const
  45662. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45663. * @private
  45664. */
  45665. ol.format.OWS.ADDRESS_PARSERS_ = ol.xml.makeStructureNS(
  45666. ol.format.OWS.NAMESPACE_URIS_, {
  45667. 'DeliveryPoint': ol.xml.makeObjectPropertySetter(
  45668. ol.format.XSD.readString),
  45669. 'City': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  45670. 'AdministrativeArea': ol.xml.makeObjectPropertySetter(
  45671. ol.format.XSD.readString),
  45672. 'PostalCode': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  45673. 'Country': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  45674. 'ElectronicMailAddress': ol.xml.makeObjectPropertySetter(
  45675. ol.format.XSD.readString)
  45676. });
  45677. /**
  45678. * @const
  45679. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45680. * @private
  45681. */
  45682. ol.format.OWS.ALLOWED_VALUES_PARSERS_ = ol.xml.makeStructureNS(
  45683. ol.format.OWS.NAMESPACE_URIS_, {
  45684. 'Value': ol.xml.makeObjectPropertyPusher(ol.format.OWS.readValue_)
  45685. });
  45686. /**
  45687. * @const
  45688. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45689. * @private
  45690. */
  45691. ol.format.OWS.CONSTRAINT_PARSERS_ = ol.xml.makeStructureNS(
  45692. ol.format.OWS.NAMESPACE_URIS_, {
  45693. 'AllowedValues': ol.xml.makeObjectPropertySetter(
  45694. ol.format.OWS.readAllowedValues_)
  45695. });
  45696. /**
  45697. * @const
  45698. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45699. * @private
  45700. */
  45701. ol.format.OWS.CONTACT_INFO_PARSERS_ = ol.xml.makeStructureNS(
  45702. ol.format.OWS.NAMESPACE_URIS_, {
  45703. 'Phone': ol.xml.makeObjectPropertySetter(ol.format.OWS.readPhone_),
  45704. 'Address': ol.xml.makeObjectPropertySetter(ol.format.OWS.readAddress_)
  45705. });
  45706. /**
  45707. * @const
  45708. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45709. * @private
  45710. */
  45711. ol.format.OWS.DCP_PARSERS_ = ol.xml.makeStructureNS(
  45712. ol.format.OWS.NAMESPACE_URIS_, {
  45713. 'HTTP': ol.xml.makeObjectPropertySetter(ol.format.OWS.readHttp_)
  45714. });
  45715. /**
  45716. * @const
  45717. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45718. * @private
  45719. */
  45720. ol.format.OWS.HTTP_PARSERS_ = ol.xml.makeStructureNS(
  45721. ol.format.OWS.NAMESPACE_URIS_, {
  45722. 'Get': ol.xml.makeObjectPropertyPusher(ol.format.OWS.readGet_),
  45723. 'Post': undefined // TODO
  45724. });
  45725. /**
  45726. * @const
  45727. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45728. * @private
  45729. */
  45730. ol.format.OWS.OPERATION_PARSERS_ = ol.xml.makeStructureNS(
  45731. ol.format.OWS.NAMESPACE_URIS_, {
  45732. 'DCP': ol.xml.makeObjectPropertySetter(ol.format.OWS.readDcp_)
  45733. });
  45734. /**
  45735. * @const
  45736. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45737. * @private
  45738. */
  45739. ol.format.OWS.OPERATIONS_METADATA_PARSERS_ = ol.xml.makeStructureNS(
  45740. ol.format.OWS.NAMESPACE_URIS_, {
  45741. 'Operation': ol.format.OWS.readOperation_
  45742. });
  45743. /**
  45744. * @const
  45745. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45746. * @private
  45747. */
  45748. ol.format.OWS.PHONE_PARSERS_ = ol.xml.makeStructureNS(
  45749. ol.format.OWS.NAMESPACE_URIS_, {
  45750. 'Voice': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  45751. 'Facsimile': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString)
  45752. });
  45753. /**
  45754. * @const
  45755. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45756. * @private
  45757. */
  45758. ol.format.OWS.REQUEST_METHOD_PARSERS_ = ol.xml.makeStructureNS(
  45759. ol.format.OWS.NAMESPACE_URIS_, {
  45760. 'Constraint': ol.xml.makeObjectPropertyPusher(
  45761. ol.format.OWS.readConstraint_)
  45762. });
  45763. /**
  45764. * @const
  45765. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45766. * @private
  45767. */
  45768. ol.format.OWS.SERVICE_CONTACT_PARSERS_ =
  45769. ol.xml.makeStructureNS(
  45770. ol.format.OWS.NAMESPACE_URIS_, {
  45771. 'IndividualName': ol.xml.makeObjectPropertySetter(
  45772. ol.format.XSD.readString),
  45773. 'PositionName': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  45774. 'ContactInfo': ol.xml.makeObjectPropertySetter(
  45775. ol.format.OWS.readContactInfo_)
  45776. });
  45777. /**
  45778. * @const
  45779. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45780. * @private
  45781. */
  45782. ol.format.OWS.SERVICE_IDENTIFICATION_PARSERS_ =
  45783. ol.xml.makeStructureNS(
  45784. ol.format.OWS.NAMESPACE_URIS_, {
  45785. 'Title': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  45786. 'ServiceTypeVersion': ol.xml.makeObjectPropertySetter(
  45787. ol.format.XSD.readString),
  45788. 'ServiceType': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString)
  45789. });
  45790. /**
  45791. * @const
  45792. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  45793. * @private
  45794. */
  45795. ol.format.OWS.SERVICE_PROVIDER_PARSERS_ =
  45796. ol.xml.makeStructureNS(
  45797. ol.format.OWS.NAMESPACE_URIS_, {
  45798. 'ProviderName': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  45799. 'ProviderSite': ol.xml.makeObjectPropertySetter(ol.format.XLink.readHref),
  45800. 'ServiceContact': ol.xml.makeObjectPropertySetter(
  45801. ol.format.OWS.readServiceContact_)
  45802. });
  45803. goog.provide('ol.geom.flat.flip');
  45804. /**
  45805. * @param {Array.<number>} flatCoordinates Flat coordinates.
  45806. * @param {number} offset Offset.
  45807. * @param {number} end End.
  45808. * @param {number} stride Stride.
  45809. * @param {Array.<number>=} opt_dest Destination.
  45810. * @param {number=} opt_destOffset Destination offset.
  45811. * @return {Array.<number>} Flat coordinates.
  45812. */
  45813. ol.geom.flat.flip.flipXY = function(flatCoordinates, offset, end, stride, opt_dest, opt_destOffset) {
  45814. var dest, destOffset;
  45815. if (opt_dest !== undefined) {
  45816. dest = opt_dest;
  45817. destOffset = opt_destOffset !== undefined ? opt_destOffset : 0;
  45818. } else {
  45819. dest = [];
  45820. destOffset = 0;
  45821. }
  45822. var j = offset;
  45823. while (j < end) {
  45824. var x = flatCoordinates[j++];
  45825. dest[destOffset++] = flatCoordinates[j++];
  45826. dest[destOffset++] = x;
  45827. for (var k = 2; k < stride; ++k) {
  45828. dest[destOffset++] = flatCoordinates[j++];
  45829. }
  45830. }
  45831. dest.length = destOffset;
  45832. return dest;
  45833. };
  45834. goog.provide('ol.format.Polyline');
  45835. goog.require('ol');
  45836. goog.require('ol.asserts');
  45837. goog.require('ol.Feature');
  45838. goog.require('ol.format.Feature');
  45839. goog.require('ol.format.TextFeature');
  45840. goog.require('ol.geom.GeometryLayout');
  45841. goog.require('ol.geom.LineString');
  45842. goog.require('ol.geom.SimpleGeometry');
  45843. goog.require('ol.geom.flat.flip');
  45844. goog.require('ol.geom.flat.inflate');
  45845. goog.require('ol.proj');
  45846. /**
  45847. * @classdesc
  45848. * Feature format for reading and writing data in the Encoded
  45849. * Polyline Algorithm Format.
  45850. *
  45851. * @constructor
  45852. * @extends {ol.format.TextFeature}
  45853. * @param {olx.format.PolylineOptions=} opt_options
  45854. * Optional configuration object.
  45855. * @api
  45856. */
  45857. ol.format.Polyline = function(opt_options) {
  45858. var options = opt_options ? opt_options : {};
  45859. ol.format.TextFeature.call(this);
  45860. /**
  45861. * @inheritDoc
  45862. */
  45863. this.defaultDataProjection = ol.proj.get('EPSG:4326');
  45864. /**
  45865. * @private
  45866. * @type {number}
  45867. */
  45868. this.factor_ = options.factor ? options.factor : 1e5;
  45869. /**
  45870. * @private
  45871. * @type {ol.geom.GeometryLayout}
  45872. */
  45873. this.geometryLayout_ = options.geometryLayout ?
  45874. options.geometryLayout : ol.geom.GeometryLayout.XY;
  45875. };
  45876. ol.inherits(ol.format.Polyline, ol.format.TextFeature);
  45877. /**
  45878. * Encode a list of n-dimensional points and return an encoded string
  45879. *
  45880. * Attention: This function will modify the passed array!
  45881. *
  45882. * @param {Array.<number>} numbers A list of n-dimensional points.
  45883. * @param {number} stride The number of dimension of the points in the list.
  45884. * @param {number=} opt_factor The factor by which the numbers will be
  45885. * multiplied. The remaining decimal places will get rounded away.
  45886. * Default is `1e5`.
  45887. * @return {string} The encoded string.
  45888. * @api
  45889. */
  45890. ol.format.Polyline.encodeDeltas = function(numbers, stride, opt_factor) {
  45891. var factor = opt_factor ? opt_factor : 1e5;
  45892. var d;
  45893. var lastNumbers = new Array(stride);
  45894. for (d = 0; d < stride; ++d) {
  45895. lastNumbers[d] = 0;
  45896. }
  45897. var i, ii;
  45898. for (i = 0, ii = numbers.length; i < ii;) {
  45899. for (d = 0; d < stride; ++d, ++i) {
  45900. var num = numbers[i];
  45901. var delta = num - lastNumbers[d];
  45902. lastNumbers[d] = num;
  45903. numbers[i] = delta;
  45904. }
  45905. }
  45906. return ol.format.Polyline.encodeFloats(numbers, factor);
  45907. };
  45908. /**
  45909. * Decode a list of n-dimensional points from an encoded string
  45910. *
  45911. * @param {string} encoded An encoded string.
  45912. * @param {number} stride The number of dimension of the points in the
  45913. * encoded string.
  45914. * @param {number=} opt_factor The factor by which the resulting numbers will
  45915. * be divided. Default is `1e5`.
  45916. * @return {Array.<number>} A list of n-dimensional points.
  45917. * @api
  45918. */
  45919. ol.format.Polyline.decodeDeltas = function(encoded, stride, opt_factor) {
  45920. var factor = opt_factor ? opt_factor : 1e5;
  45921. var d;
  45922. /** @type {Array.<number>} */
  45923. var lastNumbers = new Array(stride);
  45924. for (d = 0; d < stride; ++d) {
  45925. lastNumbers[d] = 0;
  45926. }
  45927. var numbers = ol.format.Polyline.decodeFloats(encoded, factor);
  45928. var i, ii;
  45929. for (i = 0, ii = numbers.length; i < ii;) {
  45930. for (d = 0; d < stride; ++d, ++i) {
  45931. lastNumbers[d] += numbers[i];
  45932. numbers[i] = lastNumbers[d];
  45933. }
  45934. }
  45935. return numbers;
  45936. };
  45937. /**
  45938. * Encode a list of floating point numbers and return an encoded string
  45939. *
  45940. * Attention: This function will modify the passed array!
  45941. *
  45942. * @param {Array.<number>} numbers A list of floating point numbers.
  45943. * @param {number=} opt_factor The factor by which the numbers will be
  45944. * multiplied. The remaining decimal places will get rounded away.
  45945. * Default is `1e5`.
  45946. * @return {string} The encoded string.
  45947. * @api
  45948. */
  45949. ol.format.Polyline.encodeFloats = function(numbers, opt_factor) {
  45950. var factor = opt_factor ? opt_factor : 1e5;
  45951. var i, ii;
  45952. for (i = 0, ii = numbers.length; i < ii; ++i) {
  45953. numbers[i] = Math.round(numbers[i] * factor);
  45954. }
  45955. return ol.format.Polyline.encodeSignedIntegers(numbers);
  45956. };
  45957. /**
  45958. * Decode a list of floating point numbers from an encoded string
  45959. *
  45960. * @param {string} encoded An encoded string.
  45961. * @param {number=} opt_factor The factor by which the result will be divided.
  45962. * Default is `1e5`.
  45963. * @return {Array.<number>} A list of floating point numbers.
  45964. * @api
  45965. */
  45966. ol.format.Polyline.decodeFloats = function(encoded, opt_factor) {
  45967. var factor = opt_factor ? opt_factor : 1e5;
  45968. var numbers = ol.format.Polyline.decodeSignedIntegers(encoded);
  45969. var i, ii;
  45970. for (i = 0, ii = numbers.length; i < ii; ++i) {
  45971. numbers[i] /= factor;
  45972. }
  45973. return numbers;
  45974. };
  45975. /**
  45976. * Encode a list of signed integers and return an encoded string
  45977. *
  45978. * Attention: This function will modify the passed array!
  45979. *
  45980. * @param {Array.<number>} numbers A list of signed integers.
  45981. * @return {string} The encoded string.
  45982. */
  45983. ol.format.Polyline.encodeSignedIntegers = function(numbers) {
  45984. var i, ii;
  45985. for (i = 0, ii = numbers.length; i < ii; ++i) {
  45986. var num = numbers[i];
  45987. numbers[i] = (num < 0) ? ~(num << 1) : (num << 1);
  45988. }
  45989. return ol.format.Polyline.encodeUnsignedIntegers(numbers);
  45990. };
  45991. /**
  45992. * Decode a list of signed integers from an encoded string
  45993. *
  45994. * @param {string} encoded An encoded string.
  45995. * @return {Array.<number>} A list of signed integers.
  45996. */
  45997. ol.format.Polyline.decodeSignedIntegers = function(encoded) {
  45998. var numbers = ol.format.Polyline.decodeUnsignedIntegers(encoded);
  45999. var i, ii;
  46000. for (i = 0, ii = numbers.length; i < ii; ++i) {
  46001. var num = numbers[i];
  46002. numbers[i] = (num & 1) ? ~(num >> 1) : (num >> 1);
  46003. }
  46004. return numbers;
  46005. };
  46006. /**
  46007. * Encode a list of unsigned integers and return an encoded string
  46008. *
  46009. * @param {Array.<number>} numbers A list of unsigned integers.
  46010. * @return {string} The encoded string.
  46011. */
  46012. ol.format.Polyline.encodeUnsignedIntegers = function(numbers) {
  46013. var encoded = '';
  46014. var i, ii;
  46015. for (i = 0, ii = numbers.length; i < ii; ++i) {
  46016. encoded += ol.format.Polyline.encodeUnsignedInteger(numbers[i]);
  46017. }
  46018. return encoded;
  46019. };
  46020. /**
  46021. * Decode a list of unsigned integers from an encoded string
  46022. *
  46023. * @param {string} encoded An encoded string.
  46024. * @return {Array.<number>} A list of unsigned integers.
  46025. */
  46026. ol.format.Polyline.decodeUnsignedIntegers = function(encoded) {
  46027. var numbers = [];
  46028. var current = 0;
  46029. var shift = 0;
  46030. var i, ii;
  46031. for (i = 0, ii = encoded.length; i < ii; ++i) {
  46032. var b = encoded.charCodeAt(i) - 63;
  46033. current |= (b & 0x1f) << shift;
  46034. if (b < 0x20) {
  46035. numbers.push(current);
  46036. current = 0;
  46037. shift = 0;
  46038. } else {
  46039. shift += 5;
  46040. }
  46041. }
  46042. return numbers;
  46043. };
  46044. /**
  46045. * Encode one single unsigned integer and return an encoded string
  46046. *
  46047. * @param {number} num Unsigned integer that should be encoded.
  46048. * @return {string} The encoded string.
  46049. */
  46050. ol.format.Polyline.encodeUnsignedInteger = function(num) {
  46051. var value, encoded = '';
  46052. while (num >= 0x20) {
  46053. value = (0x20 | (num & 0x1f)) + 63;
  46054. encoded += String.fromCharCode(value);
  46055. num >>= 5;
  46056. }
  46057. value = num + 63;
  46058. encoded += String.fromCharCode(value);
  46059. return encoded;
  46060. };
  46061. /**
  46062. * Read the feature from the Polyline source. The coordinates are assumed to be
  46063. * in two dimensions and in latitude, longitude order.
  46064. *
  46065. * @function
  46066. * @param {Document|Node|Object|string} source Source.
  46067. * @param {olx.format.ReadOptions=} opt_options Read options.
  46068. * @return {ol.Feature} Feature.
  46069. * @api
  46070. */
  46071. ol.format.Polyline.prototype.readFeature;
  46072. /**
  46073. * @inheritDoc
  46074. */
  46075. ol.format.Polyline.prototype.readFeatureFromText = function(text, opt_options) {
  46076. var geometry = this.readGeometryFromText(text, opt_options);
  46077. return new ol.Feature(geometry);
  46078. };
  46079. /**
  46080. * Read the feature from the source. As Polyline sources contain a single
  46081. * feature, this will return the feature in an array.
  46082. *
  46083. * @function
  46084. * @param {Document|Node|Object|string} source Source.
  46085. * @param {olx.format.ReadOptions=} opt_options Read options.
  46086. * @return {Array.<ol.Feature>} Features.
  46087. * @api
  46088. */
  46089. ol.format.Polyline.prototype.readFeatures;
  46090. /**
  46091. * @inheritDoc
  46092. */
  46093. ol.format.Polyline.prototype.readFeaturesFromText = function(text, opt_options) {
  46094. var feature = this.readFeatureFromText(text, opt_options);
  46095. return [feature];
  46096. };
  46097. /**
  46098. * Read the geometry from the source.
  46099. *
  46100. * @function
  46101. * @param {Document|Node|Object|string} source Source.
  46102. * @param {olx.format.ReadOptions=} opt_options Read options.
  46103. * @return {ol.geom.Geometry} Geometry.
  46104. * @api
  46105. */
  46106. ol.format.Polyline.prototype.readGeometry;
  46107. /**
  46108. * @inheritDoc
  46109. */
  46110. ol.format.Polyline.prototype.readGeometryFromText = function(text, opt_options) {
  46111. var stride = ol.geom.SimpleGeometry.getStrideForLayout(this.geometryLayout_);
  46112. var flatCoordinates = ol.format.Polyline.decodeDeltas(
  46113. text, stride, this.factor_);
  46114. ol.geom.flat.flip.flipXY(
  46115. flatCoordinates, 0, flatCoordinates.length, stride, flatCoordinates);
  46116. var coordinates = ol.geom.flat.inflate.coordinates(
  46117. flatCoordinates, 0, flatCoordinates.length, stride);
  46118. return /** @type {ol.geom.Geometry} */ (
  46119. ol.format.Feature.transformWithOptions(
  46120. new ol.geom.LineString(coordinates, this.geometryLayout_), false,
  46121. this.adaptOptions(opt_options)));
  46122. };
  46123. /**
  46124. * Read the projection from a Polyline source.
  46125. *
  46126. * @function
  46127. * @param {Document|Node|Object|string} source Source.
  46128. * @return {ol.proj.Projection} Projection.
  46129. * @api
  46130. */
  46131. ol.format.Polyline.prototype.readProjection;
  46132. /**
  46133. * @inheritDoc
  46134. */
  46135. ol.format.Polyline.prototype.writeFeatureText = function(feature, opt_options) {
  46136. var geometry = feature.getGeometry();
  46137. if (geometry) {
  46138. return this.writeGeometryText(geometry, opt_options);
  46139. } else {
  46140. ol.asserts.assert(false, 40); // Expected `feature` to have a geometry
  46141. return '';
  46142. }
  46143. };
  46144. /**
  46145. * @inheritDoc
  46146. */
  46147. ol.format.Polyline.prototype.writeFeaturesText = function(features, opt_options) {
  46148. return this.writeFeatureText(features[0], opt_options);
  46149. };
  46150. /**
  46151. * Write a single geometry in Polyline format.
  46152. *
  46153. * @function
  46154. * @param {ol.geom.Geometry} geometry Geometry.
  46155. * @param {olx.format.WriteOptions=} opt_options Write options.
  46156. * @return {string} Geometry.
  46157. * @api
  46158. */
  46159. ol.format.Polyline.prototype.writeGeometry;
  46160. /**
  46161. * @inheritDoc
  46162. */
  46163. ol.format.Polyline.prototype.writeGeometryText = function(geometry, opt_options) {
  46164. geometry = /** @type {ol.geom.LineString} */
  46165. (ol.format.Feature.transformWithOptions(
  46166. geometry, true, this.adaptOptions(opt_options)));
  46167. var flatCoordinates = geometry.getFlatCoordinates();
  46168. var stride = geometry.getStride();
  46169. ol.geom.flat.flip.flipXY(
  46170. flatCoordinates, 0, flatCoordinates.length, stride, flatCoordinates);
  46171. return ol.format.Polyline.encodeDeltas(flatCoordinates, stride, this.factor_);
  46172. };
  46173. goog.provide('ol.format.TopoJSON');
  46174. goog.require('ol');
  46175. goog.require('ol.Feature');
  46176. goog.require('ol.format.Feature');
  46177. goog.require('ol.format.JSONFeature');
  46178. goog.require('ol.geom.LineString');
  46179. goog.require('ol.geom.MultiLineString');
  46180. goog.require('ol.geom.MultiPoint');
  46181. goog.require('ol.geom.MultiPolygon');
  46182. goog.require('ol.geom.Point');
  46183. goog.require('ol.geom.Polygon');
  46184. goog.require('ol.proj');
  46185. /**
  46186. * @classdesc
  46187. * Feature format for reading data in the TopoJSON format.
  46188. *
  46189. * @constructor
  46190. * @extends {ol.format.JSONFeature}
  46191. * @param {olx.format.TopoJSONOptions=} opt_options Options.
  46192. * @api
  46193. */
  46194. ol.format.TopoJSON = function(opt_options) {
  46195. var options = opt_options ? opt_options : {};
  46196. ol.format.JSONFeature.call(this);
  46197. /**
  46198. * @private
  46199. * @type {string|undefined}
  46200. */
  46201. this.layerName_ = options.layerName;
  46202. /**
  46203. * @private
  46204. * @type {Array.<string>}
  46205. */
  46206. this.layers_ = options.layers ? options.layers : null;
  46207. /**
  46208. * @inheritDoc
  46209. */
  46210. this.defaultDataProjection = ol.proj.get(
  46211. options.defaultDataProjection ?
  46212. options.defaultDataProjection : 'EPSG:4326');
  46213. };
  46214. ol.inherits(ol.format.TopoJSON, ol.format.JSONFeature);
  46215. /**
  46216. * Concatenate arcs into a coordinate array.
  46217. * @param {Array.<number>} indices Indices of arcs to concatenate. Negative
  46218. * values indicate arcs need to be reversed.
  46219. * @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs (already
  46220. * transformed).
  46221. * @return {Array.<ol.Coordinate>} Coordinates array.
  46222. * @private
  46223. */
  46224. ol.format.TopoJSON.concatenateArcs_ = function(indices, arcs) {
  46225. /** @type {Array.<ol.Coordinate>} */
  46226. var coordinates = [];
  46227. var index, arc;
  46228. var i, ii;
  46229. var j, jj;
  46230. for (i = 0, ii = indices.length; i < ii; ++i) {
  46231. index = indices[i];
  46232. if (i > 0) {
  46233. // splicing together arcs, discard last point
  46234. coordinates.pop();
  46235. }
  46236. if (index >= 0) {
  46237. // forward arc
  46238. arc = arcs[index];
  46239. } else {
  46240. // reverse arc
  46241. arc = arcs[~index].slice().reverse();
  46242. }
  46243. coordinates.push.apply(coordinates, arc);
  46244. }
  46245. // provide fresh copies of coordinate arrays
  46246. for (j = 0, jj = coordinates.length; j < jj; ++j) {
  46247. coordinates[j] = coordinates[j].slice();
  46248. }
  46249. return coordinates;
  46250. };
  46251. /**
  46252. * Create a point from a TopoJSON geometry object.
  46253. *
  46254. * @param {TopoJSONGeometry} object TopoJSON object.
  46255. * @param {Array.<number>} scale Scale for each dimension.
  46256. * @param {Array.<number>} translate Translation for each dimension.
  46257. * @return {ol.geom.Point} Geometry.
  46258. * @private
  46259. */
  46260. ol.format.TopoJSON.readPointGeometry_ = function(object, scale, translate) {
  46261. var coordinates = object.coordinates;
  46262. if (scale && translate) {
  46263. ol.format.TopoJSON.transformVertex_(coordinates, scale, translate);
  46264. }
  46265. return new ol.geom.Point(coordinates);
  46266. };
  46267. /**
  46268. * Create a multi-point from a TopoJSON geometry object.
  46269. *
  46270. * @param {TopoJSONGeometry} object TopoJSON object.
  46271. * @param {Array.<number>} scale Scale for each dimension.
  46272. * @param {Array.<number>} translate Translation for each dimension.
  46273. * @return {ol.geom.MultiPoint} Geometry.
  46274. * @private
  46275. */
  46276. ol.format.TopoJSON.readMultiPointGeometry_ = function(object, scale,
  46277. translate) {
  46278. var coordinates = object.coordinates;
  46279. var i, ii;
  46280. if (scale && translate) {
  46281. for (i = 0, ii = coordinates.length; i < ii; ++i) {
  46282. ol.format.TopoJSON.transformVertex_(coordinates[i], scale, translate);
  46283. }
  46284. }
  46285. return new ol.geom.MultiPoint(coordinates);
  46286. };
  46287. /**
  46288. * Create a linestring from a TopoJSON geometry object.
  46289. *
  46290. * @param {TopoJSONGeometry} object TopoJSON object.
  46291. * @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs.
  46292. * @return {ol.geom.LineString} Geometry.
  46293. * @private
  46294. */
  46295. ol.format.TopoJSON.readLineStringGeometry_ = function(object, arcs) {
  46296. var coordinates = ol.format.TopoJSON.concatenateArcs_(object.arcs, arcs);
  46297. return new ol.geom.LineString(coordinates);
  46298. };
  46299. /**
  46300. * Create a multi-linestring from a TopoJSON geometry object.
  46301. *
  46302. * @param {TopoJSONGeometry} object TopoJSON object.
  46303. * @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs.
  46304. * @return {ol.geom.MultiLineString} Geometry.
  46305. * @private
  46306. */
  46307. ol.format.TopoJSON.readMultiLineStringGeometry_ = function(object, arcs) {
  46308. var coordinates = [];
  46309. var i, ii;
  46310. for (i = 0, ii = object.arcs.length; i < ii; ++i) {
  46311. coordinates[i] = ol.format.TopoJSON.concatenateArcs_(object.arcs[i], arcs);
  46312. }
  46313. return new ol.geom.MultiLineString(coordinates);
  46314. };
  46315. /**
  46316. * Create a polygon from a TopoJSON geometry object.
  46317. *
  46318. * @param {TopoJSONGeometry} object TopoJSON object.
  46319. * @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs.
  46320. * @return {ol.geom.Polygon} Geometry.
  46321. * @private
  46322. */
  46323. ol.format.TopoJSON.readPolygonGeometry_ = function(object, arcs) {
  46324. var coordinates = [];
  46325. var i, ii;
  46326. for (i = 0, ii = object.arcs.length; i < ii; ++i) {
  46327. coordinates[i] = ol.format.TopoJSON.concatenateArcs_(object.arcs[i], arcs);
  46328. }
  46329. return new ol.geom.Polygon(coordinates);
  46330. };
  46331. /**
  46332. * Create a multi-polygon from a TopoJSON geometry object.
  46333. *
  46334. * @param {TopoJSONGeometry} object TopoJSON object.
  46335. * @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs.
  46336. * @return {ol.geom.MultiPolygon} Geometry.
  46337. * @private
  46338. */
  46339. ol.format.TopoJSON.readMultiPolygonGeometry_ = function(object, arcs) {
  46340. var coordinates = [];
  46341. var polyArray, ringCoords, j, jj;
  46342. var i, ii;
  46343. for (i = 0, ii = object.arcs.length; i < ii; ++i) {
  46344. // for each polygon
  46345. polyArray = object.arcs[i];
  46346. ringCoords = [];
  46347. for (j = 0, jj = polyArray.length; j < jj; ++j) {
  46348. // for each ring
  46349. ringCoords[j] = ol.format.TopoJSON.concatenateArcs_(polyArray[j], arcs);
  46350. }
  46351. coordinates[i] = ringCoords;
  46352. }
  46353. return new ol.geom.MultiPolygon(coordinates);
  46354. };
  46355. /**
  46356. * Create features from a TopoJSON GeometryCollection object.
  46357. *
  46358. * @param {TopoJSONGeometryCollection} collection TopoJSON Geometry
  46359. * object.
  46360. * @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs.
  46361. * @param {Array.<number>} scale Scale for each dimension.
  46362. * @param {Array.<number>} translate Translation for each dimension.
  46363. * @param {string|undefined} property Property to set the `GeometryCollection`'s parent
  46364. * object to.
  46365. * @param {string} name Name of the `Topology`'s child object.
  46366. * @param {olx.format.ReadOptions=} opt_options Read options.
  46367. * @return {Array.<ol.Feature>} Array of features.
  46368. * @private
  46369. */
  46370. ol.format.TopoJSON.readFeaturesFromGeometryCollection_ = function(
  46371. collection, arcs, scale, translate, property, name, opt_options) {
  46372. var geometries = collection.geometries;
  46373. var features = [];
  46374. var i, ii;
  46375. for (i = 0, ii = geometries.length; i < ii; ++i) {
  46376. features[i] = ol.format.TopoJSON.readFeatureFromGeometry_(
  46377. geometries[i], arcs, scale, translate, property, name, opt_options);
  46378. }
  46379. return features;
  46380. };
  46381. /**
  46382. * Create a feature from a TopoJSON geometry object.
  46383. *
  46384. * @param {TopoJSONGeometry} object TopoJSON geometry object.
  46385. * @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs.
  46386. * @param {Array.<number>} scale Scale for each dimension.
  46387. * @param {Array.<number>} translate Translation for each dimension.
  46388. * @param {string|undefined} property Property to set the `GeometryCollection`'s parent
  46389. * object to.
  46390. * @param {string} name Name of the `Topology`'s child object.
  46391. * @param {olx.format.ReadOptions=} opt_options Read options.
  46392. * @return {ol.Feature} Feature.
  46393. * @private
  46394. */
  46395. ol.format.TopoJSON.readFeatureFromGeometry_ = function(object, arcs,
  46396. scale, translate, property, name, opt_options) {
  46397. var geometry;
  46398. var type = object.type;
  46399. var geometryReader = ol.format.TopoJSON.GEOMETRY_READERS_[type];
  46400. if ((type === 'Point') || (type === 'MultiPoint')) {
  46401. geometry = geometryReader(object, scale, translate);
  46402. } else {
  46403. geometry = geometryReader(object, arcs);
  46404. }
  46405. var feature = new ol.Feature();
  46406. feature.setGeometry(/** @type {ol.geom.Geometry} */ (
  46407. ol.format.Feature.transformWithOptions(geometry, false, opt_options)));
  46408. if (object.id !== undefined) {
  46409. feature.setId(object.id);
  46410. }
  46411. var properties = object.properties;
  46412. if (property) {
  46413. if (!properties) {
  46414. properties = {};
  46415. }
  46416. properties[property] = name;
  46417. }
  46418. if (properties) {
  46419. feature.setProperties(properties);
  46420. }
  46421. return feature;
  46422. };
  46423. /**
  46424. * Read all features from a TopoJSON source.
  46425. *
  46426. * @function
  46427. * @param {Document|Node|Object|string} source Source.
  46428. * @return {Array.<ol.Feature>} Features.
  46429. * @api
  46430. */
  46431. ol.format.TopoJSON.prototype.readFeatures;
  46432. /**
  46433. * @inheritDoc
  46434. */
  46435. ol.format.TopoJSON.prototype.readFeaturesFromObject = function(
  46436. object, opt_options) {
  46437. if (object.type == 'Topology') {
  46438. var topoJSONTopology = /** @type {TopoJSONTopology} */ (object);
  46439. var transform, scale = null, translate = null;
  46440. if (topoJSONTopology.transform) {
  46441. transform = topoJSONTopology.transform;
  46442. scale = transform.scale;
  46443. translate = transform.translate;
  46444. }
  46445. var arcs = topoJSONTopology.arcs;
  46446. if (transform) {
  46447. ol.format.TopoJSON.transformArcs_(arcs, scale, translate);
  46448. }
  46449. /** @type {Array.<ol.Feature>} */
  46450. var features = [];
  46451. var topoJSONFeatures = topoJSONTopology.objects;
  46452. var property = this.layerName_;
  46453. var objectName, feature;
  46454. for (objectName in topoJSONFeatures) {
  46455. if (this.layers_ && this.layers_.indexOf(objectName) == -1) {
  46456. continue;
  46457. }
  46458. if (topoJSONFeatures[objectName].type === 'GeometryCollection') {
  46459. feature = /** @type {TopoJSONGeometryCollection} */
  46460. (topoJSONFeatures[objectName]);
  46461. features.push.apply(features,
  46462. ol.format.TopoJSON.readFeaturesFromGeometryCollection_(
  46463. feature, arcs, scale, translate, property, objectName, opt_options));
  46464. } else {
  46465. feature = /** @type {TopoJSONGeometry} */
  46466. (topoJSONFeatures[objectName]);
  46467. features.push(ol.format.TopoJSON.readFeatureFromGeometry_(
  46468. feature, arcs, scale, translate, property, objectName, opt_options));
  46469. }
  46470. }
  46471. return features;
  46472. } else {
  46473. return [];
  46474. }
  46475. };
  46476. /**
  46477. * Apply a linear transform to array of arcs. The provided array of arcs is
  46478. * modified in place.
  46479. *
  46480. * @param {Array.<Array.<ol.Coordinate>>} arcs Array of arcs.
  46481. * @param {Array.<number>} scale Scale for each dimension.
  46482. * @param {Array.<number>} translate Translation for each dimension.
  46483. * @private
  46484. */
  46485. ol.format.TopoJSON.transformArcs_ = function(arcs, scale, translate) {
  46486. var i, ii;
  46487. for (i = 0, ii = arcs.length; i < ii; ++i) {
  46488. ol.format.TopoJSON.transformArc_(arcs[i], scale, translate);
  46489. }
  46490. };
  46491. /**
  46492. * Apply a linear transform to an arc. The provided arc is modified in place.
  46493. *
  46494. * @param {Array.<ol.Coordinate>} arc Arc.
  46495. * @param {Array.<number>} scale Scale for each dimension.
  46496. * @param {Array.<number>} translate Translation for each dimension.
  46497. * @private
  46498. */
  46499. ol.format.TopoJSON.transformArc_ = function(arc, scale, translate) {
  46500. var x = 0;
  46501. var y = 0;
  46502. var vertex;
  46503. var i, ii;
  46504. for (i = 0, ii = arc.length; i < ii; ++i) {
  46505. vertex = arc[i];
  46506. x += vertex[0];
  46507. y += vertex[1];
  46508. vertex[0] = x;
  46509. vertex[1] = y;
  46510. ol.format.TopoJSON.transformVertex_(vertex, scale, translate);
  46511. }
  46512. };
  46513. /**
  46514. * Apply a linear transform to a vertex. The provided vertex is modified in
  46515. * place.
  46516. *
  46517. * @param {ol.Coordinate} vertex Vertex.
  46518. * @param {Array.<number>} scale Scale for each dimension.
  46519. * @param {Array.<number>} translate Translation for each dimension.
  46520. * @private
  46521. */
  46522. ol.format.TopoJSON.transformVertex_ = function(vertex, scale, translate) {
  46523. vertex[0] = vertex[0] * scale[0] + translate[0];
  46524. vertex[1] = vertex[1] * scale[1] + translate[1];
  46525. };
  46526. /**
  46527. * Read the projection from a TopoJSON source.
  46528. *
  46529. * @param {Document|Node|Object|string} object Source.
  46530. * @return {ol.proj.Projection} Projection.
  46531. * @override
  46532. * @api
  46533. */
  46534. ol.format.TopoJSON.prototype.readProjection;
  46535. /**
  46536. * @inheritDoc
  46537. */
  46538. ol.format.TopoJSON.prototype.readProjectionFromObject = function(object) {
  46539. return this.defaultDataProjection;
  46540. };
  46541. /**
  46542. * @const
  46543. * @private
  46544. * @type {Object.<string, function(TopoJSONGeometry, Array, ...Array): ol.geom.Geometry>}
  46545. */
  46546. ol.format.TopoJSON.GEOMETRY_READERS_ = {
  46547. 'Point': ol.format.TopoJSON.readPointGeometry_,
  46548. 'LineString': ol.format.TopoJSON.readLineStringGeometry_,
  46549. 'Polygon': ol.format.TopoJSON.readPolygonGeometry_,
  46550. 'MultiPoint': ol.format.TopoJSON.readMultiPointGeometry_,
  46551. 'MultiLineString': ol.format.TopoJSON.readMultiLineStringGeometry_,
  46552. 'MultiPolygon': ol.format.TopoJSON.readMultiPolygonGeometry_
  46553. };
  46554. /**
  46555. * Not implemented.
  46556. * @inheritDoc
  46557. */
  46558. ol.format.TopoJSON.prototype.writeFeatureObject = function(feature, opt_options) {};
  46559. /**
  46560. * Not implemented.
  46561. * @inheritDoc
  46562. */
  46563. ol.format.TopoJSON.prototype.writeFeaturesObject = function(features, opt_options) {};
  46564. /**
  46565. * Not implemented.
  46566. * @inheritDoc
  46567. */
  46568. ol.format.TopoJSON.prototype.writeGeometryObject = function(geometry, opt_options) {};
  46569. /**
  46570. * Not implemented.
  46571. * @override
  46572. */
  46573. ol.format.TopoJSON.prototype.readGeometryFromObject = function() {};
  46574. /**
  46575. * Not implemented.
  46576. * @override
  46577. */
  46578. ol.format.TopoJSON.prototype.readFeatureFromObject = function() {};
  46579. goog.provide('ol.format.WFS');
  46580. goog.require('ol');
  46581. goog.require('ol.asserts');
  46582. goog.require('ol.format.GML2');
  46583. goog.require('ol.format.GML3');
  46584. goog.require('ol.format.GMLBase');
  46585. goog.require('ol.format.filter');
  46586. goog.require('ol.format.XMLFeature');
  46587. goog.require('ol.format.XSD');
  46588. goog.require('ol.geom.Geometry');
  46589. goog.require('ol.obj');
  46590. goog.require('ol.proj');
  46591. goog.require('ol.xml');
  46592. /**
  46593. * @classdesc
  46594. * Feature format for reading and writing data in the WFS format.
  46595. * By default, supports WFS version 1.1.0. You can pass a GML format
  46596. * as option if you want to read a WFS that contains GML2 (WFS 1.0.0).
  46597. * Also see {@link ol.format.GMLBase} which is used by this format.
  46598. *
  46599. * @constructor
  46600. * @param {olx.format.WFSOptions=} opt_options
  46601. * Optional configuration object.
  46602. * @extends {ol.format.XMLFeature}
  46603. * @api
  46604. */
  46605. ol.format.WFS = function(opt_options) {
  46606. var options = opt_options ? opt_options : {};
  46607. /**
  46608. * @private
  46609. * @type {Array.<string>|string|undefined}
  46610. */
  46611. this.featureType_ = options.featureType;
  46612. /**
  46613. * @private
  46614. * @type {Object.<string, string>|string|undefined}
  46615. */
  46616. this.featureNS_ = options.featureNS;
  46617. /**
  46618. * @private
  46619. * @type {ol.format.GMLBase}
  46620. */
  46621. this.gmlFormat_ = options.gmlFormat ?
  46622. options.gmlFormat : new ol.format.GML3();
  46623. /**
  46624. * @private
  46625. * @type {string}
  46626. */
  46627. this.schemaLocation_ = options.schemaLocation ?
  46628. options.schemaLocation :
  46629. ol.format.WFS.SCHEMA_LOCATIONS[ol.format.WFS.DEFAULT_VERSION];
  46630. ol.format.XMLFeature.call(this);
  46631. };
  46632. ol.inherits(ol.format.WFS, ol.format.XMLFeature);
  46633. /**
  46634. * @const
  46635. * @type {string}
  46636. */
  46637. ol.format.WFS.FEATURE_PREFIX = 'feature';
  46638. /**
  46639. * @const
  46640. * @type {string}
  46641. */
  46642. ol.format.WFS.XMLNS = 'http://www.w3.org/2000/xmlns/';
  46643. /**
  46644. * @const
  46645. * @type {string}
  46646. */
  46647. ol.format.WFS.OGCNS = 'http://www.opengis.net/ogc';
  46648. /**
  46649. * @const
  46650. * @type {string}
  46651. */
  46652. ol.format.WFS.WFSNS = 'http://www.opengis.net/wfs';
  46653. /**
  46654. * @const
  46655. * @type {string}
  46656. */
  46657. ol.format.WFS.FESNS = 'http://www.opengis.net/fes';
  46658. /**
  46659. * @const
  46660. * @type {Object.<string, string>}
  46661. */
  46662. ol.format.WFS.SCHEMA_LOCATIONS = {
  46663. '1.1.0': 'http://www.opengis.net/wfs ' +
  46664. 'http://schemas.opengis.net/wfs/1.1.0/wfs.xsd',
  46665. '1.0.0': 'http://www.opengis.net/wfs ' +
  46666. 'http://schemas.opengis.net/wfs/1.0.0/wfs.xsd'
  46667. };
  46668. /**
  46669. * @const
  46670. * @type {string}
  46671. */
  46672. ol.format.WFS.DEFAULT_VERSION = '1.1.0';
  46673. /**
  46674. * Read all features from a WFS FeatureCollection.
  46675. *
  46676. * @function
  46677. * @param {Document|Node|Object|string} source Source.
  46678. * @param {olx.format.ReadOptions=} opt_options Read options.
  46679. * @return {Array.<ol.Feature>} Features.
  46680. * @api
  46681. */
  46682. ol.format.WFS.prototype.readFeatures;
  46683. /**
  46684. * @inheritDoc
  46685. */
  46686. ol.format.WFS.prototype.readFeaturesFromNode = function(node, opt_options) {
  46687. var context = /** @type {ol.XmlNodeStackItem} */ ({
  46688. 'featureType': this.featureType_,
  46689. 'featureNS': this.featureNS_
  46690. });
  46691. ol.obj.assign(context, this.getReadOptions(node,
  46692. opt_options ? opt_options : {}));
  46693. var objectStack = [context];
  46694. this.gmlFormat_.FEATURE_COLLECTION_PARSERS[ol.format.GMLBase.GMLNS][
  46695. 'featureMember'] =
  46696. ol.xml.makeArrayPusher(ol.format.GMLBase.prototype.readFeaturesInternal);
  46697. var features = ol.xml.pushParseAndPop([],
  46698. this.gmlFormat_.FEATURE_COLLECTION_PARSERS, node,
  46699. objectStack, this.gmlFormat_);
  46700. if (!features) {
  46701. features = [];
  46702. }
  46703. return features;
  46704. };
  46705. /**
  46706. * Read transaction response of the source.
  46707. *
  46708. * @param {Document|Node|Object|string} source Source.
  46709. * @return {ol.WFSTransactionResponse|undefined} Transaction response.
  46710. * @api
  46711. */
  46712. ol.format.WFS.prototype.readTransactionResponse = function(source) {
  46713. if (ol.xml.isDocument(source)) {
  46714. return this.readTransactionResponseFromDocument(
  46715. /** @type {Document} */ (source));
  46716. } else if (ol.xml.isNode(source)) {
  46717. return this.readTransactionResponseFromNode(/** @type {Node} */ (source));
  46718. } else if (typeof source === 'string') {
  46719. var doc = ol.xml.parse(source);
  46720. return this.readTransactionResponseFromDocument(doc);
  46721. } else {
  46722. return undefined;
  46723. }
  46724. };
  46725. /**
  46726. * Read feature collection metadata of the source.
  46727. *
  46728. * @param {Document|Node|Object|string} source Source.
  46729. * @return {ol.WFSFeatureCollectionMetadata|undefined}
  46730. * FeatureCollection metadata.
  46731. * @api
  46732. */
  46733. ol.format.WFS.prototype.readFeatureCollectionMetadata = function(source) {
  46734. if (ol.xml.isDocument(source)) {
  46735. return this.readFeatureCollectionMetadataFromDocument(
  46736. /** @type {Document} */ (source));
  46737. } else if (ol.xml.isNode(source)) {
  46738. return this.readFeatureCollectionMetadataFromNode(
  46739. /** @type {Node} */ (source));
  46740. } else if (typeof source === 'string') {
  46741. var doc = ol.xml.parse(source);
  46742. return this.readFeatureCollectionMetadataFromDocument(doc);
  46743. } else {
  46744. return undefined;
  46745. }
  46746. };
  46747. /**
  46748. * @param {Document} doc Document.
  46749. * @return {ol.WFSFeatureCollectionMetadata|undefined}
  46750. * FeatureCollection metadata.
  46751. */
  46752. ol.format.WFS.prototype.readFeatureCollectionMetadataFromDocument = function(doc) {
  46753. for (var n = doc.firstChild; n; n = n.nextSibling) {
  46754. if (n.nodeType == Node.ELEMENT_NODE) {
  46755. return this.readFeatureCollectionMetadataFromNode(n);
  46756. }
  46757. }
  46758. return undefined;
  46759. };
  46760. /**
  46761. * @const
  46762. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  46763. * @private
  46764. */
  46765. ol.format.WFS.FEATURE_COLLECTION_PARSERS_ = {
  46766. 'http://www.opengis.net/gml': {
  46767. 'boundedBy': ol.xml.makeObjectPropertySetter(
  46768. ol.format.GMLBase.prototype.readGeometryElement, 'bounds')
  46769. }
  46770. };
  46771. /**
  46772. * @param {Node} node Node.
  46773. * @return {ol.WFSFeatureCollectionMetadata|undefined}
  46774. * FeatureCollection metadata.
  46775. */
  46776. ol.format.WFS.prototype.readFeatureCollectionMetadataFromNode = function(node) {
  46777. var result = {};
  46778. var value = ol.format.XSD.readNonNegativeIntegerString(
  46779. node.getAttribute('numberOfFeatures'));
  46780. result['numberOfFeatures'] = value;
  46781. return ol.xml.pushParseAndPop(
  46782. /** @type {ol.WFSFeatureCollectionMetadata} */ (result),
  46783. ol.format.WFS.FEATURE_COLLECTION_PARSERS_, node, [], this.gmlFormat_);
  46784. };
  46785. /**
  46786. * @const
  46787. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  46788. * @private
  46789. */
  46790. ol.format.WFS.TRANSACTION_SUMMARY_PARSERS_ = {
  46791. 'http://www.opengis.net/wfs': {
  46792. 'totalInserted': ol.xml.makeObjectPropertySetter(
  46793. ol.format.XSD.readNonNegativeInteger),
  46794. 'totalUpdated': ol.xml.makeObjectPropertySetter(
  46795. ol.format.XSD.readNonNegativeInteger),
  46796. 'totalDeleted': ol.xml.makeObjectPropertySetter(
  46797. ol.format.XSD.readNonNegativeInteger)
  46798. }
  46799. };
  46800. /**
  46801. * @param {Node} node Node.
  46802. * @param {Array.<*>} objectStack Object stack.
  46803. * @return {Object|undefined} Transaction Summary.
  46804. * @private
  46805. */
  46806. ol.format.WFS.readTransactionSummary_ = function(node, objectStack) {
  46807. return ol.xml.pushParseAndPop(
  46808. {}, ol.format.WFS.TRANSACTION_SUMMARY_PARSERS_, node, objectStack);
  46809. };
  46810. /**
  46811. * @const
  46812. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  46813. * @private
  46814. */
  46815. ol.format.WFS.OGC_FID_PARSERS_ = {
  46816. 'http://www.opengis.net/ogc': {
  46817. 'FeatureId': ol.xml.makeArrayPusher(function(node, objectStack) {
  46818. return node.getAttribute('fid');
  46819. })
  46820. }
  46821. };
  46822. /**
  46823. * @param {Node} node Node.
  46824. * @param {Array.<*>} objectStack Object stack.
  46825. * @private
  46826. */
  46827. ol.format.WFS.fidParser_ = function(node, objectStack) {
  46828. ol.xml.parseNode(ol.format.WFS.OGC_FID_PARSERS_, node, objectStack);
  46829. };
  46830. /**
  46831. * @const
  46832. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  46833. * @private
  46834. */
  46835. ol.format.WFS.INSERT_RESULTS_PARSERS_ = {
  46836. 'http://www.opengis.net/wfs': {
  46837. 'Feature': ol.format.WFS.fidParser_
  46838. }
  46839. };
  46840. /**
  46841. * @param {Node} node Node.
  46842. * @param {Array.<*>} objectStack Object stack.
  46843. * @return {Array.<string>|undefined} Insert results.
  46844. * @private
  46845. */
  46846. ol.format.WFS.readInsertResults_ = function(node, objectStack) {
  46847. return ol.xml.pushParseAndPop(
  46848. [], ol.format.WFS.INSERT_RESULTS_PARSERS_, node, objectStack);
  46849. };
  46850. /**
  46851. * @const
  46852. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  46853. * @private
  46854. */
  46855. ol.format.WFS.TRANSACTION_RESPONSE_PARSERS_ = {
  46856. 'http://www.opengis.net/wfs': {
  46857. 'TransactionSummary': ol.xml.makeObjectPropertySetter(
  46858. ol.format.WFS.readTransactionSummary_, 'transactionSummary'),
  46859. 'InsertResults': ol.xml.makeObjectPropertySetter(
  46860. ol.format.WFS.readInsertResults_, 'insertIds')
  46861. }
  46862. };
  46863. /**
  46864. * @param {Document} doc Document.
  46865. * @return {ol.WFSTransactionResponse|undefined} Transaction response.
  46866. */
  46867. ol.format.WFS.prototype.readTransactionResponseFromDocument = function(doc) {
  46868. for (var n = doc.firstChild; n; n = n.nextSibling) {
  46869. if (n.nodeType == Node.ELEMENT_NODE) {
  46870. return this.readTransactionResponseFromNode(n);
  46871. }
  46872. }
  46873. return undefined;
  46874. };
  46875. /**
  46876. * @param {Node} node Node.
  46877. * @return {ol.WFSTransactionResponse|undefined} Transaction response.
  46878. */
  46879. ol.format.WFS.prototype.readTransactionResponseFromNode = function(node) {
  46880. return ol.xml.pushParseAndPop(
  46881. /** @type {ol.WFSTransactionResponse} */({}),
  46882. ol.format.WFS.TRANSACTION_RESPONSE_PARSERS_, node, []);
  46883. };
  46884. /**
  46885. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  46886. * @private
  46887. */
  46888. ol.format.WFS.QUERY_SERIALIZERS_ = {
  46889. 'http://www.opengis.net/wfs': {
  46890. 'PropertyName': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode)
  46891. }
  46892. };
  46893. /**
  46894. * @param {Node} node Node.
  46895. * @param {ol.Feature} feature Feature.
  46896. * @param {Array.<*>} objectStack Node stack.
  46897. * @private
  46898. */
  46899. ol.format.WFS.writeFeature_ = function(node, feature, objectStack) {
  46900. var context = objectStack[objectStack.length - 1];
  46901. var featureType = context['featureType'];
  46902. var featureNS = context['featureNS'];
  46903. var gmlVersion = context['gmlVersion'];
  46904. var child = ol.xml.createElementNS(featureNS, featureType);
  46905. node.appendChild(child);
  46906. if (gmlVersion === 2) {
  46907. ol.format.GML2.prototype.writeFeatureElement(child, feature, objectStack);
  46908. } else {
  46909. ol.format.GML3.prototype.writeFeatureElement(child, feature, objectStack);
  46910. }
  46911. };
  46912. /**
  46913. * @param {Node} node Node.
  46914. * @param {number|string} fid Feature identifier.
  46915. * @param {Array.<*>} objectStack Node stack.
  46916. * @private
  46917. */
  46918. ol.format.WFS.writeOgcFidFilter_ = function(node, fid, objectStack) {
  46919. var filter = ol.xml.createElementNS(ol.format.WFS.OGCNS, 'Filter');
  46920. var child = ol.xml.createElementNS(ol.format.WFS.OGCNS, 'FeatureId');
  46921. filter.appendChild(child);
  46922. child.setAttribute('fid', fid);
  46923. node.appendChild(filter);
  46924. };
  46925. /**
  46926. * @param {string|undefined} featurePrefix The prefix of the feature.
  46927. * @param {string} featureType The type of the feature.
  46928. * @returns {string} The value of the typeName property.
  46929. * @private
  46930. */
  46931. ol.format.WFS.getTypeName_ = function(featurePrefix, featureType) {
  46932. featurePrefix = featurePrefix ? featurePrefix :
  46933. ol.format.WFS.FEATURE_PREFIX;
  46934. var prefix = featurePrefix + ':';
  46935. // The featureType already contains the prefix.
  46936. if (featureType.indexOf(prefix) === 0) {
  46937. return featureType;
  46938. } else {
  46939. return prefix + featureType;
  46940. }
  46941. };
  46942. /**
  46943. * @param {Node} node Node.
  46944. * @param {ol.Feature} feature Feature.
  46945. * @param {Array.<*>} objectStack Node stack.
  46946. * @private
  46947. */
  46948. ol.format.WFS.writeDelete_ = function(node, feature, objectStack) {
  46949. var context = objectStack[objectStack.length - 1];
  46950. ol.asserts.assert(feature.getId() !== undefined, 26); // Features must have an id set
  46951. var featureType = context['featureType'];
  46952. var featurePrefix = context['featurePrefix'];
  46953. var featureNS = context['featureNS'];
  46954. var typeName = ol.format.WFS.getTypeName_(featurePrefix, featureType);
  46955. node.setAttribute('typeName', typeName);
  46956. ol.xml.setAttributeNS(node, ol.format.WFS.XMLNS, 'xmlns:' + featurePrefix,
  46957. featureNS);
  46958. var fid = feature.getId();
  46959. if (fid !== undefined) {
  46960. ol.format.WFS.writeOgcFidFilter_(node, fid, objectStack);
  46961. }
  46962. };
  46963. /**
  46964. * @param {Node} node Node.
  46965. * @param {ol.Feature} feature Feature.
  46966. * @param {Array.<*>} objectStack Node stack.
  46967. * @private
  46968. */
  46969. ol.format.WFS.writeUpdate_ = function(node, feature, objectStack) {
  46970. var context = objectStack[objectStack.length - 1];
  46971. ol.asserts.assert(feature.getId() !== undefined, 27); // Features must have an id set
  46972. var featureType = context['featureType'];
  46973. var featurePrefix = context['featurePrefix'];
  46974. var featureNS = context['featureNS'];
  46975. var typeName = ol.format.WFS.getTypeName_(featurePrefix, featureType);
  46976. node.setAttribute('typeName', typeName);
  46977. ol.xml.setAttributeNS(node, ol.format.WFS.XMLNS, 'xmlns:' + featurePrefix,
  46978. featureNS);
  46979. var fid = feature.getId();
  46980. if (fid !== undefined) {
  46981. var keys = feature.getKeys();
  46982. var values = [];
  46983. for (var i = 0, ii = keys.length; i < ii; i++) {
  46984. var value = feature.get(keys[i]);
  46985. if (value !== undefined) {
  46986. values.push({name: keys[i], value: value});
  46987. }
  46988. }
  46989. ol.xml.pushSerializeAndPop(/** @type {ol.XmlNodeStackItem} */ (
  46990. {'gmlVersion': context['gmlVersion'], node: node,
  46991. 'hasZ': context['hasZ'], 'srsName': context['srsName']}),
  46992. ol.format.WFS.TRANSACTION_SERIALIZERS_,
  46993. ol.xml.makeSimpleNodeFactory('Property'), values,
  46994. objectStack);
  46995. ol.format.WFS.writeOgcFidFilter_(node, fid, objectStack);
  46996. }
  46997. };
  46998. /**
  46999. * @param {Node} node Node.
  47000. * @param {Object} pair Property name and value.
  47001. * @param {Array.<*>} objectStack Node stack.
  47002. * @private
  47003. */
  47004. ol.format.WFS.writeProperty_ = function(node, pair, objectStack) {
  47005. var name = ol.xml.createElementNS(ol.format.WFS.WFSNS, 'Name');
  47006. var context = objectStack[objectStack.length - 1];
  47007. var gmlVersion = context['gmlVersion'];
  47008. node.appendChild(name);
  47009. ol.format.XSD.writeStringTextNode(name, pair.name);
  47010. if (pair.value !== undefined && pair.value !== null) {
  47011. var value = ol.xml.createElementNS(ol.format.WFS.WFSNS, 'Value');
  47012. node.appendChild(value);
  47013. if (pair.value instanceof ol.geom.Geometry) {
  47014. if (gmlVersion === 2) {
  47015. ol.format.GML2.prototype.writeGeometryElement(value,
  47016. pair.value, objectStack);
  47017. } else {
  47018. ol.format.GML3.prototype.writeGeometryElement(value,
  47019. pair.value, objectStack);
  47020. }
  47021. } else {
  47022. ol.format.XSD.writeStringTextNode(value, pair.value);
  47023. }
  47024. }
  47025. };
  47026. /**
  47027. * @param {Node} node Node.
  47028. * @param {{vendorId: string, safeToIgnore: boolean, value: string}}
  47029. * nativeElement The native element.
  47030. * @param {Array.<*>} objectStack Node stack.
  47031. * @private
  47032. */
  47033. ol.format.WFS.writeNative_ = function(node, nativeElement, objectStack) {
  47034. if (nativeElement.vendorId) {
  47035. node.setAttribute('vendorId', nativeElement.vendorId);
  47036. }
  47037. if (nativeElement.safeToIgnore !== undefined) {
  47038. node.setAttribute('safeToIgnore', nativeElement.safeToIgnore);
  47039. }
  47040. if (nativeElement.value !== undefined) {
  47041. ol.format.XSD.writeStringTextNode(node, nativeElement.value);
  47042. }
  47043. };
  47044. /**
  47045. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  47046. * @private
  47047. */
  47048. ol.format.WFS.TRANSACTION_SERIALIZERS_ = {
  47049. 'http://www.opengis.net/wfs': {
  47050. 'Insert': ol.xml.makeChildAppender(ol.format.WFS.writeFeature_),
  47051. 'Update': ol.xml.makeChildAppender(ol.format.WFS.writeUpdate_),
  47052. 'Delete': ol.xml.makeChildAppender(ol.format.WFS.writeDelete_),
  47053. 'Property': ol.xml.makeChildAppender(ol.format.WFS.writeProperty_),
  47054. 'Native': ol.xml.makeChildAppender(ol.format.WFS.writeNative_)
  47055. }
  47056. };
  47057. /**
  47058. * @param {Node} node Node.
  47059. * @param {string} featureType Feature type.
  47060. * @param {Array.<*>} objectStack Node stack.
  47061. * @private
  47062. */
  47063. ol.format.WFS.writeQuery_ = function(node, featureType, objectStack) {
  47064. var context = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  47065. var featurePrefix = context['featurePrefix'];
  47066. var featureNS = context['featureNS'];
  47067. var propertyNames = context['propertyNames'];
  47068. var srsName = context['srsName'];
  47069. var typeName;
  47070. // If feature prefix is not defined, we must not use the default prefix.
  47071. if (featurePrefix) {
  47072. typeName = ol.format.WFS.getTypeName_(featurePrefix, featureType);
  47073. } else {
  47074. typeName = featureType;
  47075. }
  47076. node.setAttribute('typeName', typeName);
  47077. if (srsName) {
  47078. node.setAttribute('srsName', srsName);
  47079. }
  47080. if (featureNS) {
  47081. ol.xml.setAttributeNS(node, ol.format.WFS.XMLNS, 'xmlns:' + featurePrefix,
  47082. featureNS);
  47083. }
  47084. var item = /** @type {ol.XmlNodeStackItem} */ (ol.obj.assign({}, context));
  47085. item.node = node;
  47086. ol.xml.pushSerializeAndPop(item,
  47087. ol.format.WFS.QUERY_SERIALIZERS_,
  47088. ol.xml.makeSimpleNodeFactory('PropertyName'), propertyNames,
  47089. objectStack);
  47090. var filter = context['filter'];
  47091. if (filter) {
  47092. var child = ol.xml.createElementNS(ol.format.WFS.OGCNS, 'Filter');
  47093. node.appendChild(child);
  47094. ol.format.WFS.writeFilterCondition_(child, filter, objectStack);
  47095. }
  47096. };
  47097. /**
  47098. * @param {Node} node Node.
  47099. * @param {ol.format.filter.Filter} filter Filter.
  47100. * @param {Array.<*>} objectStack Node stack.
  47101. * @private
  47102. */
  47103. ol.format.WFS.writeFilterCondition_ = function(node, filter, objectStack) {
  47104. /** @type {ol.XmlNodeStackItem} */
  47105. var item = {node: node};
  47106. ol.xml.pushSerializeAndPop(item,
  47107. ol.format.WFS.GETFEATURE_SERIALIZERS_,
  47108. ol.xml.makeSimpleNodeFactory(filter.getTagName()),
  47109. [filter], objectStack);
  47110. };
  47111. /**
  47112. * @param {Node} node Node.
  47113. * @param {ol.format.filter.Bbox} filter Filter.
  47114. * @param {Array.<*>} objectStack Node stack.
  47115. * @private
  47116. */
  47117. ol.format.WFS.writeBboxFilter_ = function(node, filter, objectStack) {
  47118. var context = objectStack[objectStack.length - 1];
  47119. context['srsName'] = filter.srsName;
  47120. ol.format.WFS.writeOgcPropertyName_(node, filter.geometryName);
  47121. ol.format.GML3.prototype.writeGeometryElement(node, filter.extent, objectStack);
  47122. };
  47123. /**
  47124. * @param {Node} node Node.
  47125. * @param {ol.format.filter.Intersects} filter Filter.
  47126. * @param {Array.<*>} objectStack Node stack.
  47127. * @private
  47128. */
  47129. ol.format.WFS.writeIntersectsFilter_ = function(node, filter, objectStack) {
  47130. var context = objectStack[objectStack.length - 1];
  47131. context['srsName'] = filter.srsName;
  47132. ol.format.WFS.writeOgcPropertyName_(node, filter.geometryName);
  47133. ol.format.GML3.prototype.writeGeometryElement(node, filter.geometry, objectStack);
  47134. };
  47135. /**
  47136. * @param {Node} node Node.
  47137. * @param {ol.format.filter.Within} filter Filter.
  47138. * @param {Array.<*>} objectStack Node stack.
  47139. * @private
  47140. */
  47141. ol.format.WFS.writeWithinFilter_ = function(node, filter, objectStack) {
  47142. var context = objectStack[objectStack.length - 1];
  47143. context['srsName'] = filter.srsName;
  47144. ol.format.WFS.writeOgcPropertyName_(node, filter.geometryName);
  47145. ol.format.GML3.prototype.writeGeometryElement(node, filter.geometry, objectStack);
  47146. };
  47147. /**
  47148. * @param {Node} node Node.
  47149. * @param {ol.format.filter.During} filter Filter.
  47150. * @param {Array.<*>} objectStack Node stack.
  47151. * @private
  47152. */
  47153. ol.format.WFS.writeDuringFilter_ = function(node, filter, objectStack) {
  47154. var valueReference = ol.xml.createElementNS(ol.format.WFS.FESNS, 'ValueReference');
  47155. ol.format.XSD.writeStringTextNode(valueReference, filter.propertyName);
  47156. node.appendChild(valueReference);
  47157. var timePeriod = ol.xml.createElementNS(ol.format.GMLBase.GMLNS, 'TimePeriod');
  47158. node.appendChild(timePeriod);
  47159. var begin = ol.xml.createElementNS(ol.format.GMLBase.GMLNS, 'begin');
  47160. timePeriod.appendChild(begin);
  47161. ol.format.WFS.writeTimeInstant_(begin, filter.begin);
  47162. var end = ol.xml.createElementNS(ol.format.GMLBase.GMLNS, 'end');
  47163. timePeriod.appendChild(end);
  47164. ol.format.WFS.writeTimeInstant_(end, filter.end);
  47165. };
  47166. /**
  47167. * @param {Node} node Node.
  47168. * @param {ol.format.filter.LogicalNary} filter Filter.
  47169. * @param {Array.<*>} objectStack Node stack.
  47170. * @private
  47171. */
  47172. ol.format.WFS.writeLogicalFilter_ = function(node, filter, objectStack) {
  47173. /** @type {ol.XmlNodeStackItem} */
  47174. var item = {node: node};
  47175. var conditions = filter.conditions;
  47176. for (var i = 0, ii = conditions.length; i < ii; ++i) {
  47177. var condition = conditions[i];
  47178. ol.xml.pushSerializeAndPop(item,
  47179. ol.format.WFS.GETFEATURE_SERIALIZERS_,
  47180. ol.xml.makeSimpleNodeFactory(condition.getTagName()),
  47181. [condition], objectStack);
  47182. }
  47183. };
  47184. /**
  47185. * @param {Node} node Node.
  47186. * @param {ol.format.filter.Not} filter Filter.
  47187. * @param {Array.<*>} objectStack Node stack.
  47188. * @private
  47189. */
  47190. ol.format.WFS.writeNotFilter_ = function(node, filter, objectStack) {
  47191. /** @type {ol.XmlNodeStackItem} */
  47192. var item = {node: node};
  47193. var condition = filter.condition;
  47194. ol.xml.pushSerializeAndPop(item,
  47195. ol.format.WFS.GETFEATURE_SERIALIZERS_,
  47196. ol.xml.makeSimpleNodeFactory(condition.getTagName()),
  47197. [condition], objectStack);
  47198. };
  47199. /**
  47200. * @param {Node} node Node.
  47201. * @param {ol.format.filter.ComparisonBinary} filter Filter.
  47202. * @param {Array.<*>} objectStack Node stack.
  47203. * @private
  47204. */
  47205. ol.format.WFS.writeComparisonFilter_ = function(node, filter, objectStack) {
  47206. if (filter.matchCase !== undefined) {
  47207. node.setAttribute('matchCase', filter.matchCase.toString());
  47208. }
  47209. ol.format.WFS.writeOgcPropertyName_(node, filter.propertyName);
  47210. ol.format.WFS.writeOgcLiteral_(node, '' + filter.expression);
  47211. };
  47212. /**
  47213. * @param {Node} node Node.
  47214. * @param {ol.format.filter.IsNull} filter Filter.
  47215. * @param {Array.<*>} objectStack Node stack.
  47216. * @private
  47217. */
  47218. ol.format.WFS.writeIsNullFilter_ = function(node, filter, objectStack) {
  47219. ol.format.WFS.writeOgcPropertyName_(node, filter.propertyName);
  47220. };
  47221. /**
  47222. * @param {Node} node Node.
  47223. * @param {ol.format.filter.IsBetween} filter Filter.
  47224. * @param {Array.<*>} objectStack Node stack.
  47225. * @private
  47226. */
  47227. ol.format.WFS.writeIsBetweenFilter_ = function(node, filter, objectStack) {
  47228. ol.format.WFS.writeOgcPropertyName_(node, filter.propertyName);
  47229. var lowerBoundary = ol.xml.createElementNS(ol.format.WFS.OGCNS, 'LowerBoundary');
  47230. node.appendChild(lowerBoundary);
  47231. ol.format.WFS.writeOgcLiteral_(lowerBoundary, '' + filter.lowerBoundary);
  47232. var upperBoundary = ol.xml.createElementNS(ol.format.WFS.OGCNS, 'UpperBoundary');
  47233. node.appendChild(upperBoundary);
  47234. ol.format.WFS.writeOgcLiteral_(upperBoundary, '' + filter.upperBoundary);
  47235. };
  47236. /**
  47237. * @param {Node} node Node.
  47238. * @param {ol.format.filter.IsLike} filter Filter.
  47239. * @param {Array.<*>} objectStack Node stack.
  47240. * @private
  47241. */
  47242. ol.format.WFS.writeIsLikeFilter_ = function(node, filter, objectStack) {
  47243. node.setAttribute('wildCard', filter.wildCard);
  47244. node.setAttribute('singleChar', filter.singleChar);
  47245. node.setAttribute('escapeChar', filter.escapeChar);
  47246. if (filter.matchCase !== undefined) {
  47247. node.setAttribute('matchCase', filter.matchCase.toString());
  47248. }
  47249. ol.format.WFS.writeOgcPropertyName_(node, filter.propertyName);
  47250. ol.format.WFS.writeOgcLiteral_(node, '' + filter.pattern);
  47251. };
  47252. /**
  47253. * @param {string} tagName Tag name.
  47254. * @param {Node} node Node.
  47255. * @param {string} value Value.
  47256. * @private
  47257. */
  47258. ol.format.WFS.writeOgcExpression_ = function(tagName, node, value) {
  47259. var property = ol.xml.createElementNS(ol.format.WFS.OGCNS, tagName);
  47260. ol.format.XSD.writeStringTextNode(property, value);
  47261. node.appendChild(property);
  47262. };
  47263. /**
  47264. * @param {Node} node Node.
  47265. * @param {string} value PropertyName value.
  47266. * @private
  47267. */
  47268. ol.format.WFS.writeOgcPropertyName_ = function(node, value) {
  47269. ol.format.WFS.writeOgcExpression_('PropertyName', node, value);
  47270. };
  47271. /**
  47272. * @param {Node} node Node.
  47273. * @param {string} value PropertyName value.
  47274. * @private
  47275. */
  47276. ol.format.WFS.writeOgcLiteral_ = function(node, value) {
  47277. ol.format.WFS.writeOgcExpression_('Literal', node, value);
  47278. };
  47279. /**
  47280. * @param {Node} node Node.
  47281. * @param {string} time PropertyName value.
  47282. * @private
  47283. */
  47284. ol.format.WFS.writeTimeInstant_ = function(node, time) {
  47285. var timeInstant = ol.xml.createElementNS(ol.format.GMLBase.GMLNS, 'TimeInstant');
  47286. node.appendChild(timeInstant);
  47287. var timePosition = ol.xml.createElementNS(ol.format.GMLBase.GMLNS, 'timePosition');
  47288. timeInstant.appendChild(timePosition);
  47289. ol.format.XSD.writeStringTextNode(timePosition, time);
  47290. };
  47291. /**
  47292. * @type {Object.<string, Object.<string, ol.XmlSerializer>>}
  47293. * @private
  47294. */
  47295. ol.format.WFS.GETFEATURE_SERIALIZERS_ = {
  47296. 'http://www.opengis.net/wfs': {
  47297. 'Query': ol.xml.makeChildAppender(ol.format.WFS.writeQuery_)
  47298. },
  47299. 'http://www.opengis.net/ogc': {
  47300. 'During': ol.xml.makeChildAppender(ol.format.WFS.writeDuringFilter_),
  47301. 'And': ol.xml.makeChildAppender(ol.format.WFS.writeLogicalFilter_),
  47302. 'Or': ol.xml.makeChildAppender(ol.format.WFS.writeLogicalFilter_),
  47303. 'Not': ol.xml.makeChildAppender(ol.format.WFS.writeNotFilter_),
  47304. 'BBOX': ol.xml.makeChildAppender(ol.format.WFS.writeBboxFilter_),
  47305. 'Intersects': ol.xml.makeChildAppender(ol.format.WFS.writeIntersectsFilter_),
  47306. 'Within': ol.xml.makeChildAppender(ol.format.WFS.writeWithinFilter_),
  47307. 'PropertyIsEqualTo': ol.xml.makeChildAppender(ol.format.WFS.writeComparisonFilter_),
  47308. 'PropertyIsNotEqualTo': ol.xml.makeChildAppender(ol.format.WFS.writeComparisonFilter_),
  47309. 'PropertyIsLessThan': ol.xml.makeChildAppender(ol.format.WFS.writeComparisonFilter_),
  47310. 'PropertyIsLessThanOrEqualTo': ol.xml.makeChildAppender(ol.format.WFS.writeComparisonFilter_),
  47311. 'PropertyIsGreaterThan': ol.xml.makeChildAppender(ol.format.WFS.writeComparisonFilter_),
  47312. 'PropertyIsGreaterThanOrEqualTo': ol.xml.makeChildAppender(ol.format.WFS.writeComparisonFilter_),
  47313. 'PropertyIsNull': ol.xml.makeChildAppender(ol.format.WFS.writeIsNullFilter_),
  47314. 'PropertyIsBetween': ol.xml.makeChildAppender(ol.format.WFS.writeIsBetweenFilter_),
  47315. 'PropertyIsLike': ol.xml.makeChildAppender(ol.format.WFS.writeIsLikeFilter_)
  47316. }
  47317. };
  47318. /**
  47319. * Encode filter as WFS `Filter` and return the Node.
  47320. *
  47321. * @param {ol.format.filter.Filter} filter Filter.
  47322. * @return {Node} Result.
  47323. * @api
  47324. */
  47325. ol.format.WFS.writeFilter = function(filter) {
  47326. var child = ol.xml.createElementNS(ol.format.WFS.OGCNS, 'Filter');
  47327. ol.format.WFS.writeFilterCondition_(child, filter, []);
  47328. return child;
  47329. };
  47330. /**
  47331. * @param {Node} node Node.
  47332. * @param {Array.<string>} featureTypes Feature types.
  47333. * @param {Array.<*>} objectStack Node stack.
  47334. * @private
  47335. */
  47336. ol.format.WFS.writeGetFeature_ = function(node, featureTypes, objectStack) {
  47337. var context = /** @type {Object} */ (objectStack[objectStack.length - 1]);
  47338. var item = /** @type {ol.XmlNodeStackItem} */ (ol.obj.assign({}, context));
  47339. item.node = node;
  47340. ol.xml.pushSerializeAndPop(item,
  47341. ol.format.WFS.GETFEATURE_SERIALIZERS_,
  47342. ol.xml.makeSimpleNodeFactory('Query'), featureTypes,
  47343. objectStack);
  47344. };
  47345. /**
  47346. * Encode format as WFS `GetFeature` and return the Node.
  47347. *
  47348. * @param {olx.format.WFSWriteGetFeatureOptions} options Options.
  47349. * @return {Node} Result.
  47350. * @api
  47351. */
  47352. ol.format.WFS.prototype.writeGetFeature = function(options) {
  47353. var node = ol.xml.createElementNS(ol.format.WFS.WFSNS, 'GetFeature');
  47354. node.setAttribute('service', 'WFS');
  47355. node.setAttribute('version', '1.1.0');
  47356. var filter;
  47357. if (options) {
  47358. if (options.handle) {
  47359. node.setAttribute('handle', options.handle);
  47360. }
  47361. if (options.outputFormat) {
  47362. node.setAttribute('outputFormat', options.outputFormat);
  47363. }
  47364. if (options.maxFeatures !== undefined) {
  47365. node.setAttribute('maxFeatures', options.maxFeatures);
  47366. }
  47367. if (options.resultType) {
  47368. node.setAttribute('resultType', options.resultType);
  47369. }
  47370. if (options.startIndex !== undefined) {
  47371. node.setAttribute('startIndex', options.startIndex);
  47372. }
  47373. if (options.count !== undefined) {
  47374. node.setAttribute('count', options.count);
  47375. }
  47376. filter = options.filter;
  47377. if (options.bbox) {
  47378. ol.asserts.assert(options.geometryName,
  47379. 12); // `options.geometryName` must also be provided when `options.bbox` is set
  47380. var bbox = ol.format.filter.bbox(
  47381. /** @type {string} */ (options.geometryName), options.bbox, options.srsName);
  47382. if (filter) {
  47383. // if bbox and filter are both set, combine the two into a single filter
  47384. filter = ol.format.filter.and(filter, bbox);
  47385. } else {
  47386. filter = bbox;
  47387. }
  47388. }
  47389. }
  47390. ol.xml.setAttributeNS(node, 'http://www.w3.org/2001/XMLSchema-instance',
  47391. 'xsi:schemaLocation', this.schemaLocation_);
  47392. /** @type {ol.XmlNodeStackItem} */
  47393. var context = {
  47394. node: node,
  47395. 'srsName': options.srsName,
  47396. 'featureNS': options.featureNS ? options.featureNS : this.featureNS_,
  47397. 'featurePrefix': options.featurePrefix,
  47398. 'geometryName': options.geometryName,
  47399. 'filter': filter,
  47400. 'propertyNames': options.propertyNames ? options.propertyNames : []
  47401. };
  47402. ol.asserts.assert(Array.isArray(options.featureTypes),
  47403. 11); // `options.featureTypes` should be an Array
  47404. ol.format.WFS.writeGetFeature_(node, /** @type {!Array.<string>} */ (options.featureTypes), [context]);
  47405. return node;
  47406. };
  47407. /**
  47408. * Encode format as WFS `Transaction` and return the Node.
  47409. *
  47410. * @param {Array.<ol.Feature>} inserts The features to insert.
  47411. * @param {Array.<ol.Feature>} updates The features to update.
  47412. * @param {Array.<ol.Feature>} deletes The features to delete.
  47413. * @param {olx.format.WFSWriteTransactionOptions} options Write options.
  47414. * @return {Node} Result.
  47415. * @api
  47416. */
  47417. ol.format.WFS.prototype.writeTransaction = function(inserts, updates, deletes,
  47418. options) {
  47419. var objectStack = [];
  47420. var node = ol.xml.createElementNS(ol.format.WFS.WFSNS, 'Transaction');
  47421. var version = options.version ?
  47422. options.version : ol.format.WFS.DEFAULT_VERSION;
  47423. var gmlVersion = version === '1.0.0' ? 2 : 3;
  47424. node.setAttribute('service', 'WFS');
  47425. node.setAttribute('version', version);
  47426. var baseObj;
  47427. /** @type {ol.XmlNodeStackItem} */
  47428. var obj;
  47429. if (options) {
  47430. baseObj = options.gmlOptions ? options.gmlOptions : {};
  47431. if (options.handle) {
  47432. node.setAttribute('handle', options.handle);
  47433. }
  47434. }
  47435. var schemaLocation = ol.format.WFS.SCHEMA_LOCATIONS[version];
  47436. ol.xml.setAttributeNS(node, 'http://www.w3.org/2001/XMLSchema-instance',
  47437. 'xsi:schemaLocation', schemaLocation);
  47438. var featurePrefix = options.featurePrefix ? options.featurePrefix : ol.format.WFS.FEATURE_PREFIX;
  47439. if (inserts) {
  47440. obj = {node: node, 'featureNS': options.featureNS,
  47441. 'featureType': options.featureType, 'featurePrefix': featurePrefix,
  47442. 'gmlVersion': gmlVersion, 'hasZ': options.hasZ, 'srsName': options.srsName};
  47443. ol.obj.assign(obj, baseObj);
  47444. ol.xml.pushSerializeAndPop(obj,
  47445. ol.format.WFS.TRANSACTION_SERIALIZERS_,
  47446. ol.xml.makeSimpleNodeFactory('Insert'), inserts,
  47447. objectStack);
  47448. }
  47449. if (updates) {
  47450. obj = {node: node, 'featureNS': options.featureNS,
  47451. 'featureType': options.featureType, 'featurePrefix': featurePrefix,
  47452. 'gmlVersion': gmlVersion, 'hasZ': options.hasZ, 'srsName': options.srsName};
  47453. ol.obj.assign(obj, baseObj);
  47454. ol.xml.pushSerializeAndPop(obj,
  47455. ol.format.WFS.TRANSACTION_SERIALIZERS_,
  47456. ol.xml.makeSimpleNodeFactory('Update'), updates,
  47457. objectStack);
  47458. }
  47459. if (deletes) {
  47460. ol.xml.pushSerializeAndPop({node: node, 'featureNS': options.featureNS,
  47461. 'featureType': options.featureType, 'featurePrefix': featurePrefix,
  47462. 'gmlVersion': gmlVersion, 'srsName': options.srsName},
  47463. ol.format.WFS.TRANSACTION_SERIALIZERS_,
  47464. ol.xml.makeSimpleNodeFactory('Delete'), deletes,
  47465. objectStack);
  47466. }
  47467. if (options.nativeElements) {
  47468. ol.xml.pushSerializeAndPop({node: node, 'featureNS': options.featureNS,
  47469. 'featureType': options.featureType, 'featurePrefix': featurePrefix,
  47470. 'gmlVersion': gmlVersion, 'srsName': options.srsName},
  47471. ol.format.WFS.TRANSACTION_SERIALIZERS_,
  47472. ol.xml.makeSimpleNodeFactory('Native'), options.nativeElements,
  47473. objectStack);
  47474. }
  47475. return node;
  47476. };
  47477. /**
  47478. * Read the projection from a WFS source.
  47479. *
  47480. * @function
  47481. * @param {Document|Node|Object|string} source Source.
  47482. * @return {?ol.proj.Projection} Projection.
  47483. * @api
  47484. */
  47485. ol.format.WFS.prototype.readProjection;
  47486. /**
  47487. * @inheritDoc
  47488. */
  47489. ol.format.WFS.prototype.readProjectionFromDocument = function(doc) {
  47490. for (var n = doc.firstChild; n; n = n.nextSibling) {
  47491. if (n.nodeType == Node.ELEMENT_NODE) {
  47492. return this.readProjectionFromNode(n);
  47493. }
  47494. }
  47495. return null;
  47496. };
  47497. /**
  47498. * @inheritDoc
  47499. */
  47500. ol.format.WFS.prototype.readProjectionFromNode = function(node) {
  47501. if (node.firstElementChild &&
  47502. node.firstElementChild.firstElementChild) {
  47503. node = node.firstElementChild.firstElementChild;
  47504. for (var n = node.firstElementChild; n; n = n.nextElementSibling) {
  47505. if (!(n.childNodes.length === 0 ||
  47506. (n.childNodes.length === 1 &&
  47507. n.firstChild.nodeType === 3))) {
  47508. var objectStack = [{}];
  47509. this.gmlFormat_.readGeometryElement(n, objectStack);
  47510. return ol.proj.get(objectStack.pop().srsName);
  47511. }
  47512. }
  47513. }
  47514. return null;
  47515. };
  47516. goog.provide('ol.format.WKT');
  47517. goog.require('ol');
  47518. goog.require('ol.Feature');
  47519. goog.require('ol.format.Feature');
  47520. goog.require('ol.format.TextFeature');
  47521. goog.require('ol.geom.GeometryCollection');
  47522. goog.require('ol.geom.GeometryType');
  47523. goog.require('ol.geom.GeometryLayout');
  47524. goog.require('ol.geom.LineString');
  47525. goog.require('ol.geom.MultiLineString');
  47526. goog.require('ol.geom.MultiPoint');
  47527. goog.require('ol.geom.MultiPolygon');
  47528. goog.require('ol.geom.Point');
  47529. goog.require('ol.geom.Polygon');
  47530. goog.require('ol.geom.SimpleGeometry');
  47531. /**
  47532. * @classdesc
  47533. * Geometry format for reading and writing data in the `WellKnownText` (WKT)
  47534. * format.
  47535. *
  47536. * @constructor
  47537. * @extends {ol.format.TextFeature}
  47538. * @param {olx.format.WKTOptions=} opt_options Options.
  47539. * @api
  47540. */
  47541. ol.format.WKT = function(opt_options) {
  47542. var options = opt_options ? opt_options : {};
  47543. ol.format.TextFeature.call(this);
  47544. /**
  47545. * Split GeometryCollection into multiple features.
  47546. * @type {boolean}
  47547. * @private
  47548. */
  47549. this.splitCollection_ = options.splitCollection !== undefined ?
  47550. options.splitCollection : false;
  47551. };
  47552. ol.inherits(ol.format.WKT, ol.format.TextFeature);
  47553. /**
  47554. * @const
  47555. * @type {string}
  47556. */
  47557. ol.format.WKT.EMPTY = 'EMPTY';
  47558. /**
  47559. * @const
  47560. * @type {string}
  47561. */
  47562. ol.format.WKT.Z = 'Z';
  47563. /**
  47564. * @const
  47565. * @type {string}
  47566. */
  47567. ol.format.WKT.M = 'M';
  47568. /**
  47569. * @const
  47570. * @type {string}
  47571. */
  47572. ol.format.WKT.ZM = 'ZM';
  47573. /**
  47574. * @param {ol.geom.Point} geom Point geometry.
  47575. * @return {string} Coordinates part of Point as WKT.
  47576. * @private
  47577. */
  47578. ol.format.WKT.encodePointGeometry_ = function(geom) {
  47579. var coordinates = geom.getCoordinates();
  47580. if (coordinates.length === 0) {
  47581. return '';
  47582. }
  47583. return coordinates.join(' ');
  47584. };
  47585. /**
  47586. * @param {ol.geom.MultiPoint} geom MultiPoint geometry.
  47587. * @return {string} Coordinates part of MultiPoint as WKT.
  47588. * @private
  47589. */
  47590. ol.format.WKT.encodeMultiPointGeometry_ = function(geom) {
  47591. var array = [];
  47592. var components = geom.getPoints();
  47593. for (var i = 0, ii = components.length; i < ii; ++i) {
  47594. array.push('(' + ol.format.WKT.encodePointGeometry_(components[i]) + ')');
  47595. }
  47596. return array.join(',');
  47597. };
  47598. /**
  47599. * @param {ol.geom.GeometryCollection} geom GeometryCollection geometry.
  47600. * @return {string} Coordinates part of GeometryCollection as WKT.
  47601. * @private
  47602. */
  47603. ol.format.WKT.encodeGeometryCollectionGeometry_ = function(geom) {
  47604. var array = [];
  47605. var geoms = geom.getGeometries();
  47606. for (var i = 0, ii = geoms.length; i < ii; ++i) {
  47607. array.push(ol.format.WKT.encode_(geoms[i]));
  47608. }
  47609. return array.join(',');
  47610. };
  47611. /**
  47612. * @param {ol.geom.LineString|ol.geom.LinearRing} geom LineString geometry.
  47613. * @return {string} Coordinates part of LineString as WKT.
  47614. * @private
  47615. */
  47616. ol.format.WKT.encodeLineStringGeometry_ = function(geom) {
  47617. var coordinates = geom.getCoordinates();
  47618. var array = [];
  47619. for (var i = 0, ii = coordinates.length; i < ii; ++i) {
  47620. array.push(coordinates[i].join(' '));
  47621. }
  47622. return array.join(',');
  47623. };
  47624. /**
  47625. * @param {ol.geom.MultiLineString} geom MultiLineString geometry.
  47626. * @return {string} Coordinates part of MultiLineString as WKT.
  47627. * @private
  47628. */
  47629. ol.format.WKT.encodeMultiLineStringGeometry_ = function(geom) {
  47630. var array = [];
  47631. var components = geom.getLineStrings();
  47632. for (var i = 0, ii = components.length; i < ii; ++i) {
  47633. array.push('(' + ol.format.WKT.encodeLineStringGeometry_(
  47634. components[i]) + ')');
  47635. }
  47636. return array.join(',');
  47637. };
  47638. /**
  47639. * @param {ol.geom.Polygon} geom Polygon geometry.
  47640. * @return {string} Coordinates part of Polygon as WKT.
  47641. * @private
  47642. */
  47643. ol.format.WKT.encodePolygonGeometry_ = function(geom) {
  47644. var array = [];
  47645. var rings = geom.getLinearRings();
  47646. for (var i = 0, ii = rings.length; i < ii; ++i) {
  47647. array.push('(' + ol.format.WKT.encodeLineStringGeometry_(
  47648. rings[i]) + ')');
  47649. }
  47650. return array.join(',');
  47651. };
  47652. /**
  47653. * @param {ol.geom.MultiPolygon} geom MultiPolygon geometry.
  47654. * @return {string} Coordinates part of MultiPolygon as WKT.
  47655. * @private
  47656. */
  47657. ol.format.WKT.encodeMultiPolygonGeometry_ = function(geom) {
  47658. var array = [];
  47659. var components = geom.getPolygons();
  47660. for (var i = 0, ii = components.length; i < ii; ++i) {
  47661. array.push('(' + ol.format.WKT.encodePolygonGeometry_(
  47662. components[i]) + ')');
  47663. }
  47664. return array.join(',');
  47665. };
  47666. /**
  47667. * @param {ol.geom.SimpleGeometry} geom SimpleGeometry geometry.
  47668. * @return {string} Potential dimensional information for WKT type.
  47669. * @private
  47670. */
  47671. ol.format.WKT.encodeGeometryLayout_ = function(geom) {
  47672. var layout = geom.getLayout();
  47673. var dimInfo = '';
  47674. if (layout === ol.geom.GeometryLayout.XYZ || layout === ol.geom.GeometryLayout.XYZM) {
  47675. dimInfo += ol.format.WKT.Z;
  47676. }
  47677. if (layout === ol.geom.GeometryLayout.XYM || layout === ol.geom.GeometryLayout.XYZM) {
  47678. dimInfo += ol.format.WKT.M;
  47679. }
  47680. return dimInfo;
  47681. };
  47682. /**
  47683. * Encode a geometry as WKT.
  47684. * @param {ol.geom.Geometry} geom The geometry to encode.
  47685. * @return {string} WKT string for the geometry.
  47686. * @private
  47687. */
  47688. ol.format.WKT.encode_ = function(geom) {
  47689. var type = geom.getType();
  47690. var geometryEncoder = ol.format.WKT.GeometryEncoder_[type];
  47691. var enc = geometryEncoder(geom);
  47692. type = type.toUpperCase();
  47693. if (geom instanceof ol.geom.SimpleGeometry) {
  47694. var dimInfo = ol.format.WKT.encodeGeometryLayout_(geom);
  47695. if (dimInfo.length > 0) {
  47696. type += ' ' + dimInfo;
  47697. }
  47698. }
  47699. if (enc.length === 0) {
  47700. return type + ' ' + ol.format.WKT.EMPTY;
  47701. }
  47702. return type + '(' + enc + ')';
  47703. };
  47704. /**
  47705. * @const
  47706. * @type {Object.<string, function(ol.geom.Geometry): string>}
  47707. * @private
  47708. */
  47709. ol.format.WKT.GeometryEncoder_ = {
  47710. 'Point': ol.format.WKT.encodePointGeometry_,
  47711. 'LineString': ol.format.WKT.encodeLineStringGeometry_,
  47712. 'Polygon': ol.format.WKT.encodePolygonGeometry_,
  47713. 'MultiPoint': ol.format.WKT.encodeMultiPointGeometry_,
  47714. 'MultiLineString': ol.format.WKT.encodeMultiLineStringGeometry_,
  47715. 'MultiPolygon': ol.format.WKT.encodeMultiPolygonGeometry_,
  47716. 'GeometryCollection': ol.format.WKT.encodeGeometryCollectionGeometry_
  47717. };
  47718. /**
  47719. * Parse a WKT string.
  47720. * @param {string} wkt WKT string.
  47721. * @return {ol.geom.Geometry|undefined}
  47722. * The geometry created.
  47723. * @private
  47724. */
  47725. ol.format.WKT.prototype.parse_ = function(wkt) {
  47726. var lexer = new ol.format.WKT.Lexer(wkt);
  47727. var parser = new ol.format.WKT.Parser(lexer);
  47728. return parser.parse();
  47729. };
  47730. /**
  47731. * Read a feature from a WKT source.
  47732. *
  47733. * @function
  47734. * @param {Document|Node|Object|string} source Source.
  47735. * @param {olx.format.ReadOptions=} opt_options Read options.
  47736. * @return {ol.Feature} Feature.
  47737. * @api
  47738. */
  47739. ol.format.WKT.prototype.readFeature;
  47740. /**
  47741. * @inheritDoc
  47742. */
  47743. ol.format.WKT.prototype.readFeatureFromText = function(text, opt_options) {
  47744. var geom = this.readGeometryFromText(text, opt_options);
  47745. if (geom) {
  47746. var feature = new ol.Feature();
  47747. feature.setGeometry(geom);
  47748. return feature;
  47749. }
  47750. return null;
  47751. };
  47752. /**
  47753. * Read all features from a WKT source.
  47754. *
  47755. * @function
  47756. * @param {Document|Node|Object|string} source Source.
  47757. * @param {olx.format.ReadOptions=} opt_options Read options.
  47758. * @return {Array.<ol.Feature>} Features.
  47759. * @api
  47760. */
  47761. ol.format.WKT.prototype.readFeatures;
  47762. /**
  47763. * @inheritDoc
  47764. */
  47765. ol.format.WKT.prototype.readFeaturesFromText = function(text, opt_options) {
  47766. var geometries = [];
  47767. var geometry = this.readGeometryFromText(text, opt_options);
  47768. if (this.splitCollection_ &&
  47769. geometry.getType() == ol.geom.GeometryType.GEOMETRY_COLLECTION) {
  47770. geometries = (/** @type {ol.geom.GeometryCollection} */ (geometry))
  47771. .getGeometriesArray();
  47772. } else {
  47773. geometries = [geometry];
  47774. }
  47775. var feature, features = [];
  47776. for (var i = 0, ii = geometries.length; i < ii; ++i) {
  47777. feature = new ol.Feature();
  47778. feature.setGeometry(geometries[i]);
  47779. features.push(feature);
  47780. }
  47781. return features;
  47782. };
  47783. /**
  47784. * Read a single geometry from a WKT source.
  47785. *
  47786. * @function
  47787. * @param {Document|Node|Object|string} source Source.
  47788. * @param {olx.format.ReadOptions=} opt_options Read options.
  47789. * @return {ol.geom.Geometry} Geometry.
  47790. * @api
  47791. */
  47792. ol.format.WKT.prototype.readGeometry;
  47793. /**
  47794. * @inheritDoc
  47795. */
  47796. ol.format.WKT.prototype.readGeometryFromText = function(text, opt_options) {
  47797. var geometry = this.parse_(text);
  47798. if (geometry) {
  47799. return /** @type {ol.geom.Geometry} */ (
  47800. ol.format.Feature.transformWithOptions(geometry, false, opt_options));
  47801. } else {
  47802. return null;
  47803. }
  47804. };
  47805. /**
  47806. * Encode a feature as a WKT string.
  47807. *
  47808. * @function
  47809. * @param {ol.Feature} feature Feature.
  47810. * @param {olx.format.WriteOptions=} opt_options Write options.
  47811. * @return {string} WKT string.
  47812. * @api
  47813. */
  47814. ol.format.WKT.prototype.writeFeature;
  47815. /**
  47816. * @inheritDoc
  47817. */
  47818. ol.format.WKT.prototype.writeFeatureText = function(feature, opt_options) {
  47819. var geometry = feature.getGeometry();
  47820. if (geometry) {
  47821. return this.writeGeometryText(geometry, opt_options);
  47822. }
  47823. return '';
  47824. };
  47825. /**
  47826. * Encode an array of features as a WKT string.
  47827. *
  47828. * @function
  47829. * @param {Array.<ol.Feature>} features Features.
  47830. * @param {olx.format.WriteOptions=} opt_options Write options.
  47831. * @return {string} WKT string.
  47832. * @api
  47833. */
  47834. ol.format.WKT.prototype.writeFeatures;
  47835. /**
  47836. * @inheritDoc
  47837. */
  47838. ol.format.WKT.prototype.writeFeaturesText = function(features, opt_options) {
  47839. if (features.length == 1) {
  47840. return this.writeFeatureText(features[0], opt_options);
  47841. }
  47842. var geometries = [];
  47843. for (var i = 0, ii = features.length; i < ii; ++i) {
  47844. geometries.push(features[i].getGeometry());
  47845. }
  47846. var collection = new ol.geom.GeometryCollection(geometries);
  47847. return this.writeGeometryText(collection, opt_options);
  47848. };
  47849. /**
  47850. * Write a single geometry as a WKT string.
  47851. *
  47852. * @function
  47853. * @param {ol.geom.Geometry} geometry Geometry.
  47854. * @return {string} WKT string.
  47855. * @api
  47856. */
  47857. ol.format.WKT.prototype.writeGeometry;
  47858. /**
  47859. * @inheritDoc
  47860. */
  47861. ol.format.WKT.prototype.writeGeometryText = function(geometry, opt_options) {
  47862. return ol.format.WKT.encode_(/** @type {ol.geom.Geometry} */ (
  47863. ol.format.Feature.transformWithOptions(geometry, true, opt_options)));
  47864. };
  47865. /**
  47866. * @const
  47867. * @enum {number}
  47868. * @private
  47869. */
  47870. ol.format.WKT.TokenType_ = {
  47871. TEXT: 1,
  47872. LEFT_PAREN: 2,
  47873. RIGHT_PAREN: 3,
  47874. NUMBER: 4,
  47875. COMMA: 5,
  47876. EOF: 6
  47877. };
  47878. /**
  47879. * Class to tokenize a WKT string.
  47880. * @param {string} wkt WKT string.
  47881. * @constructor
  47882. * @protected
  47883. */
  47884. ol.format.WKT.Lexer = function(wkt) {
  47885. /**
  47886. * @type {string}
  47887. */
  47888. this.wkt = wkt;
  47889. /**
  47890. * @type {number}
  47891. * @private
  47892. */
  47893. this.index_ = -1;
  47894. };
  47895. /**
  47896. * @param {string} c Character.
  47897. * @return {boolean} Whether the character is alphabetic.
  47898. * @private
  47899. */
  47900. ol.format.WKT.Lexer.prototype.isAlpha_ = function(c) {
  47901. return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
  47902. };
  47903. /**
  47904. * @param {string} c Character.
  47905. * @param {boolean=} opt_decimal Whether the string number
  47906. * contains a dot, i.e. is a decimal number.
  47907. * @return {boolean} Whether the character is numeric.
  47908. * @private
  47909. */
  47910. ol.format.WKT.Lexer.prototype.isNumeric_ = function(c, opt_decimal) {
  47911. var decimal = opt_decimal !== undefined ? opt_decimal : false;
  47912. return c >= '0' && c <= '9' || c == '.' && !decimal;
  47913. };
  47914. /**
  47915. * @param {string} c Character.
  47916. * @return {boolean} Whether the character is whitespace.
  47917. * @private
  47918. */
  47919. ol.format.WKT.Lexer.prototype.isWhiteSpace_ = function(c) {
  47920. return c == ' ' || c == '\t' || c == '\r' || c == '\n';
  47921. };
  47922. /**
  47923. * @return {string} Next string character.
  47924. * @private
  47925. */
  47926. ol.format.WKT.Lexer.prototype.nextChar_ = function() {
  47927. return this.wkt.charAt(++this.index_);
  47928. };
  47929. /**
  47930. * Fetch and return the next token.
  47931. * @return {!ol.WKTToken} Next string token.
  47932. */
  47933. ol.format.WKT.Lexer.prototype.nextToken = function() {
  47934. var c = this.nextChar_();
  47935. var token = {position: this.index_, value: c};
  47936. if (c == '(') {
  47937. token.type = ol.format.WKT.TokenType_.LEFT_PAREN;
  47938. } else if (c == ',') {
  47939. token.type = ol.format.WKT.TokenType_.COMMA;
  47940. } else if (c == ')') {
  47941. token.type = ol.format.WKT.TokenType_.RIGHT_PAREN;
  47942. } else if (this.isNumeric_(c) || c == '-') {
  47943. token.type = ol.format.WKT.TokenType_.NUMBER;
  47944. token.value = this.readNumber_();
  47945. } else if (this.isAlpha_(c)) {
  47946. token.type = ol.format.WKT.TokenType_.TEXT;
  47947. token.value = this.readText_();
  47948. } else if (this.isWhiteSpace_(c)) {
  47949. return this.nextToken();
  47950. } else if (c === '') {
  47951. token.type = ol.format.WKT.TokenType_.EOF;
  47952. } else {
  47953. throw new Error('Unexpected character: ' + c);
  47954. }
  47955. return token;
  47956. };
  47957. /**
  47958. * @return {number} Numeric token value.
  47959. * @private
  47960. */
  47961. ol.format.WKT.Lexer.prototype.readNumber_ = function() {
  47962. var c, index = this.index_;
  47963. var decimal = false;
  47964. var scientificNotation = false;
  47965. do {
  47966. if (c == '.') {
  47967. decimal = true;
  47968. } else if (c == 'e' || c == 'E') {
  47969. scientificNotation = true;
  47970. }
  47971. c = this.nextChar_();
  47972. } while (
  47973. this.isNumeric_(c, decimal) ||
  47974. // if we haven't detected a scientific number before, 'e' or 'E'
  47975. // hint that we should continue to read
  47976. !scientificNotation && (c == 'e' || c == 'E') ||
  47977. // once we know that we have a scientific number, both '-' and '+'
  47978. // are allowed
  47979. scientificNotation && (c == '-' || c == '+')
  47980. );
  47981. return parseFloat(this.wkt.substring(index, this.index_--));
  47982. };
  47983. /**
  47984. * @return {string} String token value.
  47985. * @private
  47986. */
  47987. ol.format.WKT.Lexer.prototype.readText_ = function() {
  47988. var c, index = this.index_;
  47989. do {
  47990. c = this.nextChar_();
  47991. } while (this.isAlpha_(c));
  47992. return this.wkt.substring(index, this.index_--).toUpperCase();
  47993. };
  47994. /**
  47995. * Class to parse the tokens from the WKT string.
  47996. * @param {ol.format.WKT.Lexer} lexer The lexer.
  47997. * @constructor
  47998. * @protected
  47999. */
  48000. ol.format.WKT.Parser = function(lexer) {
  48001. /**
  48002. * @type {ol.format.WKT.Lexer}
  48003. * @private
  48004. */
  48005. this.lexer_ = lexer;
  48006. /**
  48007. * @type {ol.WKTToken}
  48008. * @private
  48009. */
  48010. this.token_;
  48011. /**
  48012. * @type {ol.geom.GeometryLayout}
  48013. * @private
  48014. */
  48015. this.layout_ = ol.geom.GeometryLayout.XY;
  48016. };
  48017. /**
  48018. * Fetch the next token form the lexer and replace the active token.
  48019. * @private
  48020. */
  48021. ol.format.WKT.Parser.prototype.consume_ = function() {
  48022. this.token_ = this.lexer_.nextToken();
  48023. };
  48024. /**
  48025. * Tests if the given type matches the type of the current token.
  48026. * @param {ol.format.WKT.TokenType_} type Token type.
  48027. * @return {boolean} Whether the token matches the given type.
  48028. */
  48029. ol.format.WKT.Parser.prototype.isTokenType = function(type) {
  48030. var isMatch = this.token_.type == type;
  48031. return isMatch;
  48032. };
  48033. /**
  48034. * If the given type matches the current token, consume it.
  48035. * @param {ol.format.WKT.TokenType_} type Token type.
  48036. * @return {boolean} Whether the token matches the given type.
  48037. */
  48038. ol.format.WKT.Parser.prototype.match = function(type) {
  48039. var isMatch = this.isTokenType(type);
  48040. if (isMatch) {
  48041. this.consume_();
  48042. }
  48043. return isMatch;
  48044. };
  48045. /**
  48046. * Try to parse the tokens provided by the lexer.
  48047. * @return {ol.geom.Geometry} The geometry.
  48048. */
  48049. ol.format.WKT.Parser.prototype.parse = function() {
  48050. this.consume_();
  48051. var geometry = this.parseGeometry_();
  48052. return geometry;
  48053. };
  48054. /**
  48055. * Try to parse the dimensional info.
  48056. * @return {ol.geom.GeometryLayout} The layout.
  48057. * @private
  48058. */
  48059. ol.format.WKT.Parser.prototype.parseGeometryLayout_ = function() {
  48060. var layout = ol.geom.GeometryLayout.XY;
  48061. var dimToken = this.token_;
  48062. if (this.isTokenType(ol.format.WKT.TokenType_.TEXT)) {
  48063. var dimInfo = dimToken.value;
  48064. if (dimInfo === ol.format.WKT.Z) {
  48065. layout = ol.geom.GeometryLayout.XYZ;
  48066. } else if (dimInfo === ol.format.WKT.M) {
  48067. layout = ol.geom.GeometryLayout.XYM;
  48068. } else if (dimInfo === ol.format.WKT.ZM) {
  48069. layout = ol.geom.GeometryLayout.XYZM;
  48070. }
  48071. if (layout !== ol.geom.GeometryLayout.XY) {
  48072. this.consume_();
  48073. }
  48074. }
  48075. return layout;
  48076. };
  48077. /**
  48078. * @return {!ol.geom.Geometry} The geometry.
  48079. * @private
  48080. */
  48081. ol.format.WKT.Parser.prototype.parseGeometry_ = function() {
  48082. var token = this.token_;
  48083. if (this.match(ol.format.WKT.TokenType_.TEXT)) {
  48084. var geomType = token.value;
  48085. this.layout_ = this.parseGeometryLayout_();
  48086. if (geomType == ol.geom.GeometryType.GEOMETRY_COLLECTION.toUpperCase()) {
  48087. var geometries = this.parseGeometryCollectionText_();
  48088. return new ol.geom.GeometryCollection(geometries);
  48089. } else {
  48090. var parser = ol.format.WKT.Parser.GeometryParser_[geomType];
  48091. var ctor = ol.format.WKT.Parser.GeometryConstructor_[geomType];
  48092. if (!parser || !ctor) {
  48093. throw new Error('Invalid geometry type: ' + geomType);
  48094. }
  48095. var coordinates = parser.call(this);
  48096. return new ctor(coordinates, this.layout_);
  48097. }
  48098. }
  48099. throw new Error(this.formatErrorMessage_());
  48100. };
  48101. /**
  48102. * @return {!Array.<ol.geom.Geometry>} A collection of geometries.
  48103. * @private
  48104. */
  48105. ol.format.WKT.Parser.prototype.parseGeometryCollectionText_ = function() {
  48106. if (this.match(ol.format.WKT.TokenType_.LEFT_PAREN)) {
  48107. var geometries = [];
  48108. do {
  48109. geometries.push(this.parseGeometry_());
  48110. } while (this.match(ol.format.WKT.TokenType_.COMMA));
  48111. if (this.match(ol.format.WKT.TokenType_.RIGHT_PAREN)) {
  48112. return geometries;
  48113. }
  48114. } else if (this.isEmptyGeometry_()) {
  48115. return [];
  48116. }
  48117. throw new Error(this.formatErrorMessage_());
  48118. };
  48119. /**
  48120. * @return {Array.<number>} All values in a point.
  48121. * @private
  48122. */
  48123. ol.format.WKT.Parser.prototype.parsePointText_ = function() {
  48124. if (this.match(ol.format.WKT.TokenType_.LEFT_PAREN)) {
  48125. var coordinates = this.parsePoint_();
  48126. if (this.match(ol.format.WKT.TokenType_.RIGHT_PAREN)) {
  48127. return coordinates;
  48128. }
  48129. } else if (this.isEmptyGeometry_()) {
  48130. return null;
  48131. }
  48132. throw new Error(this.formatErrorMessage_());
  48133. };
  48134. /**
  48135. * @return {!Array.<!Array.<number>>} All points in a linestring.
  48136. * @private
  48137. */
  48138. ol.format.WKT.Parser.prototype.parseLineStringText_ = function() {
  48139. if (this.match(ol.format.WKT.TokenType_.LEFT_PAREN)) {
  48140. var coordinates = this.parsePointList_();
  48141. if (this.match(ol.format.WKT.TokenType_.RIGHT_PAREN)) {
  48142. return coordinates;
  48143. }
  48144. } else if (this.isEmptyGeometry_()) {
  48145. return [];
  48146. }
  48147. throw new Error(this.formatErrorMessage_());
  48148. };
  48149. /**
  48150. * @return {!Array.<!Array.<number>>} All points in a polygon.
  48151. * @private
  48152. */
  48153. ol.format.WKT.Parser.prototype.parsePolygonText_ = function() {
  48154. if (this.match(ol.format.WKT.TokenType_.LEFT_PAREN)) {
  48155. var coordinates = this.parseLineStringTextList_();
  48156. if (this.match(ol.format.WKT.TokenType_.RIGHT_PAREN)) {
  48157. return coordinates;
  48158. }
  48159. } else if (this.isEmptyGeometry_()) {
  48160. return [];
  48161. }
  48162. throw new Error(this.formatErrorMessage_());
  48163. };
  48164. /**
  48165. * @return {!Array.<!Array.<number>>} All points in a multipoint.
  48166. * @private
  48167. */
  48168. ol.format.WKT.Parser.prototype.parseMultiPointText_ = function() {
  48169. if (this.match(ol.format.WKT.TokenType_.LEFT_PAREN)) {
  48170. var coordinates;
  48171. if (this.token_.type == ol.format.WKT.TokenType_.LEFT_PAREN) {
  48172. coordinates = this.parsePointTextList_();
  48173. } else {
  48174. coordinates = this.parsePointList_();
  48175. }
  48176. if (this.match(ol.format.WKT.TokenType_.RIGHT_PAREN)) {
  48177. return coordinates;
  48178. }
  48179. } else if (this.isEmptyGeometry_()) {
  48180. return [];
  48181. }
  48182. throw new Error(this.formatErrorMessage_());
  48183. };
  48184. /**
  48185. * @return {!Array.<!Array.<number>>} All linestring points
  48186. * in a multilinestring.
  48187. * @private
  48188. */
  48189. ol.format.WKT.Parser.prototype.parseMultiLineStringText_ = function() {
  48190. if (this.match(ol.format.WKT.TokenType_.LEFT_PAREN)) {
  48191. var coordinates = this.parseLineStringTextList_();
  48192. if (this.match(ol.format.WKT.TokenType_.RIGHT_PAREN)) {
  48193. return coordinates;
  48194. }
  48195. } else if (this.isEmptyGeometry_()) {
  48196. return [];
  48197. }
  48198. throw new Error(this.formatErrorMessage_());
  48199. };
  48200. /**
  48201. * @return {!Array.<!Array.<number>>} All polygon points in a multipolygon.
  48202. * @private
  48203. */
  48204. ol.format.WKT.Parser.prototype.parseMultiPolygonText_ = function() {
  48205. if (this.match(ol.format.WKT.TokenType_.LEFT_PAREN)) {
  48206. var coordinates = this.parsePolygonTextList_();
  48207. if (this.match(ol.format.WKT.TokenType_.RIGHT_PAREN)) {
  48208. return coordinates;
  48209. }
  48210. } else if (this.isEmptyGeometry_()) {
  48211. return [];
  48212. }
  48213. throw new Error(this.formatErrorMessage_());
  48214. };
  48215. /**
  48216. * @return {!Array.<number>} A point.
  48217. * @private
  48218. */
  48219. ol.format.WKT.Parser.prototype.parsePoint_ = function() {
  48220. var coordinates = [];
  48221. var dimensions = this.layout_.length;
  48222. for (var i = 0; i < dimensions; ++i) {
  48223. var token = this.token_;
  48224. if (this.match(ol.format.WKT.TokenType_.NUMBER)) {
  48225. coordinates.push(token.value);
  48226. } else {
  48227. break;
  48228. }
  48229. }
  48230. if (coordinates.length == dimensions) {
  48231. return coordinates;
  48232. }
  48233. throw new Error(this.formatErrorMessage_());
  48234. };
  48235. /**
  48236. * @return {!Array.<!Array.<number>>} An array of points.
  48237. * @private
  48238. */
  48239. ol.format.WKT.Parser.prototype.parsePointList_ = function() {
  48240. var coordinates = [this.parsePoint_()];
  48241. while (this.match(ol.format.WKT.TokenType_.COMMA)) {
  48242. coordinates.push(this.parsePoint_());
  48243. }
  48244. return coordinates;
  48245. };
  48246. /**
  48247. * @return {!Array.<!Array.<number>>} An array of points.
  48248. * @private
  48249. */
  48250. ol.format.WKT.Parser.prototype.parsePointTextList_ = function() {
  48251. var coordinates = [this.parsePointText_()];
  48252. while (this.match(ol.format.WKT.TokenType_.COMMA)) {
  48253. coordinates.push(this.parsePointText_());
  48254. }
  48255. return coordinates;
  48256. };
  48257. /**
  48258. * @return {!Array.<!Array.<number>>} An array of points.
  48259. * @private
  48260. */
  48261. ol.format.WKT.Parser.prototype.parseLineStringTextList_ = function() {
  48262. var coordinates = [this.parseLineStringText_()];
  48263. while (this.match(ol.format.WKT.TokenType_.COMMA)) {
  48264. coordinates.push(this.parseLineStringText_());
  48265. }
  48266. return coordinates;
  48267. };
  48268. /**
  48269. * @return {!Array.<!Array.<number>>} An array of points.
  48270. * @private
  48271. */
  48272. ol.format.WKT.Parser.prototype.parsePolygonTextList_ = function() {
  48273. var coordinates = [this.parsePolygonText_()];
  48274. while (this.match(ol.format.WKT.TokenType_.COMMA)) {
  48275. coordinates.push(this.parsePolygonText_());
  48276. }
  48277. return coordinates;
  48278. };
  48279. /**
  48280. * @return {boolean} Whether the token implies an empty geometry.
  48281. * @private
  48282. */
  48283. ol.format.WKT.Parser.prototype.isEmptyGeometry_ = function() {
  48284. var isEmpty = this.isTokenType(ol.format.WKT.TokenType_.TEXT) &&
  48285. this.token_.value == ol.format.WKT.EMPTY;
  48286. if (isEmpty) {
  48287. this.consume_();
  48288. }
  48289. return isEmpty;
  48290. };
  48291. /**
  48292. * Create an error message for an unexpected token error.
  48293. * @return {string} Error message.
  48294. * @private
  48295. */
  48296. ol.format.WKT.Parser.prototype.formatErrorMessage_ = function() {
  48297. return 'Unexpected `' + this.token_.value + '` at position ' +
  48298. this.token_.position + ' in `' + this.lexer_.wkt + '`';
  48299. };
  48300. /**
  48301. * @enum {function (new:ol.geom.Geometry, Array, ol.geom.GeometryLayout)}
  48302. * @private
  48303. */
  48304. ol.format.WKT.Parser.GeometryConstructor_ = {
  48305. 'POINT': ol.geom.Point,
  48306. 'LINESTRING': ol.geom.LineString,
  48307. 'POLYGON': ol.geom.Polygon,
  48308. 'MULTIPOINT': ol.geom.MultiPoint,
  48309. 'MULTILINESTRING': ol.geom.MultiLineString,
  48310. 'MULTIPOLYGON': ol.geom.MultiPolygon
  48311. };
  48312. /**
  48313. * @enum {(function(): Array)}
  48314. * @private
  48315. */
  48316. ol.format.WKT.Parser.GeometryParser_ = {
  48317. 'POINT': ol.format.WKT.Parser.prototype.parsePointText_,
  48318. 'LINESTRING': ol.format.WKT.Parser.prototype.parseLineStringText_,
  48319. 'POLYGON': ol.format.WKT.Parser.prototype.parsePolygonText_,
  48320. 'MULTIPOINT': ol.format.WKT.Parser.prototype.parseMultiPointText_,
  48321. 'MULTILINESTRING': ol.format.WKT.Parser.prototype.parseMultiLineStringText_,
  48322. 'MULTIPOLYGON': ol.format.WKT.Parser.prototype.parseMultiPolygonText_
  48323. };
  48324. goog.provide('ol.format.WMSCapabilities');
  48325. goog.require('ol');
  48326. goog.require('ol.format.XLink');
  48327. goog.require('ol.format.XML');
  48328. goog.require('ol.format.XSD');
  48329. goog.require('ol.xml');
  48330. /**
  48331. * @classdesc
  48332. * Format for reading WMS capabilities data
  48333. *
  48334. * @constructor
  48335. * @extends {ol.format.XML}
  48336. * @api
  48337. */
  48338. ol.format.WMSCapabilities = function() {
  48339. ol.format.XML.call(this);
  48340. /**
  48341. * @type {string|undefined}
  48342. */
  48343. this.version = undefined;
  48344. };
  48345. ol.inherits(ol.format.WMSCapabilities, ol.format.XML);
  48346. /**
  48347. * Read a WMS capabilities document.
  48348. *
  48349. * @function
  48350. * @param {Document|Node|string} source The XML source.
  48351. * @return {Object} An object representing the WMS capabilities.
  48352. * @api
  48353. */
  48354. ol.format.WMSCapabilities.prototype.read;
  48355. /**
  48356. * @inheritDoc
  48357. */
  48358. ol.format.WMSCapabilities.prototype.readFromDocument = function(doc) {
  48359. for (var n = doc.firstChild; n; n = n.nextSibling) {
  48360. if (n.nodeType == Node.ELEMENT_NODE) {
  48361. return this.readFromNode(n);
  48362. }
  48363. }
  48364. return null;
  48365. };
  48366. /**
  48367. * @inheritDoc
  48368. */
  48369. ol.format.WMSCapabilities.prototype.readFromNode = function(node) {
  48370. this.version = node.getAttribute('version').trim();
  48371. var wmsCapabilityObject = ol.xml.pushParseAndPop({
  48372. 'version': this.version
  48373. }, ol.format.WMSCapabilities.PARSERS_, node, []);
  48374. return wmsCapabilityObject ? wmsCapabilityObject : null;
  48375. };
  48376. /**
  48377. * @private
  48378. * @param {Node} node Node.
  48379. * @param {Array.<*>} objectStack Object stack.
  48380. * @return {Object|undefined} Attribution object.
  48381. */
  48382. ol.format.WMSCapabilities.readAttribution_ = function(node, objectStack) {
  48383. return ol.xml.pushParseAndPop(
  48384. {}, ol.format.WMSCapabilities.ATTRIBUTION_PARSERS_, node, objectStack);
  48385. };
  48386. /**
  48387. * @private
  48388. * @param {Node} node Node.
  48389. * @param {Array.<*>} objectStack Object stack.
  48390. * @return {Object} Bounding box object.
  48391. */
  48392. ol.format.WMSCapabilities.readBoundingBox_ = function(node, objectStack) {
  48393. var extent = [
  48394. ol.format.XSD.readDecimalString(node.getAttribute('minx')),
  48395. ol.format.XSD.readDecimalString(node.getAttribute('miny')),
  48396. ol.format.XSD.readDecimalString(node.getAttribute('maxx')),
  48397. ol.format.XSD.readDecimalString(node.getAttribute('maxy'))
  48398. ];
  48399. var resolutions = [
  48400. ol.format.XSD.readDecimalString(node.getAttribute('resx')),
  48401. ol.format.XSD.readDecimalString(node.getAttribute('resy'))
  48402. ];
  48403. return {
  48404. 'crs': node.getAttribute('CRS'),
  48405. 'extent': extent,
  48406. 'res': resolutions
  48407. };
  48408. };
  48409. /**
  48410. * @private
  48411. * @param {Node} node Node.
  48412. * @param {Array.<*>} objectStack Object stack.
  48413. * @return {ol.Extent|undefined} Bounding box object.
  48414. */
  48415. ol.format.WMSCapabilities.readEXGeographicBoundingBox_ = function(node, objectStack) {
  48416. var geographicBoundingBox = ol.xml.pushParseAndPop(
  48417. {},
  48418. ol.format.WMSCapabilities.EX_GEOGRAPHIC_BOUNDING_BOX_PARSERS_,
  48419. node, objectStack);
  48420. if (!geographicBoundingBox) {
  48421. return undefined;
  48422. }
  48423. var westBoundLongitude = /** @type {number|undefined} */
  48424. (geographicBoundingBox['westBoundLongitude']);
  48425. var southBoundLatitude = /** @type {number|undefined} */
  48426. (geographicBoundingBox['southBoundLatitude']);
  48427. var eastBoundLongitude = /** @type {number|undefined} */
  48428. (geographicBoundingBox['eastBoundLongitude']);
  48429. var northBoundLatitude = /** @type {number|undefined} */
  48430. (geographicBoundingBox['northBoundLatitude']);
  48431. if (westBoundLongitude === undefined || southBoundLatitude === undefined ||
  48432. eastBoundLongitude === undefined || northBoundLatitude === undefined) {
  48433. return undefined;
  48434. }
  48435. return [
  48436. westBoundLongitude, southBoundLatitude,
  48437. eastBoundLongitude, northBoundLatitude
  48438. ];
  48439. };
  48440. /**
  48441. * @param {Node} node Node.
  48442. * @param {Array.<*>} objectStack Object stack.
  48443. * @private
  48444. * @return {Object|undefined} Capability object.
  48445. */
  48446. ol.format.WMSCapabilities.readCapability_ = function(node, objectStack) {
  48447. return ol.xml.pushParseAndPop(
  48448. {}, ol.format.WMSCapabilities.CAPABILITY_PARSERS_, node, objectStack);
  48449. };
  48450. /**
  48451. * @param {Node} node Node.
  48452. * @param {Array.<*>} objectStack Object stack.
  48453. * @private
  48454. * @return {Object|undefined} Service object.
  48455. */
  48456. ol.format.WMSCapabilities.readService_ = function(node, objectStack) {
  48457. return ol.xml.pushParseAndPop(
  48458. {}, ol.format.WMSCapabilities.SERVICE_PARSERS_, node, objectStack);
  48459. };
  48460. /**
  48461. * @param {Node} node Node.
  48462. * @param {Array.<*>} objectStack Object stack.
  48463. * @private
  48464. * @return {Object|undefined} Contact information object.
  48465. */
  48466. ol.format.WMSCapabilities.readContactInformation_ = function(node, objectStack) {
  48467. return ol.xml.pushParseAndPop(
  48468. {}, ol.format.WMSCapabilities.CONTACT_INFORMATION_PARSERS_,
  48469. node, objectStack);
  48470. };
  48471. /**
  48472. * @param {Node} node Node.
  48473. * @param {Array.<*>} objectStack Object stack.
  48474. * @private
  48475. * @return {Object|undefined} Contact person object.
  48476. */
  48477. ol.format.WMSCapabilities.readContactPersonPrimary_ = function(node, objectStack) {
  48478. return ol.xml.pushParseAndPop(
  48479. {}, ol.format.WMSCapabilities.CONTACT_PERSON_PARSERS_,
  48480. node, objectStack);
  48481. };
  48482. /**
  48483. * @param {Node} node Node.
  48484. * @param {Array.<*>} objectStack Object stack.
  48485. * @private
  48486. * @return {Object|undefined} Contact address object.
  48487. */
  48488. ol.format.WMSCapabilities.readContactAddress_ = function(node, objectStack) {
  48489. return ol.xml.pushParseAndPop(
  48490. {}, ol.format.WMSCapabilities.CONTACT_ADDRESS_PARSERS_,
  48491. node, objectStack);
  48492. };
  48493. /**
  48494. * @param {Node} node Node.
  48495. * @param {Array.<*>} objectStack Object stack.
  48496. * @private
  48497. * @return {Array.<string>|undefined} Format array.
  48498. */
  48499. ol.format.WMSCapabilities.readException_ = function(node, objectStack) {
  48500. return ol.xml.pushParseAndPop(
  48501. [], ol.format.WMSCapabilities.EXCEPTION_PARSERS_, node, objectStack);
  48502. };
  48503. /**
  48504. * @param {Node} node Node.
  48505. * @param {Array.<*>} objectStack Object stack.
  48506. * @private
  48507. * @return {Object|undefined} Layer object.
  48508. */
  48509. ol.format.WMSCapabilities.readCapabilityLayer_ = function(node, objectStack) {
  48510. return ol.xml.pushParseAndPop(
  48511. {}, ol.format.WMSCapabilities.LAYER_PARSERS_, node, objectStack);
  48512. };
  48513. /**
  48514. * @private
  48515. * @param {Node} node Node.
  48516. * @param {Array.<*>} objectStack Object stack.
  48517. * @return {Object|undefined} Layer object.
  48518. */
  48519. ol.format.WMSCapabilities.readLayer_ = function(node, objectStack) {
  48520. var parentLayerObject = /** @type {Object.<string,*>} */
  48521. (objectStack[objectStack.length - 1]);
  48522. var layerObject = ol.xml.pushParseAndPop(
  48523. {}, ol.format.WMSCapabilities.LAYER_PARSERS_, node, objectStack);
  48524. if (!layerObject) {
  48525. return undefined;
  48526. }
  48527. var queryable =
  48528. ol.format.XSD.readBooleanString(node.getAttribute('queryable'));
  48529. if (queryable === undefined) {
  48530. queryable = parentLayerObject['queryable'];
  48531. }
  48532. layerObject['queryable'] = queryable !== undefined ? queryable : false;
  48533. var cascaded = ol.format.XSD.readNonNegativeIntegerString(
  48534. node.getAttribute('cascaded'));
  48535. if (cascaded === undefined) {
  48536. cascaded = parentLayerObject['cascaded'];
  48537. }
  48538. layerObject['cascaded'] = cascaded;
  48539. var opaque = ol.format.XSD.readBooleanString(node.getAttribute('opaque'));
  48540. if (opaque === undefined) {
  48541. opaque = parentLayerObject['opaque'];
  48542. }
  48543. layerObject['opaque'] = opaque !== undefined ? opaque : false;
  48544. var noSubsets =
  48545. ol.format.XSD.readBooleanString(node.getAttribute('noSubsets'));
  48546. if (noSubsets === undefined) {
  48547. noSubsets = parentLayerObject['noSubsets'];
  48548. }
  48549. layerObject['noSubsets'] = noSubsets !== undefined ? noSubsets : false;
  48550. var fixedWidth =
  48551. ol.format.XSD.readDecimalString(node.getAttribute('fixedWidth'));
  48552. if (!fixedWidth) {
  48553. fixedWidth = parentLayerObject['fixedWidth'];
  48554. }
  48555. layerObject['fixedWidth'] = fixedWidth;
  48556. var fixedHeight =
  48557. ol.format.XSD.readDecimalString(node.getAttribute('fixedHeight'));
  48558. if (!fixedHeight) {
  48559. fixedHeight = parentLayerObject['fixedHeight'];
  48560. }
  48561. layerObject['fixedHeight'] = fixedHeight;
  48562. // See 7.2.4.8
  48563. var addKeys = ['Style', 'CRS', 'AuthorityURL'];
  48564. addKeys.forEach(function(key) {
  48565. if (key in parentLayerObject) {
  48566. var childValue = layerObject[key] || [];
  48567. layerObject[key] = childValue.concat(parentLayerObject[key]);
  48568. }
  48569. });
  48570. var replaceKeys = ['EX_GeographicBoundingBox', 'BoundingBox', 'Dimension',
  48571. 'Attribution', 'MinScaleDenominator', 'MaxScaleDenominator'];
  48572. replaceKeys.forEach(function(key) {
  48573. if (!(key in layerObject)) {
  48574. var parentValue = parentLayerObject[key];
  48575. layerObject[key] = parentValue;
  48576. }
  48577. });
  48578. return layerObject;
  48579. };
  48580. /**
  48581. * @private
  48582. * @param {Node} node Node.
  48583. * @param {Array.<*>} objectStack Object stack.
  48584. * @return {Object} Dimension object.
  48585. */
  48586. ol.format.WMSCapabilities.readDimension_ = function(node, objectStack) {
  48587. var dimensionObject = {
  48588. 'name': node.getAttribute('name'),
  48589. 'units': node.getAttribute('units'),
  48590. 'unitSymbol': node.getAttribute('unitSymbol'),
  48591. 'default': node.getAttribute('default'),
  48592. 'multipleValues': ol.format.XSD.readBooleanString(
  48593. node.getAttribute('multipleValues')),
  48594. 'nearestValue': ol.format.XSD.readBooleanString(
  48595. node.getAttribute('nearestValue')),
  48596. 'current': ol.format.XSD.readBooleanString(node.getAttribute('current')),
  48597. 'values': ol.format.XSD.readString(node)
  48598. };
  48599. return dimensionObject;
  48600. };
  48601. /**
  48602. * @private
  48603. * @param {Node} node Node.
  48604. * @param {Array.<*>} objectStack Object stack.
  48605. * @return {Object|undefined} Online resource object.
  48606. */
  48607. ol.format.WMSCapabilities.readFormatOnlineresource_ = function(node, objectStack) {
  48608. return ol.xml.pushParseAndPop(
  48609. {}, ol.format.WMSCapabilities.FORMAT_ONLINERESOURCE_PARSERS_,
  48610. node, objectStack);
  48611. };
  48612. /**
  48613. * @private
  48614. * @param {Node} node Node.
  48615. * @param {Array.<*>} objectStack Object stack.
  48616. * @return {Object|undefined} Request object.
  48617. */
  48618. ol.format.WMSCapabilities.readRequest_ = function(node, objectStack) {
  48619. return ol.xml.pushParseAndPop(
  48620. {}, ol.format.WMSCapabilities.REQUEST_PARSERS_, node, objectStack);
  48621. };
  48622. /**
  48623. * @private
  48624. * @param {Node} node Node.
  48625. * @param {Array.<*>} objectStack Object stack.
  48626. * @return {Object|undefined} DCP type object.
  48627. */
  48628. ol.format.WMSCapabilities.readDCPType_ = function(node, objectStack) {
  48629. return ol.xml.pushParseAndPop(
  48630. {}, ol.format.WMSCapabilities.DCPTYPE_PARSERS_, node, objectStack);
  48631. };
  48632. /**
  48633. * @private
  48634. * @param {Node} node Node.
  48635. * @param {Array.<*>} objectStack Object stack.
  48636. * @return {Object|undefined} HTTP object.
  48637. */
  48638. ol.format.WMSCapabilities.readHTTP_ = function(node, objectStack) {
  48639. return ol.xml.pushParseAndPop(
  48640. {}, ol.format.WMSCapabilities.HTTP_PARSERS_, node, objectStack);
  48641. };
  48642. /**
  48643. * @private
  48644. * @param {Node} node Node.
  48645. * @param {Array.<*>} objectStack Object stack.
  48646. * @return {Object|undefined} Operation type object.
  48647. */
  48648. ol.format.WMSCapabilities.readOperationType_ = function(node, objectStack) {
  48649. return ol.xml.pushParseAndPop(
  48650. {}, ol.format.WMSCapabilities.OPERATIONTYPE_PARSERS_, node, objectStack);
  48651. };
  48652. /**
  48653. * @private
  48654. * @param {Node} node Node.
  48655. * @param {Array.<*>} objectStack Object stack.
  48656. * @return {Object|undefined} Online resource object.
  48657. */
  48658. ol.format.WMSCapabilities.readSizedFormatOnlineresource_ = function(node, objectStack) {
  48659. var formatOnlineresource =
  48660. ol.format.WMSCapabilities.readFormatOnlineresource_(node, objectStack);
  48661. if (formatOnlineresource) {
  48662. var size = [
  48663. ol.format.XSD.readNonNegativeIntegerString(node.getAttribute('width')),
  48664. ol.format.XSD.readNonNegativeIntegerString(node.getAttribute('height'))
  48665. ];
  48666. formatOnlineresource['size'] = size;
  48667. return formatOnlineresource;
  48668. }
  48669. return undefined;
  48670. };
  48671. /**
  48672. * @private
  48673. * @param {Node} node Node.
  48674. * @param {Array.<*>} objectStack Object stack.
  48675. * @return {Object|undefined} Authority URL object.
  48676. */
  48677. ol.format.WMSCapabilities.readAuthorityURL_ = function(node, objectStack) {
  48678. var authorityObject =
  48679. ol.format.WMSCapabilities.readFormatOnlineresource_(node, objectStack);
  48680. if (authorityObject) {
  48681. authorityObject['name'] = node.getAttribute('name');
  48682. return authorityObject;
  48683. }
  48684. return undefined;
  48685. };
  48686. /**
  48687. * @private
  48688. * @param {Node} node Node.
  48689. * @param {Array.<*>} objectStack Object stack.
  48690. * @return {Object|undefined} Metadata URL object.
  48691. */
  48692. ol.format.WMSCapabilities.readMetadataURL_ = function(node, objectStack) {
  48693. var metadataObject =
  48694. ol.format.WMSCapabilities.readFormatOnlineresource_(node, objectStack);
  48695. if (metadataObject) {
  48696. metadataObject['type'] = node.getAttribute('type');
  48697. return metadataObject;
  48698. }
  48699. return undefined;
  48700. };
  48701. /**
  48702. * @private
  48703. * @param {Node} node Node.
  48704. * @param {Array.<*>} objectStack Object stack.
  48705. * @return {Object|undefined} Style object.
  48706. */
  48707. ol.format.WMSCapabilities.readStyle_ = function(node, objectStack) {
  48708. return ol.xml.pushParseAndPop(
  48709. {}, ol.format.WMSCapabilities.STYLE_PARSERS_, node, objectStack);
  48710. };
  48711. /**
  48712. * @private
  48713. * @param {Node} node Node.
  48714. * @param {Array.<*>} objectStack Object stack.
  48715. * @return {Array.<string>|undefined} Keyword list.
  48716. */
  48717. ol.format.WMSCapabilities.readKeywordList_ = function(node, objectStack) {
  48718. return ol.xml.pushParseAndPop(
  48719. [], ol.format.WMSCapabilities.KEYWORDLIST_PARSERS_, node, objectStack);
  48720. };
  48721. /**
  48722. * @const
  48723. * @private
  48724. * @type {Array.<string>}
  48725. */
  48726. ol.format.WMSCapabilities.NAMESPACE_URIS_ = [
  48727. null,
  48728. 'http://www.opengis.net/wms'
  48729. ];
  48730. /**
  48731. * @const
  48732. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48733. * @private
  48734. */
  48735. ol.format.WMSCapabilities.PARSERS_ = ol.xml.makeStructureNS(
  48736. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48737. 'Service': ol.xml.makeObjectPropertySetter(
  48738. ol.format.WMSCapabilities.readService_),
  48739. 'Capability': ol.xml.makeObjectPropertySetter(
  48740. ol.format.WMSCapabilities.readCapability_)
  48741. });
  48742. /**
  48743. * @const
  48744. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48745. * @private
  48746. */
  48747. ol.format.WMSCapabilities.CAPABILITY_PARSERS_ = ol.xml.makeStructureNS(
  48748. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48749. 'Request': ol.xml.makeObjectPropertySetter(
  48750. ol.format.WMSCapabilities.readRequest_),
  48751. 'Exception': ol.xml.makeObjectPropertySetter(
  48752. ol.format.WMSCapabilities.readException_),
  48753. 'Layer': ol.xml.makeObjectPropertySetter(
  48754. ol.format.WMSCapabilities.readCapabilityLayer_)
  48755. });
  48756. /**
  48757. * @const
  48758. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48759. * @private
  48760. */
  48761. ol.format.WMSCapabilities.SERVICE_PARSERS_ = ol.xml.makeStructureNS(
  48762. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48763. 'Name': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48764. 'Title': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48765. 'Abstract': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48766. 'KeywordList': ol.xml.makeObjectPropertySetter(
  48767. ol.format.WMSCapabilities.readKeywordList_),
  48768. 'OnlineResource': ol.xml.makeObjectPropertySetter(
  48769. ol.format.XLink.readHref),
  48770. 'ContactInformation': ol.xml.makeObjectPropertySetter(
  48771. ol.format.WMSCapabilities.readContactInformation_),
  48772. 'Fees': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48773. 'AccessConstraints': ol.xml.makeObjectPropertySetter(
  48774. ol.format.XSD.readString),
  48775. 'LayerLimit': ol.xml.makeObjectPropertySetter(
  48776. ol.format.XSD.readNonNegativeInteger),
  48777. 'MaxWidth': ol.xml.makeObjectPropertySetter(
  48778. ol.format.XSD.readNonNegativeInteger),
  48779. 'MaxHeight': ol.xml.makeObjectPropertySetter(
  48780. ol.format.XSD.readNonNegativeInteger)
  48781. });
  48782. /**
  48783. * @const
  48784. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48785. * @private
  48786. */
  48787. ol.format.WMSCapabilities.CONTACT_INFORMATION_PARSERS_ = ol.xml.makeStructureNS(
  48788. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48789. 'ContactPersonPrimary': ol.xml.makeObjectPropertySetter(
  48790. ol.format.WMSCapabilities.readContactPersonPrimary_),
  48791. 'ContactPosition': ol.xml.makeObjectPropertySetter(
  48792. ol.format.XSD.readString),
  48793. 'ContactAddress': ol.xml.makeObjectPropertySetter(
  48794. ol.format.WMSCapabilities.readContactAddress_),
  48795. 'ContactVoiceTelephone': ol.xml.makeObjectPropertySetter(
  48796. ol.format.XSD.readString),
  48797. 'ContactFacsimileTelephone': ol.xml.makeObjectPropertySetter(
  48798. ol.format.XSD.readString),
  48799. 'ContactElectronicMailAddress': ol.xml.makeObjectPropertySetter(
  48800. ol.format.XSD.readString)
  48801. });
  48802. /**
  48803. * @const
  48804. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48805. * @private
  48806. */
  48807. ol.format.WMSCapabilities.CONTACT_PERSON_PARSERS_ = ol.xml.makeStructureNS(
  48808. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48809. 'ContactPerson': ol.xml.makeObjectPropertySetter(
  48810. ol.format.XSD.readString),
  48811. 'ContactOrganization': ol.xml.makeObjectPropertySetter(
  48812. ol.format.XSD.readString)
  48813. });
  48814. /**
  48815. * @const
  48816. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48817. * @private
  48818. */
  48819. ol.format.WMSCapabilities.CONTACT_ADDRESS_PARSERS_ = ol.xml.makeStructureNS(
  48820. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48821. 'AddressType': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48822. 'Address': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48823. 'City': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48824. 'StateOrProvince': ol.xml.makeObjectPropertySetter(
  48825. ol.format.XSD.readString),
  48826. 'PostCode': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48827. 'Country': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString)
  48828. });
  48829. /**
  48830. * @const
  48831. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48832. * @private
  48833. */
  48834. ol.format.WMSCapabilities.EXCEPTION_PARSERS_ = ol.xml.makeStructureNS(
  48835. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48836. 'Format': ol.xml.makeArrayPusher(ol.format.XSD.readString)
  48837. });
  48838. /**
  48839. * @const
  48840. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48841. * @private
  48842. */
  48843. ol.format.WMSCapabilities.LAYER_PARSERS_ = ol.xml.makeStructureNS(
  48844. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48845. 'Name': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48846. 'Title': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48847. 'Abstract': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48848. 'KeywordList': ol.xml.makeObjectPropertySetter(
  48849. ol.format.WMSCapabilities.readKeywordList_),
  48850. 'CRS': ol.xml.makeObjectPropertyPusher(ol.format.XSD.readString),
  48851. 'EX_GeographicBoundingBox': ol.xml.makeObjectPropertySetter(
  48852. ol.format.WMSCapabilities.readEXGeographicBoundingBox_),
  48853. 'BoundingBox': ol.xml.makeObjectPropertyPusher(
  48854. ol.format.WMSCapabilities.readBoundingBox_),
  48855. 'Dimension': ol.xml.makeObjectPropertyPusher(
  48856. ol.format.WMSCapabilities.readDimension_),
  48857. 'Attribution': ol.xml.makeObjectPropertySetter(
  48858. ol.format.WMSCapabilities.readAttribution_),
  48859. 'AuthorityURL': ol.xml.makeObjectPropertyPusher(
  48860. ol.format.WMSCapabilities.readAuthorityURL_),
  48861. 'Identifier': ol.xml.makeObjectPropertyPusher(ol.format.XSD.readString),
  48862. 'MetadataURL': ol.xml.makeObjectPropertyPusher(
  48863. ol.format.WMSCapabilities.readMetadataURL_),
  48864. 'DataURL': ol.xml.makeObjectPropertyPusher(
  48865. ol.format.WMSCapabilities.readFormatOnlineresource_),
  48866. 'FeatureListURL': ol.xml.makeObjectPropertyPusher(
  48867. ol.format.WMSCapabilities.readFormatOnlineresource_),
  48868. 'Style': ol.xml.makeObjectPropertyPusher(
  48869. ol.format.WMSCapabilities.readStyle_),
  48870. 'MinScaleDenominator': ol.xml.makeObjectPropertySetter(
  48871. ol.format.XSD.readDecimal),
  48872. 'MaxScaleDenominator': ol.xml.makeObjectPropertySetter(
  48873. ol.format.XSD.readDecimal),
  48874. 'Layer': ol.xml.makeObjectPropertyPusher(
  48875. ol.format.WMSCapabilities.readLayer_)
  48876. });
  48877. /**
  48878. * @const
  48879. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48880. * @private
  48881. */
  48882. ol.format.WMSCapabilities.ATTRIBUTION_PARSERS_ = ol.xml.makeStructureNS(
  48883. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48884. 'Title': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48885. 'OnlineResource': ol.xml.makeObjectPropertySetter(
  48886. ol.format.XLink.readHref),
  48887. 'LogoURL': ol.xml.makeObjectPropertySetter(
  48888. ol.format.WMSCapabilities.readSizedFormatOnlineresource_)
  48889. });
  48890. /**
  48891. * @const
  48892. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48893. * @private
  48894. */
  48895. ol.format.WMSCapabilities.EX_GEOGRAPHIC_BOUNDING_BOX_PARSERS_ =
  48896. ol.xml.makeStructureNS(ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48897. 'westBoundLongitude': ol.xml.makeObjectPropertySetter(
  48898. ol.format.XSD.readDecimal),
  48899. 'eastBoundLongitude': ol.xml.makeObjectPropertySetter(
  48900. ol.format.XSD.readDecimal),
  48901. 'southBoundLatitude': ol.xml.makeObjectPropertySetter(
  48902. ol.format.XSD.readDecimal),
  48903. 'northBoundLatitude': ol.xml.makeObjectPropertySetter(
  48904. ol.format.XSD.readDecimal)
  48905. });
  48906. /**
  48907. * @const
  48908. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48909. * @private
  48910. */
  48911. ol.format.WMSCapabilities.REQUEST_PARSERS_ = ol.xml.makeStructureNS(
  48912. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48913. 'GetCapabilities': ol.xml.makeObjectPropertySetter(
  48914. ol.format.WMSCapabilities.readOperationType_),
  48915. 'GetMap': ol.xml.makeObjectPropertySetter(
  48916. ol.format.WMSCapabilities.readOperationType_),
  48917. 'GetFeatureInfo': ol.xml.makeObjectPropertySetter(
  48918. ol.format.WMSCapabilities.readOperationType_)
  48919. });
  48920. /**
  48921. * @const
  48922. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48923. * @private
  48924. */
  48925. ol.format.WMSCapabilities.OPERATIONTYPE_PARSERS_ = ol.xml.makeStructureNS(
  48926. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48927. 'Format': ol.xml.makeObjectPropertyPusher(ol.format.XSD.readString),
  48928. 'DCPType': ol.xml.makeObjectPropertyPusher(
  48929. ol.format.WMSCapabilities.readDCPType_)
  48930. });
  48931. /**
  48932. * @const
  48933. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48934. * @private
  48935. */
  48936. ol.format.WMSCapabilities.DCPTYPE_PARSERS_ = ol.xml.makeStructureNS(
  48937. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48938. 'HTTP': ol.xml.makeObjectPropertySetter(
  48939. ol.format.WMSCapabilities.readHTTP_)
  48940. });
  48941. /**
  48942. * @const
  48943. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48944. * @private
  48945. */
  48946. ol.format.WMSCapabilities.HTTP_PARSERS_ = ol.xml.makeStructureNS(
  48947. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48948. 'Get': ol.xml.makeObjectPropertySetter(
  48949. ol.format.WMSCapabilities.readFormatOnlineresource_),
  48950. 'Post': ol.xml.makeObjectPropertySetter(
  48951. ol.format.WMSCapabilities.readFormatOnlineresource_)
  48952. });
  48953. /**
  48954. * @const
  48955. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48956. * @private
  48957. */
  48958. ol.format.WMSCapabilities.STYLE_PARSERS_ = ol.xml.makeStructureNS(
  48959. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48960. 'Name': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48961. 'Title': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48962. 'Abstract': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48963. 'LegendURL': ol.xml.makeObjectPropertyPusher(
  48964. ol.format.WMSCapabilities.readSizedFormatOnlineresource_),
  48965. 'StyleSheetURL': ol.xml.makeObjectPropertySetter(
  48966. ol.format.WMSCapabilities.readFormatOnlineresource_),
  48967. 'StyleURL': ol.xml.makeObjectPropertySetter(
  48968. ol.format.WMSCapabilities.readFormatOnlineresource_)
  48969. });
  48970. /**
  48971. * @const
  48972. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48973. * @private
  48974. */
  48975. ol.format.WMSCapabilities.FORMAT_ONLINERESOURCE_PARSERS_ =
  48976. ol.xml.makeStructureNS(ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48977. 'Format': ol.xml.makeObjectPropertySetter(ol.format.XSD.readString),
  48978. 'OnlineResource': ol.xml.makeObjectPropertySetter(
  48979. ol.format.XLink.readHref)
  48980. });
  48981. /**
  48982. * @const
  48983. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  48984. * @private
  48985. */
  48986. ol.format.WMSCapabilities.KEYWORDLIST_PARSERS_ = ol.xml.makeStructureNS(
  48987. ol.format.WMSCapabilities.NAMESPACE_URIS_, {
  48988. 'Keyword': ol.xml.makeArrayPusher(ol.format.XSD.readString)
  48989. });
  48990. goog.provide('ol.format.WMSGetFeatureInfo');
  48991. goog.require('ol');
  48992. goog.require('ol.array');
  48993. goog.require('ol.format.GML2');
  48994. goog.require('ol.format.XMLFeature');
  48995. goog.require('ol.obj');
  48996. goog.require('ol.xml');
  48997. /**
  48998. * @classdesc
  48999. * Format for reading WMSGetFeatureInfo format. It uses
  49000. * {@link ol.format.GML2} to read features.
  49001. *
  49002. * @constructor
  49003. * @extends {ol.format.XMLFeature}
  49004. * @param {olx.format.WMSGetFeatureInfoOptions=} opt_options Options.
  49005. * @api
  49006. */
  49007. ol.format.WMSGetFeatureInfo = function(opt_options) {
  49008. var options = opt_options ? opt_options : {};
  49009. /**
  49010. * @private
  49011. * @type {string}
  49012. */
  49013. this.featureNS_ = 'http://mapserver.gis.umn.edu/mapserver';
  49014. /**
  49015. * @private
  49016. * @type {ol.format.GML2}
  49017. */
  49018. this.gmlFormat_ = new ol.format.GML2();
  49019. /**
  49020. * @private
  49021. * @type {Array.<string>}
  49022. */
  49023. this.layers_ = options.layers ? options.layers : null;
  49024. ol.format.XMLFeature.call(this);
  49025. };
  49026. ol.inherits(ol.format.WMSGetFeatureInfo, ol.format.XMLFeature);
  49027. /**
  49028. * @const
  49029. * @type {string}
  49030. * @private
  49031. */
  49032. ol.format.WMSGetFeatureInfo.featureIdentifier_ = '_feature';
  49033. /**
  49034. * @const
  49035. * @type {string}
  49036. * @private
  49037. */
  49038. ol.format.WMSGetFeatureInfo.layerIdentifier_ = '_layer';
  49039. /**
  49040. * @param {Node} node Node.
  49041. * @param {Array.<*>} objectStack Object stack.
  49042. * @return {Array.<ol.Feature>} Features.
  49043. * @private
  49044. */
  49045. ol.format.WMSGetFeatureInfo.prototype.readFeatures_ = function(node, objectStack) {
  49046. node.setAttribute('namespaceURI', this.featureNS_);
  49047. var localName = node.localName;
  49048. /** @type {Array.<ol.Feature>} */
  49049. var features = [];
  49050. if (node.childNodes.length === 0) {
  49051. return features;
  49052. }
  49053. if (localName == 'msGMLOutput') {
  49054. for (var i = 0, ii = node.childNodes.length; i < ii; i++) {
  49055. var layer = node.childNodes[i];
  49056. if (layer.nodeType !== Node.ELEMENT_NODE) {
  49057. continue;
  49058. }
  49059. var context = objectStack[0];
  49060. var toRemove = ol.format.WMSGetFeatureInfo.layerIdentifier_;
  49061. var layerName = layer.localName.replace(toRemove, '');
  49062. if (this.layers_ && !ol.array.includes(this.layers_, layerName)) {
  49063. continue;
  49064. }
  49065. var featureType = layerName +
  49066. ol.format.WMSGetFeatureInfo.featureIdentifier_;
  49067. context['featureType'] = featureType;
  49068. context['featureNS'] = this.featureNS_;
  49069. var parsers = {};
  49070. parsers[featureType] = ol.xml.makeArrayPusher(
  49071. this.gmlFormat_.readFeatureElement, this.gmlFormat_);
  49072. var parsersNS = ol.xml.makeStructureNS(
  49073. [context['featureNS'], null], parsers);
  49074. layer.setAttribute('namespaceURI', this.featureNS_);
  49075. var layerFeatures = ol.xml.pushParseAndPop(
  49076. [], parsersNS, layer, objectStack, this.gmlFormat_);
  49077. if (layerFeatures) {
  49078. ol.array.extend(features, layerFeatures);
  49079. }
  49080. }
  49081. }
  49082. if (localName == 'FeatureCollection') {
  49083. var gmlFeatures = ol.xml.pushParseAndPop([],
  49084. this.gmlFormat_.FEATURE_COLLECTION_PARSERS, node,
  49085. [{}], this.gmlFormat_);
  49086. if (gmlFeatures) {
  49087. features = gmlFeatures;
  49088. }
  49089. }
  49090. return features;
  49091. };
  49092. /**
  49093. * Read all features from a WMSGetFeatureInfo response.
  49094. *
  49095. * @function
  49096. * @param {Document|Node|Object|string} source Source.
  49097. * @param {olx.format.ReadOptions=} opt_options Options.
  49098. * @return {Array.<ol.Feature>} Features.
  49099. * @api
  49100. */
  49101. ol.format.WMSGetFeatureInfo.prototype.readFeatures;
  49102. /**
  49103. * @inheritDoc
  49104. */
  49105. ol.format.WMSGetFeatureInfo.prototype.readFeaturesFromNode = function(node, opt_options) {
  49106. var options = {};
  49107. if (opt_options) {
  49108. ol.obj.assign(options, this.getReadOptions(node, opt_options));
  49109. }
  49110. return this.readFeatures_(node, [options]);
  49111. };
  49112. /**
  49113. * Not implemented.
  49114. * @inheritDoc
  49115. */
  49116. ol.format.WMSGetFeatureInfo.prototype.writeFeatureNode = function(feature, opt_options) {};
  49117. /**
  49118. * Not implemented.
  49119. * @inheritDoc
  49120. */
  49121. ol.format.WMSGetFeatureInfo.prototype.writeFeaturesNode = function(features, opt_options) {};
  49122. /**
  49123. * Not implemented.
  49124. * @inheritDoc
  49125. */
  49126. ol.format.WMSGetFeatureInfo.prototype.writeGeometryNode = function(geometry, opt_options) {};
  49127. goog.provide('ol.format.WMTSCapabilities');
  49128. goog.require('ol');
  49129. goog.require('ol.extent');
  49130. goog.require('ol.format.OWS');
  49131. goog.require('ol.format.XLink');
  49132. goog.require('ol.format.XML');
  49133. goog.require('ol.format.XSD');
  49134. goog.require('ol.xml');
  49135. /**
  49136. * @classdesc
  49137. * Format for reading WMTS capabilities data.
  49138. *
  49139. * @constructor
  49140. * @extends {ol.format.XML}
  49141. * @api
  49142. */
  49143. ol.format.WMTSCapabilities = function() {
  49144. ol.format.XML.call(this);
  49145. /**
  49146. * @type {ol.format.OWS}
  49147. * @private
  49148. */
  49149. this.owsParser_ = new ol.format.OWS();
  49150. };
  49151. ol.inherits(ol.format.WMTSCapabilities, ol.format.XML);
  49152. /**
  49153. * Read a WMTS capabilities document.
  49154. *
  49155. * @function
  49156. * @param {Document|Node|string} source The XML source.
  49157. * @return {Object} An object representing the WMTS capabilities.
  49158. * @api
  49159. */
  49160. ol.format.WMTSCapabilities.prototype.read;
  49161. /**
  49162. * @inheritDoc
  49163. */
  49164. ol.format.WMTSCapabilities.prototype.readFromDocument = function(doc) {
  49165. for (var n = doc.firstChild; n; n = n.nextSibling) {
  49166. if (n.nodeType == Node.ELEMENT_NODE) {
  49167. return this.readFromNode(n);
  49168. }
  49169. }
  49170. return null;
  49171. };
  49172. /**
  49173. * @inheritDoc
  49174. */
  49175. ol.format.WMTSCapabilities.prototype.readFromNode = function(node) {
  49176. var version = node.getAttribute('version').trim();
  49177. var WMTSCapabilityObject = this.owsParser_.readFromNode(node);
  49178. if (!WMTSCapabilityObject) {
  49179. return null;
  49180. }
  49181. WMTSCapabilityObject['version'] = version;
  49182. WMTSCapabilityObject = ol.xml.pushParseAndPop(WMTSCapabilityObject,
  49183. ol.format.WMTSCapabilities.PARSERS_, node, []);
  49184. return WMTSCapabilityObject ? WMTSCapabilityObject : null;
  49185. };
  49186. /**
  49187. * @private
  49188. * @param {Node} node Node.
  49189. * @param {Array.<*>} objectStack Object stack.
  49190. * @return {Object|undefined} Attribution object.
  49191. */
  49192. ol.format.WMTSCapabilities.readContents_ = function(node, objectStack) {
  49193. return ol.xml.pushParseAndPop({},
  49194. ol.format.WMTSCapabilities.CONTENTS_PARSERS_, node, objectStack);
  49195. };
  49196. /**
  49197. * @private
  49198. * @param {Node} node Node.
  49199. * @param {Array.<*>} objectStack Object stack.
  49200. * @return {Object|undefined} Layers object.
  49201. */
  49202. ol.format.WMTSCapabilities.readLayer_ = function(node, objectStack) {
  49203. return ol.xml.pushParseAndPop({},
  49204. ol.format.WMTSCapabilities.LAYER_PARSERS_, node, objectStack);
  49205. };
  49206. /**
  49207. * @private
  49208. * @param {Node} node Node.
  49209. * @param {Array.<*>} objectStack Object stack.
  49210. * @return {Object|undefined} Tile Matrix Set object.
  49211. */
  49212. ol.format.WMTSCapabilities.readTileMatrixSet_ = function(node, objectStack) {
  49213. return ol.xml.pushParseAndPop({},
  49214. ol.format.WMTSCapabilities.TMS_PARSERS_, node, objectStack);
  49215. };
  49216. /**
  49217. * @private
  49218. * @param {Node} node Node.
  49219. * @param {Array.<*>} objectStack Object stack.
  49220. * @return {Object|undefined} Style object.
  49221. */
  49222. ol.format.WMTSCapabilities.readStyle_ = function(node, objectStack) {
  49223. var style = ol.xml.pushParseAndPop({},
  49224. ol.format.WMTSCapabilities.STYLE_PARSERS_, node, objectStack);
  49225. if (!style) {
  49226. return undefined;
  49227. }
  49228. var isDefault = node.getAttribute('isDefault') === 'true';
  49229. style['isDefault'] = isDefault;
  49230. return style;
  49231. };
  49232. /**
  49233. * @private
  49234. * @param {Node} node Node.
  49235. * @param {Array.<*>} objectStack Object stack.
  49236. * @return {Object|undefined} Tile Matrix Set Link object.
  49237. */
  49238. ol.format.WMTSCapabilities.readTileMatrixSetLink_ = function(node,
  49239. objectStack) {
  49240. return ol.xml.pushParseAndPop({},
  49241. ol.format.WMTSCapabilities.TMS_LINKS_PARSERS_, node, objectStack);
  49242. };
  49243. /**
  49244. * @private
  49245. * @param {Node} node Node.
  49246. * @param {Array.<*>} objectStack Object stack.
  49247. * @return {Object|undefined} Dimension object.
  49248. */
  49249. ol.format.WMTSCapabilities.readDimensions_ = function(node, objectStack) {
  49250. return ol.xml.pushParseAndPop({},
  49251. ol.format.WMTSCapabilities.DIMENSION_PARSERS_, node, objectStack);
  49252. };
  49253. /**
  49254. * @private
  49255. * @param {Node} node Node.
  49256. * @param {Array.<*>} objectStack Object stack.
  49257. * @return {Object|undefined} Resource URL object.
  49258. */
  49259. ol.format.WMTSCapabilities.readResourceUrl_ = function(node, objectStack) {
  49260. var format = node.getAttribute('format');
  49261. var template = node.getAttribute('template');
  49262. var resourceType = node.getAttribute('resourceType');
  49263. var resource = {};
  49264. if (format) {
  49265. resource['format'] = format;
  49266. }
  49267. if (template) {
  49268. resource['template'] = template;
  49269. }
  49270. if (resourceType) {
  49271. resource['resourceType'] = resourceType;
  49272. }
  49273. return resource;
  49274. };
  49275. /**
  49276. * @private
  49277. * @param {Node} node Node.
  49278. * @param {Array.<*>} objectStack Object stack.
  49279. * @return {Object|undefined} WGS84 BBox object.
  49280. */
  49281. ol.format.WMTSCapabilities.readWgs84BoundingBox_ = function(node, objectStack) {
  49282. var coordinates = ol.xml.pushParseAndPop([],
  49283. ol.format.WMTSCapabilities.WGS84_BBOX_READERS_, node, objectStack);
  49284. if (coordinates.length != 2) {
  49285. return undefined;
  49286. }
  49287. return ol.extent.boundingExtent(coordinates);
  49288. };
  49289. /**
  49290. * @private
  49291. * @param {Node} node Node.
  49292. * @param {Array.<*>} objectStack Object stack.
  49293. * @return {Object|undefined} Legend object.
  49294. */
  49295. ol.format.WMTSCapabilities.readLegendUrl_ = function(node, objectStack) {
  49296. var legend = {};
  49297. legend['format'] = node.getAttribute('format');
  49298. legend['href'] = ol.format.XLink.readHref(node);
  49299. return legend;
  49300. };
  49301. /**
  49302. * @private
  49303. * @param {Node} node Node.
  49304. * @param {Array.<*>} objectStack Object stack.
  49305. * @return {Object|undefined} Coordinates object.
  49306. */
  49307. ol.format.WMTSCapabilities.readCoordinates_ = function(node, objectStack) {
  49308. var coordinates = ol.format.XSD.readString(node).split(' ');
  49309. if (!coordinates || coordinates.length != 2) {
  49310. return undefined;
  49311. }
  49312. var x = +coordinates[0];
  49313. var y = +coordinates[1];
  49314. if (isNaN(x) || isNaN(y)) {
  49315. return undefined;
  49316. }
  49317. return [x, y];
  49318. };
  49319. /**
  49320. * @private
  49321. * @param {Node} node Node.
  49322. * @param {Array.<*>} objectStack Object stack.
  49323. * @return {Object|undefined} TileMatrix object.
  49324. */
  49325. ol.format.WMTSCapabilities.readTileMatrix_ = function(node, objectStack) {
  49326. return ol.xml.pushParseAndPop({},
  49327. ol.format.WMTSCapabilities.TM_PARSERS_, node, objectStack);
  49328. };
  49329. /**
  49330. * @private
  49331. * @param {Node} node Node.
  49332. * @param {Array.<*>} objectStack Object stack.
  49333. * @return {Object|undefined} TileMatrixSetLimits Object.
  49334. */
  49335. ol.format.WMTSCapabilities.readTileMatrixLimitsList_ = function(node,
  49336. objectStack) {
  49337. return ol.xml.pushParseAndPop([],
  49338. ol.format.WMTSCapabilities.TMS_LIMITS_LIST_PARSERS_, node,
  49339. objectStack);
  49340. };
  49341. /**
  49342. * @private
  49343. * @param {Node} node Node.
  49344. * @param {Array.<*>} objectStack Object stack.
  49345. * @return {Object|undefined} TileMatrixLimits Array.
  49346. */
  49347. ol.format.WMTSCapabilities.readTileMatrixLimits_ = function(node, objectStack) {
  49348. return ol.xml.pushParseAndPop({},
  49349. ol.format.WMTSCapabilities.TMS_LIMITS_PARSERS_, node, objectStack);
  49350. };
  49351. /**
  49352. * @const
  49353. * @private
  49354. * @type {Array.<string>}
  49355. */
  49356. ol.format.WMTSCapabilities.NAMESPACE_URIS_ = [
  49357. null,
  49358. 'http://www.opengis.net/wmts/1.0'
  49359. ];
  49360. /**
  49361. * @const
  49362. * @private
  49363. * @type {Array.<string>}
  49364. */
  49365. ol.format.WMTSCapabilities.OWS_NAMESPACE_URIS_ = [
  49366. null,
  49367. 'http://www.opengis.net/ows/1.1'
  49368. ];
  49369. /**
  49370. * @const
  49371. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  49372. * @private
  49373. */
  49374. ol.format.WMTSCapabilities.PARSERS_ = ol.xml.makeStructureNS(
  49375. ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
  49376. 'Contents': ol.xml.makeObjectPropertySetter(
  49377. ol.format.WMTSCapabilities.readContents_)
  49378. });
  49379. /**
  49380. * @const
  49381. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  49382. * @private
  49383. */
  49384. ol.format.WMTSCapabilities.CONTENTS_PARSERS_ = ol.xml.makeStructureNS(
  49385. ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
  49386. 'Layer': ol.xml.makeObjectPropertyPusher(
  49387. ol.format.WMTSCapabilities.readLayer_),
  49388. 'TileMatrixSet': ol.xml.makeObjectPropertyPusher(
  49389. ol.format.WMTSCapabilities.readTileMatrixSet_)
  49390. });
  49391. /**
  49392. * @const
  49393. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  49394. * @private
  49395. */
  49396. ol.format.WMTSCapabilities.LAYER_PARSERS_ = ol.xml.makeStructureNS(
  49397. ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
  49398. 'Style': ol.xml.makeObjectPropertyPusher(
  49399. ol.format.WMTSCapabilities.readStyle_),
  49400. 'Format': ol.xml.makeObjectPropertyPusher(
  49401. ol.format.XSD.readString),
  49402. 'TileMatrixSetLink': ol.xml.makeObjectPropertyPusher(
  49403. ol.format.WMTSCapabilities.readTileMatrixSetLink_),
  49404. 'Dimension': ol.xml.makeObjectPropertyPusher(
  49405. ol.format.WMTSCapabilities.readDimensions_),
  49406. 'ResourceURL': ol.xml.makeObjectPropertyPusher(
  49407. ol.format.WMTSCapabilities.readResourceUrl_)
  49408. }, ol.xml.makeStructureNS(ol.format.WMTSCapabilities.OWS_NAMESPACE_URIS_, {
  49409. 'Title': ol.xml.makeObjectPropertySetter(
  49410. ol.format.XSD.readString),
  49411. 'Abstract': ol.xml.makeObjectPropertySetter(
  49412. ol.format.XSD.readString),
  49413. 'WGS84BoundingBox': ol.xml.makeObjectPropertySetter(
  49414. ol.format.WMTSCapabilities.readWgs84BoundingBox_),
  49415. 'Identifier': ol.xml.makeObjectPropertySetter(
  49416. ol.format.XSD.readString)
  49417. }));
  49418. /**
  49419. * @const
  49420. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  49421. * @private
  49422. */
  49423. ol.format.WMTSCapabilities.STYLE_PARSERS_ = ol.xml.makeStructureNS(
  49424. ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
  49425. 'LegendURL': ol.xml.makeObjectPropertyPusher(
  49426. ol.format.WMTSCapabilities.readLegendUrl_)
  49427. }, ol.xml.makeStructureNS(ol.format.WMTSCapabilities.OWS_NAMESPACE_URIS_, {
  49428. 'Title': ol.xml.makeObjectPropertySetter(
  49429. ol.format.XSD.readString),
  49430. 'Identifier': ol.xml.makeObjectPropertySetter(
  49431. ol.format.XSD.readString)
  49432. }));
  49433. /**
  49434. * @const
  49435. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  49436. * @private
  49437. */
  49438. ol.format.WMTSCapabilities.TMS_LINKS_PARSERS_ = ol.xml.makeStructureNS(
  49439. ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
  49440. 'TileMatrixSet': ol.xml.makeObjectPropertySetter(
  49441. ol.format.XSD.readString),
  49442. 'TileMatrixSetLimits': ol.xml.makeObjectPropertySetter(
  49443. ol.format.WMTSCapabilities.readTileMatrixLimitsList_)
  49444. });
  49445. /**
  49446. * @const
  49447. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  49448. * @private
  49449. */
  49450. ol.format.WMTSCapabilities.TMS_LIMITS_LIST_PARSERS_ = ol.xml.makeStructureNS(
  49451. ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
  49452. 'TileMatrixLimits': ol.xml.makeArrayPusher(
  49453. ol.format.WMTSCapabilities.readTileMatrixLimits_)
  49454. });
  49455. /**
  49456. * @const
  49457. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  49458. * @private
  49459. */
  49460. ol.format.WMTSCapabilities.TMS_LIMITS_PARSERS_ = ol.xml.makeStructureNS(
  49461. ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
  49462. 'TileMatrix': ol.xml.makeObjectPropertySetter(
  49463. ol.format.XSD.readString),
  49464. 'MinTileRow': ol.xml.makeObjectPropertySetter(
  49465. ol.format.XSD.readNonNegativeInteger),
  49466. 'MaxTileRow': ol.xml.makeObjectPropertySetter(
  49467. ol.format.XSD.readNonNegativeInteger),
  49468. 'MinTileCol': ol.xml.makeObjectPropertySetter(
  49469. ol.format.XSD.readNonNegativeInteger),
  49470. 'MaxTileCol': ol.xml.makeObjectPropertySetter(
  49471. ol.format.XSD.readNonNegativeInteger)
  49472. });
  49473. /**
  49474. * @const
  49475. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  49476. * @private
  49477. */
  49478. ol.format.WMTSCapabilities.DIMENSION_PARSERS_ = ol.xml.makeStructureNS(
  49479. ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
  49480. 'Default': ol.xml.makeObjectPropertySetter(
  49481. ol.format.XSD.readString),
  49482. 'Value': ol.xml.makeObjectPropertyPusher(
  49483. ol.format.XSD.readString)
  49484. }, ol.xml.makeStructureNS(ol.format.WMTSCapabilities.OWS_NAMESPACE_URIS_, {
  49485. 'Identifier': ol.xml.makeObjectPropertySetter(
  49486. ol.format.XSD.readString)
  49487. }));
  49488. /**
  49489. * @const
  49490. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  49491. * @private
  49492. */
  49493. ol.format.WMTSCapabilities.WGS84_BBOX_READERS_ = ol.xml.makeStructureNS(
  49494. ol.format.WMTSCapabilities.OWS_NAMESPACE_URIS_, {
  49495. 'LowerCorner': ol.xml.makeArrayPusher(
  49496. ol.format.WMTSCapabilities.readCoordinates_),
  49497. 'UpperCorner': ol.xml.makeArrayPusher(
  49498. ol.format.WMTSCapabilities.readCoordinates_)
  49499. });
  49500. /**
  49501. * @const
  49502. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  49503. * @private
  49504. */
  49505. ol.format.WMTSCapabilities.TMS_PARSERS_ = ol.xml.makeStructureNS(
  49506. ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
  49507. 'WellKnownScaleSet': ol.xml.makeObjectPropertySetter(
  49508. ol.format.XSD.readString),
  49509. 'TileMatrix': ol.xml.makeObjectPropertyPusher(
  49510. ol.format.WMTSCapabilities.readTileMatrix_)
  49511. }, ol.xml.makeStructureNS(ol.format.WMTSCapabilities.OWS_NAMESPACE_URIS_, {
  49512. 'SupportedCRS': ol.xml.makeObjectPropertySetter(
  49513. ol.format.XSD.readString),
  49514. 'Identifier': ol.xml.makeObjectPropertySetter(
  49515. ol.format.XSD.readString)
  49516. }));
  49517. /**
  49518. * @const
  49519. * @type {Object.<string, Object.<string, ol.XmlParser>>}
  49520. * @private
  49521. */
  49522. ol.format.WMTSCapabilities.TM_PARSERS_ = ol.xml.makeStructureNS(
  49523. ol.format.WMTSCapabilities.NAMESPACE_URIS_, {
  49524. 'TopLeftCorner': ol.xml.makeObjectPropertySetter(
  49525. ol.format.WMTSCapabilities.readCoordinates_),
  49526. 'ScaleDenominator': ol.xml.makeObjectPropertySetter(
  49527. ol.format.XSD.readDecimal),
  49528. 'TileWidth': ol.xml.makeObjectPropertySetter(
  49529. ol.format.XSD.readNonNegativeInteger),
  49530. 'TileHeight': ol.xml.makeObjectPropertySetter(
  49531. ol.format.XSD.readNonNegativeInteger),
  49532. 'MatrixWidth': ol.xml.makeObjectPropertySetter(
  49533. ol.format.XSD.readNonNegativeInteger),
  49534. 'MatrixHeight': ol.xml.makeObjectPropertySetter(
  49535. ol.format.XSD.readNonNegativeInteger)
  49536. }, ol.xml.makeStructureNS(ol.format.WMTSCapabilities.OWS_NAMESPACE_URIS_, {
  49537. 'Identifier': ol.xml.makeObjectPropertySetter(
  49538. ol.format.XSD.readString)
  49539. }));
  49540. goog.provide('ol.GeolocationProperty');
  49541. /**
  49542. * @enum {string}
  49543. */
  49544. ol.GeolocationProperty = {
  49545. ACCURACY: 'accuracy',
  49546. ACCURACY_GEOMETRY: 'accuracyGeometry',
  49547. ALTITUDE: 'altitude',
  49548. ALTITUDE_ACCURACY: 'altitudeAccuracy',
  49549. HEADING: 'heading',
  49550. POSITION: 'position',
  49551. PROJECTION: 'projection',
  49552. SPEED: 'speed',
  49553. TRACKING: 'tracking',
  49554. TRACKING_OPTIONS: 'trackingOptions'
  49555. };
  49556. // FIXME handle geolocation not supported
  49557. goog.provide('ol.Geolocation');
  49558. goog.require('ol');
  49559. goog.require('ol.GeolocationProperty');
  49560. goog.require('ol.Object');
  49561. goog.require('ol.Sphere');
  49562. goog.require('ol.events');
  49563. goog.require('ol.events.EventType');
  49564. goog.require('ol.geom.Polygon');
  49565. goog.require('ol.has');
  49566. goog.require('ol.math');
  49567. goog.require('ol.proj');
  49568. goog.require('ol.proj.EPSG4326');
  49569. /**
  49570. * @classdesc
  49571. * Helper class for providing HTML5 Geolocation capabilities.
  49572. * The [Geolocation API](http://www.w3.org/TR/geolocation-API/)
  49573. * is used to locate a user's position.
  49574. *
  49575. * To get notified of position changes, register a listener for the generic
  49576. * `change` event on your instance of `ol.Geolocation`.
  49577. *
  49578. * Example:
  49579. *
  49580. * var geolocation = new ol.Geolocation({
  49581. * // take the projection to use from the map's view
  49582. * projection: view.getProjection()
  49583. * });
  49584. * // listen to changes in position
  49585. * geolocation.on('change', function(evt) {
  49586. * window.console.log(geolocation.getPosition());
  49587. * });
  49588. *
  49589. * @fires error
  49590. * @constructor
  49591. * @extends {ol.Object}
  49592. * @param {olx.GeolocationOptions=} opt_options Options.
  49593. * @api
  49594. */
  49595. ol.Geolocation = function(opt_options) {
  49596. ol.Object.call(this);
  49597. var options = opt_options || {};
  49598. /**
  49599. * The unprojected (EPSG:4326) device position.
  49600. * @private
  49601. * @type {ol.Coordinate}
  49602. */
  49603. this.position_ = null;
  49604. /**
  49605. * @private
  49606. * @type {ol.TransformFunction}
  49607. */
  49608. this.transform_ = ol.proj.identityTransform;
  49609. /**
  49610. * @private
  49611. * @type {ol.Sphere}
  49612. */
  49613. this.sphere_ = new ol.Sphere(ol.proj.EPSG4326.RADIUS);
  49614. /**
  49615. * @private
  49616. * @type {number|undefined}
  49617. */
  49618. this.watchId_ = undefined;
  49619. ol.events.listen(
  49620. this, ol.Object.getChangeEventType(ol.GeolocationProperty.PROJECTION),
  49621. this.handleProjectionChanged_, this);
  49622. ol.events.listen(
  49623. this, ol.Object.getChangeEventType(ol.GeolocationProperty.TRACKING),
  49624. this.handleTrackingChanged_, this);
  49625. if (options.projection !== undefined) {
  49626. this.setProjection(options.projection);
  49627. }
  49628. if (options.trackingOptions !== undefined) {
  49629. this.setTrackingOptions(options.trackingOptions);
  49630. }
  49631. this.setTracking(options.tracking !== undefined ? options.tracking : false);
  49632. };
  49633. ol.inherits(ol.Geolocation, ol.Object);
  49634. /**
  49635. * @inheritDoc
  49636. */
  49637. ol.Geolocation.prototype.disposeInternal = function() {
  49638. this.setTracking(false);
  49639. ol.Object.prototype.disposeInternal.call(this);
  49640. };
  49641. /**
  49642. * @private
  49643. */
  49644. ol.Geolocation.prototype.handleProjectionChanged_ = function() {
  49645. var projection = this.getProjection();
  49646. if (projection) {
  49647. this.transform_ = ol.proj.getTransformFromProjections(
  49648. ol.proj.get('EPSG:4326'), projection);
  49649. if (this.position_) {
  49650. this.set(
  49651. ol.GeolocationProperty.POSITION, this.transform_(this.position_));
  49652. }
  49653. }
  49654. };
  49655. /**
  49656. * @private
  49657. */
  49658. ol.Geolocation.prototype.handleTrackingChanged_ = function() {
  49659. if (ol.has.GEOLOCATION) {
  49660. var tracking = this.getTracking();
  49661. if (tracking && this.watchId_ === undefined) {
  49662. this.watchId_ = navigator.geolocation.watchPosition(
  49663. this.positionChange_.bind(this),
  49664. this.positionError_.bind(this),
  49665. this.getTrackingOptions());
  49666. } else if (!tracking && this.watchId_ !== undefined) {
  49667. navigator.geolocation.clearWatch(this.watchId_);
  49668. this.watchId_ = undefined;
  49669. }
  49670. }
  49671. };
  49672. /**
  49673. * @private
  49674. * @param {GeolocationPosition} position position event.
  49675. */
  49676. ol.Geolocation.prototype.positionChange_ = function(position) {
  49677. var coords = position.coords;
  49678. this.set(ol.GeolocationProperty.ACCURACY, coords.accuracy);
  49679. this.set(ol.GeolocationProperty.ALTITUDE,
  49680. coords.altitude === null ? undefined : coords.altitude);
  49681. this.set(ol.GeolocationProperty.ALTITUDE_ACCURACY,
  49682. coords.altitudeAccuracy === null ?
  49683. undefined : coords.altitudeAccuracy);
  49684. this.set(ol.GeolocationProperty.HEADING, coords.heading === null ?
  49685. undefined : ol.math.toRadians(coords.heading));
  49686. if (!this.position_) {
  49687. this.position_ = [coords.longitude, coords.latitude];
  49688. } else {
  49689. this.position_[0] = coords.longitude;
  49690. this.position_[1] = coords.latitude;
  49691. }
  49692. var projectedPosition = this.transform_(this.position_);
  49693. this.set(ol.GeolocationProperty.POSITION, projectedPosition);
  49694. this.set(ol.GeolocationProperty.SPEED,
  49695. coords.speed === null ? undefined : coords.speed);
  49696. var geometry = ol.geom.Polygon.circular(
  49697. this.sphere_, this.position_, coords.accuracy);
  49698. geometry.applyTransform(this.transform_);
  49699. this.set(ol.GeolocationProperty.ACCURACY_GEOMETRY, geometry);
  49700. this.changed();
  49701. };
  49702. /**
  49703. * Triggered when the Geolocation returns an error.
  49704. * @event error
  49705. * @api
  49706. */
  49707. /**
  49708. * @private
  49709. * @param {GeolocationPositionError} error error object.
  49710. */
  49711. ol.Geolocation.prototype.positionError_ = function(error) {
  49712. error.type = ol.events.EventType.ERROR;
  49713. this.setTracking(false);
  49714. this.dispatchEvent(/** @type {{type: string, target: undefined}} */ (error));
  49715. };
  49716. /**
  49717. * Get the accuracy of the position in meters.
  49718. * @return {number|undefined} The accuracy of the position measurement in
  49719. * meters.
  49720. * @observable
  49721. * @api
  49722. */
  49723. ol.Geolocation.prototype.getAccuracy = function() {
  49724. return /** @type {number|undefined} */ (
  49725. this.get(ol.GeolocationProperty.ACCURACY));
  49726. };
  49727. /**
  49728. * Get a geometry of the position accuracy.
  49729. * @return {?ol.geom.Polygon} A geometry of the position accuracy.
  49730. * @observable
  49731. * @api
  49732. */
  49733. ol.Geolocation.prototype.getAccuracyGeometry = function() {
  49734. return /** @type {?ol.geom.Polygon} */ (
  49735. this.get(ol.GeolocationProperty.ACCURACY_GEOMETRY) || null);
  49736. };
  49737. /**
  49738. * Get the altitude associated with the position.
  49739. * @return {number|undefined} The altitude of the position in meters above mean
  49740. * sea level.
  49741. * @observable
  49742. * @api
  49743. */
  49744. ol.Geolocation.prototype.getAltitude = function() {
  49745. return /** @type {number|undefined} */ (
  49746. this.get(ol.GeolocationProperty.ALTITUDE));
  49747. };
  49748. /**
  49749. * Get the altitude accuracy of the position.
  49750. * @return {number|undefined} The accuracy of the altitude measurement in
  49751. * meters.
  49752. * @observable
  49753. * @api
  49754. */
  49755. ol.Geolocation.prototype.getAltitudeAccuracy = function() {
  49756. return /** @type {number|undefined} */ (
  49757. this.get(ol.GeolocationProperty.ALTITUDE_ACCURACY));
  49758. };
  49759. /**
  49760. * Get the heading as radians clockwise from North.
  49761. * @return {number|undefined} The heading of the device in radians from north.
  49762. * @observable
  49763. * @api
  49764. */
  49765. ol.Geolocation.prototype.getHeading = function() {
  49766. return /** @type {number|undefined} */ (
  49767. this.get(ol.GeolocationProperty.HEADING));
  49768. };
  49769. /**
  49770. * Get the position of the device.
  49771. * @return {ol.Coordinate|undefined} The current position of the device reported
  49772. * in the current projection.
  49773. * @observable
  49774. * @api
  49775. */
  49776. ol.Geolocation.prototype.getPosition = function() {
  49777. return /** @type {ol.Coordinate|undefined} */ (
  49778. this.get(ol.GeolocationProperty.POSITION));
  49779. };
  49780. /**
  49781. * Get the projection associated with the position.
  49782. * @return {ol.proj.Projection|undefined} The projection the position is
  49783. * reported in.
  49784. * @observable
  49785. * @api
  49786. */
  49787. ol.Geolocation.prototype.getProjection = function() {
  49788. return /** @type {ol.proj.Projection|undefined} */ (
  49789. this.get(ol.GeolocationProperty.PROJECTION));
  49790. };
  49791. /**
  49792. * Get the speed in meters per second.
  49793. * @return {number|undefined} The instantaneous speed of the device in meters
  49794. * per second.
  49795. * @observable
  49796. * @api
  49797. */
  49798. ol.Geolocation.prototype.getSpeed = function() {
  49799. return /** @type {number|undefined} */ (
  49800. this.get(ol.GeolocationProperty.SPEED));
  49801. };
  49802. /**
  49803. * Determine if the device location is being tracked.
  49804. * @return {boolean} The device location is being tracked.
  49805. * @observable
  49806. * @api
  49807. */
  49808. ol.Geolocation.prototype.getTracking = function() {
  49809. return /** @type {boolean} */ (
  49810. this.get(ol.GeolocationProperty.TRACKING));
  49811. };
  49812. /**
  49813. * Get the tracking options.
  49814. * @see http://www.w3.org/TR/geolocation-API/#position-options
  49815. * @return {GeolocationPositionOptions|undefined} PositionOptions as defined by
  49816. * the [HTML5 Geolocation spec
  49817. * ](http://www.w3.org/TR/geolocation-API/#position_options_interface).
  49818. * @observable
  49819. * @api
  49820. */
  49821. ol.Geolocation.prototype.getTrackingOptions = function() {
  49822. return /** @type {GeolocationPositionOptions|undefined} */ (
  49823. this.get(ol.GeolocationProperty.TRACKING_OPTIONS));
  49824. };
  49825. /**
  49826. * Set the projection to use for transforming the coordinates.
  49827. * @param {ol.ProjectionLike} projection The projection the position is
  49828. * reported in.
  49829. * @observable
  49830. * @api
  49831. */
  49832. ol.Geolocation.prototype.setProjection = function(projection) {
  49833. this.set(ol.GeolocationProperty.PROJECTION, ol.proj.get(projection));
  49834. };
  49835. /**
  49836. * Enable or disable tracking.
  49837. * @param {boolean} tracking Enable tracking.
  49838. * @observable
  49839. * @api
  49840. */
  49841. ol.Geolocation.prototype.setTracking = function(tracking) {
  49842. this.set(ol.GeolocationProperty.TRACKING, tracking);
  49843. };
  49844. /**
  49845. * Set the tracking options.
  49846. * @see http://www.w3.org/TR/geolocation-API/#position-options
  49847. * @param {GeolocationPositionOptions} options PositionOptions as defined by the
  49848. * [HTML5 Geolocation spec
  49849. * ](http://www.w3.org/TR/geolocation-API/#position_options_interface).
  49850. * @observable
  49851. * @api
  49852. */
  49853. ol.Geolocation.prototype.setTrackingOptions = function(options) {
  49854. this.set(ol.GeolocationProperty.TRACKING_OPTIONS, options);
  49855. };
  49856. goog.provide('ol.geom.Circle');
  49857. goog.require('ol');
  49858. goog.require('ol.extent');
  49859. goog.require('ol.geom.GeometryLayout');
  49860. goog.require('ol.geom.GeometryType');
  49861. goog.require('ol.geom.SimpleGeometry');
  49862. goog.require('ol.geom.flat.deflate');
  49863. /**
  49864. * @classdesc
  49865. * Circle geometry.
  49866. *
  49867. * @constructor
  49868. * @extends {ol.geom.SimpleGeometry}
  49869. * @param {ol.Coordinate} center Center.
  49870. * @param {number=} opt_radius Radius.
  49871. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  49872. * @api
  49873. */
  49874. ol.geom.Circle = function(center, opt_radius, opt_layout) {
  49875. ol.geom.SimpleGeometry.call(this);
  49876. var radius = opt_radius ? opt_radius : 0;
  49877. this.setCenterAndRadius(center, radius, opt_layout);
  49878. };
  49879. ol.inherits(ol.geom.Circle, ol.geom.SimpleGeometry);
  49880. /**
  49881. * Make a complete copy of the geometry.
  49882. * @return {!ol.geom.Circle} Clone.
  49883. * @override
  49884. * @api
  49885. */
  49886. ol.geom.Circle.prototype.clone = function() {
  49887. var circle = new ol.geom.Circle(null);
  49888. circle.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
  49889. return circle;
  49890. };
  49891. /**
  49892. * @inheritDoc
  49893. */
  49894. ol.geom.Circle.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  49895. var flatCoordinates = this.flatCoordinates;
  49896. var dx = x - flatCoordinates[0];
  49897. var dy = y - flatCoordinates[1];
  49898. var squaredDistance = dx * dx + dy * dy;
  49899. if (squaredDistance < minSquaredDistance) {
  49900. var i;
  49901. if (squaredDistance === 0) {
  49902. for (i = 0; i < this.stride; ++i) {
  49903. closestPoint[i] = flatCoordinates[i];
  49904. }
  49905. } else {
  49906. var delta = this.getRadius() / Math.sqrt(squaredDistance);
  49907. closestPoint[0] = flatCoordinates[0] + delta * dx;
  49908. closestPoint[1] = flatCoordinates[1] + delta * dy;
  49909. for (i = 2; i < this.stride; ++i) {
  49910. closestPoint[i] = flatCoordinates[i];
  49911. }
  49912. }
  49913. closestPoint.length = this.stride;
  49914. return squaredDistance;
  49915. } else {
  49916. return minSquaredDistance;
  49917. }
  49918. };
  49919. /**
  49920. * @inheritDoc
  49921. */
  49922. ol.geom.Circle.prototype.containsXY = function(x, y) {
  49923. var flatCoordinates = this.flatCoordinates;
  49924. var dx = x - flatCoordinates[0];
  49925. var dy = y - flatCoordinates[1];
  49926. return dx * dx + dy * dy <= this.getRadiusSquared_();
  49927. };
  49928. /**
  49929. * Return the center of the circle as {@link ol.Coordinate coordinate}.
  49930. * @return {ol.Coordinate} Center.
  49931. * @api
  49932. */
  49933. ol.geom.Circle.prototype.getCenter = function() {
  49934. return this.flatCoordinates.slice(0, this.stride);
  49935. };
  49936. /**
  49937. * @inheritDoc
  49938. */
  49939. ol.geom.Circle.prototype.computeExtent = function(extent) {
  49940. var flatCoordinates = this.flatCoordinates;
  49941. var radius = flatCoordinates[this.stride] - flatCoordinates[0];
  49942. return ol.extent.createOrUpdate(
  49943. flatCoordinates[0] - radius, flatCoordinates[1] - radius,
  49944. flatCoordinates[0] + radius, flatCoordinates[1] + radius,
  49945. extent);
  49946. };
  49947. /**
  49948. * Return the radius of the circle.
  49949. * @return {number} Radius.
  49950. * @api
  49951. */
  49952. ol.geom.Circle.prototype.getRadius = function() {
  49953. return Math.sqrt(this.getRadiusSquared_());
  49954. };
  49955. /**
  49956. * @private
  49957. * @return {number} Radius squared.
  49958. */
  49959. ol.geom.Circle.prototype.getRadiusSquared_ = function() {
  49960. var dx = this.flatCoordinates[this.stride] - this.flatCoordinates[0];
  49961. var dy = this.flatCoordinates[this.stride + 1] - this.flatCoordinates[1];
  49962. return dx * dx + dy * dy;
  49963. };
  49964. /**
  49965. * @inheritDoc
  49966. * @api
  49967. */
  49968. ol.geom.Circle.prototype.getType = function() {
  49969. return ol.geom.GeometryType.CIRCLE;
  49970. };
  49971. /**
  49972. * @inheritDoc
  49973. * @api
  49974. */
  49975. ol.geom.Circle.prototype.intersectsExtent = function(extent) {
  49976. var circleExtent = this.getExtent();
  49977. if (ol.extent.intersects(extent, circleExtent)) {
  49978. var center = this.getCenter();
  49979. if (extent[0] <= center[0] && extent[2] >= center[0]) {
  49980. return true;
  49981. }
  49982. if (extent[1] <= center[1] && extent[3] >= center[1]) {
  49983. return true;
  49984. }
  49985. return ol.extent.forEachCorner(extent, this.intersectsCoordinate, this);
  49986. }
  49987. return false;
  49988. };
  49989. /**
  49990. * Set the center of the circle as {@link ol.Coordinate coordinate}.
  49991. * @param {ol.Coordinate} center Center.
  49992. * @api
  49993. */
  49994. ol.geom.Circle.prototype.setCenter = function(center) {
  49995. var stride = this.stride;
  49996. var radius = this.flatCoordinates[stride] - this.flatCoordinates[0];
  49997. var flatCoordinates = center.slice();
  49998. flatCoordinates[stride] = flatCoordinates[0] + radius;
  49999. var i;
  50000. for (i = 1; i < stride; ++i) {
  50001. flatCoordinates[stride + i] = center[i];
  50002. }
  50003. this.setFlatCoordinates(this.layout, flatCoordinates);
  50004. };
  50005. /**
  50006. * Set the center (as {@link ol.Coordinate coordinate}) and the radius (as
  50007. * number) of the circle.
  50008. * @param {ol.Coordinate} center Center.
  50009. * @param {number} radius Radius.
  50010. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  50011. * @api
  50012. */
  50013. ol.geom.Circle.prototype.setCenterAndRadius = function(center, radius, opt_layout) {
  50014. if (!center) {
  50015. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
  50016. } else {
  50017. this.setLayout(opt_layout, center, 0);
  50018. if (!this.flatCoordinates) {
  50019. this.flatCoordinates = [];
  50020. }
  50021. /** @type {Array.<number>} */
  50022. var flatCoordinates = this.flatCoordinates;
  50023. var offset = ol.geom.flat.deflate.coordinate(
  50024. flatCoordinates, 0, center, this.stride);
  50025. flatCoordinates[offset++] = flatCoordinates[0] + radius;
  50026. var i, ii;
  50027. for (i = 1, ii = this.stride; i < ii; ++i) {
  50028. flatCoordinates[offset++] = flatCoordinates[i];
  50029. }
  50030. flatCoordinates.length = offset;
  50031. this.changed();
  50032. }
  50033. };
  50034. /**
  50035. * @inheritDoc
  50036. */
  50037. ol.geom.Circle.prototype.getCoordinates = function() {};
  50038. /**
  50039. * @inheritDoc
  50040. */
  50041. ol.geom.Circle.prototype.setCoordinates = function(coordinates, opt_layout) {};
  50042. /**
  50043. * @param {ol.geom.GeometryLayout} layout Layout.
  50044. * @param {Array.<number>} flatCoordinates Flat coordinates.
  50045. */
  50046. ol.geom.Circle.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
  50047. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  50048. this.changed();
  50049. };
  50050. /**
  50051. * Set the radius of the circle. The radius is in the units of the projection.
  50052. * @param {number} radius Radius.
  50053. * @api
  50054. */
  50055. ol.geom.Circle.prototype.setRadius = function(radius) {
  50056. this.flatCoordinates[this.stride] = this.flatCoordinates[0] + radius;
  50057. this.changed();
  50058. };
  50059. /**
  50060. * Transform each coordinate of the circle from one coordinate reference system
  50061. * to another. The geometry is modified in place.
  50062. * If you do not want the geometry modified in place, first clone() it and
  50063. * then use this function on the clone.
  50064. *
  50065. * Internally a circle is currently represented by two points: the center of
  50066. * the circle `[cx, cy]`, and the point to the right of the circle
  50067. * `[cx + r, cy]`. This `transform` function just transforms these two points.
  50068. * So the resulting geometry is also a circle, and that circle does not
  50069. * correspond to the shape that would be obtained by transforming every point
  50070. * of the original circle.
  50071. *
  50072. * @param {ol.ProjectionLike} source The current projection. Can be a
  50073. * string identifier or a {@link ol.proj.Projection} object.
  50074. * @param {ol.ProjectionLike} destination The desired projection. Can be a
  50075. * string identifier or a {@link ol.proj.Projection} object.
  50076. * @return {ol.geom.Circle} This geometry. Note that original geometry is
  50077. * modified in place.
  50078. * @function
  50079. * @api
  50080. */
  50081. ol.geom.Circle.prototype.transform;
  50082. goog.provide('ol.geom.flat.geodesic');
  50083. goog.require('ol.math');
  50084. goog.require('ol.proj');
  50085. /**
  50086. * @private
  50087. * @param {function(number): ol.Coordinate} interpolate Interpolate function.
  50088. * @param {ol.TransformFunction} transform Transform from longitude/latitude to
  50089. * projected coordinates.
  50090. * @param {number} squaredTolerance Squared tolerance.
  50091. * @return {Array.<number>} Flat coordinates.
  50092. */
  50093. ol.geom.flat.geodesic.line_ = function(interpolate, transform, squaredTolerance) {
  50094. // FIXME reduce garbage generation
  50095. // FIXME optimize stack operations
  50096. /** @type {Array.<number>} */
  50097. var flatCoordinates = [];
  50098. var geoA = interpolate(0);
  50099. var geoB = interpolate(1);
  50100. var a = transform(geoA);
  50101. var b = transform(geoB);
  50102. /** @type {Array.<ol.Coordinate>} */
  50103. var geoStack = [geoB, geoA];
  50104. /** @type {Array.<ol.Coordinate>} */
  50105. var stack = [b, a];
  50106. /** @type {Array.<number>} */
  50107. var fractionStack = [1, 0];
  50108. /** @type {Object.<string, boolean>} */
  50109. var fractions = {};
  50110. var maxIterations = 1e5;
  50111. var geoM, m, fracA, fracB, fracM, key;
  50112. while (--maxIterations > 0 && fractionStack.length > 0) {
  50113. // Pop the a coordinate off the stack
  50114. fracA = fractionStack.pop();
  50115. geoA = geoStack.pop();
  50116. a = stack.pop();
  50117. // Add the a coordinate if it has not been added yet
  50118. key = fracA.toString();
  50119. if (!(key in fractions)) {
  50120. flatCoordinates.push(a[0], a[1]);
  50121. fractions[key] = true;
  50122. }
  50123. // Pop the b coordinate off the stack
  50124. fracB = fractionStack.pop();
  50125. geoB = geoStack.pop();
  50126. b = stack.pop();
  50127. // Find the m point between the a and b coordinates
  50128. fracM = (fracA + fracB) / 2;
  50129. geoM = interpolate(fracM);
  50130. m = transform(geoM);
  50131. if (ol.math.squaredSegmentDistance(m[0], m[1], a[0], a[1],
  50132. b[0], b[1]) < squaredTolerance) {
  50133. // If the m point is sufficiently close to the straight line, then we
  50134. // discard it. Just use the b coordinate and move on to the next line
  50135. // segment.
  50136. flatCoordinates.push(b[0], b[1]);
  50137. key = fracB.toString();
  50138. fractions[key] = true;
  50139. } else {
  50140. // Otherwise, we need to subdivide the current line segment. Split it
  50141. // into two and push the two line segments onto the stack.
  50142. fractionStack.push(fracB, fracM, fracM, fracA);
  50143. stack.push(b, m, m, a);
  50144. geoStack.push(geoB, geoM, geoM, geoA);
  50145. }
  50146. }
  50147. return flatCoordinates;
  50148. };
  50149. /**
  50150. * Generate a great-circle arcs between two lat/lon points.
  50151. * @param {number} lon1 Longitude 1 in degrees.
  50152. * @param {number} lat1 Latitude 1 in degrees.
  50153. * @param {number} lon2 Longitude 2 in degrees.
  50154. * @param {number} lat2 Latitude 2 in degrees.
  50155. * @param {ol.proj.Projection} projection Projection.
  50156. * @param {number} squaredTolerance Squared tolerance.
  50157. * @return {Array.<number>} Flat coordinates.
  50158. */
  50159. ol.geom.flat.geodesic.greatCircleArc = function(
  50160. lon1, lat1, lon2, lat2, projection, squaredTolerance) {
  50161. var geoProjection = ol.proj.get('EPSG:4326');
  50162. var cosLat1 = Math.cos(ol.math.toRadians(lat1));
  50163. var sinLat1 = Math.sin(ol.math.toRadians(lat1));
  50164. var cosLat2 = Math.cos(ol.math.toRadians(lat2));
  50165. var sinLat2 = Math.sin(ol.math.toRadians(lat2));
  50166. var cosDeltaLon = Math.cos(ol.math.toRadians(lon2 - lon1));
  50167. var sinDeltaLon = Math.sin(ol.math.toRadians(lon2 - lon1));
  50168. var d = sinLat1 * sinLat2 + cosLat1 * cosLat2 * cosDeltaLon;
  50169. return ol.geom.flat.geodesic.line_(
  50170. /**
  50171. * @param {number} frac Fraction.
  50172. * @return {ol.Coordinate} Coordinate.
  50173. */
  50174. function(frac) {
  50175. if (1 <= d) {
  50176. return [lon2, lat2];
  50177. }
  50178. var D = frac * Math.acos(d);
  50179. var cosD = Math.cos(D);
  50180. var sinD = Math.sin(D);
  50181. var y = sinDeltaLon * cosLat2;
  50182. var x = cosLat1 * sinLat2 - sinLat1 * cosLat2 * cosDeltaLon;
  50183. var theta = Math.atan2(y, x);
  50184. var lat = Math.asin(sinLat1 * cosD + cosLat1 * sinD * Math.cos(theta));
  50185. var lon = ol.math.toRadians(lon1) +
  50186. Math.atan2(Math.sin(theta) * sinD * cosLat1,
  50187. cosD - sinLat1 * Math.sin(lat));
  50188. return [ol.math.toDegrees(lon), ol.math.toDegrees(lat)];
  50189. }, ol.proj.getTransform(geoProjection, projection), squaredTolerance);
  50190. };
  50191. /**
  50192. * Generate a meridian (line at constant longitude).
  50193. * @param {number} lon Longitude.
  50194. * @param {number} lat1 Latitude 1.
  50195. * @param {number} lat2 Latitude 2.
  50196. * @param {ol.proj.Projection} projection Projection.
  50197. * @param {number} squaredTolerance Squared tolerance.
  50198. * @return {Array.<number>} Flat coordinates.
  50199. */
  50200. ol.geom.flat.geodesic.meridian = function(lon, lat1, lat2, projection, squaredTolerance) {
  50201. var epsg4326Projection = ol.proj.get('EPSG:4326');
  50202. return ol.geom.flat.geodesic.line_(
  50203. /**
  50204. * @param {number} frac Fraction.
  50205. * @return {ol.Coordinate} Coordinate.
  50206. */
  50207. function(frac) {
  50208. return [lon, lat1 + ((lat2 - lat1) * frac)];
  50209. },
  50210. ol.proj.getTransform(epsg4326Projection, projection), squaredTolerance);
  50211. };
  50212. /**
  50213. * Generate a parallel (line at constant latitude).
  50214. * @param {number} lat Latitude.
  50215. * @param {number} lon1 Longitude 1.
  50216. * @param {number} lon2 Longitude 2.
  50217. * @param {ol.proj.Projection} projection Projection.
  50218. * @param {number} squaredTolerance Squared tolerance.
  50219. * @return {Array.<number>} Flat coordinates.
  50220. */
  50221. ol.geom.flat.geodesic.parallel = function(lat, lon1, lon2, projection, squaredTolerance) {
  50222. var epsg4326Projection = ol.proj.get('EPSG:4326');
  50223. return ol.geom.flat.geodesic.line_(
  50224. /**
  50225. * @param {number} frac Fraction.
  50226. * @return {ol.Coordinate} Coordinate.
  50227. */
  50228. function(frac) {
  50229. return [lon1 + ((lon2 - lon1) * frac), lat];
  50230. },
  50231. ol.proj.getTransform(epsg4326Projection, projection), squaredTolerance);
  50232. };
  50233. goog.provide('ol.Graticule');
  50234. goog.require('ol.coordinate');
  50235. goog.require('ol.extent');
  50236. goog.require('ol.geom.GeometryLayout');
  50237. goog.require('ol.geom.LineString');
  50238. goog.require('ol.geom.Point');
  50239. goog.require('ol.geom.flat.geodesic');
  50240. goog.require('ol.math');
  50241. goog.require('ol.proj');
  50242. goog.require('ol.render.EventType');
  50243. goog.require('ol.style.Fill');
  50244. goog.require('ol.style.Stroke');
  50245. goog.require('ol.style.Text');
  50246. /**
  50247. * Render a grid for a coordinate system on a map.
  50248. * @constructor
  50249. * @param {olx.GraticuleOptions=} opt_options Options.
  50250. * @api
  50251. */
  50252. ol.Graticule = function(opt_options) {
  50253. var options = opt_options || {};
  50254. /**
  50255. * @type {ol.Map}
  50256. * @private
  50257. */
  50258. this.map_ = null;
  50259. /**
  50260. * @type {ol.proj.Projection}
  50261. * @private
  50262. */
  50263. this.projection_ = null;
  50264. /**
  50265. * @type {number}
  50266. * @private
  50267. */
  50268. this.maxLat_ = Infinity;
  50269. /**
  50270. * @type {number}
  50271. * @private
  50272. */
  50273. this.maxLon_ = Infinity;
  50274. /**
  50275. * @type {number}
  50276. * @private
  50277. */
  50278. this.minLat_ = -Infinity;
  50279. /**
  50280. * @type {number}
  50281. * @private
  50282. */
  50283. this.minLon_ = -Infinity;
  50284. /**
  50285. * @type {number}
  50286. * @private
  50287. */
  50288. this.maxLatP_ = Infinity;
  50289. /**
  50290. * @type {number}
  50291. * @private
  50292. */
  50293. this.maxLonP_ = Infinity;
  50294. /**
  50295. * @type {number}
  50296. * @private
  50297. */
  50298. this.minLatP_ = -Infinity;
  50299. /**
  50300. * @type {number}
  50301. * @private
  50302. */
  50303. this.minLonP_ = -Infinity;
  50304. /**
  50305. * @type {number}
  50306. * @private
  50307. */
  50308. this.targetSize_ = options.targetSize !== undefined ?
  50309. options.targetSize : 100;
  50310. /**
  50311. * @type {number}
  50312. * @private
  50313. */
  50314. this.maxLines_ = options.maxLines !== undefined ? options.maxLines : 100;
  50315. /**
  50316. * @type {Array.<ol.geom.LineString>}
  50317. * @private
  50318. */
  50319. this.meridians_ = [];
  50320. /**
  50321. * @type {Array.<ol.geom.LineString>}
  50322. * @private
  50323. */
  50324. this.parallels_ = [];
  50325. /**
  50326. * @type {ol.style.Stroke}
  50327. * @private
  50328. */
  50329. this.strokeStyle_ = options.strokeStyle !== undefined ?
  50330. options.strokeStyle : ol.Graticule.DEFAULT_STROKE_STYLE_;
  50331. /**
  50332. * @type {ol.TransformFunction|undefined}
  50333. * @private
  50334. */
  50335. this.fromLonLatTransform_ = undefined;
  50336. /**
  50337. * @type {ol.TransformFunction|undefined}
  50338. * @private
  50339. */
  50340. this.toLonLatTransform_ = undefined;
  50341. /**
  50342. * @type {ol.Coordinate}
  50343. * @private
  50344. */
  50345. this.projectionCenterLonLat_ = null;
  50346. /**
  50347. * @type {Array.<ol.GraticuleLabelDataType>}
  50348. * @private
  50349. */
  50350. this.meridiansLabels_ = null;
  50351. /**
  50352. * @type {Array.<ol.GraticuleLabelDataType>}
  50353. * @private
  50354. */
  50355. this.parallelsLabels_ = null;
  50356. if (options.showLabels == true) {
  50357. var degreesToString = ol.coordinate.degreesToStringHDMS;
  50358. /**
  50359. * @type {null|function(number):string}
  50360. * @private
  50361. */
  50362. this.lonLabelFormatter_ = options.lonLabelFormatter == undefined ?
  50363. degreesToString.bind(this, 'EW') : options.lonLabelFormatter;
  50364. /**
  50365. * @type {function(number):string}
  50366. * @private
  50367. */
  50368. this.latLabelFormatter_ = options.latLabelFormatter == undefined ?
  50369. degreesToString.bind(this, 'NS') : options.latLabelFormatter;
  50370. /**
  50371. * Longitude label position in fractions (0..1) of view extent. 0 means
  50372. * bottom, 1 means top.
  50373. * @type {number}
  50374. * @private
  50375. */
  50376. this.lonLabelPosition_ = options.lonLabelPosition == undefined ? 0 :
  50377. options.lonLabelPosition;
  50378. /**
  50379. * Latitude Label position in fractions (0..1) of view extent. 0 means left, 1
  50380. * means right.
  50381. * @type {number}
  50382. * @private
  50383. */
  50384. this.latLabelPosition_ = options.latLabelPosition == undefined ? 1 :
  50385. options.latLabelPosition;
  50386. /**
  50387. * @type {ol.style.Text}
  50388. * @private
  50389. */
  50390. this.lonLabelStyle_ = options.lonLabelStyle !== undefined ? options.lonLabelStyle :
  50391. new ol.style.Text({
  50392. font: '12px Calibri,sans-serif',
  50393. textBaseline: 'bottom',
  50394. fill: new ol.style.Fill({
  50395. color: 'rgba(0,0,0,1)'
  50396. }),
  50397. stroke: new ol.style.Stroke({
  50398. color: 'rgba(255,255,255,1)',
  50399. width: 3
  50400. })
  50401. });
  50402. /**
  50403. * @type {ol.style.Text}
  50404. * @private
  50405. */
  50406. this.latLabelStyle_ = options.latLabelStyle !== undefined ? options.latLabelStyle :
  50407. new ol.style.Text({
  50408. font: '12px Calibri,sans-serif',
  50409. textAlign: 'end',
  50410. fill: new ol.style.Fill({
  50411. color: 'rgba(0,0,0,1)'
  50412. }),
  50413. stroke: new ol.style.Stroke({
  50414. color: 'rgba(255,255,255,1)',
  50415. width: 3
  50416. })
  50417. });
  50418. this.meridiansLabels_ = [];
  50419. this.parallelsLabels_ = [];
  50420. }
  50421. this.setMap(options.map !== undefined ? options.map : null);
  50422. };
  50423. /**
  50424. * @type {ol.style.Stroke}
  50425. * @private
  50426. * @const
  50427. */
  50428. ol.Graticule.DEFAULT_STROKE_STYLE_ = new ol.style.Stroke({
  50429. color: 'rgba(0,0,0,0.2)'
  50430. });
  50431. /**
  50432. * TODO can be configurable
  50433. * @type {Array.<number>}
  50434. * @private
  50435. */
  50436. ol.Graticule.intervals_ = [90, 45, 30, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05,
  50437. 0.01, 0.005, 0.002, 0.001];
  50438. /**
  50439. * @param {number} lon Longitude.
  50440. * @param {number} minLat Minimal latitude.
  50441. * @param {number} maxLat Maximal latitude.
  50442. * @param {number} squaredTolerance Squared tolerance.
  50443. * @param {ol.Extent} extent Extent.
  50444. * @param {number} index Index.
  50445. * @return {number} Index.
  50446. * @private
  50447. */
  50448. ol.Graticule.prototype.addMeridian_ = function(lon, minLat, maxLat, squaredTolerance, extent, index) {
  50449. var lineString = this.getMeridian_(lon, minLat, maxLat,
  50450. squaredTolerance, index);
  50451. if (ol.extent.intersects(lineString.getExtent(), extent)) {
  50452. if (this.meridiansLabels_) {
  50453. var textPoint = this.getMeridianPoint_(lineString, extent, index);
  50454. this.meridiansLabels_[index] = {
  50455. geom: textPoint,
  50456. text: this.lonLabelFormatter_(lon)
  50457. };
  50458. }
  50459. this.meridians_[index++] = lineString;
  50460. }
  50461. return index;
  50462. };
  50463. /**
  50464. * @param {ol.geom.LineString} lineString Meridian
  50465. * @param {ol.Extent} extent Extent.
  50466. * @param {number} index Index.
  50467. * @return {ol.geom.Point} Meridian point.
  50468. * @private
  50469. */
  50470. ol.Graticule.prototype.getMeridianPoint_ = function(lineString, extent, index) {
  50471. var flatCoordinates = lineString.getFlatCoordinates();
  50472. var clampedBottom = Math.max(extent[1], flatCoordinates[1]);
  50473. var clampedTop = Math.min(extent[3], flatCoordinates[flatCoordinates.length - 1]);
  50474. var lat = ol.math.clamp(
  50475. extent[1] + Math.abs(extent[1] - extent[3]) * this.lonLabelPosition_,
  50476. clampedBottom, clampedTop);
  50477. var coordinate = [flatCoordinates[0], lat];
  50478. var point = this.meridiansLabels_[index] !== undefined ?
  50479. this.meridiansLabels_[index].geom : new ol.geom.Point(null);
  50480. point.setCoordinates(coordinate);
  50481. return point;
  50482. };
  50483. /**
  50484. * @param {number} lat Latitude.
  50485. * @param {number} minLon Minimal longitude.
  50486. * @param {number} maxLon Maximal longitude.
  50487. * @param {number} squaredTolerance Squared tolerance.
  50488. * @param {ol.Extent} extent Extent.
  50489. * @param {number} index Index.
  50490. * @return {number} Index.
  50491. * @private
  50492. */
  50493. ol.Graticule.prototype.addParallel_ = function(lat, minLon, maxLon, squaredTolerance, extent, index) {
  50494. var lineString = this.getParallel_(lat, minLon, maxLon, squaredTolerance,
  50495. index);
  50496. if (ol.extent.intersects(lineString.getExtent(), extent)) {
  50497. if (this.parallelsLabels_) {
  50498. var textPoint = this.getParallelPoint_(lineString, extent, index);
  50499. this.parallelsLabels_[index] = {
  50500. geom: textPoint,
  50501. text: this.latLabelFormatter_(lat)
  50502. };
  50503. }
  50504. this.parallels_[index++] = lineString;
  50505. }
  50506. return index;
  50507. };
  50508. /**
  50509. * @param {ol.geom.LineString} lineString Parallels.
  50510. * @param {ol.Extent} extent Extent.
  50511. * @param {number} index Index.
  50512. * @return {ol.geom.Point} Parallel point.
  50513. * @private
  50514. */
  50515. ol.Graticule.prototype.getParallelPoint_ = function(lineString, extent, index) {
  50516. var flatCoordinates = lineString.getFlatCoordinates();
  50517. var clampedLeft = Math.max(extent[0], flatCoordinates[0]);
  50518. var clampedRight = Math.min(extent[2], flatCoordinates[flatCoordinates.length - 2]);
  50519. var lon = ol.math.clamp(
  50520. extent[0] + Math.abs(extent[0] - extent[2]) * this.latLabelPosition_,
  50521. clampedLeft, clampedRight);
  50522. var coordinate = [lon, flatCoordinates[1]];
  50523. var point = this.parallelsLabels_[index] !== undefined ?
  50524. this.parallelsLabels_[index].geom : new ol.geom.Point(null);
  50525. point.setCoordinates(coordinate);
  50526. return point;
  50527. };
  50528. /**
  50529. * @param {ol.Extent} extent Extent.
  50530. * @param {ol.Coordinate} center Center.
  50531. * @param {number} resolution Resolution.
  50532. * @param {number} squaredTolerance Squared tolerance.
  50533. * @private
  50534. */
  50535. ol.Graticule.prototype.createGraticule_ = function(extent, center, resolution, squaredTolerance) {
  50536. var interval = this.getInterval_(resolution);
  50537. if (interval == -1) {
  50538. this.meridians_.length = this.parallels_.length = 0;
  50539. if (this.meridiansLabels_) {
  50540. this.meridiansLabels_.length = 0;
  50541. }
  50542. if (this.parallelsLabels_) {
  50543. this.parallelsLabels_.length = 0;
  50544. }
  50545. return;
  50546. }
  50547. var centerLonLat = this.toLonLatTransform_(center);
  50548. var centerLon = centerLonLat[0];
  50549. var centerLat = centerLonLat[1];
  50550. var maxLines = this.maxLines_;
  50551. var cnt, idx, lat, lon;
  50552. var validExtent = [
  50553. Math.max(extent[0], this.minLonP_),
  50554. Math.max(extent[1], this.minLatP_),
  50555. Math.min(extent[2], this.maxLonP_),
  50556. Math.min(extent[3], this.maxLatP_)
  50557. ];
  50558. validExtent = ol.proj.transformExtent(validExtent, this.projection_,
  50559. 'EPSG:4326');
  50560. var maxLat = validExtent[3];
  50561. var maxLon = validExtent[2];
  50562. var minLat = validExtent[1];
  50563. var minLon = validExtent[0];
  50564. // Create meridians
  50565. centerLon = Math.floor(centerLon / interval) * interval;
  50566. lon = ol.math.clamp(centerLon, this.minLon_, this.maxLon_);
  50567. idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, 0);
  50568. cnt = 0;
  50569. while (lon != this.minLon_ && cnt++ < maxLines) {
  50570. lon = Math.max(lon - interval, this.minLon_);
  50571. idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, idx);
  50572. }
  50573. lon = ol.math.clamp(centerLon, this.minLon_, this.maxLon_);
  50574. cnt = 0;
  50575. while (lon != this.maxLon_ && cnt++ < maxLines) {
  50576. lon = Math.min(lon + interval, this.maxLon_);
  50577. idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, idx);
  50578. }
  50579. this.meridians_.length = idx;
  50580. if (this.meridiansLabels_) {
  50581. this.meridiansLabels_.length = idx;
  50582. }
  50583. // Create parallels
  50584. centerLat = Math.floor(centerLat / interval) * interval;
  50585. lat = ol.math.clamp(centerLat, this.minLat_, this.maxLat_);
  50586. idx = this.addParallel_(lat, minLon, maxLon, squaredTolerance, extent, 0);
  50587. cnt = 0;
  50588. while (lat != this.minLat_ && cnt++ < maxLines) {
  50589. lat = Math.max(lat - interval, this.minLat_);
  50590. idx = this.addParallel_(lat, minLon, maxLon, squaredTolerance, extent, idx);
  50591. }
  50592. lat = ol.math.clamp(centerLat, this.minLat_, this.maxLat_);
  50593. cnt = 0;
  50594. while (lat != this.maxLat_ && cnt++ < maxLines) {
  50595. lat = Math.min(lat + interval, this.maxLat_);
  50596. idx = this.addParallel_(lat, minLon, maxLon, squaredTolerance, extent, idx);
  50597. }
  50598. this.parallels_.length = idx;
  50599. if (this.parallelsLabels_) {
  50600. this.parallelsLabels_.length = idx;
  50601. }
  50602. };
  50603. /**
  50604. * @param {number} resolution Resolution.
  50605. * @return {number} The interval in degrees.
  50606. * @private
  50607. */
  50608. ol.Graticule.prototype.getInterval_ = function(resolution) {
  50609. var centerLon = this.projectionCenterLonLat_[0];
  50610. var centerLat = this.projectionCenterLonLat_[1];
  50611. var interval = -1;
  50612. var i, ii, delta, dist;
  50613. var target = Math.pow(this.targetSize_ * resolution, 2);
  50614. /** @type {Array.<number>} **/
  50615. var p1 = [];
  50616. /** @type {Array.<number>} **/
  50617. var p2 = [];
  50618. for (i = 0, ii = ol.Graticule.intervals_.length; i < ii; ++i) {
  50619. delta = ol.Graticule.intervals_[i] / 2;
  50620. p1[0] = centerLon - delta;
  50621. p1[1] = centerLat - delta;
  50622. p2[0] = centerLon + delta;
  50623. p2[1] = centerLat + delta;
  50624. this.fromLonLatTransform_(p1, p1);
  50625. this.fromLonLatTransform_(p2, p2);
  50626. dist = Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2);
  50627. if (dist <= target) {
  50628. break;
  50629. }
  50630. interval = ol.Graticule.intervals_[i];
  50631. }
  50632. return interval;
  50633. };
  50634. /**
  50635. * Get the map associated with this graticule.
  50636. * @return {ol.Map} The map.
  50637. * @api
  50638. */
  50639. ol.Graticule.prototype.getMap = function() {
  50640. return this.map_;
  50641. };
  50642. /**
  50643. * @param {number} lon Longitude.
  50644. * @param {number} minLat Minimal latitude.
  50645. * @param {number} maxLat Maximal latitude.
  50646. * @param {number} squaredTolerance Squared tolerance.
  50647. * @return {ol.geom.LineString} The meridian line string.
  50648. * @param {number} index Index.
  50649. * @private
  50650. */
  50651. ol.Graticule.prototype.getMeridian_ = function(lon, minLat, maxLat,
  50652. squaredTolerance, index) {
  50653. var flatCoordinates = ol.geom.flat.geodesic.meridian(lon,
  50654. minLat, maxLat, this.projection_, squaredTolerance);
  50655. var lineString = this.meridians_[index] !== undefined ?
  50656. this.meridians_[index] : new ol.geom.LineString(null);
  50657. lineString.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates);
  50658. return lineString;
  50659. };
  50660. /**
  50661. * Get the list of meridians. Meridians are lines of equal longitude.
  50662. * @return {Array.<ol.geom.LineString>} The meridians.
  50663. * @api
  50664. */
  50665. ol.Graticule.prototype.getMeridians = function() {
  50666. return this.meridians_;
  50667. };
  50668. /**
  50669. * @param {number} lat Latitude.
  50670. * @param {number} minLon Minimal longitude.
  50671. * @param {number} maxLon Maximal longitude.
  50672. * @param {number} squaredTolerance Squared tolerance.
  50673. * @return {ol.geom.LineString} The parallel line string.
  50674. * @param {number} index Index.
  50675. * @private
  50676. */
  50677. ol.Graticule.prototype.getParallel_ = function(lat, minLon, maxLon,
  50678. squaredTolerance, index) {
  50679. var flatCoordinates = ol.geom.flat.geodesic.parallel(lat,
  50680. minLon, maxLon, this.projection_, squaredTolerance);
  50681. var lineString = this.parallels_[index] !== undefined ?
  50682. this.parallels_[index] : new ol.geom.LineString(null);
  50683. lineString.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates);
  50684. return lineString;
  50685. };
  50686. /**
  50687. * Get the list of parallels. Parallels are lines of equal latitude.
  50688. * @return {Array.<ol.geom.LineString>} The parallels.
  50689. * @api
  50690. */
  50691. ol.Graticule.prototype.getParallels = function() {
  50692. return this.parallels_;
  50693. };
  50694. /**
  50695. * @param {ol.render.Event} e Event.
  50696. * @private
  50697. */
  50698. ol.Graticule.prototype.handlePostCompose_ = function(e) {
  50699. var vectorContext = e.vectorContext;
  50700. var frameState = e.frameState;
  50701. var extent = frameState.extent;
  50702. var viewState = frameState.viewState;
  50703. var center = viewState.center;
  50704. var projection = viewState.projection;
  50705. var resolution = viewState.resolution;
  50706. var pixelRatio = frameState.pixelRatio;
  50707. var squaredTolerance =
  50708. resolution * resolution / (4 * pixelRatio * pixelRatio);
  50709. var updateProjectionInfo = !this.projection_ ||
  50710. !ol.proj.equivalent(this.projection_, projection);
  50711. if (updateProjectionInfo) {
  50712. this.updateProjectionInfo_(projection);
  50713. }
  50714. this.createGraticule_(extent, center, resolution, squaredTolerance);
  50715. // Draw the lines
  50716. vectorContext.setFillStrokeStyle(null, this.strokeStyle_);
  50717. var i, l, line;
  50718. for (i = 0, l = this.meridians_.length; i < l; ++i) {
  50719. line = this.meridians_[i];
  50720. vectorContext.drawGeometry(line);
  50721. }
  50722. for (i = 0, l = this.parallels_.length; i < l; ++i) {
  50723. line = this.parallels_[i];
  50724. vectorContext.drawGeometry(line);
  50725. }
  50726. var labelData;
  50727. if (this.meridiansLabels_) {
  50728. for (i = 0, l = this.meridiansLabels_.length; i < l; ++i) {
  50729. labelData = this.meridiansLabels_[i];
  50730. this.lonLabelStyle_.setText(labelData.text);
  50731. vectorContext.setTextStyle(this.lonLabelStyle_);
  50732. vectorContext.drawGeometry(labelData.geom);
  50733. }
  50734. }
  50735. if (this.parallelsLabels_) {
  50736. for (i = 0, l = this.parallelsLabels_.length; i < l; ++i) {
  50737. labelData = this.parallelsLabels_[i];
  50738. this.latLabelStyle_.setText(labelData.text);
  50739. vectorContext.setTextStyle(this.latLabelStyle_);
  50740. vectorContext.drawGeometry(labelData.geom);
  50741. }
  50742. }
  50743. };
  50744. /**
  50745. * @param {ol.proj.Projection} projection Projection.
  50746. * @private
  50747. */
  50748. ol.Graticule.prototype.updateProjectionInfo_ = function(projection) {
  50749. var epsg4326Projection = ol.proj.get('EPSG:4326');
  50750. var extent = projection.getExtent();
  50751. var worldExtent = projection.getWorldExtent();
  50752. var worldExtentP = ol.proj.transformExtent(worldExtent,
  50753. epsg4326Projection, projection);
  50754. var maxLat = worldExtent[3];
  50755. var maxLon = worldExtent[2];
  50756. var minLat = worldExtent[1];
  50757. var minLon = worldExtent[0];
  50758. var maxLatP = worldExtentP[3];
  50759. var maxLonP = worldExtentP[2];
  50760. var minLatP = worldExtentP[1];
  50761. var minLonP = worldExtentP[0];
  50762. this.maxLat_ = maxLat;
  50763. this.maxLon_ = maxLon;
  50764. this.minLat_ = minLat;
  50765. this.minLon_ = minLon;
  50766. this.maxLatP_ = maxLatP;
  50767. this.maxLonP_ = maxLonP;
  50768. this.minLatP_ = minLatP;
  50769. this.minLonP_ = minLonP;
  50770. this.fromLonLatTransform_ = ol.proj.getTransform(
  50771. epsg4326Projection, projection);
  50772. this.toLonLatTransform_ = ol.proj.getTransform(
  50773. projection, epsg4326Projection);
  50774. this.projectionCenterLonLat_ = this.toLonLatTransform_(
  50775. ol.extent.getCenter(extent));
  50776. this.projection_ = projection;
  50777. };
  50778. /**
  50779. * Set the map for this graticule. The graticule will be rendered on the
  50780. * provided map.
  50781. * @param {ol.Map} map Map.
  50782. * @api
  50783. */
  50784. ol.Graticule.prototype.setMap = function(map) {
  50785. if (this.map_) {
  50786. this.map_.un(ol.render.EventType.POSTCOMPOSE,
  50787. this.handlePostCompose_, this);
  50788. this.map_.render();
  50789. }
  50790. if (map) {
  50791. map.on(ol.render.EventType.POSTCOMPOSE,
  50792. this.handlePostCompose_, this);
  50793. map.render();
  50794. }
  50795. this.map_ = map;
  50796. };
  50797. goog.provide('ol.ImageBase');
  50798. goog.require('ol');
  50799. goog.require('ol.events.EventTarget');
  50800. goog.require('ol.events.EventType');
  50801. /**
  50802. * @constructor
  50803. * @abstract
  50804. * @extends {ol.events.EventTarget}
  50805. * @param {ol.Extent} extent Extent.
  50806. * @param {number|undefined} resolution Resolution.
  50807. * @param {number} pixelRatio Pixel ratio.
  50808. * @param {ol.ImageState} state State.
  50809. * @param {Array.<ol.Attribution>} attributions Attributions.
  50810. */
  50811. ol.ImageBase = function(extent, resolution, pixelRatio, state, attributions) {
  50812. ol.events.EventTarget.call(this);
  50813. /**
  50814. * @private
  50815. * @type {Array.<ol.Attribution>}
  50816. */
  50817. this.attributions_ = attributions;
  50818. /**
  50819. * @protected
  50820. * @type {ol.Extent}
  50821. */
  50822. this.extent = extent;
  50823. /**
  50824. * @private
  50825. * @type {number}
  50826. */
  50827. this.pixelRatio_ = pixelRatio;
  50828. /**
  50829. * @protected
  50830. * @type {number|undefined}
  50831. */
  50832. this.resolution = resolution;
  50833. /**
  50834. * @protected
  50835. * @type {ol.ImageState}
  50836. */
  50837. this.state = state;
  50838. };
  50839. ol.inherits(ol.ImageBase, ol.events.EventTarget);
  50840. /**
  50841. * @protected
  50842. */
  50843. ol.ImageBase.prototype.changed = function() {
  50844. this.dispatchEvent(ol.events.EventType.CHANGE);
  50845. };
  50846. /**
  50847. * @return {Array.<ol.Attribution>} Attributions.
  50848. */
  50849. ol.ImageBase.prototype.getAttributions = function() {
  50850. return this.attributions_;
  50851. };
  50852. /**
  50853. * @return {ol.Extent} Extent.
  50854. */
  50855. ol.ImageBase.prototype.getExtent = function() {
  50856. return this.extent;
  50857. };
  50858. /**
  50859. * @abstract
  50860. * @param {Object=} opt_context Object.
  50861. * @return {HTMLCanvasElement|Image|HTMLVideoElement} Image.
  50862. */
  50863. ol.ImageBase.prototype.getImage = function(opt_context) {};
  50864. /**
  50865. * @return {number} PixelRatio.
  50866. */
  50867. ol.ImageBase.prototype.getPixelRatio = function() {
  50868. return this.pixelRatio_;
  50869. };
  50870. /**
  50871. * @return {number} Resolution.
  50872. */
  50873. ol.ImageBase.prototype.getResolution = function() {
  50874. return /** @type {number} */ (this.resolution);
  50875. };
  50876. /**
  50877. * @return {ol.ImageState} State.
  50878. */
  50879. ol.ImageBase.prototype.getState = function() {
  50880. return this.state;
  50881. };
  50882. /**
  50883. * Load not yet loaded URI.
  50884. * @abstract
  50885. */
  50886. ol.ImageBase.prototype.load = function() {};
  50887. goog.provide('ol.Image');
  50888. goog.require('ol');
  50889. goog.require('ol.ImageBase');
  50890. goog.require('ol.ImageState');
  50891. goog.require('ol.events');
  50892. goog.require('ol.events.EventType');
  50893. goog.require('ol.extent');
  50894. goog.require('ol.obj');
  50895. /**
  50896. * @constructor
  50897. * @extends {ol.ImageBase}
  50898. * @param {ol.Extent} extent Extent.
  50899. * @param {number|undefined} resolution Resolution.
  50900. * @param {number} pixelRatio Pixel ratio.
  50901. * @param {Array.<ol.Attribution>} attributions Attributions.
  50902. * @param {string} src Image source URI.
  50903. * @param {?string} crossOrigin Cross origin.
  50904. * @param {ol.ImageLoadFunctionType} imageLoadFunction Image load function.
  50905. */
  50906. ol.Image = function(extent, resolution, pixelRatio, attributions, src,
  50907. crossOrigin, imageLoadFunction) {
  50908. ol.ImageBase.call(this, extent, resolution, pixelRatio, ol.ImageState.IDLE,
  50909. attributions);
  50910. /**
  50911. * @private
  50912. * @type {string}
  50913. */
  50914. this.src_ = src;
  50915. /**
  50916. * @private
  50917. * @type {HTMLCanvasElement|Image|HTMLVideoElement}
  50918. */
  50919. this.image_ = new Image();
  50920. if (crossOrigin !== null) {
  50921. this.image_.crossOrigin = crossOrigin;
  50922. }
  50923. /**
  50924. * @private
  50925. * @type {Object.<number, (HTMLCanvasElement|Image|HTMLVideoElement)>}
  50926. */
  50927. this.imageByContext_ = {};
  50928. /**
  50929. * @private
  50930. * @type {Array.<ol.EventsKey>}
  50931. */
  50932. this.imageListenerKeys_ = null;
  50933. /**
  50934. * @protected
  50935. * @type {ol.ImageState}
  50936. */
  50937. this.state = ol.ImageState.IDLE;
  50938. /**
  50939. * @private
  50940. * @type {ol.ImageLoadFunctionType}
  50941. */
  50942. this.imageLoadFunction_ = imageLoadFunction;
  50943. };
  50944. ol.inherits(ol.Image, ol.ImageBase);
  50945. /**
  50946. * @inheritDoc
  50947. * @api
  50948. */
  50949. ol.Image.prototype.getImage = function(opt_context) {
  50950. if (opt_context !== undefined) {
  50951. var image;
  50952. var key = ol.getUid(opt_context);
  50953. if (key in this.imageByContext_) {
  50954. return this.imageByContext_[key];
  50955. } else if (ol.obj.isEmpty(this.imageByContext_)) {
  50956. image = this.image_;
  50957. } else {
  50958. image = /** @type {Image} */ (this.image_.cloneNode(false));
  50959. }
  50960. this.imageByContext_[key] = image;
  50961. return image;
  50962. } else {
  50963. return this.image_;
  50964. }
  50965. };
  50966. /**
  50967. * Tracks loading or read errors.
  50968. *
  50969. * @private
  50970. */
  50971. ol.Image.prototype.handleImageError_ = function() {
  50972. this.state = ol.ImageState.ERROR;
  50973. this.unlistenImage_();
  50974. this.changed();
  50975. };
  50976. /**
  50977. * Tracks successful image load.
  50978. *
  50979. * @private
  50980. */
  50981. ol.Image.prototype.handleImageLoad_ = function() {
  50982. if (this.resolution === undefined) {
  50983. this.resolution = ol.extent.getHeight(this.extent) / this.image_.height;
  50984. }
  50985. this.state = ol.ImageState.LOADED;
  50986. this.unlistenImage_();
  50987. this.changed();
  50988. };
  50989. /**
  50990. * Load the image or retry if loading previously failed.
  50991. * Loading is taken care of by the tile queue, and calling this method is
  50992. * only needed for preloading or for reloading in case of an error.
  50993. * @override
  50994. * @api
  50995. */
  50996. ol.Image.prototype.load = function() {
  50997. if (this.state == ol.ImageState.IDLE || this.state == ol.ImageState.ERROR) {
  50998. this.state = ol.ImageState.LOADING;
  50999. this.changed();
  51000. this.imageListenerKeys_ = [
  51001. ol.events.listenOnce(this.image_, ol.events.EventType.ERROR,
  51002. this.handleImageError_, this),
  51003. ol.events.listenOnce(this.image_, ol.events.EventType.LOAD,
  51004. this.handleImageLoad_, this)
  51005. ];
  51006. this.imageLoadFunction_(this, this.src_);
  51007. }
  51008. };
  51009. /**
  51010. * @param {HTMLCanvasElement|Image|HTMLVideoElement} image Image.
  51011. */
  51012. ol.Image.prototype.setImage = function(image) {
  51013. this.image_ = image;
  51014. };
  51015. /**
  51016. * Discards event handlers which listen for load completion or errors.
  51017. *
  51018. * @private
  51019. */
  51020. ol.Image.prototype.unlistenImage_ = function() {
  51021. this.imageListenerKeys_.forEach(ol.events.unlistenByKey);
  51022. this.imageListenerKeys_ = null;
  51023. };
  51024. goog.provide('ol.ImageCanvas');
  51025. goog.require('ol');
  51026. goog.require('ol.ImageBase');
  51027. goog.require('ol.ImageState');
  51028. /**
  51029. * @constructor
  51030. * @extends {ol.ImageBase}
  51031. * @param {ol.Extent} extent Extent.
  51032. * @param {number} resolution Resolution.
  51033. * @param {number} pixelRatio Pixel ratio.
  51034. * @param {Array.<ol.Attribution>} attributions Attributions.
  51035. * @param {HTMLCanvasElement} canvas Canvas.
  51036. * @param {ol.ImageCanvasLoader=} opt_loader Optional loader function to
  51037. * support asynchronous canvas drawing.
  51038. */
  51039. ol.ImageCanvas = function(extent, resolution, pixelRatio, attributions,
  51040. canvas, opt_loader) {
  51041. /**
  51042. * Optional canvas loader function.
  51043. * @type {?ol.ImageCanvasLoader}
  51044. * @private
  51045. */
  51046. this.loader_ = opt_loader !== undefined ? opt_loader : null;
  51047. var state = opt_loader !== undefined ?
  51048. ol.ImageState.IDLE : ol.ImageState.LOADED;
  51049. ol.ImageBase.call(this, extent, resolution, pixelRatio, state, attributions);
  51050. /**
  51051. * @private
  51052. * @type {HTMLCanvasElement}
  51053. */
  51054. this.canvas_ = canvas;
  51055. /**
  51056. * @private
  51057. * @type {Error}
  51058. */
  51059. this.error_ = null;
  51060. };
  51061. ol.inherits(ol.ImageCanvas, ol.ImageBase);
  51062. /**
  51063. * Get any error associated with asynchronous rendering.
  51064. * @return {Error} Any error that occurred during rendering.
  51065. */
  51066. ol.ImageCanvas.prototype.getError = function() {
  51067. return this.error_;
  51068. };
  51069. /**
  51070. * Handle async drawing complete.
  51071. * @param {Error} err Any error during drawing.
  51072. * @private
  51073. */
  51074. ol.ImageCanvas.prototype.handleLoad_ = function(err) {
  51075. if (err) {
  51076. this.error_ = err;
  51077. this.state = ol.ImageState.ERROR;
  51078. } else {
  51079. this.state = ol.ImageState.LOADED;
  51080. }
  51081. this.changed();
  51082. };
  51083. /**
  51084. * @inheritDoc
  51085. */
  51086. ol.ImageCanvas.prototype.load = function() {
  51087. if (this.state == ol.ImageState.IDLE) {
  51088. this.state = ol.ImageState.LOADING;
  51089. this.changed();
  51090. this.loader_(this.handleLoad_.bind(this));
  51091. }
  51092. };
  51093. /**
  51094. * @inheritDoc
  51095. */
  51096. ol.ImageCanvas.prototype.getImage = function(opt_context) {
  51097. return this.canvas_;
  51098. };
  51099. goog.provide('ol.Tile');
  51100. goog.require('ol');
  51101. goog.require('ol.TileState');
  51102. goog.require('ol.events.EventTarget');
  51103. goog.require('ol.events.EventType');
  51104. /**
  51105. * @classdesc
  51106. * Base class for tiles.
  51107. *
  51108. * @constructor
  51109. * @abstract
  51110. * @extends {ol.events.EventTarget}
  51111. * @param {ol.TileCoord} tileCoord Tile coordinate.
  51112. * @param {ol.TileState} state State.
  51113. */
  51114. ol.Tile = function(tileCoord, state) {
  51115. ol.events.EventTarget.call(this);
  51116. /**
  51117. * @type {ol.TileCoord}
  51118. */
  51119. this.tileCoord = tileCoord;
  51120. /**
  51121. * @protected
  51122. * @type {ol.TileState}
  51123. */
  51124. this.state = state;
  51125. /**
  51126. * An "interim" tile for this tile. The interim tile may be used while this
  51127. * one is loading, for "smooth" transitions when changing params/dimensions
  51128. * on the source.
  51129. * @type {ol.Tile}
  51130. */
  51131. this.interimTile = null;
  51132. /**
  51133. * A key assigned to the tile. This is used by the tile source to determine
  51134. * if this tile can effectively be used, or if a new tile should be created
  51135. * and this one be used as an interim tile for this new tile.
  51136. * @type {string}
  51137. */
  51138. this.key = '';
  51139. };
  51140. ol.inherits(ol.Tile, ol.events.EventTarget);
  51141. /**
  51142. * @protected
  51143. */
  51144. ol.Tile.prototype.changed = function() {
  51145. this.dispatchEvent(ol.events.EventType.CHANGE);
  51146. };
  51147. /**
  51148. * @return {string} Key.
  51149. */
  51150. ol.Tile.prototype.getKey = function() {
  51151. return this.key + '/' + this.tileCoord;
  51152. };
  51153. /**
  51154. * Get the interim tile most suitable for rendering using the chain of interim
  51155. * tiles. This corresponds to the most recent tile that has been loaded, if no
  51156. * such tile exists, the original tile is returned.
  51157. * @return {!ol.Tile} Best tile for rendering.
  51158. */
  51159. ol.Tile.prototype.getInterimTile = function() {
  51160. if (!this.interimTile) {
  51161. //empty chain
  51162. return this;
  51163. }
  51164. var tile = this.interimTile;
  51165. // find the first loaded tile and return it. Since the chain is sorted in
  51166. // decreasing order of creation time, there is no need to search the remainder
  51167. // of the list (all those tiles correspond to older requests and will be
  51168. // cleaned up by refreshInterimChain)
  51169. do {
  51170. if (tile.getState() == ol.TileState.LOADED) {
  51171. return tile;
  51172. }
  51173. tile = tile.interimTile;
  51174. } while (tile);
  51175. // we can not find a better tile
  51176. return this;
  51177. };
  51178. /**
  51179. * Goes through the chain of interim tiles and discards sections of the chain
  51180. * that are no longer relevant.
  51181. */
  51182. ol.Tile.prototype.refreshInterimChain = function() {
  51183. if (!this.interimTile) {
  51184. return;
  51185. }
  51186. var tile = this.interimTile;
  51187. var prev = this;
  51188. do {
  51189. if (tile.getState() == ol.TileState.LOADED) {
  51190. //we have a loaded tile, we can discard the rest of the list
  51191. //we would could abort any LOADING tile request
  51192. //older than this tile (i.e. any LOADING tile following this entry in the chain)
  51193. tile.interimTile = null;
  51194. break;
  51195. } else if (tile.getState() == ol.TileState.LOADING) {
  51196. //keep this LOADING tile any loaded tiles later in the chain are
  51197. //older than this tile, so we're still interested in the request
  51198. prev = tile;
  51199. } else if (tile.getState() == ol.TileState.IDLE) {
  51200. //the head of the list is the most current tile, we don't need
  51201. //to start any other requests for this chain
  51202. prev.interimTile = tile.interimTile;
  51203. } else {
  51204. prev = tile;
  51205. }
  51206. tile = prev.interimTile;
  51207. } while (tile);
  51208. };
  51209. /**
  51210. * Get the tile coordinate for this tile.
  51211. * @return {ol.TileCoord} The tile coordinate.
  51212. * @api
  51213. */
  51214. ol.Tile.prototype.getTileCoord = function() {
  51215. return this.tileCoord;
  51216. };
  51217. /**
  51218. * @return {ol.TileState} State.
  51219. */
  51220. ol.Tile.prototype.getState = function() {
  51221. return this.state;
  51222. };
  51223. /**
  51224. * @param {ol.TileState} state State.
  51225. */
  51226. ol.Tile.prototype.setState = function(state) {
  51227. this.state = state;
  51228. this.changed();
  51229. };
  51230. /**
  51231. * Load the image or retry if loading previously failed.
  51232. * Loading is taken care of by the tile queue, and calling this method is
  51233. * only needed for preloading or for reloading in case of an error.
  51234. * @abstract
  51235. * @api
  51236. */
  51237. ol.Tile.prototype.load = function() {};
  51238. goog.provide('ol.ImageTile');
  51239. goog.require('ol');
  51240. goog.require('ol.Tile');
  51241. goog.require('ol.TileState');
  51242. goog.require('ol.dom');
  51243. goog.require('ol.events');
  51244. goog.require('ol.events.EventType');
  51245. /**
  51246. * @constructor
  51247. * @extends {ol.Tile}
  51248. * @param {ol.TileCoord} tileCoord Tile coordinate.
  51249. * @param {ol.TileState} state State.
  51250. * @param {string} src Image source URI.
  51251. * @param {?string} crossOrigin Cross origin.
  51252. * @param {ol.TileLoadFunctionType} tileLoadFunction Tile load function.
  51253. */
  51254. ol.ImageTile = function(tileCoord, state, src, crossOrigin, tileLoadFunction) {
  51255. ol.Tile.call(this, tileCoord, state);
  51256. /**
  51257. * Image URI
  51258. *
  51259. * @private
  51260. * @type {string}
  51261. */
  51262. this.src_ = src;
  51263. /**
  51264. * @private
  51265. * @type {Image|HTMLCanvasElement}
  51266. */
  51267. this.image_ = new Image();
  51268. if (crossOrigin !== null) {
  51269. this.image_.crossOrigin = crossOrigin;
  51270. }
  51271. /**
  51272. * @private
  51273. * @type {Array.<ol.EventsKey>}
  51274. */
  51275. this.imageListenerKeys_ = null;
  51276. /**
  51277. * @private
  51278. * @type {ol.TileLoadFunctionType}
  51279. */
  51280. this.tileLoadFunction_ = tileLoadFunction;
  51281. };
  51282. ol.inherits(ol.ImageTile, ol.Tile);
  51283. /**
  51284. * @inheritDoc
  51285. */
  51286. ol.ImageTile.prototype.disposeInternal = function() {
  51287. if (this.state == ol.TileState.LOADING) {
  51288. this.unlistenImage_();
  51289. this.image_.src = ol.ImageTile.blankImage.toDataURL('image/png');
  51290. }
  51291. if (this.interimTile) {
  51292. this.interimTile.dispose();
  51293. }
  51294. this.state = ol.TileState.ABORT;
  51295. this.changed();
  51296. ol.Tile.prototype.disposeInternal.call(this);
  51297. };
  51298. /**
  51299. * Get the HTML image element for this tile (may be a Canvas, Image, or Video).
  51300. * @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
  51301. * @api
  51302. */
  51303. ol.ImageTile.prototype.getImage = function() {
  51304. return this.image_;
  51305. };
  51306. /**
  51307. * @inheritDoc
  51308. */
  51309. ol.ImageTile.prototype.getKey = function() {
  51310. return this.src_;
  51311. };
  51312. /**
  51313. * Tracks loading or read errors.
  51314. *
  51315. * @private
  51316. */
  51317. ol.ImageTile.prototype.handleImageError_ = function() {
  51318. this.state = ol.TileState.ERROR;
  51319. this.unlistenImage_();
  51320. this.image_ = ol.ImageTile.blankImage;
  51321. this.changed();
  51322. };
  51323. /**
  51324. * Tracks successful image load.
  51325. *
  51326. * @private
  51327. */
  51328. ol.ImageTile.prototype.handleImageLoad_ = function() {
  51329. if (this.image_.naturalWidth && this.image_.naturalHeight) {
  51330. this.state = ol.TileState.LOADED;
  51331. } else {
  51332. this.state = ol.TileState.EMPTY;
  51333. }
  51334. this.unlistenImage_();
  51335. this.changed();
  51336. };
  51337. /**
  51338. * @inheritDoc
  51339. * @api
  51340. */
  51341. ol.ImageTile.prototype.load = function() {
  51342. if (this.state == ol.TileState.IDLE || this.state == ol.TileState.ERROR) {
  51343. this.state = ol.TileState.LOADING;
  51344. this.changed();
  51345. this.imageListenerKeys_ = [
  51346. ol.events.listenOnce(this.image_, ol.events.EventType.ERROR,
  51347. this.handleImageError_, this),
  51348. ol.events.listenOnce(this.image_, ol.events.EventType.LOAD,
  51349. this.handleImageLoad_, this)
  51350. ];
  51351. this.tileLoadFunction_(this, this.src_);
  51352. }
  51353. };
  51354. /**
  51355. * Discards event handlers which listen for load completion or errors.
  51356. *
  51357. * @private
  51358. */
  51359. ol.ImageTile.prototype.unlistenImage_ = function() {
  51360. this.imageListenerKeys_.forEach(ol.events.unlistenByKey);
  51361. this.imageListenerKeys_ = null;
  51362. };
  51363. /**
  51364. * A blank image.
  51365. * @type {HTMLCanvasElement}
  51366. */
  51367. ol.ImageTile.blankImage = (function() {
  51368. var ctx = ol.dom.createCanvasContext2D(1, 1);
  51369. ctx.fillStyle = 'rgba(0,0,0,0)';
  51370. ctx.fillRect(0, 0, 1, 1);
  51371. return ctx.canvas;
  51372. })();
  51373. // FIXME should handle all geo-referenced data, not just vector data
  51374. goog.provide('ol.interaction.DragAndDrop');
  51375. goog.require('ol');
  51376. goog.require('ol.functions');
  51377. goog.require('ol.events');
  51378. goog.require('ol.events.Event');
  51379. goog.require('ol.events.EventType');
  51380. goog.require('ol.interaction.Interaction');
  51381. goog.require('ol.proj');
  51382. /**
  51383. * @classdesc
  51384. * Handles input of vector data by drag and drop.
  51385. *
  51386. * @constructor
  51387. * @extends {ol.interaction.Interaction}
  51388. * @fires ol.interaction.DragAndDrop.Event
  51389. * @param {olx.interaction.DragAndDropOptions=} opt_options Options.
  51390. * @api
  51391. */
  51392. ol.interaction.DragAndDrop = function(opt_options) {
  51393. var options = opt_options ? opt_options : {};
  51394. ol.interaction.Interaction.call(this, {
  51395. handleEvent: ol.interaction.DragAndDrop.handleEvent
  51396. });
  51397. /**
  51398. * @private
  51399. * @type {Array.<function(new: ol.format.Feature)>}
  51400. */
  51401. this.formatConstructors_ = options.formatConstructors ?
  51402. options.formatConstructors : [];
  51403. /**
  51404. * @private
  51405. * @type {ol.proj.Projection}
  51406. */
  51407. this.projection_ = options.projection ?
  51408. ol.proj.get(options.projection) : null;
  51409. /**
  51410. * @private
  51411. * @type {Array.<ol.EventsKey>}
  51412. */
  51413. this.dropListenKeys_ = null;
  51414. /**
  51415. * @private
  51416. * @type {ol.source.Vector}
  51417. */
  51418. this.source_ = options.source || null;
  51419. /**
  51420. * @private
  51421. * @type {Element}
  51422. */
  51423. this.target = options.target ? options.target : null;
  51424. };
  51425. ol.inherits(ol.interaction.DragAndDrop, ol.interaction.Interaction);
  51426. /**
  51427. * @param {Event} event Event.
  51428. * @this {ol.interaction.DragAndDrop}
  51429. * @private
  51430. */
  51431. ol.interaction.DragAndDrop.handleDrop_ = function(event) {
  51432. var files = event.dataTransfer.files;
  51433. var i, ii, file;
  51434. for (i = 0, ii = files.length; i < ii; ++i) {
  51435. file = files.item(i);
  51436. var reader = new FileReader();
  51437. reader.addEventListener(ol.events.EventType.LOAD,
  51438. this.handleResult_.bind(this, file));
  51439. reader.readAsText(file);
  51440. }
  51441. };
  51442. /**
  51443. * @param {Event} event Event.
  51444. * @private
  51445. */
  51446. ol.interaction.DragAndDrop.handleStop_ = function(event) {
  51447. event.stopPropagation();
  51448. event.preventDefault();
  51449. event.dataTransfer.dropEffect = 'copy';
  51450. };
  51451. /**
  51452. * @param {File} file File.
  51453. * @param {Event} event Load event.
  51454. * @private
  51455. */
  51456. ol.interaction.DragAndDrop.prototype.handleResult_ = function(file, event) {
  51457. var result = event.target.result;
  51458. var map = this.getMap();
  51459. var projection = this.projection_;
  51460. if (!projection) {
  51461. var view = map.getView();
  51462. projection = view.getProjection();
  51463. }
  51464. var formatConstructors = this.formatConstructors_;
  51465. var features = [];
  51466. var i, ii;
  51467. for (i = 0, ii = formatConstructors.length; i < ii; ++i) {
  51468. /**
  51469. * Avoid "cannot instantiate abstract class" error.
  51470. * @type {Function}
  51471. */
  51472. var formatConstructor = formatConstructors[i];
  51473. /**
  51474. * @type {ol.format.Feature}
  51475. */
  51476. var format = new formatConstructor();
  51477. features = this.tryReadFeatures_(format, result, {
  51478. featureProjection: projection
  51479. });
  51480. if (features && features.length > 0) {
  51481. break;
  51482. }
  51483. }
  51484. if (this.source_) {
  51485. this.source_.clear();
  51486. this.source_.addFeatures(features);
  51487. }
  51488. this.dispatchEvent(
  51489. new ol.interaction.DragAndDrop.Event(
  51490. ol.interaction.DragAndDrop.EventType_.ADD_FEATURES, file,
  51491. features, projection));
  51492. };
  51493. /**
  51494. * Handles the {@link ol.MapBrowserEvent map browser event} unconditionally and
  51495. * neither prevents the browser default nor stops event propagation.
  51496. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  51497. * @return {boolean} `false` to stop event propagation.
  51498. * @this {ol.interaction.DragAndDrop}
  51499. * @api
  51500. */
  51501. ol.interaction.DragAndDrop.handleEvent = ol.functions.TRUE;
  51502. /**
  51503. * @private
  51504. */
  51505. ol.interaction.DragAndDrop.prototype.registerListeners_ = function() {
  51506. var map = this.getMap();
  51507. if (map) {
  51508. var dropArea = this.target ? this.target : map.getViewport();
  51509. this.dropListenKeys_ = [
  51510. ol.events.listen(dropArea, ol.events.EventType.DROP,
  51511. ol.interaction.DragAndDrop.handleDrop_, this),
  51512. ol.events.listen(dropArea, ol.events.EventType.DRAGENTER,
  51513. ol.interaction.DragAndDrop.handleStop_, this),
  51514. ol.events.listen(dropArea, ol.events.EventType.DRAGOVER,
  51515. ol.interaction.DragAndDrop.handleStop_, this),
  51516. ol.events.listen(dropArea, ol.events.EventType.DROP,
  51517. ol.interaction.DragAndDrop.handleStop_, this)
  51518. ];
  51519. }
  51520. };
  51521. /**
  51522. * @inheritDoc
  51523. */
  51524. ol.interaction.DragAndDrop.prototype.setActive = function(active) {
  51525. ol.interaction.Interaction.prototype.setActive.call(this, active);
  51526. if (active) {
  51527. this.registerListeners_();
  51528. } else {
  51529. this.unregisterListeners_();
  51530. }
  51531. };
  51532. /**
  51533. * @inheritDoc
  51534. */
  51535. ol.interaction.DragAndDrop.prototype.setMap = function(map) {
  51536. this.unregisterListeners_();
  51537. ol.interaction.Interaction.prototype.setMap.call(this, map);
  51538. if (this.getActive()) {
  51539. this.registerListeners_();
  51540. }
  51541. };
  51542. /**
  51543. * @param {ol.format.Feature} format Format.
  51544. * @param {string} text Text.
  51545. * @param {olx.format.ReadOptions} options Read options.
  51546. * @private
  51547. * @return {Array.<ol.Feature>} Features.
  51548. */
  51549. ol.interaction.DragAndDrop.prototype.tryReadFeatures_ = function(format, text, options) {
  51550. try {
  51551. return format.readFeatures(text, options);
  51552. } catch (e) {
  51553. return null;
  51554. }
  51555. };
  51556. /**
  51557. * @private
  51558. */
  51559. ol.interaction.DragAndDrop.prototype.unregisterListeners_ = function() {
  51560. if (this.dropListenKeys_) {
  51561. this.dropListenKeys_.forEach(ol.events.unlistenByKey);
  51562. this.dropListenKeys_ = null;
  51563. }
  51564. };
  51565. /**
  51566. * @enum {string}
  51567. * @private
  51568. */
  51569. ol.interaction.DragAndDrop.EventType_ = {
  51570. /**
  51571. * Triggered when features are added
  51572. * @event ol.interaction.DragAndDrop.Event#addfeatures
  51573. * @api
  51574. */
  51575. ADD_FEATURES: 'addfeatures'
  51576. };
  51577. /**
  51578. * @classdesc
  51579. * Events emitted by {@link ol.interaction.DragAndDrop} instances are instances
  51580. * of this type.
  51581. *
  51582. * @constructor
  51583. * @extends {ol.events.Event}
  51584. * @implements {oli.interaction.DragAndDropEvent}
  51585. * @param {ol.interaction.DragAndDrop.EventType_} type Type.
  51586. * @param {File} file File.
  51587. * @param {Array.<ol.Feature>=} opt_features Features.
  51588. * @param {ol.proj.Projection=} opt_projection Projection.
  51589. */
  51590. ol.interaction.DragAndDrop.Event = function(type, file, opt_features, opt_projection) {
  51591. ol.events.Event.call(this, type);
  51592. /**
  51593. * The features parsed from dropped data.
  51594. * @type {Array.<ol.Feature>|undefined}
  51595. * @api
  51596. */
  51597. this.features = opt_features;
  51598. /**
  51599. * The dropped file.
  51600. * @type {File}
  51601. * @api
  51602. */
  51603. this.file = file;
  51604. /**
  51605. * The feature projection.
  51606. * @type {ol.proj.Projection|undefined}
  51607. * @api
  51608. */
  51609. this.projection = opt_projection;
  51610. };
  51611. ol.inherits(ol.interaction.DragAndDrop.Event, ol.events.Event);
  51612. goog.provide('ol.interaction.DragRotateAndZoom');
  51613. goog.require('ol');
  51614. goog.require('ol.RotationConstraint');
  51615. goog.require('ol.ViewHint');
  51616. goog.require('ol.events.condition');
  51617. goog.require('ol.interaction.Interaction');
  51618. goog.require('ol.interaction.Pointer');
  51619. /**
  51620. * @classdesc
  51621. * Allows the user to zoom and rotate the map by clicking and dragging
  51622. * on the map. By default, this interaction is limited to when the shift
  51623. * key is held down.
  51624. *
  51625. * This interaction is only supported for mouse devices.
  51626. *
  51627. * And this interaction is not included in the default interactions.
  51628. *
  51629. * @constructor
  51630. * @extends {ol.interaction.Pointer}
  51631. * @param {olx.interaction.DragRotateAndZoomOptions=} opt_options Options.
  51632. * @api
  51633. */
  51634. ol.interaction.DragRotateAndZoom = function(opt_options) {
  51635. var options = opt_options ? opt_options : {};
  51636. ol.interaction.Pointer.call(this, {
  51637. handleDownEvent: ol.interaction.DragRotateAndZoom.handleDownEvent_,
  51638. handleDragEvent: ol.interaction.DragRotateAndZoom.handleDragEvent_,
  51639. handleUpEvent: ol.interaction.DragRotateAndZoom.handleUpEvent_
  51640. });
  51641. /**
  51642. * @private
  51643. * @type {ol.EventsConditionType}
  51644. */
  51645. this.condition_ = options.condition ?
  51646. options.condition : ol.events.condition.shiftKeyOnly;
  51647. /**
  51648. * @private
  51649. * @type {number|undefined}
  51650. */
  51651. this.lastAngle_ = undefined;
  51652. /**
  51653. * @private
  51654. * @type {number|undefined}
  51655. */
  51656. this.lastMagnitude_ = undefined;
  51657. /**
  51658. * @private
  51659. * @type {number}
  51660. */
  51661. this.lastScaleDelta_ = 0;
  51662. /**
  51663. * @private
  51664. * @type {number}
  51665. */
  51666. this.duration_ = options.duration !== undefined ? options.duration : 400;
  51667. };
  51668. ol.inherits(ol.interaction.DragRotateAndZoom, ol.interaction.Pointer);
  51669. /**
  51670. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  51671. * @this {ol.interaction.DragRotateAndZoom}
  51672. * @private
  51673. */
  51674. ol.interaction.DragRotateAndZoom.handleDragEvent_ = function(mapBrowserEvent) {
  51675. if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
  51676. return;
  51677. }
  51678. var map = mapBrowserEvent.map;
  51679. var size = map.getSize();
  51680. var offset = mapBrowserEvent.pixel;
  51681. var deltaX = offset[0] - size[0] / 2;
  51682. var deltaY = size[1] / 2 - offset[1];
  51683. var theta = Math.atan2(deltaY, deltaX);
  51684. var magnitude = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
  51685. var view = map.getView();
  51686. if (view.getConstraints().rotation !== ol.RotationConstraint.disable && this.lastAngle_ !== undefined) {
  51687. var angleDelta = theta - this.lastAngle_;
  51688. ol.interaction.Interaction.rotateWithoutConstraints(
  51689. view, view.getRotation() - angleDelta);
  51690. }
  51691. this.lastAngle_ = theta;
  51692. if (this.lastMagnitude_ !== undefined) {
  51693. var resolution = this.lastMagnitude_ * (view.getResolution() / magnitude);
  51694. ol.interaction.Interaction.zoomWithoutConstraints(view, resolution);
  51695. }
  51696. if (this.lastMagnitude_ !== undefined) {
  51697. this.lastScaleDelta_ = this.lastMagnitude_ / magnitude;
  51698. }
  51699. this.lastMagnitude_ = magnitude;
  51700. };
  51701. /**
  51702. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  51703. * @return {boolean} Stop drag sequence?
  51704. * @this {ol.interaction.DragRotateAndZoom}
  51705. * @private
  51706. */
  51707. ol.interaction.DragRotateAndZoom.handleUpEvent_ = function(mapBrowserEvent) {
  51708. if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
  51709. return true;
  51710. }
  51711. var map = mapBrowserEvent.map;
  51712. var view = map.getView();
  51713. view.setHint(ol.ViewHint.INTERACTING, -1);
  51714. var direction = this.lastScaleDelta_ - 1;
  51715. ol.interaction.Interaction.rotate(view, view.getRotation());
  51716. ol.interaction.Interaction.zoom(view, view.getResolution(),
  51717. undefined, this.duration_, direction);
  51718. this.lastScaleDelta_ = 0;
  51719. return false;
  51720. };
  51721. /**
  51722. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  51723. * @return {boolean} Start drag sequence?
  51724. * @this {ol.interaction.DragRotateAndZoom}
  51725. * @private
  51726. */
  51727. ol.interaction.DragRotateAndZoom.handleDownEvent_ = function(mapBrowserEvent) {
  51728. if (!ol.events.condition.mouseOnly(mapBrowserEvent)) {
  51729. return false;
  51730. }
  51731. if (this.condition_(mapBrowserEvent)) {
  51732. mapBrowserEvent.map.getView().setHint(ol.ViewHint.INTERACTING, 1);
  51733. this.lastAngle_ = undefined;
  51734. this.lastMagnitude_ = undefined;
  51735. return true;
  51736. } else {
  51737. return false;
  51738. }
  51739. };
  51740. goog.provide('ol.interaction.DrawEventType');
  51741. /**
  51742. * @enum {string}
  51743. */
  51744. ol.interaction.DrawEventType = {
  51745. /**
  51746. * Triggered upon feature draw start
  51747. * @event ol.interaction.Draw.Event#drawstart
  51748. * @api
  51749. */
  51750. DRAWSTART: 'drawstart',
  51751. /**
  51752. * Triggered upon feature draw end
  51753. * @event ol.interaction.Draw.Event#drawend
  51754. * @api
  51755. */
  51756. DRAWEND: 'drawend'
  51757. };
  51758. goog.provide('ol.render.canvas.Instruction');
  51759. /**
  51760. * @enum {number}
  51761. */
  51762. ol.render.canvas.Instruction = {
  51763. BEGIN_GEOMETRY: 0,
  51764. BEGIN_PATH: 1,
  51765. CIRCLE: 2,
  51766. CLOSE_PATH: 3,
  51767. CUSTOM: 4,
  51768. DRAW_IMAGE: 5,
  51769. DRAW_TEXT: 6,
  51770. END_GEOMETRY: 7,
  51771. FILL: 8,
  51772. MOVE_TO_LINE_TO: 9,
  51773. SET_FILL_STYLE: 10,
  51774. SET_STROKE_STYLE: 11,
  51775. SET_TEXT_STYLE: 12,
  51776. STROKE: 13
  51777. };
  51778. goog.provide('ol.render.canvas.Replay');
  51779. goog.require('ol');
  51780. goog.require('ol.array');
  51781. goog.require('ol.extent');
  51782. goog.require('ol.extent.Relationship');
  51783. goog.require('ol.geom.GeometryType');
  51784. goog.require('ol.geom.flat.inflate');
  51785. goog.require('ol.geom.flat.transform');
  51786. goog.require('ol.has');
  51787. goog.require('ol.obj');
  51788. goog.require('ol.render.VectorContext');
  51789. goog.require('ol.render.canvas.Instruction');
  51790. goog.require('ol.transform');
  51791. /**
  51792. * @constructor
  51793. * @extends {ol.render.VectorContext}
  51794. * @param {number} tolerance Tolerance.
  51795. * @param {ol.Extent} maxExtent Maximum extent.
  51796. * @param {number} resolution Resolution.
  51797. * @param {boolean} overlaps The replay can have overlapping geometries.
  51798. * @struct
  51799. */
  51800. ol.render.canvas.Replay = function(tolerance, maxExtent, resolution, overlaps) {
  51801. ol.render.VectorContext.call(this);
  51802. /**
  51803. * @protected
  51804. * @type {number}
  51805. */
  51806. this.tolerance = tolerance;
  51807. /**
  51808. * @protected
  51809. * @const
  51810. * @type {ol.Extent}
  51811. */
  51812. this.maxExtent = maxExtent;
  51813. /**
  51814. * @protected
  51815. * @type {boolean}
  51816. */
  51817. this.overlaps = overlaps;
  51818. /**
  51819. * @protected
  51820. * @type {number}
  51821. */
  51822. this.maxLineWidth = 0;
  51823. /**
  51824. * @protected
  51825. * @const
  51826. * @type {number}
  51827. */
  51828. this.resolution = resolution;
  51829. /**
  51830. * @private
  51831. * @type {ol.Coordinate}
  51832. */
  51833. this.fillOrigin_;
  51834. /**
  51835. * @private
  51836. * @type {Array.<*>}
  51837. */
  51838. this.beginGeometryInstruction1_ = null;
  51839. /**
  51840. * @private
  51841. * @type {Array.<*>}
  51842. */
  51843. this.beginGeometryInstruction2_ = null;
  51844. /**
  51845. * @protected
  51846. * @type {Array.<*>}
  51847. */
  51848. this.instructions = [];
  51849. /**
  51850. * @protected
  51851. * @type {Array.<number>}
  51852. */
  51853. this.coordinates = [];
  51854. /**
  51855. * @private
  51856. * @type {Object.<number,ol.Coordinate|Array.<ol.Coordinate>|Array.<Array.<ol.Coordinate>>>}
  51857. */
  51858. this.coordinateCache_ = {};
  51859. /**
  51860. * @private
  51861. * @type {!ol.Transform}
  51862. */
  51863. this.renderedTransform_ = ol.transform.create();
  51864. /**
  51865. * @protected
  51866. * @type {Array.<*>}
  51867. */
  51868. this.hitDetectionInstructions = [];
  51869. /**
  51870. * @private
  51871. * @type {Array.<number>}
  51872. */
  51873. this.pixelCoordinates_ = null;
  51874. /**
  51875. * @private
  51876. * @type {!ol.Transform}
  51877. */
  51878. this.tmpLocalTransform_ = ol.transform.create();
  51879. /**
  51880. * @private
  51881. * @type {!ol.Transform}
  51882. */
  51883. this.resetTransform_ = ol.transform.create();
  51884. };
  51885. ol.inherits(ol.render.canvas.Replay, ol.render.VectorContext);
  51886. /**
  51887. * @param {Array.<number>} flatCoordinates Flat coordinates.
  51888. * @param {number} offset Offset.
  51889. * @param {number} end End.
  51890. * @param {number} stride Stride.
  51891. * @param {boolean} closed Last input coordinate equals first.
  51892. * @param {boolean} skipFirst Skip first coordinate.
  51893. * @protected
  51894. * @return {number} My end.
  51895. */
  51896. ol.render.canvas.Replay.prototype.appendFlatCoordinates = function(flatCoordinates, offset, end, stride, closed, skipFirst) {
  51897. var myEnd = this.coordinates.length;
  51898. var extent = this.getBufferedMaxExtent();
  51899. if (skipFirst) {
  51900. offset += stride;
  51901. }
  51902. var lastCoord = [flatCoordinates[offset], flatCoordinates[offset + 1]];
  51903. var nextCoord = [NaN, NaN];
  51904. var skipped = true;
  51905. var i, lastRel, nextRel;
  51906. for (i = offset + stride; i < end; i += stride) {
  51907. nextCoord[0] = flatCoordinates[i];
  51908. nextCoord[1] = flatCoordinates[i + 1];
  51909. nextRel = ol.extent.coordinateRelationship(extent, nextCoord);
  51910. if (nextRel !== lastRel) {
  51911. if (skipped) {
  51912. this.coordinates[myEnd++] = lastCoord[0];
  51913. this.coordinates[myEnd++] = lastCoord[1];
  51914. }
  51915. this.coordinates[myEnd++] = nextCoord[0];
  51916. this.coordinates[myEnd++] = nextCoord[1];
  51917. skipped = false;
  51918. } else if (nextRel === ol.extent.Relationship.INTERSECTING) {
  51919. this.coordinates[myEnd++] = nextCoord[0];
  51920. this.coordinates[myEnd++] = nextCoord[1];
  51921. skipped = false;
  51922. } else {
  51923. skipped = true;
  51924. }
  51925. lastCoord[0] = nextCoord[0];
  51926. lastCoord[1] = nextCoord[1];
  51927. lastRel = nextRel;
  51928. }
  51929. // Last coordinate equals first or only one point to append:
  51930. if ((closed && skipped) || i === offset + stride) {
  51931. this.coordinates[myEnd++] = lastCoord[0];
  51932. this.coordinates[myEnd++] = lastCoord[1];
  51933. }
  51934. return myEnd;
  51935. };
  51936. /**
  51937. * @param {Array.<number>} flatCoordinates Flat coordinates.
  51938. * @param {number} offset Offset.
  51939. * @param {Array.<number>} ends Ends.
  51940. * @param {number} stride Stride.
  51941. * @param {Array.<number>} replayEnds Replay ends.
  51942. * @return {number} Offset.
  51943. */
  51944. ol.render.canvas.Replay.prototype.drawCustomCoordinates_ = function(flatCoordinates, offset, ends, stride, replayEnds) {
  51945. for (var i = 0, ii = ends.length; i < ii; ++i) {
  51946. var end = ends[i];
  51947. var replayEnd = this.appendFlatCoordinates(flatCoordinates, offset, end, stride, false, false);
  51948. replayEnds.push(replayEnd);
  51949. offset = end;
  51950. }
  51951. return offset;
  51952. };
  51953. /**
  51954. * @inheritDoc.
  51955. */
  51956. ol.render.canvas.Replay.prototype.drawCustom = function(geometry, feature, renderer) {
  51957. this.beginGeometry(geometry, feature);
  51958. var type = geometry.getType();
  51959. var stride = geometry.getStride();
  51960. var replayBegin = this.coordinates.length;
  51961. var flatCoordinates, replayEnd, replayEnds, replayEndss;
  51962. var offset;
  51963. if (type == ol.geom.GeometryType.MULTI_POLYGON) {
  51964. geometry = /** @type {ol.geom.MultiPolygon} */ (geometry);
  51965. flatCoordinates = geometry.getOrientedFlatCoordinates();
  51966. replayEndss = [];
  51967. var endss = geometry.getEndss();
  51968. offset = 0;
  51969. for (var i = 0, ii = endss.length; i < ii; ++i) {
  51970. var myEnds = [];
  51971. offset = this.drawCustomCoordinates_(flatCoordinates, offset, endss[i], stride, myEnds);
  51972. replayEndss.push(myEnds);
  51973. }
  51974. this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
  51975. replayBegin, replayEndss, geometry, renderer, ol.geom.flat.inflate.coordinatesss]);
  51976. } else if (type == ol.geom.GeometryType.POLYGON || type == ol.geom.GeometryType.MULTI_LINE_STRING) {
  51977. replayEnds = [];
  51978. flatCoordinates = (type == ol.geom.GeometryType.POLYGON) ?
  51979. /** @type {ol.geom.Polygon} */ (geometry).getOrientedFlatCoordinates() :
  51980. geometry.getFlatCoordinates();
  51981. offset = this.drawCustomCoordinates_(flatCoordinates, 0,
  51982. /** @type {ol.geom.Polygon|ol.geom.MultiLineString} */ (geometry).getEnds(),
  51983. stride, replayEnds);
  51984. this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
  51985. replayBegin, replayEnds, geometry, renderer, ol.geom.flat.inflate.coordinatess]);
  51986. } else if (type == ol.geom.GeometryType.LINE_STRING || type == ol.geom.GeometryType.MULTI_POINT) {
  51987. flatCoordinates = geometry.getFlatCoordinates();
  51988. replayEnd = this.appendFlatCoordinates(
  51989. flatCoordinates, 0, flatCoordinates.length, stride, false, false);
  51990. this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
  51991. replayBegin, replayEnd, geometry, renderer, ol.geom.flat.inflate.coordinates]);
  51992. } else if (type == ol.geom.GeometryType.POINT) {
  51993. flatCoordinates = geometry.getFlatCoordinates();
  51994. this.coordinates.push(flatCoordinates[0], flatCoordinates[1]);
  51995. replayEnd = this.coordinates.length;
  51996. this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
  51997. replayBegin, replayEnd, geometry, renderer]);
  51998. }
  51999. this.endGeometry(geometry, feature);
  52000. };
  52001. /**
  52002. * @protected
  52003. * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
  52004. * @param {ol.Feature|ol.render.Feature} feature Feature.
  52005. */
  52006. ol.render.canvas.Replay.prototype.beginGeometry = function(geometry, feature) {
  52007. this.beginGeometryInstruction1_ =
  52008. [ol.render.canvas.Instruction.BEGIN_GEOMETRY, feature, 0];
  52009. this.instructions.push(this.beginGeometryInstruction1_);
  52010. this.beginGeometryInstruction2_ =
  52011. [ol.render.canvas.Instruction.BEGIN_GEOMETRY, feature, 0];
  52012. this.hitDetectionInstructions.push(this.beginGeometryInstruction2_);
  52013. };
  52014. /**
  52015. * @private
  52016. * @param {CanvasRenderingContext2D} context Context.
  52017. * @param {number} rotation Rotation.
  52018. */
  52019. ol.render.canvas.Replay.prototype.fill_ = function(context, rotation) {
  52020. if (this.fillOrigin_) {
  52021. var origin = ol.transform.apply(this.renderedTransform_, this.fillOrigin_.slice());
  52022. context.translate(origin[0], origin[1]);
  52023. context.rotate(rotation);
  52024. }
  52025. context.fill();
  52026. if (this.fillOrigin_) {
  52027. context.setTransform.apply(context, this.resetTransform_);
  52028. }
  52029. };
  52030. /**
  52031. * @private
  52032. * @param {CanvasRenderingContext2D} context Context.
  52033. * @param {number} pixelRatio Pixel ratio.
  52034. * @param {ol.Transform} transform Transform.
  52035. * @param {number} viewRotation View rotation.
  52036. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  52037. * to skip.
  52038. * @param {Array.<*>} instructions Instructions array.
  52039. * @param {function((ol.Feature|ol.render.Feature)): T|undefined}
  52040. * featureCallback Feature callback.
  52041. * @param {ol.Extent=} opt_hitExtent Only check features that intersect this
  52042. * extent.
  52043. * @return {T|undefined} Callback result.
  52044. * @template T
  52045. */
  52046. ol.render.canvas.Replay.prototype.replay_ = function(
  52047. context, pixelRatio, transform, viewRotation, skippedFeaturesHash,
  52048. instructions, featureCallback, opt_hitExtent) {
  52049. /** @type {Array.<number>} */
  52050. var pixelCoordinates;
  52051. if (this.pixelCoordinates_ && ol.array.equals(transform, this.renderedTransform_)) {
  52052. pixelCoordinates = this.pixelCoordinates_;
  52053. } else {
  52054. if (!this.pixelCoordinates_) {
  52055. this.pixelCoordinates_ = [];
  52056. }
  52057. pixelCoordinates = ol.geom.flat.transform.transform2D(
  52058. this.coordinates, 0, this.coordinates.length, 2,
  52059. transform, this.pixelCoordinates_);
  52060. ol.transform.setFromArray(this.renderedTransform_, transform);
  52061. }
  52062. var skipFeatures = !ol.obj.isEmpty(skippedFeaturesHash);
  52063. var i = 0; // instruction index
  52064. var ii = instructions.length; // end of instructions
  52065. var d = 0; // data index
  52066. var dd; // end of per-instruction data
  52067. var localTransform = this.tmpLocalTransform_;
  52068. var resetTransform = this.resetTransform_;
  52069. var prevX, prevY, roundX, roundY;
  52070. var pendingFill = 0;
  52071. var pendingStroke = 0;
  52072. var coordinateCache = this.coordinateCache_;
  52073. var state = /** @type {olx.render.State} */ ({
  52074. context: context,
  52075. pixelRatio: pixelRatio,
  52076. resolution: this.resolution,
  52077. rotation: viewRotation
  52078. });
  52079. // When the batch size gets too big, performance decreases. 200 is a good
  52080. // balance between batch size and number of fill/stroke instructions.
  52081. var batchSize =
  52082. this.instructions != instructions || this.overlaps ? 0 : 200;
  52083. while (i < ii) {
  52084. var instruction = instructions[i];
  52085. var type = /** @type {ol.render.canvas.Instruction} */ (instruction[0]);
  52086. var /** @type {ol.Feature|ol.render.Feature} */ feature, fill, stroke, text, x, y;
  52087. switch (type) {
  52088. case ol.render.canvas.Instruction.BEGIN_GEOMETRY:
  52089. feature = /** @type {ol.Feature|ol.render.Feature} */ (instruction[1]);
  52090. if ((skipFeatures &&
  52091. skippedFeaturesHash[ol.getUid(feature).toString()]) ||
  52092. !feature.getGeometry()) {
  52093. i = /** @type {number} */ (instruction[2]);
  52094. } else if (opt_hitExtent !== undefined && !ol.extent.intersects(
  52095. opt_hitExtent, feature.getGeometry().getExtent())) {
  52096. i = /** @type {number} */ (instruction[2]) + 1;
  52097. } else {
  52098. ++i;
  52099. }
  52100. break;
  52101. case ol.render.canvas.Instruction.BEGIN_PATH:
  52102. if (pendingFill > batchSize) {
  52103. this.fill_(context, viewRotation);
  52104. pendingFill = 0;
  52105. }
  52106. if (pendingStroke > batchSize) {
  52107. context.stroke();
  52108. pendingStroke = 0;
  52109. }
  52110. if (!pendingFill && !pendingStroke) {
  52111. context.beginPath();
  52112. prevX = prevY = NaN;
  52113. }
  52114. ++i;
  52115. break;
  52116. case ol.render.canvas.Instruction.CIRCLE:
  52117. d = /** @type {number} */ (instruction[1]);
  52118. var x1 = pixelCoordinates[d];
  52119. var y1 = pixelCoordinates[d + 1];
  52120. var x2 = pixelCoordinates[d + 2];
  52121. var y2 = pixelCoordinates[d + 3];
  52122. var dx = x2 - x1;
  52123. var dy = y2 - y1;
  52124. var r = Math.sqrt(dx * dx + dy * dy);
  52125. context.moveTo(x1 + r, y1);
  52126. context.arc(x1, y1, r, 0, 2 * Math.PI, true);
  52127. ++i;
  52128. break;
  52129. case ol.render.canvas.Instruction.CLOSE_PATH:
  52130. context.closePath();
  52131. ++i;
  52132. break;
  52133. case ol.render.canvas.Instruction.CUSTOM:
  52134. d = /** @type {number} */ (instruction[1]);
  52135. dd = instruction[2];
  52136. var geometry = /** @type {ol.geom.SimpleGeometry} */ (instruction[3]);
  52137. var renderer = instruction[4];
  52138. var fn = instruction.length == 6 ? instruction[5] : undefined;
  52139. state.geometry = geometry;
  52140. state.feature = feature;
  52141. if (!(i in coordinateCache)) {
  52142. coordinateCache[i] = [];
  52143. }
  52144. var coords = coordinateCache[i];
  52145. if (fn) {
  52146. fn(pixelCoordinates, d, dd, 2, coords);
  52147. } else {
  52148. coords[0] = pixelCoordinates[d];
  52149. coords[1] = pixelCoordinates[d + 1];
  52150. coords.length = 2;
  52151. }
  52152. renderer(coords, state);
  52153. ++i;
  52154. break;
  52155. case ol.render.canvas.Instruction.DRAW_IMAGE:
  52156. d = /** @type {number} */ (instruction[1]);
  52157. dd = /** @type {number} */ (instruction[2]);
  52158. var image = /** @type {HTMLCanvasElement|HTMLVideoElement|Image} */
  52159. (instruction[3]);
  52160. // Remaining arguments in DRAW_IMAGE are in alphabetical order
  52161. var anchorX = /** @type {number} */ (instruction[4]) * pixelRatio;
  52162. var anchorY = /** @type {number} */ (instruction[5]) * pixelRatio;
  52163. var height = /** @type {number} */ (instruction[6]);
  52164. var opacity = /** @type {number} */ (instruction[7]);
  52165. var originX = /** @type {number} */ (instruction[8]);
  52166. var originY = /** @type {number} */ (instruction[9]);
  52167. var rotateWithView = /** @type {boolean} */ (instruction[10]);
  52168. var rotation = /** @type {number} */ (instruction[11]);
  52169. var scale = /** @type {number} */ (instruction[12]);
  52170. var snapToPixel = /** @type {boolean} */ (instruction[13]);
  52171. var width = /** @type {number} */ (instruction[14]);
  52172. if (rotateWithView) {
  52173. rotation += viewRotation;
  52174. }
  52175. for (; d < dd; d += 2) {
  52176. x = pixelCoordinates[d] - anchorX;
  52177. y = pixelCoordinates[d + 1] - anchorY;
  52178. if (snapToPixel) {
  52179. x = Math.round(x);
  52180. y = Math.round(y);
  52181. }
  52182. if (scale != 1 || rotation !== 0) {
  52183. var centerX = x + anchorX;
  52184. var centerY = y + anchorY;
  52185. ol.transform.compose(localTransform,
  52186. centerX, centerY, scale, scale, rotation, -centerX, -centerY);
  52187. context.setTransform.apply(context, localTransform);
  52188. }
  52189. var alpha = context.globalAlpha;
  52190. if (opacity != 1) {
  52191. context.globalAlpha = alpha * opacity;
  52192. }
  52193. var w = (width + originX > image.width) ? image.width - originX : width;
  52194. var h = (height + originY > image.height) ? image.height - originY : height;
  52195. context.drawImage(image, originX, originY, w, h,
  52196. x, y, w * pixelRatio, h * pixelRatio);
  52197. if (opacity != 1) {
  52198. context.globalAlpha = alpha;
  52199. }
  52200. if (scale != 1 || rotation !== 0) {
  52201. context.setTransform.apply(context, resetTransform);
  52202. }
  52203. }
  52204. ++i;
  52205. break;
  52206. case ol.render.canvas.Instruction.DRAW_TEXT:
  52207. d = /** @type {number} */ (instruction[1]);
  52208. dd = /** @type {number} */ (instruction[2]);
  52209. text = /** @type {string} */ (instruction[3]);
  52210. var offsetX = /** @type {number} */ (instruction[4]) * pixelRatio;
  52211. var offsetY = /** @type {number} */ (instruction[5]) * pixelRatio;
  52212. rotation = /** @type {number} */ (instruction[6]);
  52213. scale = /** @type {number} */ (instruction[7]) * pixelRatio;
  52214. fill = /** @type {boolean} */ (instruction[8]);
  52215. stroke = /** @type {boolean} */ (instruction[9]);
  52216. rotateWithView = /** @type {boolean} */ (instruction[10]);
  52217. if (rotateWithView) {
  52218. rotation += viewRotation;
  52219. }
  52220. for (; d < dd; d += 2) {
  52221. x = pixelCoordinates[d] + offsetX;
  52222. y = pixelCoordinates[d + 1] + offsetY;
  52223. if (scale != 1 || rotation !== 0) {
  52224. ol.transform.compose(localTransform, x, y, scale, scale, rotation, -x, -y);
  52225. context.setTransform.apply(context, localTransform);
  52226. }
  52227. // Support multiple lines separated by \n
  52228. var lines = text.split('\n');
  52229. var numLines = lines.length;
  52230. var fontSize, lineY;
  52231. if (numLines > 1) {
  52232. // Estimate line height using width of capital M, and add padding
  52233. fontSize = Math.round(context.measureText('M').width * 1.5);
  52234. lineY = y - (((numLines - 1) / 2) * fontSize);
  52235. } else {
  52236. // No need to calculate line height/offset for a single line
  52237. fontSize = 0;
  52238. lineY = y;
  52239. }
  52240. for (var lineIndex = 0; lineIndex < numLines; lineIndex++) {
  52241. var line = lines[lineIndex];
  52242. if (stroke) {
  52243. context.strokeText(line, x, lineY);
  52244. }
  52245. if (fill) {
  52246. context.fillText(line, x, lineY);
  52247. }
  52248. // Move next line down by fontSize px
  52249. lineY = lineY + fontSize;
  52250. }
  52251. if (scale != 1 || rotation !== 0) {
  52252. context.setTransform.apply(context, resetTransform);
  52253. }
  52254. }
  52255. ++i;
  52256. break;
  52257. case ol.render.canvas.Instruction.END_GEOMETRY:
  52258. if (featureCallback !== undefined) {
  52259. feature = /** @type {ol.Feature|ol.render.Feature} */ (instruction[1]);
  52260. var result = featureCallback(feature);
  52261. if (result) {
  52262. return result;
  52263. }
  52264. }
  52265. ++i;
  52266. break;
  52267. case ol.render.canvas.Instruction.FILL:
  52268. if (batchSize) {
  52269. pendingFill++;
  52270. } else {
  52271. this.fill_(context, viewRotation);
  52272. }
  52273. ++i;
  52274. break;
  52275. case ol.render.canvas.Instruction.MOVE_TO_LINE_TO:
  52276. d = /** @type {number} */ (instruction[1]);
  52277. dd = /** @type {number} */ (instruction[2]);
  52278. x = pixelCoordinates[d];
  52279. y = pixelCoordinates[d + 1];
  52280. roundX = (x + 0.5) | 0;
  52281. roundY = (y + 0.5) | 0;
  52282. if (roundX !== prevX || roundY !== prevY) {
  52283. context.moveTo(x, y);
  52284. prevX = roundX;
  52285. prevY = roundY;
  52286. }
  52287. for (d += 2; d < dd; d += 2) {
  52288. x = pixelCoordinates[d];
  52289. y = pixelCoordinates[d + 1];
  52290. roundX = (x + 0.5) | 0;
  52291. roundY = (y + 0.5) | 0;
  52292. if (d == dd - 2 || roundX !== prevX || roundY !== prevY) {
  52293. context.lineTo(x, y);
  52294. prevX = roundX;
  52295. prevY = roundY;
  52296. }
  52297. }
  52298. ++i;
  52299. break;
  52300. case ol.render.canvas.Instruction.SET_FILL_STYLE:
  52301. this.fillOrigin_ = instruction[2];
  52302. if (pendingFill) {
  52303. this.fill_(context, viewRotation);
  52304. pendingFill = 0;
  52305. if (pendingStroke) {
  52306. context.stroke();
  52307. pendingStroke = 0;
  52308. }
  52309. }
  52310. context.fillStyle = /** @type {ol.ColorLike} */ (instruction[1]);
  52311. ++i;
  52312. break;
  52313. case ol.render.canvas.Instruction.SET_STROKE_STYLE:
  52314. var usePixelRatio = instruction[8] !== undefined ?
  52315. instruction[8] : true;
  52316. var renderedPixelRatio = instruction[9];
  52317. var lineWidth = /** @type {number} */ (instruction[2]);
  52318. if (pendingStroke) {
  52319. context.stroke();
  52320. pendingStroke = 0;
  52321. }
  52322. context.strokeStyle = /** @type {ol.ColorLike} */ (instruction[1]);
  52323. context.lineWidth = usePixelRatio ? lineWidth * pixelRatio : lineWidth;
  52324. context.lineCap = /** @type {string} */ (instruction[3]);
  52325. context.lineJoin = /** @type {string} */ (instruction[4]);
  52326. context.miterLimit = /** @type {number} */ (instruction[5]);
  52327. if (ol.has.CANVAS_LINE_DASH) {
  52328. var lineDash = /** @type {Array.<number>} */ (instruction[6]);
  52329. var lineDashOffset = /** @type {number} */ (instruction[7]);
  52330. if (usePixelRatio && pixelRatio !== renderedPixelRatio) {
  52331. lineDash = lineDash.map(function(dash) {
  52332. return dash * pixelRatio / renderedPixelRatio;
  52333. });
  52334. lineDashOffset *= pixelRatio / renderedPixelRatio;
  52335. instruction[6] = lineDash;
  52336. instruction[7] = lineDashOffset;
  52337. instruction[9] = pixelRatio;
  52338. }
  52339. context.lineDashOffset = lineDashOffset;
  52340. context.setLineDash(lineDash);
  52341. }
  52342. ++i;
  52343. break;
  52344. case ol.render.canvas.Instruction.SET_TEXT_STYLE:
  52345. context.font = /** @type {string} */ (instruction[1]);
  52346. context.textAlign = /** @type {string} */ (instruction[2]);
  52347. context.textBaseline = /** @type {string} */ (instruction[3]);
  52348. ++i;
  52349. break;
  52350. case ol.render.canvas.Instruction.STROKE:
  52351. if (batchSize) {
  52352. pendingStroke++;
  52353. } else {
  52354. context.stroke();
  52355. }
  52356. ++i;
  52357. break;
  52358. default:
  52359. ++i; // consume the instruction anyway, to avoid an infinite loop
  52360. break;
  52361. }
  52362. }
  52363. if (pendingFill) {
  52364. this.fill_(context, viewRotation);
  52365. }
  52366. if (pendingStroke) {
  52367. context.stroke();
  52368. }
  52369. return undefined;
  52370. };
  52371. /**
  52372. * @param {CanvasRenderingContext2D} context Context.
  52373. * @param {number} pixelRatio Pixel ratio.
  52374. * @param {ol.Transform} transform Transform.
  52375. * @param {number} viewRotation View rotation.
  52376. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  52377. * to skip.
  52378. */
  52379. ol.render.canvas.Replay.prototype.replay = function(
  52380. context, pixelRatio, transform, viewRotation, skippedFeaturesHash) {
  52381. var instructions = this.instructions;
  52382. this.replay_(context, pixelRatio, transform, viewRotation,
  52383. skippedFeaturesHash, instructions, undefined, undefined);
  52384. };
  52385. /**
  52386. * @param {CanvasRenderingContext2D} context Context.
  52387. * @param {ol.Transform} transform Transform.
  52388. * @param {number} viewRotation View rotation.
  52389. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  52390. * to skip.
  52391. * @param {function((ol.Feature|ol.render.Feature)): T=} opt_featureCallback
  52392. * Feature callback.
  52393. * @param {ol.Extent=} opt_hitExtent Only check features that intersect this
  52394. * extent.
  52395. * @return {T|undefined} Callback result.
  52396. * @template T
  52397. */
  52398. ol.render.canvas.Replay.prototype.replayHitDetection = function(
  52399. context, transform, viewRotation, skippedFeaturesHash,
  52400. opt_featureCallback, opt_hitExtent) {
  52401. var instructions = this.hitDetectionInstructions;
  52402. return this.replay_(context, 1, transform, viewRotation,
  52403. skippedFeaturesHash, instructions, opt_featureCallback, opt_hitExtent);
  52404. };
  52405. /**
  52406. * Reverse the hit detection instructions.
  52407. */
  52408. ol.render.canvas.Replay.prototype.reverseHitDetectionInstructions = function() {
  52409. var hitDetectionInstructions = this.hitDetectionInstructions;
  52410. // step 1 - reverse array
  52411. hitDetectionInstructions.reverse();
  52412. // step 2 - reverse instructions within geometry blocks
  52413. var i;
  52414. var n = hitDetectionInstructions.length;
  52415. var instruction;
  52416. var type;
  52417. var begin = -1;
  52418. for (i = 0; i < n; ++i) {
  52419. instruction = hitDetectionInstructions[i];
  52420. type = /** @type {ol.render.canvas.Instruction} */ (instruction[0]);
  52421. if (type == ol.render.canvas.Instruction.END_GEOMETRY) {
  52422. begin = i;
  52423. } else if (type == ol.render.canvas.Instruction.BEGIN_GEOMETRY) {
  52424. instruction[2] = i;
  52425. ol.array.reverseSubArray(this.hitDetectionInstructions, begin, i);
  52426. begin = -1;
  52427. }
  52428. }
  52429. };
  52430. /**
  52431. * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
  52432. * @param {ol.Feature|ol.render.Feature} feature Feature.
  52433. */
  52434. ol.render.canvas.Replay.prototype.endGeometry = function(geometry, feature) {
  52435. this.beginGeometryInstruction1_[2] = this.instructions.length;
  52436. this.beginGeometryInstruction1_ = null;
  52437. this.beginGeometryInstruction2_[2] = this.hitDetectionInstructions.length;
  52438. this.beginGeometryInstruction2_ = null;
  52439. var endGeometryInstruction =
  52440. [ol.render.canvas.Instruction.END_GEOMETRY, feature];
  52441. this.instructions.push(endGeometryInstruction);
  52442. this.hitDetectionInstructions.push(endGeometryInstruction);
  52443. };
  52444. /**
  52445. * FIXME empty description for jsdoc
  52446. */
  52447. ol.render.canvas.Replay.prototype.finish = ol.nullFunction;
  52448. /**
  52449. * Get the buffered rendering extent. Rendering will be clipped to the extent
  52450. * provided to the constructor. To account for symbolizers that may intersect
  52451. * this extent, we calculate a buffered extent (e.g. based on stroke width).
  52452. * @return {ol.Extent} The buffered rendering extent.
  52453. * @protected
  52454. */
  52455. ol.render.canvas.Replay.prototype.getBufferedMaxExtent = function() {
  52456. return this.maxExtent;
  52457. };
  52458. goog.provide('ol.render.canvas.ImageReplay');
  52459. goog.require('ol');
  52460. goog.require('ol.render.canvas.Instruction');
  52461. goog.require('ol.render.canvas.Replay');
  52462. /**
  52463. * @constructor
  52464. * @extends {ol.render.canvas.Replay}
  52465. * @param {number} tolerance Tolerance.
  52466. * @param {ol.Extent} maxExtent Maximum extent.
  52467. * @param {number} resolution Resolution.
  52468. * @param {boolean} overlaps The replay can have overlapping geometries.
  52469. * @struct
  52470. */
  52471. ol.render.canvas.ImageReplay = function(tolerance, maxExtent, resolution, overlaps) {
  52472. ol.render.canvas.Replay.call(this, tolerance, maxExtent, resolution, overlaps);
  52473. /**
  52474. * @private
  52475. * @type {HTMLCanvasElement|HTMLVideoElement|Image}
  52476. */
  52477. this.hitDetectionImage_ = null;
  52478. /**
  52479. * @private
  52480. * @type {HTMLCanvasElement|HTMLVideoElement|Image}
  52481. */
  52482. this.image_ = null;
  52483. /**
  52484. * @private
  52485. * @type {number|undefined}
  52486. */
  52487. this.anchorX_ = undefined;
  52488. /**
  52489. * @private
  52490. * @type {number|undefined}
  52491. */
  52492. this.anchorY_ = undefined;
  52493. /**
  52494. * @private
  52495. * @type {number|undefined}
  52496. */
  52497. this.height_ = undefined;
  52498. /**
  52499. * @private
  52500. * @type {number|undefined}
  52501. */
  52502. this.opacity_ = undefined;
  52503. /**
  52504. * @private
  52505. * @type {number|undefined}
  52506. */
  52507. this.originX_ = undefined;
  52508. /**
  52509. * @private
  52510. * @type {number|undefined}
  52511. */
  52512. this.originY_ = undefined;
  52513. /**
  52514. * @private
  52515. * @type {boolean|undefined}
  52516. */
  52517. this.rotateWithView_ = undefined;
  52518. /**
  52519. * @private
  52520. * @type {number|undefined}
  52521. */
  52522. this.rotation_ = undefined;
  52523. /**
  52524. * @private
  52525. * @type {number|undefined}
  52526. */
  52527. this.scale_ = undefined;
  52528. /**
  52529. * @private
  52530. * @type {boolean|undefined}
  52531. */
  52532. this.snapToPixel_ = undefined;
  52533. /**
  52534. * @private
  52535. * @type {number|undefined}
  52536. */
  52537. this.width_ = undefined;
  52538. };
  52539. ol.inherits(ol.render.canvas.ImageReplay, ol.render.canvas.Replay);
  52540. /**
  52541. * @param {Array.<number>} flatCoordinates Flat coordinates.
  52542. * @param {number} offset Offset.
  52543. * @param {number} end End.
  52544. * @param {number} stride Stride.
  52545. * @private
  52546. * @return {number} My end.
  52547. */
  52548. ol.render.canvas.ImageReplay.prototype.drawCoordinates_ = function(flatCoordinates, offset, end, stride) {
  52549. return this.appendFlatCoordinates(
  52550. flatCoordinates, offset, end, stride, false, false);
  52551. };
  52552. /**
  52553. * @inheritDoc
  52554. */
  52555. ol.render.canvas.ImageReplay.prototype.drawPoint = function(pointGeometry, feature) {
  52556. if (!this.image_) {
  52557. return;
  52558. }
  52559. this.beginGeometry(pointGeometry, feature);
  52560. var flatCoordinates = pointGeometry.getFlatCoordinates();
  52561. var stride = pointGeometry.getStride();
  52562. var myBegin = this.coordinates.length;
  52563. var myEnd = this.drawCoordinates_(
  52564. flatCoordinates, 0, flatCoordinates.length, stride);
  52565. this.instructions.push([
  52566. ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd, this.image_,
  52567. // Remaining arguments to DRAW_IMAGE are in alphabetical order
  52568. this.anchorX_, this.anchorY_, this.height_, this.opacity_,
  52569. this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
  52570. this.scale_, this.snapToPixel_, this.width_
  52571. ]);
  52572. this.hitDetectionInstructions.push([
  52573. ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd,
  52574. this.hitDetectionImage_,
  52575. // Remaining arguments to DRAW_IMAGE are in alphabetical order
  52576. this.anchorX_, this.anchorY_, this.height_, this.opacity_,
  52577. this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
  52578. this.scale_, this.snapToPixel_, this.width_
  52579. ]);
  52580. this.endGeometry(pointGeometry, feature);
  52581. };
  52582. /**
  52583. * @inheritDoc
  52584. */
  52585. ol.render.canvas.ImageReplay.prototype.drawMultiPoint = function(multiPointGeometry, feature) {
  52586. if (!this.image_) {
  52587. return;
  52588. }
  52589. this.beginGeometry(multiPointGeometry, feature);
  52590. var flatCoordinates = multiPointGeometry.getFlatCoordinates();
  52591. var stride = multiPointGeometry.getStride();
  52592. var myBegin = this.coordinates.length;
  52593. var myEnd = this.drawCoordinates_(
  52594. flatCoordinates, 0, flatCoordinates.length, stride);
  52595. this.instructions.push([
  52596. ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd, this.image_,
  52597. // Remaining arguments to DRAW_IMAGE are in alphabetical order
  52598. this.anchorX_, this.anchorY_, this.height_, this.opacity_,
  52599. this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
  52600. this.scale_, this.snapToPixel_, this.width_
  52601. ]);
  52602. this.hitDetectionInstructions.push([
  52603. ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd,
  52604. this.hitDetectionImage_,
  52605. // Remaining arguments to DRAW_IMAGE are in alphabetical order
  52606. this.anchorX_, this.anchorY_, this.height_, this.opacity_,
  52607. this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
  52608. this.scale_, this.snapToPixel_, this.width_
  52609. ]);
  52610. this.endGeometry(multiPointGeometry, feature);
  52611. };
  52612. /**
  52613. * @inheritDoc
  52614. */
  52615. ol.render.canvas.ImageReplay.prototype.finish = function() {
  52616. this.reverseHitDetectionInstructions();
  52617. // FIXME this doesn't really protect us against further calls to draw*Geometry
  52618. this.anchorX_ = undefined;
  52619. this.anchorY_ = undefined;
  52620. this.hitDetectionImage_ = null;
  52621. this.image_ = null;
  52622. this.height_ = undefined;
  52623. this.scale_ = undefined;
  52624. this.opacity_ = undefined;
  52625. this.originX_ = undefined;
  52626. this.originY_ = undefined;
  52627. this.rotateWithView_ = undefined;
  52628. this.rotation_ = undefined;
  52629. this.snapToPixel_ = undefined;
  52630. this.width_ = undefined;
  52631. };
  52632. /**
  52633. * @inheritDoc
  52634. */
  52635. ol.render.canvas.ImageReplay.prototype.setImageStyle = function(imageStyle) {
  52636. var anchor = imageStyle.getAnchor();
  52637. var size = imageStyle.getSize();
  52638. var hitDetectionImage = imageStyle.getHitDetectionImage(1);
  52639. var image = imageStyle.getImage(1);
  52640. var origin = imageStyle.getOrigin();
  52641. this.anchorX_ = anchor[0];
  52642. this.anchorY_ = anchor[1];
  52643. this.hitDetectionImage_ = hitDetectionImage;
  52644. this.image_ = image;
  52645. this.height_ = size[1];
  52646. this.opacity_ = imageStyle.getOpacity();
  52647. this.originX_ = origin[0];
  52648. this.originY_ = origin[1];
  52649. this.rotateWithView_ = imageStyle.getRotateWithView();
  52650. this.rotation_ = imageStyle.getRotation();
  52651. this.scale_ = imageStyle.getScale();
  52652. this.snapToPixel_ = imageStyle.getSnapToPixel();
  52653. this.width_ = size[0];
  52654. };
  52655. goog.provide('ol.render.canvas.LineStringReplay');
  52656. goog.require('ol');
  52657. goog.require('ol.array');
  52658. goog.require('ol.colorlike');
  52659. goog.require('ol.extent');
  52660. goog.require('ol.render.canvas');
  52661. goog.require('ol.render.canvas.Instruction');
  52662. goog.require('ol.render.canvas.Replay');
  52663. /**
  52664. * @constructor
  52665. * @extends {ol.render.canvas.Replay}
  52666. * @param {number} tolerance Tolerance.
  52667. * @param {ol.Extent} maxExtent Maximum extent.
  52668. * @param {number} resolution Resolution.
  52669. * @param {boolean} overlaps The replay can have overlapping geometries.
  52670. * @struct
  52671. */
  52672. ol.render.canvas.LineStringReplay = function(tolerance, maxExtent, resolution, overlaps) {
  52673. ol.render.canvas.Replay.call(this, tolerance, maxExtent, resolution, overlaps);
  52674. /**
  52675. * @private
  52676. * @type {ol.Extent}
  52677. */
  52678. this.bufferedMaxExtent_ = null;
  52679. /**
  52680. * @private
  52681. * @type {{currentStrokeStyle: (ol.ColorLike|undefined),
  52682. * currentLineCap: (string|undefined),
  52683. * currentLineDash: Array.<number>,
  52684. * currentLineDashOffset: (number|undefined),
  52685. * currentLineJoin: (string|undefined),
  52686. * currentLineWidth: (number|undefined),
  52687. * currentMiterLimit: (number|undefined),
  52688. * lastStroke: (number|undefined),
  52689. * strokeStyle: (ol.ColorLike|undefined),
  52690. * lineCap: (string|undefined),
  52691. * lineDash: Array.<number>,
  52692. * lineDashOffset: (number|undefined),
  52693. * lineJoin: (string|undefined),
  52694. * lineWidth: (number|undefined),
  52695. * miterLimit: (number|undefined)}|null}
  52696. */
  52697. this.state_ = {
  52698. currentStrokeStyle: undefined,
  52699. currentLineCap: undefined,
  52700. currentLineDash: null,
  52701. currentLineDashOffset: undefined,
  52702. currentLineJoin: undefined,
  52703. currentLineWidth: undefined,
  52704. currentMiterLimit: undefined,
  52705. lastStroke: undefined,
  52706. strokeStyle: undefined,
  52707. lineCap: undefined,
  52708. lineDash: null,
  52709. lineDashOffset: undefined,
  52710. lineJoin: undefined,
  52711. lineWidth: undefined,
  52712. miterLimit: undefined
  52713. };
  52714. };
  52715. ol.inherits(ol.render.canvas.LineStringReplay, ol.render.canvas.Replay);
  52716. /**
  52717. * @param {Array.<number>} flatCoordinates Flat coordinates.
  52718. * @param {number} offset Offset.
  52719. * @param {number} end End.
  52720. * @param {number} stride Stride.
  52721. * @private
  52722. * @return {number} end.
  52723. */
  52724. ol.render.canvas.LineStringReplay.prototype.drawFlatCoordinates_ = function(flatCoordinates, offset, end, stride) {
  52725. var myBegin = this.coordinates.length;
  52726. var myEnd = this.appendFlatCoordinates(
  52727. flatCoordinates, offset, end, stride, false, false);
  52728. var moveToLineToInstruction =
  52729. [ol.render.canvas.Instruction.MOVE_TO_LINE_TO, myBegin, myEnd];
  52730. this.instructions.push(moveToLineToInstruction);
  52731. this.hitDetectionInstructions.push(moveToLineToInstruction);
  52732. return end;
  52733. };
  52734. /**
  52735. * @inheritDoc
  52736. */
  52737. ol.render.canvas.LineStringReplay.prototype.getBufferedMaxExtent = function() {
  52738. if (!this.bufferedMaxExtent_) {
  52739. this.bufferedMaxExtent_ = ol.extent.clone(this.maxExtent);
  52740. if (this.maxLineWidth > 0) {
  52741. var width = this.resolution * (this.maxLineWidth + 1) / 2;
  52742. ol.extent.buffer(this.bufferedMaxExtent_, width, this.bufferedMaxExtent_);
  52743. }
  52744. }
  52745. return this.bufferedMaxExtent_;
  52746. };
  52747. /**
  52748. * @private
  52749. */
  52750. ol.render.canvas.LineStringReplay.prototype.setStrokeStyle_ = function() {
  52751. var state = this.state_;
  52752. var strokeStyle = state.strokeStyle;
  52753. var lineCap = state.lineCap;
  52754. var lineDash = state.lineDash;
  52755. var lineDashOffset = state.lineDashOffset;
  52756. var lineJoin = state.lineJoin;
  52757. var lineWidth = state.lineWidth;
  52758. var miterLimit = state.miterLimit;
  52759. if (state.currentStrokeStyle != strokeStyle ||
  52760. state.currentLineCap != lineCap ||
  52761. !ol.array.equals(state.currentLineDash, lineDash) ||
  52762. state.currentLineDashOffset != lineDashOffset ||
  52763. state.currentLineJoin != lineJoin ||
  52764. state.currentLineWidth != lineWidth ||
  52765. state.currentMiterLimit != miterLimit) {
  52766. if (state.lastStroke != undefined && state.lastStroke != this.coordinates.length) {
  52767. this.instructions.push([ol.render.canvas.Instruction.STROKE]);
  52768. state.lastStroke = this.coordinates.length;
  52769. }
  52770. state.lastStroke = 0;
  52771. this.instructions.push([
  52772. ol.render.canvas.Instruction.SET_STROKE_STYLE,
  52773. strokeStyle, lineWidth, lineCap, lineJoin, miterLimit, lineDash, lineDashOffset, true, 1
  52774. ], [
  52775. ol.render.canvas.Instruction.BEGIN_PATH
  52776. ]);
  52777. state.currentStrokeStyle = strokeStyle;
  52778. state.currentLineCap = lineCap;
  52779. state.currentLineDash = lineDash;
  52780. state.currentLineDashOffset = lineDashOffset;
  52781. state.currentLineJoin = lineJoin;
  52782. state.currentLineWidth = lineWidth;
  52783. state.currentMiterLimit = miterLimit;
  52784. }
  52785. };
  52786. /**
  52787. * @inheritDoc
  52788. */
  52789. ol.render.canvas.LineStringReplay.prototype.drawLineString = function(lineStringGeometry, feature) {
  52790. var state = this.state_;
  52791. var strokeStyle = state.strokeStyle;
  52792. var lineWidth = state.lineWidth;
  52793. if (strokeStyle === undefined || lineWidth === undefined) {
  52794. return;
  52795. }
  52796. this.setStrokeStyle_();
  52797. this.beginGeometry(lineStringGeometry, feature);
  52798. this.hitDetectionInstructions.push([
  52799. ol.render.canvas.Instruction.SET_STROKE_STYLE,
  52800. state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
  52801. state.miterLimit, state.lineDash, state.lineDashOffset, true, 1
  52802. ], [
  52803. ol.render.canvas.Instruction.BEGIN_PATH
  52804. ]);
  52805. var flatCoordinates = lineStringGeometry.getFlatCoordinates();
  52806. var stride = lineStringGeometry.getStride();
  52807. this.drawFlatCoordinates_(flatCoordinates, 0, flatCoordinates.length, stride);
  52808. this.hitDetectionInstructions.push([ol.render.canvas.Instruction.STROKE]);
  52809. this.endGeometry(lineStringGeometry, feature);
  52810. };
  52811. /**
  52812. * @inheritDoc
  52813. */
  52814. ol.render.canvas.LineStringReplay.prototype.drawMultiLineString = function(multiLineStringGeometry, feature) {
  52815. var state = this.state_;
  52816. var strokeStyle = state.strokeStyle;
  52817. var lineWidth = state.lineWidth;
  52818. if (strokeStyle === undefined || lineWidth === undefined) {
  52819. return;
  52820. }
  52821. this.setStrokeStyle_();
  52822. this.beginGeometry(multiLineStringGeometry, feature);
  52823. this.hitDetectionInstructions.push([
  52824. ol.render.canvas.Instruction.SET_STROKE_STYLE,
  52825. state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
  52826. state.miterLimit, state.lineDash, state.lineDashOffset, true, 1
  52827. ], [
  52828. ol.render.canvas.Instruction.BEGIN_PATH
  52829. ]);
  52830. var ends = multiLineStringGeometry.getEnds();
  52831. var flatCoordinates = multiLineStringGeometry.getFlatCoordinates();
  52832. var stride = multiLineStringGeometry.getStride();
  52833. var offset = 0;
  52834. var i, ii;
  52835. for (i = 0, ii = ends.length; i < ii; ++i) {
  52836. offset = this.drawFlatCoordinates_(
  52837. flatCoordinates, offset, ends[i], stride);
  52838. }
  52839. this.hitDetectionInstructions.push([ol.render.canvas.Instruction.STROKE]);
  52840. this.endGeometry(multiLineStringGeometry, feature);
  52841. };
  52842. /**
  52843. * @inheritDoc
  52844. */
  52845. ol.render.canvas.LineStringReplay.prototype.finish = function() {
  52846. var state = this.state_;
  52847. if (state.lastStroke != undefined && state.lastStroke != this.coordinates.length) {
  52848. this.instructions.push([ol.render.canvas.Instruction.STROKE]);
  52849. }
  52850. this.reverseHitDetectionInstructions();
  52851. this.state_ = null;
  52852. };
  52853. /**
  52854. * @inheritDoc
  52855. */
  52856. ol.render.canvas.LineStringReplay.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
  52857. var strokeStyleColor = strokeStyle.getColor();
  52858. this.state_.strokeStyle = ol.colorlike.asColorLike(strokeStyleColor ?
  52859. strokeStyleColor : ol.render.canvas.defaultStrokeStyle);
  52860. var strokeStyleLineCap = strokeStyle.getLineCap();
  52861. this.state_.lineCap = strokeStyleLineCap !== undefined ?
  52862. strokeStyleLineCap : ol.render.canvas.defaultLineCap;
  52863. var strokeStyleLineDash = strokeStyle.getLineDash();
  52864. this.state_.lineDash = strokeStyleLineDash ?
  52865. strokeStyleLineDash : ol.render.canvas.defaultLineDash;
  52866. var strokeStyleLineDashOffset = strokeStyle.getLineDashOffset();
  52867. this.state_.lineDashOffset = strokeStyleLineDashOffset ?
  52868. strokeStyleLineDashOffset : ol.render.canvas.defaultLineDashOffset;
  52869. var strokeStyleLineJoin = strokeStyle.getLineJoin();
  52870. this.state_.lineJoin = strokeStyleLineJoin !== undefined ?
  52871. strokeStyleLineJoin : ol.render.canvas.defaultLineJoin;
  52872. var strokeStyleWidth = strokeStyle.getWidth();
  52873. this.state_.lineWidth = strokeStyleWidth !== undefined ?
  52874. strokeStyleWidth : ol.render.canvas.defaultLineWidth;
  52875. var strokeStyleMiterLimit = strokeStyle.getMiterLimit();
  52876. this.state_.miterLimit = strokeStyleMiterLimit !== undefined ?
  52877. strokeStyleMiterLimit : ol.render.canvas.defaultMiterLimit;
  52878. if (this.state_.lineWidth > this.maxLineWidth) {
  52879. this.maxLineWidth = this.state_.lineWidth;
  52880. // invalidate the buffered max extent cache
  52881. this.bufferedMaxExtent_ = null;
  52882. }
  52883. };
  52884. goog.provide('ol.render.canvas.PolygonReplay');
  52885. goog.require('ol');
  52886. goog.require('ol.array');
  52887. goog.require('ol.color');
  52888. goog.require('ol.colorlike');
  52889. goog.require('ol.extent');
  52890. goog.require('ol.geom.flat.simplify');
  52891. goog.require('ol.render.canvas');
  52892. goog.require('ol.render.canvas.Instruction');
  52893. goog.require('ol.render.canvas.Replay');
  52894. /**
  52895. * @constructor
  52896. * @extends {ol.render.canvas.Replay}
  52897. * @param {number} tolerance Tolerance.
  52898. * @param {ol.Extent} maxExtent Maximum extent.
  52899. * @param {number} resolution Resolution.
  52900. * @param {boolean} overlaps The replay can have overlapping geometries.
  52901. * @struct
  52902. */
  52903. ol.render.canvas.PolygonReplay = function(tolerance, maxExtent, resolution, overlaps) {
  52904. ol.render.canvas.Replay.call(this, tolerance, maxExtent, resolution, overlaps);
  52905. /**
  52906. * @private
  52907. * @type {ol.Extent}
  52908. */
  52909. this.bufferedMaxExtent_ = null;
  52910. /**
  52911. * @private
  52912. * @type {{currentFillStyle: (ol.ColorLike|undefined),
  52913. * currentStrokeStyle: (ol.ColorLike|undefined),
  52914. * currentLineCap: (string|undefined),
  52915. * currentLineDash: Array.<number>,
  52916. * currentLineDashOffset: (number|undefined),
  52917. * currentLineJoin: (string|undefined),
  52918. * currentLineWidth: (number|undefined),
  52919. * currentMiterLimit: (number|undefined),
  52920. * fillStyle: (ol.ColorLike|undefined),
  52921. * strokeStyle: (ol.ColorLike|undefined),
  52922. * lineCap: (string|undefined),
  52923. * lineDash: Array.<number>,
  52924. * lineDashOffset: (number|undefined),
  52925. * lineJoin: (string|undefined),
  52926. * lineWidth: (number|undefined),
  52927. * miterLimit: (number|undefined)}|null}
  52928. */
  52929. this.state_ = {
  52930. currentFillStyle: undefined,
  52931. currentStrokeStyle: undefined,
  52932. currentLineCap: undefined,
  52933. currentLineDash: null,
  52934. currentLineDashOffset: undefined,
  52935. currentLineJoin: undefined,
  52936. currentLineWidth: undefined,
  52937. currentMiterLimit: undefined,
  52938. fillStyle: undefined,
  52939. strokeStyle: undefined,
  52940. lineCap: undefined,
  52941. lineDash: null,
  52942. lineDashOffset: undefined,
  52943. lineJoin: undefined,
  52944. lineWidth: undefined,
  52945. miterLimit: undefined
  52946. };
  52947. };
  52948. ol.inherits(ol.render.canvas.PolygonReplay, ol.render.canvas.Replay);
  52949. /**
  52950. * @param {Array.<number>} flatCoordinates Flat coordinates.
  52951. * @param {number} offset Offset.
  52952. * @param {Array.<number>} ends Ends.
  52953. * @param {number} stride Stride.
  52954. * @private
  52955. * @return {number} End.
  52956. */
  52957. ol.render.canvas.PolygonReplay.prototype.drawFlatCoordinatess_ = function(flatCoordinates, offset, ends, stride) {
  52958. var state = this.state_;
  52959. var fill = state.fillStyle !== undefined;
  52960. var stroke = state.strokeStyle != undefined;
  52961. var numEnds = ends.length;
  52962. var beginPathInstruction = [ol.render.canvas.Instruction.BEGIN_PATH];
  52963. this.instructions.push(beginPathInstruction);
  52964. this.hitDetectionInstructions.push(beginPathInstruction);
  52965. for (var i = 0; i < numEnds; ++i) {
  52966. var end = ends[i];
  52967. var myBegin = this.coordinates.length;
  52968. var myEnd = this.appendFlatCoordinates(
  52969. flatCoordinates, offset, end, stride, true, !stroke);
  52970. var moveToLineToInstruction =
  52971. [ol.render.canvas.Instruction.MOVE_TO_LINE_TO, myBegin, myEnd];
  52972. this.instructions.push(moveToLineToInstruction);
  52973. this.hitDetectionInstructions.push(moveToLineToInstruction);
  52974. if (stroke) {
  52975. // Performance optimization: only call closePath() when we have a stroke.
  52976. // Otherwise the ring is closed already (see appendFlatCoordinates above).
  52977. var closePathInstruction = [ol.render.canvas.Instruction.CLOSE_PATH];
  52978. this.instructions.push(closePathInstruction);
  52979. this.hitDetectionInstructions.push(closePathInstruction);
  52980. }
  52981. offset = end;
  52982. }
  52983. var fillInstruction = [ol.render.canvas.Instruction.FILL];
  52984. this.hitDetectionInstructions.push(fillInstruction);
  52985. if (fill) {
  52986. this.instructions.push(fillInstruction);
  52987. }
  52988. if (stroke) {
  52989. var strokeInstruction = [ol.render.canvas.Instruction.STROKE];
  52990. this.instructions.push(strokeInstruction);
  52991. this.hitDetectionInstructions.push(strokeInstruction);
  52992. }
  52993. return offset;
  52994. };
  52995. /**
  52996. * @inheritDoc
  52997. */
  52998. ol.render.canvas.PolygonReplay.prototype.drawCircle = function(circleGeometry, feature) {
  52999. var state = this.state_;
  53000. var fillStyle = state.fillStyle;
  53001. var strokeStyle = state.strokeStyle;
  53002. if (fillStyle === undefined && strokeStyle === undefined) {
  53003. return;
  53004. }
  53005. this.setFillStrokeStyles_(circleGeometry);
  53006. this.beginGeometry(circleGeometry, feature);
  53007. // always fill the circle for hit detection
  53008. this.hitDetectionInstructions.push([
  53009. ol.render.canvas.Instruction.SET_FILL_STYLE,
  53010. ol.color.asString(ol.render.canvas.defaultFillStyle)
  53011. ]);
  53012. if (state.strokeStyle !== undefined) {
  53013. this.hitDetectionInstructions.push([
  53014. ol.render.canvas.Instruction.SET_STROKE_STYLE,
  53015. state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
  53016. state.miterLimit, state.lineDash, state.lineDashOffset, true, 1
  53017. ]);
  53018. }
  53019. var flatCoordinates = circleGeometry.getFlatCoordinates();
  53020. var stride = circleGeometry.getStride();
  53021. var myBegin = this.coordinates.length;
  53022. this.appendFlatCoordinates(
  53023. flatCoordinates, 0, flatCoordinates.length, stride, false, false);
  53024. var beginPathInstruction = [ol.render.canvas.Instruction.BEGIN_PATH];
  53025. var circleInstruction = [ol.render.canvas.Instruction.CIRCLE, myBegin];
  53026. this.instructions.push(beginPathInstruction, circleInstruction);
  53027. this.hitDetectionInstructions.push(beginPathInstruction, circleInstruction);
  53028. var fillInstruction = [ol.render.canvas.Instruction.FILL];
  53029. this.hitDetectionInstructions.push(fillInstruction);
  53030. if (state.fillStyle !== undefined) {
  53031. this.instructions.push(fillInstruction);
  53032. }
  53033. if (state.strokeStyle !== undefined) {
  53034. var strokeInstruction = [ol.render.canvas.Instruction.STROKE];
  53035. this.instructions.push(strokeInstruction);
  53036. this.hitDetectionInstructions.push(strokeInstruction);
  53037. }
  53038. this.endGeometry(circleGeometry, feature);
  53039. };
  53040. /**
  53041. * @inheritDoc
  53042. */
  53043. ol.render.canvas.PolygonReplay.prototype.drawPolygon = function(polygonGeometry, feature) {
  53044. var state = this.state_;
  53045. this.setFillStrokeStyles_(polygonGeometry);
  53046. this.beginGeometry(polygonGeometry, feature);
  53047. // always fill the polygon for hit detection
  53048. this.hitDetectionInstructions.push([
  53049. ol.render.canvas.Instruction.SET_FILL_STYLE,
  53050. ol.color.asString(ol.render.canvas.defaultFillStyle)]
  53051. );
  53052. if (state.strokeStyle !== undefined) {
  53053. this.hitDetectionInstructions.push([
  53054. ol.render.canvas.Instruction.SET_STROKE_STYLE,
  53055. state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
  53056. state.miterLimit, state.lineDash, state.lineDashOffset, true, 1
  53057. ]);
  53058. }
  53059. var ends = polygonGeometry.getEnds();
  53060. var flatCoordinates = polygonGeometry.getOrientedFlatCoordinates();
  53061. var stride = polygonGeometry.getStride();
  53062. this.drawFlatCoordinatess_(flatCoordinates, 0, ends, stride);
  53063. this.endGeometry(polygonGeometry, feature);
  53064. };
  53065. /**
  53066. * @inheritDoc
  53067. */
  53068. ol.render.canvas.PolygonReplay.prototype.drawMultiPolygon = function(multiPolygonGeometry, feature) {
  53069. var state = this.state_;
  53070. var fillStyle = state.fillStyle;
  53071. var strokeStyle = state.strokeStyle;
  53072. if (fillStyle === undefined && strokeStyle === undefined) {
  53073. return;
  53074. }
  53075. this.setFillStrokeStyles_(multiPolygonGeometry);
  53076. this.beginGeometry(multiPolygonGeometry, feature);
  53077. // always fill the multi-polygon for hit detection
  53078. this.hitDetectionInstructions.push([
  53079. ol.render.canvas.Instruction.SET_FILL_STYLE,
  53080. ol.color.asString(ol.render.canvas.defaultFillStyle)
  53081. ]);
  53082. if (state.strokeStyle !== undefined) {
  53083. this.hitDetectionInstructions.push([
  53084. ol.render.canvas.Instruction.SET_STROKE_STYLE,
  53085. state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
  53086. state.miterLimit, state.lineDash, state.lineDashOffset, true, 1
  53087. ]);
  53088. }
  53089. var endss = multiPolygonGeometry.getEndss();
  53090. var flatCoordinates = multiPolygonGeometry.getOrientedFlatCoordinates();
  53091. var stride = multiPolygonGeometry.getStride();
  53092. var offset = 0;
  53093. var i, ii;
  53094. for (i = 0, ii = endss.length; i < ii; ++i) {
  53095. offset = this.drawFlatCoordinatess_(
  53096. flatCoordinates, offset, endss[i], stride);
  53097. }
  53098. this.endGeometry(multiPolygonGeometry, feature);
  53099. };
  53100. /**
  53101. * @inheritDoc
  53102. */
  53103. ol.render.canvas.PolygonReplay.prototype.finish = function() {
  53104. this.reverseHitDetectionInstructions();
  53105. this.state_ = null;
  53106. // We want to preserve topology when drawing polygons. Polygons are
  53107. // simplified using quantization and point elimination. However, we might
  53108. // have received a mix of quantized and non-quantized geometries, so ensure
  53109. // that all are quantized by quantizing all coordinates in the batch.
  53110. var tolerance = this.tolerance;
  53111. if (tolerance !== 0) {
  53112. var coordinates = this.coordinates;
  53113. var i, ii;
  53114. for (i = 0, ii = coordinates.length; i < ii; ++i) {
  53115. coordinates[i] = ol.geom.flat.simplify.snap(coordinates[i], tolerance);
  53116. }
  53117. }
  53118. };
  53119. /**
  53120. * @inheritDoc
  53121. */
  53122. ol.render.canvas.PolygonReplay.prototype.getBufferedMaxExtent = function() {
  53123. if (!this.bufferedMaxExtent_) {
  53124. this.bufferedMaxExtent_ = ol.extent.clone(this.maxExtent);
  53125. if (this.maxLineWidth > 0) {
  53126. var width = this.resolution * (this.maxLineWidth + 1) / 2;
  53127. ol.extent.buffer(this.bufferedMaxExtent_, width, this.bufferedMaxExtent_);
  53128. }
  53129. }
  53130. return this.bufferedMaxExtent_;
  53131. };
  53132. /**
  53133. * @inheritDoc
  53134. */
  53135. ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
  53136. var state = this.state_;
  53137. if (fillStyle) {
  53138. var fillStyleColor = fillStyle.getColor();
  53139. state.fillStyle = ol.colorlike.asColorLike(fillStyleColor ?
  53140. fillStyleColor : ol.render.canvas.defaultFillStyle);
  53141. } else {
  53142. state.fillStyle = undefined;
  53143. }
  53144. if (strokeStyle) {
  53145. var strokeStyleColor = strokeStyle.getColor();
  53146. state.strokeStyle = ol.colorlike.asColorLike(strokeStyleColor ?
  53147. strokeStyleColor : ol.render.canvas.defaultStrokeStyle);
  53148. var strokeStyleLineCap = strokeStyle.getLineCap();
  53149. state.lineCap = strokeStyleLineCap !== undefined ?
  53150. strokeStyleLineCap : ol.render.canvas.defaultLineCap;
  53151. var strokeStyleLineDash = strokeStyle.getLineDash();
  53152. state.lineDash = strokeStyleLineDash ?
  53153. strokeStyleLineDash.slice() : ol.render.canvas.defaultLineDash;
  53154. var strokeStyleLineDashOffset = strokeStyle.getLineDashOffset();
  53155. state.lineDashOffset = strokeStyleLineDashOffset ?
  53156. strokeStyleLineDashOffset : ol.render.canvas.defaultLineDashOffset;
  53157. var strokeStyleLineJoin = strokeStyle.getLineJoin();
  53158. state.lineJoin = strokeStyleLineJoin !== undefined ?
  53159. strokeStyleLineJoin : ol.render.canvas.defaultLineJoin;
  53160. var strokeStyleWidth = strokeStyle.getWidth();
  53161. state.lineWidth = strokeStyleWidth !== undefined ?
  53162. strokeStyleWidth : ol.render.canvas.defaultLineWidth;
  53163. var strokeStyleMiterLimit = strokeStyle.getMiterLimit();
  53164. state.miterLimit = strokeStyleMiterLimit !== undefined ?
  53165. strokeStyleMiterLimit : ol.render.canvas.defaultMiterLimit;
  53166. if (state.lineWidth > this.maxLineWidth) {
  53167. this.maxLineWidth = state.lineWidth;
  53168. // invalidate the buffered max extent cache
  53169. this.bufferedMaxExtent_ = null;
  53170. }
  53171. } else {
  53172. state.strokeStyle = undefined;
  53173. state.lineCap = undefined;
  53174. state.lineDash = null;
  53175. state.lineDashOffset = undefined;
  53176. state.lineJoin = undefined;
  53177. state.lineWidth = undefined;
  53178. state.miterLimit = undefined;
  53179. }
  53180. };
  53181. /**
  53182. * @private
  53183. * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
  53184. */
  53185. ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyles_ = function(geometry) {
  53186. var state = this.state_;
  53187. var fillStyle = state.fillStyle;
  53188. var strokeStyle = state.strokeStyle;
  53189. var lineCap = state.lineCap;
  53190. var lineDash = state.lineDash;
  53191. var lineDashOffset = state.lineDashOffset;
  53192. var lineJoin = state.lineJoin;
  53193. var lineWidth = state.lineWidth;
  53194. var miterLimit = state.miterLimit;
  53195. if (fillStyle !== undefined && (typeof fillStyle !== 'string' || state.currentFillStyle != fillStyle)) {
  53196. var fillInstruction = [ol.render.canvas.Instruction.SET_FILL_STYLE, fillStyle];
  53197. if (typeof fillStyle !== 'string') {
  53198. var fillExtent = geometry.getExtent();
  53199. fillInstruction.push([fillExtent[0], fillExtent[3]]);
  53200. }
  53201. this.instructions.push(fillInstruction);
  53202. state.currentFillStyle = state.fillStyle;
  53203. }
  53204. if (strokeStyle !== undefined) {
  53205. if (state.currentStrokeStyle != strokeStyle ||
  53206. state.currentLineCap != lineCap ||
  53207. !ol.array.equals(state.currentLineDash, lineDash) ||
  53208. state.currentLineDashOffset != lineDashOffset ||
  53209. state.currentLineJoin != lineJoin ||
  53210. state.currentLineWidth != lineWidth ||
  53211. state.currentMiterLimit != miterLimit) {
  53212. this.instructions.push([
  53213. ol.render.canvas.Instruction.SET_STROKE_STYLE,
  53214. strokeStyle, lineWidth, lineCap, lineJoin, miterLimit, lineDash, lineDashOffset, true, 1
  53215. ]);
  53216. state.currentStrokeStyle = strokeStyle;
  53217. state.currentLineCap = lineCap;
  53218. state.currentLineDash = lineDash;
  53219. state.currentLineDashOffset = lineDashOffset;
  53220. state.currentLineJoin = lineJoin;
  53221. state.currentLineWidth = lineWidth;
  53222. state.currentMiterLimit = miterLimit;
  53223. }
  53224. }
  53225. };
  53226. goog.provide('ol.render.canvas.TextReplay');
  53227. goog.require('ol');
  53228. goog.require('ol.colorlike');
  53229. goog.require('ol.render.canvas');
  53230. goog.require('ol.render.canvas.Instruction');
  53231. goog.require('ol.render.canvas.Replay');
  53232. /**
  53233. * @constructor
  53234. * @extends {ol.render.canvas.Replay}
  53235. * @param {number} tolerance Tolerance.
  53236. * @param {ol.Extent} maxExtent Maximum extent.
  53237. * @param {number} resolution Resolution.
  53238. * @param {boolean} overlaps The replay can have overlapping geometries.
  53239. * @struct
  53240. */
  53241. ol.render.canvas.TextReplay = function(tolerance, maxExtent, resolution, overlaps) {
  53242. ol.render.canvas.Replay.call(this, tolerance, maxExtent, resolution, overlaps);
  53243. /**
  53244. * @private
  53245. * @type {?ol.CanvasFillState}
  53246. */
  53247. this.replayFillState_ = null;
  53248. /**
  53249. * @private
  53250. * @type {?ol.CanvasStrokeState}
  53251. */
  53252. this.replayStrokeState_ = null;
  53253. /**
  53254. * @private
  53255. * @type {?ol.CanvasTextState}
  53256. */
  53257. this.replayTextState_ = null;
  53258. /**
  53259. * @private
  53260. * @type {string}
  53261. */
  53262. this.text_ = '';
  53263. /**
  53264. * @private
  53265. * @type {number}
  53266. */
  53267. this.textOffsetX_ = 0;
  53268. /**
  53269. * @private
  53270. * @type {number}
  53271. */
  53272. this.textOffsetY_ = 0;
  53273. /**
  53274. * @private
  53275. * @type {boolean|undefined}
  53276. */
  53277. this.textRotateWithView_ = undefined;
  53278. /**
  53279. * @private
  53280. * @type {number}
  53281. */
  53282. this.textRotation_ = 0;
  53283. /**
  53284. * @private
  53285. * @type {number}
  53286. */
  53287. this.textScale_ = 0;
  53288. /**
  53289. * @private
  53290. * @type {?ol.CanvasFillState}
  53291. */
  53292. this.textFillState_ = null;
  53293. /**
  53294. * @private
  53295. * @type {?ol.CanvasStrokeState}
  53296. */
  53297. this.textStrokeState_ = null;
  53298. /**
  53299. * @private
  53300. * @type {?ol.CanvasTextState}
  53301. */
  53302. this.textState_ = null;
  53303. };
  53304. ol.inherits(ol.render.canvas.TextReplay, ol.render.canvas.Replay);
  53305. /**
  53306. * @inheritDoc
  53307. */
  53308. ol.render.canvas.TextReplay.prototype.drawText = function(flatCoordinates, offset, end, stride, geometry, feature) {
  53309. if (this.text_ === '' || !this.textState_ ||
  53310. (!this.textFillState_ && !this.textStrokeState_)) {
  53311. return;
  53312. }
  53313. if (this.textFillState_) {
  53314. this.setReplayFillState_(this.textFillState_);
  53315. }
  53316. if (this.textStrokeState_) {
  53317. this.setReplayStrokeState_(this.textStrokeState_);
  53318. }
  53319. this.setReplayTextState_(this.textState_);
  53320. this.beginGeometry(geometry, feature);
  53321. var myBegin = this.coordinates.length;
  53322. var myEnd =
  53323. this.appendFlatCoordinates(flatCoordinates, offset, end, stride, false, false);
  53324. var fill = !!this.textFillState_;
  53325. var stroke = !!this.textStrokeState_;
  53326. var drawTextInstruction = [
  53327. ol.render.canvas.Instruction.DRAW_TEXT, myBegin, myEnd, this.text_,
  53328. this.textOffsetX_, this.textOffsetY_, this.textRotation_, this.textScale_,
  53329. fill, stroke, this.textRotateWithView_];
  53330. this.instructions.push(drawTextInstruction);
  53331. this.hitDetectionInstructions.push(drawTextInstruction);
  53332. this.endGeometry(geometry, feature);
  53333. };
  53334. /**
  53335. * @param {ol.CanvasFillState} fillState Fill state.
  53336. * @private
  53337. */
  53338. ol.render.canvas.TextReplay.prototype.setReplayFillState_ = function(fillState) {
  53339. var replayFillState = this.replayFillState_;
  53340. if (replayFillState &&
  53341. replayFillState.fillStyle == fillState.fillStyle) {
  53342. return;
  53343. }
  53344. var setFillStyleInstruction =
  53345. [ol.render.canvas.Instruction.SET_FILL_STYLE, fillState.fillStyle];
  53346. this.instructions.push(setFillStyleInstruction);
  53347. this.hitDetectionInstructions.push(setFillStyleInstruction);
  53348. if (!replayFillState) {
  53349. this.replayFillState_ = {
  53350. fillStyle: fillState.fillStyle
  53351. };
  53352. } else {
  53353. replayFillState.fillStyle = fillState.fillStyle;
  53354. }
  53355. };
  53356. /**
  53357. * @param {ol.CanvasStrokeState} strokeState Stroke state.
  53358. * @private
  53359. */
  53360. ol.render.canvas.TextReplay.prototype.setReplayStrokeState_ = function(strokeState) {
  53361. var replayStrokeState = this.replayStrokeState_;
  53362. if (replayStrokeState &&
  53363. replayStrokeState.lineCap == strokeState.lineCap &&
  53364. replayStrokeState.lineDash == strokeState.lineDash &&
  53365. replayStrokeState.lineDashOffset == strokeState.lineDashOffset &&
  53366. replayStrokeState.lineJoin == strokeState.lineJoin &&
  53367. replayStrokeState.lineWidth == strokeState.lineWidth &&
  53368. replayStrokeState.miterLimit == strokeState.miterLimit &&
  53369. replayStrokeState.strokeStyle == strokeState.strokeStyle) {
  53370. return;
  53371. }
  53372. var setStrokeStyleInstruction = [
  53373. ol.render.canvas.Instruction.SET_STROKE_STYLE, strokeState.strokeStyle,
  53374. strokeState.lineWidth, strokeState.lineCap, strokeState.lineJoin,
  53375. strokeState.miterLimit, strokeState.lineDash, strokeState.lineDashOffset, false, 1
  53376. ];
  53377. this.instructions.push(setStrokeStyleInstruction);
  53378. this.hitDetectionInstructions.push(setStrokeStyleInstruction);
  53379. if (!replayStrokeState) {
  53380. this.replayStrokeState_ = {
  53381. lineCap: strokeState.lineCap,
  53382. lineDash: strokeState.lineDash,
  53383. lineDashOffset: strokeState.lineDashOffset,
  53384. lineJoin: strokeState.lineJoin,
  53385. lineWidth: strokeState.lineWidth,
  53386. miterLimit: strokeState.miterLimit,
  53387. strokeStyle: strokeState.strokeStyle
  53388. };
  53389. } else {
  53390. replayStrokeState.lineCap = strokeState.lineCap;
  53391. replayStrokeState.lineDash = strokeState.lineDash;
  53392. replayStrokeState.lineDashOffset = strokeState.lineDashOffset;
  53393. replayStrokeState.lineJoin = strokeState.lineJoin;
  53394. replayStrokeState.lineWidth = strokeState.lineWidth;
  53395. replayStrokeState.miterLimit = strokeState.miterLimit;
  53396. replayStrokeState.strokeStyle = strokeState.strokeStyle;
  53397. }
  53398. };
  53399. /**
  53400. * @param {ol.CanvasTextState} textState Text state.
  53401. * @private
  53402. */
  53403. ol.render.canvas.TextReplay.prototype.setReplayTextState_ = function(textState) {
  53404. var replayTextState = this.replayTextState_;
  53405. if (replayTextState &&
  53406. replayTextState.font == textState.font &&
  53407. replayTextState.textAlign == textState.textAlign &&
  53408. replayTextState.textBaseline == textState.textBaseline) {
  53409. return;
  53410. }
  53411. var setTextStyleInstruction = [ol.render.canvas.Instruction.SET_TEXT_STYLE,
  53412. textState.font, textState.textAlign, textState.textBaseline];
  53413. this.instructions.push(setTextStyleInstruction);
  53414. this.hitDetectionInstructions.push(setTextStyleInstruction);
  53415. if (!replayTextState) {
  53416. this.replayTextState_ = {
  53417. font: textState.font,
  53418. textAlign: textState.textAlign,
  53419. textBaseline: textState.textBaseline
  53420. };
  53421. } else {
  53422. replayTextState.font = textState.font;
  53423. replayTextState.textAlign = textState.textAlign;
  53424. replayTextState.textBaseline = textState.textBaseline;
  53425. }
  53426. };
  53427. /**
  53428. * @inheritDoc
  53429. */
  53430. ol.render.canvas.TextReplay.prototype.setTextStyle = function(textStyle) {
  53431. if (!textStyle) {
  53432. this.text_ = '';
  53433. } else {
  53434. var textFillStyle = textStyle.getFill();
  53435. if (!textFillStyle) {
  53436. this.textFillState_ = null;
  53437. } else {
  53438. var textFillStyleColor = textFillStyle.getColor();
  53439. var fillStyle = ol.colorlike.asColorLike(textFillStyleColor ?
  53440. textFillStyleColor : ol.render.canvas.defaultFillStyle);
  53441. if (!this.textFillState_) {
  53442. this.textFillState_ = {
  53443. fillStyle: fillStyle
  53444. };
  53445. } else {
  53446. var textFillState = this.textFillState_;
  53447. textFillState.fillStyle = fillStyle;
  53448. }
  53449. }
  53450. var textStrokeStyle = textStyle.getStroke();
  53451. if (!textStrokeStyle) {
  53452. this.textStrokeState_ = null;
  53453. } else {
  53454. var textStrokeStyleColor = textStrokeStyle.getColor();
  53455. var textStrokeStyleLineCap = textStrokeStyle.getLineCap();
  53456. var textStrokeStyleLineDash = textStrokeStyle.getLineDash();
  53457. var textStrokeStyleLineDashOffset = textStrokeStyle.getLineDashOffset();
  53458. var textStrokeStyleLineJoin = textStrokeStyle.getLineJoin();
  53459. var textStrokeStyleWidth = textStrokeStyle.getWidth();
  53460. var textStrokeStyleMiterLimit = textStrokeStyle.getMiterLimit();
  53461. var lineCap = textStrokeStyleLineCap !== undefined ?
  53462. textStrokeStyleLineCap : ol.render.canvas.defaultLineCap;
  53463. var lineDash = textStrokeStyleLineDash ?
  53464. textStrokeStyleLineDash.slice() : ol.render.canvas.defaultLineDash;
  53465. var lineDashOffset = textStrokeStyleLineDashOffset !== undefined ?
  53466. textStrokeStyleLineDashOffset : ol.render.canvas.defaultLineDashOffset;
  53467. var lineJoin = textStrokeStyleLineJoin !== undefined ?
  53468. textStrokeStyleLineJoin : ol.render.canvas.defaultLineJoin;
  53469. var lineWidth = textStrokeStyleWidth !== undefined ?
  53470. textStrokeStyleWidth : ol.render.canvas.defaultLineWidth;
  53471. var miterLimit = textStrokeStyleMiterLimit !== undefined ?
  53472. textStrokeStyleMiterLimit : ol.render.canvas.defaultMiterLimit;
  53473. var strokeStyle = ol.colorlike.asColorLike(textStrokeStyleColor ?
  53474. textStrokeStyleColor : ol.render.canvas.defaultStrokeStyle);
  53475. if (!this.textStrokeState_) {
  53476. this.textStrokeState_ = {
  53477. lineCap: lineCap,
  53478. lineDash: lineDash,
  53479. lineDashOffset: lineDashOffset,
  53480. lineJoin: lineJoin,
  53481. lineWidth: lineWidth,
  53482. miterLimit: miterLimit,
  53483. strokeStyle: strokeStyle
  53484. };
  53485. } else {
  53486. var textStrokeState = this.textStrokeState_;
  53487. textStrokeState.lineCap = lineCap;
  53488. textStrokeState.lineDash = lineDash;
  53489. textStrokeState.lineDashOffset = lineDashOffset;
  53490. textStrokeState.lineJoin = lineJoin;
  53491. textStrokeState.lineWidth = lineWidth;
  53492. textStrokeState.miterLimit = miterLimit;
  53493. textStrokeState.strokeStyle = strokeStyle;
  53494. }
  53495. }
  53496. var textFont = textStyle.getFont();
  53497. var textOffsetX = textStyle.getOffsetX();
  53498. var textOffsetY = textStyle.getOffsetY();
  53499. var textRotateWithView = textStyle.getRotateWithView();
  53500. var textRotation = textStyle.getRotation();
  53501. var textScale = textStyle.getScale();
  53502. var textText = textStyle.getText();
  53503. var textTextAlign = textStyle.getTextAlign();
  53504. var textTextBaseline = textStyle.getTextBaseline();
  53505. var font = textFont !== undefined ?
  53506. textFont : ol.render.canvas.defaultFont;
  53507. var textAlign = textTextAlign !== undefined ?
  53508. textTextAlign : ol.render.canvas.defaultTextAlign;
  53509. var textBaseline = textTextBaseline !== undefined ?
  53510. textTextBaseline : ol.render.canvas.defaultTextBaseline;
  53511. if (!this.textState_) {
  53512. this.textState_ = {
  53513. font: font,
  53514. textAlign: textAlign,
  53515. textBaseline: textBaseline
  53516. };
  53517. } else {
  53518. var textState = this.textState_;
  53519. textState.font = font;
  53520. textState.textAlign = textAlign;
  53521. textState.textBaseline = textBaseline;
  53522. }
  53523. this.text_ = textText !== undefined ? textText : '';
  53524. this.textOffsetX_ = textOffsetX !== undefined ? textOffsetX : 0;
  53525. this.textOffsetY_ = textOffsetY !== undefined ? textOffsetY : 0;
  53526. this.textRotateWithView_ = textRotateWithView !== undefined ? textRotateWithView : false;
  53527. this.textRotation_ = textRotation !== undefined ? textRotation : 0;
  53528. this.textScale_ = textScale !== undefined ? textScale : 1;
  53529. }
  53530. };
  53531. goog.provide('ol.render.canvas.ReplayGroup');
  53532. goog.require('ol');
  53533. goog.require('ol.array');
  53534. goog.require('ol.dom');
  53535. goog.require('ol.extent');
  53536. goog.require('ol.geom.flat.transform');
  53537. goog.require('ol.obj');
  53538. goog.require('ol.render.ReplayGroup');
  53539. goog.require('ol.render.canvas.Replay');
  53540. goog.require('ol.render.canvas.ImageReplay');
  53541. goog.require('ol.render.canvas.LineStringReplay');
  53542. goog.require('ol.render.canvas.PolygonReplay');
  53543. goog.require('ol.render.canvas.TextReplay');
  53544. goog.require('ol.render.replay');
  53545. goog.require('ol.transform');
  53546. /**
  53547. * @constructor
  53548. * @extends {ol.render.ReplayGroup}
  53549. * @param {number} tolerance Tolerance.
  53550. * @param {ol.Extent} maxExtent Max extent.
  53551. * @param {number} resolution Resolution.
  53552. * @param {boolean} overlaps The replay group can have overlapping geometries.
  53553. * @param {number=} opt_renderBuffer Optional rendering buffer.
  53554. * @struct
  53555. */
  53556. ol.render.canvas.ReplayGroup = function(
  53557. tolerance, maxExtent, resolution, overlaps, opt_renderBuffer) {
  53558. ol.render.ReplayGroup.call(this);
  53559. /**
  53560. * @private
  53561. * @type {number}
  53562. */
  53563. this.tolerance_ = tolerance;
  53564. /**
  53565. * @private
  53566. * @type {ol.Extent}
  53567. */
  53568. this.maxExtent_ = maxExtent;
  53569. /**
  53570. * @private
  53571. * @type {boolean}
  53572. */
  53573. this.overlaps_ = overlaps;
  53574. /**
  53575. * @private
  53576. * @type {number}
  53577. */
  53578. this.resolution_ = resolution;
  53579. /**
  53580. * @private
  53581. * @type {number|undefined}
  53582. */
  53583. this.renderBuffer_ = opt_renderBuffer;
  53584. /**
  53585. * @private
  53586. * @type {!Object.<string,
  53587. * Object.<ol.render.ReplayType, ol.render.canvas.Replay>>}
  53588. */
  53589. this.replaysByZIndex_ = {};
  53590. /**
  53591. * @private
  53592. * @type {CanvasRenderingContext2D}
  53593. */
  53594. this.hitDetectionContext_ = ol.dom.createCanvasContext2D(1, 1);
  53595. /**
  53596. * @private
  53597. * @type {ol.Transform}
  53598. */
  53599. this.hitDetectionTransform_ = ol.transform.create();
  53600. };
  53601. ol.inherits(ol.render.canvas.ReplayGroup, ol.render.ReplayGroup);
  53602. /**
  53603. * This cache is used for storing calculated pixel circles for increasing performance.
  53604. * It is a static property to allow each Replaygroup to access it.
  53605. * @type {Object.<number, Array.<Array.<(boolean|undefined)>>>}
  53606. * @private
  53607. */
  53608. ol.render.canvas.ReplayGroup.circleArrayCache_ = {
  53609. 0: [[true]]
  53610. };
  53611. /**
  53612. * This method fills a row in the array from the given coordinate to the
  53613. * middle with `true`.
  53614. * @param {Array.<Array.<(boolean|undefined)>>} array The array that will be altered.
  53615. * @param {number} x X coordinate.
  53616. * @param {number} y Y coordinate.
  53617. * @private
  53618. */
  53619. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_ = function(array, x, y) {
  53620. var i;
  53621. var radius = Math.floor(array.length / 2);
  53622. if (x >= radius) {
  53623. for (i = radius; i < x; i++) {
  53624. array[i][y] = true;
  53625. }
  53626. } else if (x < radius) {
  53627. for (i = x + 1; i < radius; i++) {
  53628. array[i][y] = true;
  53629. }
  53630. }
  53631. };
  53632. /**
  53633. * This methods creates a circle inside a fitting array. Points inside the
  53634. * circle are marked by true, points on the outside are undefined.
  53635. * It uses the midpoint circle algorithm.
  53636. * A cache is used to increase performance.
  53637. * @param {number} radius Radius.
  53638. * @returns {Array.<Array.<(boolean|undefined)>>} An array with marked circle points.
  53639. * @private
  53640. */
  53641. ol.render.canvas.ReplayGroup.getCircleArray_ = function(radius) {
  53642. if (ol.render.canvas.ReplayGroup.circleArrayCache_[radius] !== undefined) {
  53643. return ol.render.canvas.ReplayGroup.circleArrayCache_[radius];
  53644. }
  53645. var arraySize = radius * 2 + 1;
  53646. var arr = new Array(arraySize);
  53647. for (var i = 0; i < arraySize; i++) {
  53648. arr[i] = new Array(arraySize);
  53649. }
  53650. var x = radius;
  53651. var y = 0;
  53652. var error = 0;
  53653. while (x >= y) {
  53654. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + x, radius + y);
  53655. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + y, radius + x);
  53656. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - y, radius + x);
  53657. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - x, radius + y);
  53658. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - x, radius - y);
  53659. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - y, radius - x);
  53660. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + y, radius - x);
  53661. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + x, radius - y);
  53662. y++;
  53663. error += 1 + 2 * y;
  53664. if (2 * (error - x) + 1 > 0) {
  53665. x -= 1;
  53666. error += 1 - 2 * x;
  53667. }
  53668. }
  53669. ol.render.canvas.ReplayGroup.circleArrayCache_[radius] = arr;
  53670. return arr;
  53671. };
  53672. /**
  53673. * @param {Array.<ol.render.ReplayType>} replays Replays.
  53674. * @return {boolean} Has replays of the provided types.
  53675. */
  53676. ol.render.canvas.ReplayGroup.prototype.hasReplays = function(replays) {
  53677. for (var zIndex in this.replaysByZIndex_) {
  53678. var candidates = this.replaysByZIndex_[zIndex];
  53679. for (var i = 0, ii = replays.length; i < ii; ++i) {
  53680. if (replays[i] in candidates) {
  53681. return true;
  53682. }
  53683. }
  53684. }
  53685. return false;
  53686. };
  53687. /**
  53688. * FIXME empty description for jsdoc
  53689. */
  53690. ol.render.canvas.ReplayGroup.prototype.finish = function() {
  53691. var zKey;
  53692. for (zKey in this.replaysByZIndex_) {
  53693. var replays = this.replaysByZIndex_[zKey];
  53694. var replayKey;
  53695. for (replayKey in replays) {
  53696. replays[replayKey].finish();
  53697. }
  53698. }
  53699. };
  53700. /**
  53701. * @param {ol.Coordinate} coordinate Coordinate.
  53702. * @param {number} resolution Resolution.
  53703. * @param {number} rotation Rotation.
  53704. * @param {number} hitTolerance Hit tolerance in pixels.
  53705. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  53706. * to skip.
  53707. * @param {function((ol.Feature|ol.render.Feature)): T} callback Feature
  53708. * callback.
  53709. * @return {T|undefined} Callback result.
  53710. * @template T
  53711. */
  53712. ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
  53713. coordinate, resolution, rotation, hitTolerance, skippedFeaturesHash, callback) {
  53714. hitTolerance = Math.round(hitTolerance);
  53715. var contextSize = hitTolerance * 2 + 1;
  53716. var transform = ol.transform.compose(this.hitDetectionTransform_,
  53717. hitTolerance + 0.5, hitTolerance + 0.5,
  53718. 1 / resolution, -1 / resolution,
  53719. -rotation,
  53720. -coordinate[0], -coordinate[1]);
  53721. var context = this.hitDetectionContext_;
  53722. if (context.canvas.width !== contextSize || context.canvas.height !== contextSize) {
  53723. context.canvas.width = contextSize;
  53724. context.canvas.height = contextSize;
  53725. } else {
  53726. context.clearRect(0, 0, contextSize, contextSize);
  53727. }
  53728. /**
  53729. * @type {ol.Extent}
  53730. */
  53731. var hitExtent;
  53732. if (this.renderBuffer_ !== undefined) {
  53733. hitExtent = ol.extent.createEmpty();
  53734. ol.extent.extendCoordinate(hitExtent, coordinate);
  53735. ol.extent.buffer(hitExtent, resolution * (this.renderBuffer_ + hitTolerance), hitExtent);
  53736. }
  53737. var mask = ol.render.canvas.ReplayGroup.getCircleArray_(hitTolerance);
  53738. return this.replayHitDetection_(context, transform, rotation,
  53739. skippedFeaturesHash,
  53740. /**
  53741. * @param {ol.Feature|ol.render.Feature} feature Feature.
  53742. * @return {?} Callback result.
  53743. */
  53744. function(feature) {
  53745. var imageData = context.getImageData(0, 0, contextSize, contextSize).data;
  53746. for (var i = 0; i < contextSize; i++) {
  53747. for (var j = 0; j < contextSize; j++) {
  53748. if (mask[i][j]) {
  53749. if (imageData[(j * contextSize + i) * 4 + 3] > 0) {
  53750. var result = callback(feature);
  53751. if (result) {
  53752. return result;
  53753. } else {
  53754. context.clearRect(0, 0, contextSize, contextSize);
  53755. return undefined;
  53756. }
  53757. }
  53758. }
  53759. }
  53760. }
  53761. }, hitExtent);
  53762. };
  53763. /**
  53764. * @param {ol.Transform} transform Transform.
  53765. * @return {Array.<number>} Clip coordinates.
  53766. */
  53767. ol.render.canvas.ReplayGroup.prototype.getClipCoords = function(transform) {
  53768. var maxExtent = this.maxExtent_;
  53769. var minX = maxExtent[0];
  53770. var minY = maxExtent[1];
  53771. var maxX = maxExtent[2];
  53772. var maxY = maxExtent[3];
  53773. var flatClipCoords = [minX, minY, minX, maxY, maxX, maxY, maxX, minY];
  53774. ol.geom.flat.transform.transform2D(
  53775. flatClipCoords, 0, 8, 2, transform, flatClipCoords);
  53776. return flatClipCoords;
  53777. };
  53778. /**
  53779. * @inheritDoc
  53780. */
  53781. ol.render.canvas.ReplayGroup.prototype.getReplay = function(zIndex, replayType) {
  53782. var zIndexKey = zIndex !== undefined ? zIndex.toString() : '0';
  53783. var replays = this.replaysByZIndex_[zIndexKey];
  53784. if (replays === undefined) {
  53785. replays = {};
  53786. this.replaysByZIndex_[zIndexKey] = replays;
  53787. }
  53788. var replay = replays[replayType];
  53789. if (replay === undefined) {
  53790. var Constructor = ol.render.canvas.ReplayGroup.BATCH_CONSTRUCTORS_[replayType];
  53791. replay = new Constructor(this.tolerance_, this.maxExtent_,
  53792. this.resolution_, this.overlaps_);
  53793. replays[replayType] = replay;
  53794. }
  53795. return replay;
  53796. };
  53797. /**
  53798. * @inheritDoc
  53799. */
  53800. ol.render.canvas.ReplayGroup.prototype.isEmpty = function() {
  53801. return ol.obj.isEmpty(this.replaysByZIndex_);
  53802. };
  53803. /**
  53804. * @param {CanvasRenderingContext2D} context Context.
  53805. * @param {number} pixelRatio Pixel ratio.
  53806. * @param {ol.Transform} transform Transform.
  53807. * @param {number} viewRotation View rotation.
  53808. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  53809. * to skip.
  53810. * @param {Array.<ol.render.ReplayType>=} opt_replayTypes Ordered replay types
  53811. * to replay. Default is {@link ol.render.replay.ORDER}
  53812. */
  53813. ol.render.canvas.ReplayGroup.prototype.replay = function(context, pixelRatio,
  53814. transform, viewRotation, skippedFeaturesHash, opt_replayTypes) {
  53815. /** @type {Array.<number>} */
  53816. var zs = Object.keys(this.replaysByZIndex_).map(Number);
  53817. zs.sort(ol.array.numberSafeCompareFunction);
  53818. // setup clipping so that the parts of over-simplified geometries are not
  53819. // visible outside the current extent when panning
  53820. var flatClipCoords = this.getClipCoords(transform);
  53821. context.save();
  53822. context.beginPath();
  53823. context.moveTo(flatClipCoords[0], flatClipCoords[1]);
  53824. context.lineTo(flatClipCoords[2], flatClipCoords[3]);
  53825. context.lineTo(flatClipCoords[4], flatClipCoords[5]);
  53826. context.lineTo(flatClipCoords[6], flatClipCoords[7]);
  53827. context.clip();
  53828. var replayTypes = opt_replayTypes ? opt_replayTypes : ol.render.replay.ORDER;
  53829. var i, ii, j, jj, replays, replay;
  53830. for (i = 0, ii = zs.length; i < ii; ++i) {
  53831. replays = this.replaysByZIndex_[zs[i].toString()];
  53832. for (j = 0, jj = replayTypes.length; j < jj; ++j) {
  53833. replay = replays[replayTypes[j]];
  53834. if (replay !== undefined) {
  53835. replay.replay(context, pixelRatio, transform, viewRotation,
  53836. skippedFeaturesHash);
  53837. }
  53838. }
  53839. }
  53840. context.restore();
  53841. };
  53842. /**
  53843. * @private
  53844. * @param {CanvasRenderingContext2D} context Context.
  53845. * @param {ol.Transform} transform Transform.
  53846. * @param {number} viewRotation View rotation.
  53847. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  53848. * to skip.
  53849. * @param {function((ol.Feature|ol.render.Feature)): T} featureCallback
  53850. * Feature callback.
  53851. * @param {ol.Extent=} opt_hitExtent Only check features that intersect this
  53852. * extent.
  53853. * @return {T|undefined} Callback result.
  53854. * @template T
  53855. */
  53856. ol.render.canvas.ReplayGroup.prototype.replayHitDetection_ = function(
  53857. context, transform, viewRotation, skippedFeaturesHash,
  53858. featureCallback, opt_hitExtent) {
  53859. /** @type {Array.<number>} */
  53860. var zs = Object.keys(this.replaysByZIndex_).map(Number);
  53861. zs.sort(function(a, b) {
  53862. return b - a;
  53863. });
  53864. var i, ii, j, replays, replay, result;
  53865. for (i = 0, ii = zs.length; i < ii; ++i) {
  53866. replays = this.replaysByZIndex_[zs[i].toString()];
  53867. for (j = ol.render.replay.ORDER.length - 1; j >= 0; --j) {
  53868. replay = replays[ol.render.replay.ORDER[j]];
  53869. if (replay !== undefined) {
  53870. result = replay.replayHitDetection(context, transform, viewRotation,
  53871. skippedFeaturesHash, featureCallback, opt_hitExtent);
  53872. if (result) {
  53873. return result;
  53874. }
  53875. }
  53876. }
  53877. }
  53878. return undefined;
  53879. };
  53880. /**
  53881. * @const
  53882. * @private
  53883. * @type {Object.<ol.render.ReplayType,
  53884. * function(new: ol.render.canvas.Replay, number, ol.Extent,
  53885. * number, boolean)>}
  53886. */
  53887. ol.render.canvas.ReplayGroup.BATCH_CONSTRUCTORS_ = {
  53888. 'Circle': ol.render.canvas.PolygonReplay,
  53889. 'Default': ol.render.canvas.Replay,
  53890. 'Image': ol.render.canvas.ImageReplay,
  53891. 'LineString': ol.render.canvas.LineStringReplay,
  53892. 'Polygon': ol.render.canvas.PolygonReplay,
  53893. 'Text': ol.render.canvas.TextReplay
  53894. };
  53895. goog.provide('ol.renderer.Layer');
  53896. goog.require('ol');
  53897. goog.require('ol.ImageState');
  53898. goog.require('ol.Observable');
  53899. goog.require('ol.TileState');
  53900. goog.require('ol.asserts');
  53901. goog.require('ol.events');
  53902. goog.require('ol.events.EventType');
  53903. goog.require('ol.functions');
  53904. goog.require('ol.source.State');
  53905. /**
  53906. * @constructor
  53907. * @extends {ol.Observable}
  53908. * @param {ol.layer.Layer} layer Layer.
  53909. * @struct
  53910. */
  53911. ol.renderer.Layer = function(layer) {
  53912. ol.Observable.call(this);
  53913. /**
  53914. * @private
  53915. * @type {ol.layer.Layer}
  53916. */
  53917. this.layer_ = layer;
  53918. };
  53919. ol.inherits(ol.renderer.Layer, ol.Observable);
  53920. /**
  53921. * @param {ol.Coordinate} coordinate Coordinate.
  53922. * @param {olx.FrameState} frameState Frame state.
  53923. * @param {number} hitTolerance Hit tolerance in pixels.
  53924. * @param {function(this: S, (ol.Feature|ol.render.Feature), ol.layer.Layer): T}
  53925. * callback Feature callback.
  53926. * @param {S} thisArg Value to use as `this` when executing `callback`.
  53927. * @return {T|undefined} Callback result.
  53928. * @template S,T
  53929. */
  53930. ol.renderer.Layer.prototype.forEachFeatureAtCoordinate = ol.nullFunction;
  53931. /**
  53932. * @param {ol.Coordinate} coordinate Coordinate.
  53933. * @param {olx.FrameState} frameState Frame state.
  53934. * @return {boolean} Is there a feature at the given coordinate?
  53935. */
  53936. ol.renderer.Layer.prototype.hasFeatureAtCoordinate = ol.functions.FALSE;
  53937. /**
  53938. * Create a function that adds loaded tiles to the tile lookup.
  53939. * @param {ol.source.Tile} source Tile source.
  53940. * @param {ol.proj.Projection} projection Projection of the tiles.
  53941. * @param {Object.<number, Object.<string, ol.Tile>>} tiles Lookup of loaded
  53942. * tiles by zoom level.
  53943. * @return {function(number, ol.TileRange):boolean} A function that can be
  53944. * called with a zoom level and a tile range to add loaded tiles to the
  53945. * lookup.
  53946. * @protected
  53947. */
  53948. ol.renderer.Layer.prototype.createLoadedTileFinder = function(source, projection, tiles) {
  53949. return (
  53950. /**
  53951. * @param {number} zoom Zoom level.
  53952. * @param {ol.TileRange} tileRange Tile range.
  53953. * @return {boolean} The tile range is fully loaded.
  53954. */
  53955. function(zoom, tileRange) {
  53956. function callback(tile) {
  53957. if (!tiles[zoom]) {
  53958. tiles[zoom] = {};
  53959. }
  53960. tiles[zoom][tile.tileCoord.toString()] = tile;
  53961. }
  53962. return source.forEachLoadedTile(projection, zoom, tileRange, callback);
  53963. });
  53964. };
  53965. /**
  53966. * @return {ol.layer.Layer} Layer.
  53967. */
  53968. ol.renderer.Layer.prototype.getLayer = function() {
  53969. return this.layer_;
  53970. };
  53971. /**
  53972. * Handle changes in image state.
  53973. * @param {ol.events.Event} event Image change event.
  53974. * @private
  53975. */
  53976. ol.renderer.Layer.prototype.handleImageChange_ = function(event) {
  53977. var image = /** @type {ol.Image} */ (event.target);
  53978. if (image.getState() === ol.ImageState.LOADED) {
  53979. this.renderIfReadyAndVisible();
  53980. }
  53981. };
  53982. /**
  53983. * Load the image if not already loaded, and register the image change
  53984. * listener if needed.
  53985. * @param {ol.ImageBase} image Image.
  53986. * @return {boolean} `true` if the image is already loaded, `false`
  53987. * otherwise.
  53988. * @protected
  53989. */
  53990. ol.renderer.Layer.prototype.loadImage = function(image) {
  53991. var imageState = image.getState();
  53992. if (imageState != ol.ImageState.LOADED &&
  53993. imageState != ol.ImageState.ERROR) {
  53994. ol.events.listen(image, ol.events.EventType.CHANGE,
  53995. this.handleImageChange_, this);
  53996. }
  53997. if (imageState == ol.ImageState.IDLE) {
  53998. image.load();
  53999. imageState = image.getState();
  54000. }
  54001. return imageState == ol.ImageState.LOADED;
  54002. };
  54003. /**
  54004. * @protected
  54005. */
  54006. ol.renderer.Layer.prototype.renderIfReadyAndVisible = function() {
  54007. var layer = this.getLayer();
  54008. if (layer.getVisible() && layer.getSourceState() == ol.source.State.READY) {
  54009. this.changed();
  54010. }
  54011. };
  54012. /**
  54013. * @param {olx.FrameState} frameState Frame state.
  54014. * @param {ol.source.Tile} tileSource Tile source.
  54015. * @protected
  54016. */
  54017. ol.renderer.Layer.prototype.scheduleExpireCache = function(frameState, tileSource) {
  54018. if (tileSource.canExpireCache()) {
  54019. /**
  54020. * @param {ol.source.Tile} tileSource Tile source.
  54021. * @param {ol.Map} map Map.
  54022. * @param {olx.FrameState} frameState Frame state.
  54023. */
  54024. var postRenderFunction = function(tileSource, map, frameState) {
  54025. var tileSourceKey = ol.getUid(tileSource).toString();
  54026. if (tileSourceKey in frameState.usedTiles) {
  54027. tileSource.expireCache(frameState.viewState.projection,
  54028. frameState.usedTiles[tileSourceKey]);
  54029. }
  54030. }.bind(null, tileSource);
  54031. frameState.postRenderFunctions.push(
  54032. /** @type {ol.PostRenderFunction} */ (postRenderFunction)
  54033. );
  54034. }
  54035. };
  54036. /**
  54037. * @param {Object.<string, ol.Attribution>} attributionsSet Attributions
  54038. * set (target).
  54039. * @param {Array.<ol.Attribution>} attributions Attributions (source).
  54040. * @protected
  54041. */
  54042. ol.renderer.Layer.prototype.updateAttributions = function(attributionsSet, attributions) {
  54043. if (attributions) {
  54044. var attribution, i, ii;
  54045. for (i = 0, ii = attributions.length; i < ii; ++i) {
  54046. attribution = attributions[i];
  54047. attributionsSet[ol.getUid(attribution).toString()] = attribution;
  54048. }
  54049. }
  54050. };
  54051. /**
  54052. * @param {olx.FrameState} frameState Frame state.
  54053. * @param {ol.source.Source} source Source.
  54054. * @protected
  54055. */
  54056. ol.renderer.Layer.prototype.updateLogos = function(frameState, source) {
  54057. var logo = source.getLogo();
  54058. if (logo !== undefined) {
  54059. if (typeof logo === 'string') {
  54060. frameState.logos[logo] = '';
  54061. } else if (logo) {
  54062. ol.asserts.assert(typeof logo.href == 'string', 44); // `logo.href` should be a string.
  54063. ol.asserts.assert(typeof logo.src == 'string', 45); // `logo.src` should be a string.
  54064. frameState.logos[logo.src] = logo.href;
  54065. }
  54066. }
  54067. };
  54068. /**
  54069. * @param {Object.<string, Object.<string, ol.TileRange>>} usedTiles Used tiles.
  54070. * @param {ol.source.Tile} tileSource Tile source.
  54071. * @param {number} z Z.
  54072. * @param {ol.TileRange} tileRange Tile range.
  54073. * @protected
  54074. */
  54075. ol.renderer.Layer.prototype.updateUsedTiles = function(usedTiles, tileSource, z, tileRange) {
  54076. // FIXME should we use tilesToDrawByZ instead?
  54077. var tileSourceKey = ol.getUid(tileSource).toString();
  54078. var zKey = z.toString();
  54079. if (tileSourceKey in usedTiles) {
  54080. if (zKey in usedTiles[tileSourceKey]) {
  54081. usedTiles[tileSourceKey][zKey].extend(tileRange);
  54082. } else {
  54083. usedTiles[tileSourceKey][zKey] = tileRange;
  54084. }
  54085. } else {
  54086. usedTiles[tileSourceKey] = {};
  54087. usedTiles[tileSourceKey][zKey] = tileRange;
  54088. }
  54089. };
  54090. /**
  54091. * Manage tile pyramid.
  54092. * This function performs a number of functions related to the tiles at the
  54093. * current zoom and lower zoom levels:
  54094. * - registers idle tiles in frameState.wantedTiles so that they are not
  54095. * discarded by the tile queue
  54096. * - enqueues missing tiles
  54097. * @param {olx.FrameState} frameState Frame state.
  54098. * @param {ol.source.Tile} tileSource Tile source.
  54099. * @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
  54100. * @param {number} pixelRatio Pixel ratio.
  54101. * @param {ol.proj.Projection} projection Projection.
  54102. * @param {ol.Extent} extent Extent.
  54103. * @param {number} currentZ Current Z.
  54104. * @param {number} preload Load low resolution tiles up to 'preload' levels.
  54105. * @param {function(this: T, ol.Tile)=} opt_tileCallback Tile callback.
  54106. * @param {T=} opt_this Object to use as `this` in `opt_tileCallback`.
  54107. * @protected
  54108. * @template T
  54109. */
  54110. ol.renderer.Layer.prototype.manageTilePyramid = function(
  54111. frameState, tileSource, tileGrid, pixelRatio, projection, extent,
  54112. currentZ, preload, opt_tileCallback, opt_this) {
  54113. var tileSourceKey = ol.getUid(tileSource).toString();
  54114. if (!(tileSourceKey in frameState.wantedTiles)) {
  54115. frameState.wantedTiles[tileSourceKey] = {};
  54116. }
  54117. var wantedTiles = frameState.wantedTiles[tileSourceKey];
  54118. var tileQueue = frameState.tileQueue;
  54119. var minZoom = tileGrid.getMinZoom();
  54120. var tile, tileRange, tileResolution, x, y, z;
  54121. for (z = currentZ; z >= minZoom; --z) {
  54122. tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z, tileRange);
  54123. tileResolution = tileGrid.getResolution(z);
  54124. for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
  54125. for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
  54126. if (currentZ - z <= preload) {
  54127. tile = tileSource.getTile(z, x, y, pixelRatio, projection);
  54128. if (tile.getState() == ol.TileState.IDLE) {
  54129. wantedTiles[tile.getKey()] = true;
  54130. if (!tileQueue.isKeyQueued(tile.getKey())) {
  54131. tileQueue.enqueue([tile, tileSourceKey,
  54132. tileGrid.getTileCoordCenter(tile.tileCoord), tileResolution]);
  54133. }
  54134. }
  54135. if (opt_tileCallback !== undefined) {
  54136. opt_tileCallback.call(opt_this, tile);
  54137. }
  54138. } else {
  54139. tileSource.useTile(z, x, y, projection);
  54140. }
  54141. }
  54142. }
  54143. }
  54144. };
  54145. goog.provide('ol.renderer.canvas.Layer');
  54146. goog.require('ol');
  54147. goog.require('ol.extent');
  54148. goog.require('ol.functions');
  54149. goog.require('ol.render.Event');
  54150. goog.require('ol.render.EventType');
  54151. goog.require('ol.render.canvas');
  54152. goog.require('ol.render.canvas.Immediate');
  54153. goog.require('ol.renderer.Layer');
  54154. goog.require('ol.transform');
  54155. /**
  54156. * @constructor
  54157. * @abstract
  54158. * @extends {ol.renderer.Layer}
  54159. * @param {ol.layer.Layer} layer Layer.
  54160. */
  54161. ol.renderer.canvas.Layer = function(layer) {
  54162. ol.renderer.Layer.call(this, layer);
  54163. /**
  54164. * @protected
  54165. * @type {number}
  54166. */
  54167. this.renderedResolution;
  54168. /**
  54169. * @private
  54170. * @type {ol.Transform}
  54171. */
  54172. this.transform_ = ol.transform.create();
  54173. };
  54174. ol.inherits(ol.renderer.canvas.Layer, ol.renderer.Layer);
  54175. /**
  54176. * @param {CanvasRenderingContext2D} context Context.
  54177. * @param {olx.FrameState} frameState Frame state.
  54178. * @param {ol.Extent} extent Clip extent.
  54179. * @protected
  54180. */
  54181. ol.renderer.canvas.Layer.prototype.clip = function(context, frameState, extent) {
  54182. var pixelRatio = frameState.pixelRatio;
  54183. var width = frameState.size[0] * pixelRatio;
  54184. var height = frameState.size[1] * pixelRatio;
  54185. var rotation = frameState.viewState.rotation;
  54186. var topLeft = ol.extent.getTopLeft(/** @type {ol.Extent} */ (extent));
  54187. var topRight = ol.extent.getTopRight(/** @type {ol.Extent} */ (extent));
  54188. var bottomRight = ol.extent.getBottomRight(/** @type {ol.Extent} */ (extent));
  54189. var bottomLeft = ol.extent.getBottomLeft(/** @type {ol.Extent} */ (extent));
  54190. ol.transform.apply(frameState.coordinateToPixelTransform, topLeft);
  54191. ol.transform.apply(frameState.coordinateToPixelTransform, topRight);
  54192. ol.transform.apply(frameState.coordinateToPixelTransform, bottomRight);
  54193. ol.transform.apply(frameState.coordinateToPixelTransform, bottomLeft);
  54194. context.save();
  54195. ol.render.canvas.rotateAtOffset(context, -rotation, width / 2, height / 2);
  54196. context.beginPath();
  54197. context.moveTo(topLeft[0] * pixelRatio, topLeft[1] * pixelRatio);
  54198. context.lineTo(topRight[0] * pixelRatio, topRight[1] * pixelRatio);
  54199. context.lineTo(bottomRight[0] * pixelRatio, bottomRight[1] * pixelRatio);
  54200. context.lineTo(bottomLeft[0] * pixelRatio, bottomLeft[1] * pixelRatio);
  54201. context.clip();
  54202. ol.render.canvas.rotateAtOffset(context, rotation, width / 2, height / 2);
  54203. };
  54204. /**
  54205. * @param {ol.render.EventType} type Event type.
  54206. * @param {CanvasRenderingContext2D} context Context.
  54207. * @param {olx.FrameState} frameState Frame state.
  54208. * @param {ol.Transform=} opt_transform Transform.
  54209. * @private
  54210. */
  54211. ol.renderer.canvas.Layer.prototype.dispatchComposeEvent_ = function(type, context, frameState, opt_transform) {
  54212. var layer = this.getLayer();
  54213. if (layer.hasListener(type)) {
  54214. var width = frameState.size[0] * frameState.pixelRatio;
  54215. var height = frameState.size[1] * frameState.pixelRatio;
  54216. var rotation = frameState.viewState.rotation;
  54217. ol.render.canvas.rotateAtOffset(context, -rotation, width / 2, height / 2);
  54218. var transform = opt_transform !== undefined ?
  54219. opt_transform : this.getTransform(frameState, 0);
  54220. var render = new ol.render.canvas.Immediate(
  54221. context, frameState.pixelRatio, frameState.extent, transform,
  54222. frameState.viewState.rotation);
  54223. var composeEvent = new ol.render.Event(type, render, frameState,
  54224. context, null);
  54225. layer.dispatchEvent(composeEvent);
  54226. ol.render.canvas.rotateAtOffset(context, rotation, width / 2, height / 2);
  54227. }
  54228. };
  54229. /**
  54230. * @param {ol.Coordinate} coordinate Coordinate.
  54231. * @param {olx.FrameState} frameState FrameState.
  54232. * @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer
  54233. * callback.
  54234. * @param {S} thisArg Value to use as `this` when executing `callback`.
  54235. * @return {T|undefined} Callback result.
  54236. * @template S,T,U
  54237. */
  54238. ol.renderer.canvas.Layer.prototype.forEachLayerAtCoordinate = function(coordinate, frameState, callback, thisArg) {
  54239. var hasFeature = this.forEachFeatureAtCoordinate(
  54240. coordinate, frameState, 0, ol.functions.TRUE, this);
  54241. if (hasFeature) {
  54242. return callback.call(thisArg, this.getLayer(), null);
  54243. } else {
  54244. return undefined;
  54245. }
  54246. };
  54247. /**
  54248. * @param {CanvasRenderingContext2D} context Context.
  54249. * @param {olx.FrameState} frameState Frame state.
  54250. * @param {ol.LayerState} layerState Layer state.
  54251. * @param {ol.Transform=} opt_transform Transform.
  54252. * @protected
  54253. */
  54254. ol.renderer.canvas.Layer.prototype.postCompose = function(context, frameState, layerState, opt_transform) {
  54255. this.dispatchComposeEvent_(ol.render.EventType.POSTCOMPOSE, context,
  54256. frameState, opt_transform);
  54257. };
  54258. /**
  54259. * @param {CanvasRenderingContext2D} context Context.
  54260. * @param {olx.FrameState} frameState Frame state.
  54261. * @param {ol.Transform=} opt_transform Transform.
  54262. * @protected
  54263. */
  54264. ol.renderer.canvas.Layer.prototype.preCompose = function(context, frameState, opt_transform) {
  54265. this.dispatchComposeEvent_(ol.render.EventType.PRECOMPOSE, context,
  54266. frameState, opt_transform);
  54267. };
  54268. /**
  54269. * @param {CanvasRenderingContext2D} context Context.
  54270. * @param {olx.FrameState} frameState Frame state.
  54271. * @param {ol.Transform=} opt_transform Transform.
  54272. * @protected
  54273. */
  54274. ol.renderer.canvas.Layer.prototype.dispatchRenderEvent = function(context, frameState, opt_transform) {
  54275. this.dispatchComposeEvent_(ol.render.EventType.RENDER, context,
  54276. frameState, opt_transform);
  54277. };
  54278. /**
  54279. * @param {olx.FrameState} frameState Frame state.
  54280. * @param {number} offsetX Offset on the x-axis in view coordinates.
  54281. * @protected
  54282. * @return {!ol.Transform} Transform.
  54283. */
  54284. ol.renderer.canvas.Layer.prototype.getTransform = function(frameState, offsetX) {
  54285. var viewState = frameState.viewState;
  54286. var pixelRatio = frameState.pixelRatio;
  54287. var dx1 = pixelRatio * frameState.size[0] / 2;
  54288. var dy1 = pixelRatio * frameState.size[1] / 2;
  54289. var sx = pixelRatio / viewState.resolution;
  54290. var sy = -sx;
  54291. var angle = -viewState.rotation;
  54292. var dx2 = -viewState.center[0] + offsetX;
  54293. var dy2 = -viewState.center[1];
  54294. return ol.transform.compose(this.transform_, dx1, dy1, sx, sy, angle, dx2, dy2);
  54295. };
  54296. /**
  54297. * @abstract
  54298. * @param {olx.FrameState} frameState Frame state.
  54299. * @param {ol.LayerState} layerState Layer state.
  54300. * @param {CanvasRenderingContext2D} context Context.
  54301. */
  54302. ol.renderer.canvas.Layer.prototype.composeFrame = function(frameState, layerState, context) {};
  54303. /**
  54304. * @abstract
  54305. * @param {olx.FrameState} frameState Frame state.
  54306. * @param {ol.LayerState} layerState Layer state.
  54307. * @return {boolean} whether composeFrame should be called.
  54308. */
  54309. ol.renderer.canvas.Layer.prototype.prepareFrame = function(frameState, layerState) {};
  54310. goog.provide('ol.renderer.vector');
  54311. goog.require('ol');
  54312. goog.require('ol.ImageState');
  54313. goog.require('ol.geom.GeometryType');
  54314. goog.require('ol.render.ReplayType');
  54315. /**
  54316. * @param {ol.Feature|ol.render.Feature} feature1 Feature 1.
  54317. * @param {ol.Feature|ol.render.Feature} feature2 Feature 2.
  54318. * @return {number} Order.
  54319. */
  54320. ol.renderer.vector.defaultOrder = function(feature1, feature2) {
  54321. return ol.getUid(feature1) - ol.getUid(feature2);
  54322. };
  54323. /**
  54324. * @param {number} resolution Resolution.
  54325. * @param {number} pixelRatio Pixel ratio.
  54326. * @return {number} Squared pixel tolerance.
  54327. */
  54328. ol.renderer.vector.getSquaredTolerance = function(resolution, pixelRatio) {
  54329. var tolerance = ol.renderer.vector.getTolerance(resolution, pixelRatio);
  54330. return tolerance * tolerance;
  54331. };
  54332. /**
  54333. * @param {number} resolution Resolution.
  54334. * @param {number} pixelRatio Pixel ratio.
  54335. * @return {number} Pixel tolerance.
  54336. */
  54337. ol.renderer.vector.getTolerance = function(resolution, pixelRatio) {
  54338. return ol.SIMPLIFY_TOLERANCE * resolution / pixelRatio;
  54339. };
  54340. /**
  54341. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  54342. * @param {ol.geom.Circle} geometry Geometry.
  54343. * @param {ol.style.Style} style Style.
  54344. * @param {ol.Feature} feature Feature.
  54345. * @private
  54346. */
  54347. ol.renderer.vector.renderCircleGeometry_ = function(replayGroup, geometry, style, feature) {
  54348. var fillStyle = style.getFill();
  54349. var strokeStyle = style.getStroke();
  54350. if (fillStyle || strokeStyle) {
  54351. var circleReplay = replayGroup.getReplay(
  54352. style.getZIndex(), ol.render.ReplayType.CIRCLE);
  54353. circleReplay.setFillStrokeStyle(fillStyle, strokeStyle);
  54354. circleReplay.drawCircle(geometry, feature);
  54355. }
  54356. var textStyle = style.getText();
  54357. if (textStyle) {
  54358. var textReplay = replayGroup.getReplay(
  54359. style.getZIndex(), ol.render.ReplayType.TEXT);
  54360. textReplay.setTextStyle(textStyle);
  54361. textReplay.drawText(geometry.getCenter(), 0, 2, 2, geometry, feature);
  54362. }
  54363. };
  54364. /**
  54365. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  54366. * @param {ol.Feature|ol.render.Feature} feature Feature.
  54367. * @param {ol.style.Style} style Style.
  54368. * @param {number} squaredTolerance Squared tolerance.
  54369. * @param {function(this: T, ol.events.Event)} listener Listener function.
  54370. * @param {T} thisArg Value to use as `this` when executing `listener`.
  54371. * @return {boolean} `true` if style is loading.
  54372. * @template T
  54373. */
  54374. ol.renderer.vector.renderFeature = function(
  54375. replayGroup, feature, style, squaredTolerance, listener, thisArg) {
  54376. var loading = false;
  54377. var imageStyle, imageState;
  54378. imageStyle = style.getImage();
  54379. if (imageStyle) {
  54380. imageState = imageStyle.getImageState();
  54381. if (imageState == ol.ImageState.LOADED ||
  54382. imageState == ol.ImageState.ERROR) {
  54383. imageStyle.unlistenImageChange(listener, thisArg);
  54384. } else {
  54385. if (imageState == ol.ImageState.IDLE) {
  54386. imageStyle.load();
  54387. }
  54388. imageState = imageStyle.getImageState();
  54389. imageStyle.listenImageChange(listener, thisArg);
  54390. loading = true;
  54391. }
  54392. }
  54393. ol.renderer.vector.renderFeature_(replayGroup, feature, style,
  54394. squaredTolerance);
  54395. return loading;
  54396. };
  54397. /**
  54398. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  54399. * @param {ol.Feature|ol.render.Feature} feature Feature.
  54400. * @param {ol.style.Style} style Style.
  54401. * @param {number} squaredTolerance Squared tolerance.
  54402. * @private
  54403. */
  54404. ol.renderer.vector.renderFeature_ = function(
  54405. replayGroup, feature, style, squaredTolerance) {
  54406. var geometry = style.getGeometryFunction()(feature);
  54407. if (!geometry) {
  54408. return;
  54409. }
  54410. var simplifiedGeometry = geometry.getSimplifiedGeometry(squaredTolerance);
  54411. var renderer = style.getRenderer();
  54412. if (renderer) {
  54413. ol.renderer.vector.renderGeometry_(replayGroup, simplifiedGeometry, style, feature);
  54414. } else {
  54415. var geometryRenderer =
  54416. ol.renderer.vector.GEOMETRY_RENDERERS_[simplifiedGeometry.getType()];
  54417. geometryRenderer(replayGroup, simplifiedGeometry, style, feature);
  54418. }
  54419. };
  54420. /**
  54421. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  54422. * @param {ol.geom.Geometry} geometry Geometry.
  54423. * @param {ol.style.Style} style Style.
  54424. * @param {ol.Feature|ol.render.Feature} feature Feature.
  54425. * @private
  54426. */
  54427. ol.renderer.vector.renderGeometry_ = function(replayGroup, geometry, style, feature) {
  54428. if (geometry.getType() == ol.geom.GeometryType.GEOMETRY_COLLECTION) {
  54429. var geometries = /** @type {ol.geom.GeometryCollection} */ (geometry).getGeometries();
  54430. for (var i = 0, ii = geometries.length; i < ii; ++i) {
  54431. ol.renderer.vector.renderGeometry_(replayGroup, geometries[i], style, feature);
  54432. }
  54433. return;
  54434. }
  54435. var replay = replayGroup.getReplay(style.getZIndex(), ol.render.ReplayType.DEFAULT);
  54436. replay.drawCustom(/** @type {ol.geom.SimpleGeometry} */ (geometry), feature, style.getRenderer());
  54437. };
  54438. /**
  54439. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  54440. * @param {ol.geom.GeometryCollection} geometry Geometry.
  54441. * @param {ol.style.Style} style Style.
  54442. * @param {ol.Feature} feature Feature.
  54443. * @private
  54444. */
  54445. ol.renderer.vector.renderGeometryCollectionGeometry_ = function(replayGroup, geometry, style, feature) {
  54446. var geometries = geometry.getGeometriesArray();
  54447. var i, ii;
  54448. for (i = 0, ii = geometries.length; i < ii; ++i) {
  54449. var geometryRenderer =
  54450. ol.renderer.vector.GEOMETRY_RENDERERS_[geometries[i].getType()];
  54451. geometryRenderer(replayGroup, geometries[i], style, feature);
  54452. }
  54453. };
  54454. /**
  54455. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  54456. * @param {ol.geom.LineString|ol.render.Feature} geometry Geometry.
  54457. * @param {ol.style.Style} style Style.
  54458. * @param {ol.Feature|ol.render.Feature} feature Feature.
  54459. * @private
  54460. */
  54461. ol.renderer.vector.renderLineStringGeometry_ = function(replayGroup, geometry, style, feature) {
  54462. var strokeStyle = style.getStroke();
  54463. if (strokeStyle) {
  54464. var lineStringReplay = replayGroup.getReplay(
  54465. style.getZIndex(), ol.render.ReplayType.LINE_STRING);
  54466. lineStringReplay.setFillStrokeStyle(null, strokeStyle);
  54467. lineStringReplay.drawLineString(geometry, feature);
  54468. }
  54469. var textStyle = style.getText();
  54470. if (textStyle) {
  54471. var textReplay = replayGroup.getReplay(
  54472. style.getZIndex(), ol.render.ReplayType.TEXT);
  54473. textReplay.setTextStyle(textStyle);
  54474. textReplay.drawText(geometry.getFlatMidpoint(), 0, 2, 2, geometry, feature);
  54475. }
  54476. };
  54477. /**
  54478. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  54479. * @param {ol.geom.MultiLineString|ol.render.Feature} geometry Geometry.
  54480. * @param {ol.style.Style} style Style.
  54481. * @param {ol.Feature|ol.render.Feature} feature Feature.
  54482. * @private
  54483. */
  54484. ol.renderer.vector.renderMultiLineStringGeometry_ = function(replayGroup, geometry, style, feature) {
  54485. var strokeStyle = style.getStroke();
  54486. if (strokeStyle) {
  54487. var lineStringReplay = replayGroup.getReplay(
  54488. style.getZIndex(), ol.render.ReplayType.LINE_STRING);
  54489. lineStringReplay.setFillStrokeStyle(null, strokeStyle);
  54490. lineStringReplay.drawMultiLineString(geometry, feature);
  54491. }
  54492. var textStyle = style.getText();
  54493. if (textStyle) {
  54494. var textReplay = replayGroup.getReplay(
  54495. style.getZIndex(), ol.render.ReplayType.TEXT);
  54496. textReplay.setTextStyle(textStyle);
  54497. var flatMidpointCoordinates = geometry.getFlatMidpoints();
  54498. textReplay.drawText(flatMidpointCoordinates, 0,
  54499. flatMidpointCoordinates.length, 2, geometry, feature);
  54500. }
  54501. };
  54502. /**
  54503. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  54504. * @param {ol.geom.MultiPolygon} geometry Geometry.
  54505. * @param {ol.style.Style} style Style.
  54506. * @param {ol.Feature} feature Feature.
  54507. * @private
  54508. */
  54509. ol.renderer.vector.renderMultiPolygonGeometry_ = function(replayGroup, geometry, style, feature) {
  54510. var fillStyle = style.getFill();
  54511. var strokeStyle = style.getStroke();
  54512. if (strokeStyle || fillStyle) {
  54513. var polygonReplay = replayGroup.getReplay(
  54514. style.getZIndex(), ol.render.ReplayType.POLYGON);
  54515. polygonReplay.setFillStrokeStyle(fillStyle, strokeStyle);
  54516. polygonReplay.drawMultiPolygon(geometry, feature);
  54517. }
  54518. var textStyle = style.getText();
  54519. if (textStyle) {
  54520. var textReplay = replayGroup.getReplay(
  54521. style.getZIndex(), ol.render.ReplayType.TEXT);
  54522. textReplay.setTextStyle(textStyle);
  54523. var flatInteriorPointCoordinates = geometry.getFlatInteriorPoints();
  54524. textReplay.drawText(flatInteriorPointCoordinates, 0,
  54525. flatInteriorPointCoordinates.length, 2, geometry, feature);
  54526. }
  54527. };
  54528. /**
  54529. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  54530. * @param {ol.geom.Point|ol.render.Feature} geometry Geometry.
  54531. * @param {ol.style.Style} style Style.
  54532. * @param {ol.Feature|ol.render.Feature} feature Feature.
  54533. * @private
  54534. */
  54535. ol.renderer.vector.renderPointGeometry_ = function(replayGroup, geometry, style, feature) {
  54536. var imageStyle = style.getImage();
  54537. if (imageStyle) {
  54538. if (imageStyle.getImageState() != ol.ImageState.LOADED) {
  54539. return;
  54540. }
  54541. var imageReplay = replayGroup.getReplay(
  54542. style.getZIndex(), ol.render.ReplayType.IMAGE);
  54543. imageReplay.setImageStyle(imageStyle);
  54544. imageReplay.drawPoint(geometry, feature);
  54545. }
  54546. var textStyle = style.getText();
  54547. if (textStyle) {
  54548. var textReplay = replayGroup.getReplay(
  54549. style.getZIndex(), ol.render.ReplayType.TEXT);
  54550. textReplay.setTextStyle(textStyle);
  54551. textReplay.drawText(geometry.getFlatCoordinates(), 0, 2, 2, geometry,
  54552. feature);
  54553. }
  54554. };
  54555. /**
  54556. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  54557. * @param {ol.geom.MultiPoint|ol.render.Feature} geometry Geometry.
  54558. * @param {ol.style.Style} style Style.
  54559. * @param {ol.Feature|ol.render.Feature} feature Feature.
  54560. * @private
  54561. */
  54562. ol.renderer.vector.renderMultiPointGeometry_ = function(replayGroup, geometry, style, feature) {
  54563. var imageStyle = style.getImage();
  54564. if (imageStyle) {
  54565. if (imageStyle.getImageState() != ol.ImageState.LOADED) {
  54566. return;
  54567. }
  54568. var imageReplay = replayGroup.getReplay(
  54569. style.getZIndex(), ol.render.ReplayType.IMAGE);
  54570. imageReplay.setImageStyle(imageStyle);
  54571. imageReplay.drawMultiPoint(geometry, feature);
  54572. }
  54573. var textStyle = style.getText();
  54574. if (textStyle) {
  54575. var textReplay = replayGroup.getReplay(
  54576. style.getZIndex(), ol.render.ReplayType.TEXT);
  54577. textReplay.setTextStyle(textStyle);
  54578. var flatCoordinates = geometry.getFlatCoordinates();
  54579. textReplay.drawText(flatCoordinates, 0, flatCoordinates.length,
  54580. geometry.getStride(), geometry, feature);
  54581. }
  54582. };
  54583. /**
  54584. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  54585. * @param {ol.geom.Polygon|ol.render.Feature} geometry Geometry.
  54586. * @param {ol.style.Style} style Style.
  54587. * @param {ol.Feature|ol.render.Feature} feature Feature.
  54588. * @private
  54589. */
  54590. ol.renderer.vector.renderPolygonGeometry_ = function(replayGroup, geometry, style, feature) {
  54591. var fillStyle = style.getFill();
  54592. var strokeStyle = style.getStroke();
  54593. if (fillStyle || strokeStyle) {
  54594. var polygonReplay = replayGroup.getReplay(
  54595. style.getZIndex(), ol.render.ReplayType.POLYGON);
  54596. polygonReplay.setFillStrokeStyle(fillStyle, strokeStyle);
  54597. polygonReplay.drawPolygon(geometry, feature);
  54598. }
  54599. var textStyle = style.getText();
  54600. if (textStyle) {
  54601. var textReplay = replayGroup.getReplay(
  54602. style.getZIndex(), ol.render.ReplayType.TEXT);
  54603. textReplay.setTextStyle(textStyle);
  54604. textReplay.drawText(
  54605. geometry.getFlatInteriorPoint(), 0, 2, 2, geometry, feature);
  54606. }
  54607. };
  54608. /**
  54609. * @const
  54610. * @private
  54611. * @type {Object.<ol.geom.GeometryType,
  54612. * function(ol.render.ReplayGroup, ol.geom.Geometry,
  54613. * ol.style.Style, Object)>}
  54614. */
  54615. ol.renderer.vector.GEOMETRY_RENDERERS_ = {
  54616. 'Point': ol.renderer.vector.renderPointGeometry_,
  54617. 'LineString': ol.renderer.vector.renderLineStringGeometry_,
  54618. 'Polygon': ol.renderer.vector.renderPolygonGeometry_,
  54619. 'MultiPoint': ol.renderer.vector.renderMultiPointGeometry_,
  54620. 'MultiLineString': ol.renderer.vector.renderMultiLineStringGeometry_,
  54621. 'MultiPolygon': ol.renderer.vector.renderMultiPolygonGeometry_,
  54622. 'GeometryCollection': ol.renderer.vector.renderGeometryCollectionGeometry_,
  54623. 'Circle': ol.renderer.vector.renderCircleGeometry_
  54624. };
  54625. goog.provide('ol.renderer.canvas.VectorLayer');
  54626. goog.require('ol');
  54627. goog.require('ol.ViewHint');
  54628. goog.require('ol.dom');
  54629. goog.require('ol.extent');
  54630. goog.require('ol.render.EventType');
  54631. goog.require('ol.render.canvas');
  54632. goog.require('ol.render.canvas.ReplayGroup');
  54633. goog.require('ol.renderer.canvas.Layer');
  54634. goog.require('ol.renderer.vector');
  54635. /**
  54636. * @constructor
  54637. * @extends {ol.renderer.canvas.Layer}
  54638. * @param {ol.layer.Vector} vectorLayer Vector layer.
  54639. */
  54640. ol.renderer.canvas.VectorLayer = function(vectorLayer) {
  54641. ol.renderer.canvas.Layer.call(this, vectorLayer);
  54642. /**
  54643. * @private
  54644. * @type {boolean}
  54645. */
  54646. this.dirty_ = false;
  54647. /**
  54648. * @private
  54649. * @type {number}
  54650. */
  54651. this.renderedRevision_ = -1;
  54652. /**
  54653. * @private
  54654. * @type {number}
  54655. */
  54656. this.renderedResolution_ = NaN;
  54657. /**
  54658. * @private
  54659. * @type {ol.Extent}
  54660. */
  54661. this.renderedExtent_ = ol.extent.createEmpty();
  54662. /**
  54663. * @private
  54664. * @type {function(ol.Feature, ol.Feature): number|null}
  54665. */
  54666. this.renderedRenderOrder_ = null;
  54667. /**
  54668. * @private
  54669. * @type {ol.render.canvas.ReplayGroup}
  54670. */
  54671. this.replayGroup_ = null;
  54672. /**
  54673. * @private
  54674. * @type {CanvasRenderingContext2D}
  54675. */
  54676. this.context_ = ol.dom.createCanvasContext2D();
  54677. };
  54678. ol.inherits(ol.renderer.canvas.VectorLayer, ol.renderer.canvas.Layer);
  54679. /**
  54680. * @inheritDoc
  54681. */
  54682. ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, layerState, context) {
  54683. var extent = frameState.extent;
  54684. var pixelRatio = frameState.pixelRatio;
  54685. var skippedFeatureUids = layerState.managed ?
  54686. frameState.skippedFeatureUids : {};
  54687. var viewState = frameState.viewState;
  54688. var projection = viewState.projection;
  54689. var rotation = viewState.rotation;
  54690. var projectionExtent = projection.getExtent();
  54691. var vectorSource = /** @type {ol.source.Vector} */ (this.getLayer().getSource());
  54692. var transform = this.getTransform(frameState, 0);
  54693. this.preCompose(context, frameState, transform);
  54694. // clipped rendering if layer extent is set
  54695. var clipExtent = layerState.extent;
  54696. var clipped = clipExtent !== undefined;
  54697. if (clipped) {
  54698. this.clip(context, frameState, /** @type {ol.Extent} */ (clipExtent));
  54699. }
  54700. var replayGroup = this.replayGroup_;
  54701. if (replayGroup && !replayGroup.isEmpty()) {
  54702. var layer = this.getLayer();
  54703. var drawOffsetX = 0;
  54704. var drawOffsetY = 0;
  54705. var replayContext;
  54706. var transparentLayer = layerState.opacity !== 1;
  54707. var hasRenderListeners = layer.hasListener(ol.render.EventType.RENDER);
  54708. if (transparentLayer || hasRenderListeners) {
  54709. var drawWidth = context.canvas.width;
  54710. var drawHeight = context.canvas.height;
  54711. if (rotation) {
  54712. var drawSize = Math.round(Math.sqrt(drawWidth * drawWidth + drawHeight * drawHeight));
  54713. drawOffsetX = (drawSize - drawWidth) / 2;
  54714. drawOffsetY = (drawSize - drawHeight) / 2;
  54715. drawWidth = drawHeight = drawSize;
  54716. }
  54717. // resize and clear
  54718. this.context_.canvas.width = drawWidth;
  54719. this.context_.canvas.height = drawHeight;
  54720. replayContext = this.context_;
  54721. } else {
  54722. replayContext = context;
  54723. }
  54724. var alpha = replayContext.globalAlpha;
  54725. if (!transparentLayer) {
  54726. // for performance reasons, context.save / context.restore is not used
  54727. // to save and restore the transformation matrix and the opacity.
  54728. // see http://jsperf.com/context-save-restore-versus-variable
  54729. replayContext.globalAlpha = layerState.opacity;
  54730. }
  54731. if (replayContext != context) {
  54732. replayContext.translate(drawOffsetX, drawOffsetY);
  54733. }
  54734. var width = frameState.size[0] * pixelRatio;
  54735. var height = frameState.size[1] * pixelRatio;
  54736. ol.render.canvas.rotateAtOffset(replayContext, -rotation,
  54737. width / 2, height / 2);
  54738. replayGroup.replay(replayContext, pixelRatio, transform, rotation,
  54739. skippedFeatureUids);
  54740. if (vectorSource.getWrapX() && projection.canWrapX() &&
  54741. !ol.extent.containsExtent(projectionExtent, extent)) {
  54742. var startX = extent[0];
  54743. var worldWidth = ol.extent.getWidth(projectionExtent);
  54744. var world = 0;
  54745. var offsetX;
  54746. while (startX < projectionExtent[0]) {
  54747. --world;
  54748. offsetX = worldWidth * world;
  54749. transform = this.getTransform(frameState, offsetX);
  54750. replayGroup.replay(replayContext, pixelRatio, transform, rotation,
  54751. skippedFeatureUids);
  54752. startX += worldWidth;
  54753. }
  54754. world = 0;
  54755. startX = extent[2];
  54756. while (startX > projectionExtent[2]) {
  54757. ++world;
  54758. offsetX = worldWidth * world;
  54759. transform = this.getTransform(frameState, offsetX);
  54760. replayGroup.replay(replayContext, pixelRatio, transform, rotation,
  54761. skippedFeatureUids);
  54762. startX -= worldWidth;
  54763. }
  54764. // restore original transform for render and compose events
  54765. transform = this.getTransform(frameState, 0);
  54766. }
  54767. ol.render.canvas.rotateAtOffset(replayContext, rotation,
  54768. width / 2, height / 2);
  54769. if (replayContext != context) {
  54770. if (hasRenderListeners) {
  54771. this.dispatchRenderEvent(replayContext, frameState, transform);
  54772. }
  54773. if (transparentLayer) {
  54774. var mainContextAlpha = context.globalAlpha;
  54775. context.globalAlpha = layerState.opacity;
  54776. context.drawImage(replayContext.canvas, -drawOffsetX, -drawOffsetY);
  54777. context.globalAlpha = mainContextAlpha;
  54778. } else {
  54779. context.drawImage(replayContext.canvas, -drawOffsetX, -drawOffsetY);
  54780. }
  54781. replayContext.translate(-drawOffsetX, -drawOffsetY);
  54782. }
  54783. if (!transparentLayer) {
  54784. replayContext.globalAlpha = alpha;
  54785. }
  54786. }
  54787. if (clipped) {
  54788. context.restore();
  54789. }
  54790. this.postCompose(context, frameState, layerState, transform);
  54791. };
  54792. /**
  54793. * @inheritDoc
  54794. */
  54795. ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
  54796. if (!this.replayGroup_) {
  54797. return undefined;
  54798. } else {
  54799. var resolution = frameState.viewState.resolution;
  54800. var rotation = frameState.viewState.rotation;
  54801. var layer = this.getLayer();
  54802. /** @type {Object.<string, boolean>} */
  54803. var features = {};
  54804. return this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution,
  54805. rotation, hitTolerance, {},
  54806. /**
  54807. * @param {ol.Feature|ol.render.Feature} feature Feature.
  54808. * @return {?} Callback result.
  54809. */
  54810. function(feature) {
  54811. var key = ol.getUid(feature).toString();
  54812. if (!(key in features)) {
  54813. features[key] = true;
  54814. return callback.call(thisArg, feature, layer);
  54815. }
  54816. });
  54817. }
  54818. };
  54819. /**
  54820. * Handle changes in image style state.
  54821. * @param {ol.events.Event} event Image style change event.
  54822. * @private
  54823. */
  54824. ol.renderer.canvas.VectorLayer.prototype.handleStyleImageChange_ = function(event) {
  54825. this.renderIfReadyAndVisible();
  54826. };
  54827. /**
  54828. * @inheritDoc
  54829. */
  54830. ol.renderer.canvas.VectorLayer.prototype.prepareFrame = function(frameState, layerState) {
  54831. var vectorLayer = /** @type {ol.layer.Vector} */ (this.getLayer());
  54832. var vectorSource = vectorLayer.getSource();
  54833. this.updateAttributions(
  54834. frameState.attributions, vectorSource.getAttributions());
  54835. this.updateLogos(frameState, vectorSource);
  54836. var animating = frameState.viewHints[ol.ViewHint.ANIMATING];
  54837. var interacting = frameState.viewHints[ol.ViewHint.INTERACTING];
  54838. var updateWhileAnimating = vectorLayer.getUpdateWhileAnimating();
  54839. var updateWhileInteracting = vectorLayer.getUpdateWhileInteracting();
  54840. if (!this.dirty_ && (!updateWhileAnimating && animating) ||
  54841. (!updateWhileInteracting && interacting)) {
  54842. return true;
  54843. }
  54844. var frameStateExtent = frameState.extent;
  54845. var viewState = frameState.viewState;
  54846. var projection = viewState.projection;
  54847. var resolution = viewState.resolution;
  54848. var pixelRatio = frameState.pixelRatio;
  54849. var vectorLayerRevision = vectorLayer.getRevision();
  54850. var vectorLayerRenderBuffer = vectorLayer.getRenderBuffer();
  54851. var vectorLayerRenderOrder = vectorLayer.getRenderOrder();
  54852. if (vectorLayerRenderOrder === undefined) {
  54853. vectorLayerRenderOrder = ol.renderer.vector.defaultOrder;
  54854. }
  54855. var extent = ol.extent.buffer(frameStateExtent,
  54856. vectorLayerRenderBuffer * resolution);
  54857. var projectionExtent = viewState.projection.getExtent();
  54858. if (vectorSource.getWrapX() && viewState.projection.canWrapX() &&
  54859. !ol.extent.containsExtent(projectionExtent, frameState.extent)) {
  54860. // For the replay group, we need an extent that intersects the real world
  54861. // (-180° to +180°). To support geometries in a coordinate range from -540°
  54862. // to +540°, we add at least 1 world width on each side of the projection
  54863. // extent. If the viewport is wider than the world, we need to add half of
  54864. // the viewport width to make sure we cover the whole viewport.
  54865. var worldWidth = ol.extent.getWidth(projectionExtent);
  54866. var buffer = Math.max(ol.extent.getWidth(extent) / 2, worldWidth);
  54867. extent[0] = projectionExtent[0] - buffer;
  54868. extent[2] = projectionExtent[2] + buffer;
  54869. }
  54870. if (!this.dirty_ &&
  54871. this.renderedResolution_ == resolution &&
  54872. this.renderedRevision_ == vectorLayerRevision &&
  54873. this.renderedRenderOrder_ == vectorLayerRenderOrder &&
  54874. ol.extent.containsExtent(this.renderedExtent_, extent)) {
  54875. return true;
  54876. }
  54877. this.replayGroup_ = null;
  54878. this.dirty_ = false;
  54879. var replayGroup = new ol.render.canvas.ReplayGroup(
  54880. ol.renderer.vector.getTolerance(resolution, pixelRatio), extent,
  54881. resolution, vectorSource.getOverlaps(), vectorLayer.getRenderBuffer());
  54882. vectorSource.loadFeatures(extent, resolution, projection);
  54883. /**
  54884. * @param {ol.Feature} feature Feature.
  54885. * @this {ol.renderer.canvas.VectorLayer}
  54886. */
  54887. var renderFeature = function(feature) {
  54888. var styles;
  54889. var styleFunction = feature.getStyleFunction();
  54890. if (styleFunction) {
  54891. styles = styleFunction.call(feature, resolution);
  54892. } else {
  54893. styleFunction = vectorLayer.getStyleFunction();
  54894. if (styleFunction) {
  54895. styles = styleFunction(feature, resolution);
  54896. }
  54897. }
  54898. if (styles) {
  54899. var dirty = this.renderFeature(
  54900. feature, resolution, pixelRatio, styles, replayGroup);
  54901. this.dirty_ = this.dirty_ || dirty;
  54902. }
  54903. }.bind(this);
  54904. if (vectorLayerRenderOrder) {
  54905. /** @type {Array.<ol.Feature>} */
  54906. var features = [];
  54907. vectorSource.forEachFeatureInExtent(extent,
  54908. /**
  54909. * @param {ol.Feature} feature Feature.
  54910. */
  54911. function(feature) {
  54912. features.push(feature);
  54913. }, this);
  54914. features.sort(vectorLayerRenderOrder);
  54915. for (var i = 0, ii = features.length; i < ii; ++i) {
  54916. renderFeature(features[i]);
  54917. }
  54918. } else {
  54919. vectorSource.forEachFeatureInExtent(extent, renderFeature, this);
  54920. }
  54921. replayGroup.finish();
  54922. this.renderedResolution_ = resolution;
  54923. this.renderedRevision_ = vectorLayerRevision;
  54924. this.renderedRenderOrder_ = vectorLayerRenderOrder;
  54925. this.renderedExtent_ = extent;
  54926. this.replayGroup_ = replayGroup;
  54927. return true;
  54928. };
  54929. /**
  54930. * @param {ol.Feature} feature Feature.
  54931. * @param {number} resolution Resolution.
  54932. * @param {number} pixelRatio Pixel ratio.
  54933. * @param {(ol.style.Style|Array.<ol.style.Style>)} styles The style or array of
  54934. * styles.
  54935. * @param {ol.render.canvas.ReplayGroup} replayGroup Replay group.
  54936. * @return {boolean} `true` if an image is loading.
  54937. */
  54938. ol.renderer.canvas.VectorLayer.prototype.renderFeature = function(feature, resolution, pixelRatio, styles, replayGroup) {
  54939. if (!styles) {
  54940. return false;
  54941. }
  54942. var loading = false;
  54943. if (Array.isArray(styles)) {
  54944. for (var i = 0, ii = styles.length; i < ii; ++i) {
  54945. loading = ol.renderer.vector.renderFeature(
  54946. replayGroup, feature, styles[i],
  54947. ol.renderer.vector.getSquaredTolerance(resolution, pixelRatio),
  54948. this.handleStyleImageChange_, this) || loading;
  54949. }
  54950. } else {
  54951. loading = ol.renderer.vector.renderFeature(
  54952. replayGroup, feature, styles,
  54953. ol.renderer.vector.getSquaredTolerance(resolution, pixelRatio),
  54954. this.handleStyleImageChange_, this) || loading;
  54955. }
  54956. return loading;
  54957. };
  54958. // This file is automatically generated, do not edit
  54959. /* eslint openlayers-internal/no-missing-requires: 0 */
  54960. goog.provide('ol.renderer.webgl.defaultmapshader');
  54961. goog.require('ol');
  54962. goog.require('ol.webgl.Fragment');
  54963. goog.require('ol.webgl.Vertex');
  54964. if (ol.ENABLE_WEBGL) {
  54965. /**
  54966. * @constructor
  54967. * @extends {ol.webgl.Fragment}
  54968. * @struct
  54969. */
  54970. ol.renderer.webgl.defaultmapshader.Fragment = function() {
  54971. ol.webgl.Fragment.call(this, ol.renderer.webgl.defaultmapshader.Fragment.SOURCE);
  54972. };
  54973. ol.inherits(ol.renderer.webgl.defaultmapshader.Fragment, ol.webgl.Fragment);
  54974. /**
  54975. * @const
  54976. * @type {string}
  54977. */
  54978. ol.renderer.webgl.defaultmapshader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\n\n\nuniform float u_opacity;\nuniform sampler2D u_texture;\n\nvoid main(void) {\n vec4 texColor = texture2D(u_texture, v_texCoord);\n gl_FragColor.rgb = texColor.rgb;\n gl_FragColor.a = texColor.a * u_opacity;\n}\n';
  54979. /**
  54980. * @const
  54981. * @type {string}
  54982. */
  54983. ol.renderer.webgl.defaultmapshader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;uniform float f;uniform sampler2D g;void main(void){vec4 texColor=texture2D(g,a);gl_FragColor.rgb=texColor.rgb;gl_FragColor.a=texColor.a*f;}';
  54984. /**
  54985. * @const
  54986. * @type {string}
  54987. */
  54988. ol.renderer.webgl.defaultmapshader.Fragment.SOURCE = ol.DEBUG_WEBGL ?
  54989. ol.renderer.webgl.defaultmapshader.Fragment.DEBUG_SOURCE :
  54990. ol.renderer.webgl.defaultmapshader.Fragment.OPTIMIZED_SOURCE;
  54991. ol.renderer.webgl.defaultmapshader.fragment = new ol.renderer.webgl.defaultmapshader.Fragment();
  54992. /**
  54993. * @constructor
  54994. * @extends {ol.webgl.Vertex}
  54995. * @struct
  54996. */
  54997. ol.renderer.webgl.defaultmapshader.Vertex = function() {
  54998. ol.webgl.Vertex.call(this, ol.renderer.webgl.defaultmapshader.Vertex.SOURCE);
  54999. };
  55000. ol.inherits(ol.renderer.webgl.defaultmapshader.Vertex, ol.webgl.Vertex);
  55001. /**
  55002. * @const
  55003. * @type {string}
  55004. */
  55005. ol.renderer.webgl.defaultmapshader.Vertex.DEBUG_SOURCE = 'varying vec2 v_texCoord;\n\n\nattribute vec2 a_position;\nattribute vec2 a_texCoord;\n\nuniform mat4 u_texCoordMatrix;\nuniform mat4 u_projectionMatrix;\n\nvoid main(void) {\n gl_Position = u_projectionMatrix * vec4(a_position, 0., 1.);\n v_texCoord = (u_texCoordMatrix * vec4(a_texCoord, 0., 1.)).st;\n}\n\n\n';
  55006. /**
  55007. * @const
  55008. * @type {string}
  55009. */
  55010. ol.renderer.webgl.defaultmapshader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;attribute vec2 b;attribute vec2 c;uniform mat4 d;uniform mat4 e;void main(void){gl_Position=e*vec4(b,0.,1.);a=(d*vec4(c,0.,1.)).st;}';
  55011. /**
  55012. * @const
  55013. * @type {string}
  55014. */
  55015. ol.renderer.webgl.defaultmapshader.Vertex.SOURCE = ol.DEBUG_WEBGL ?
  55016. ol.renderer.webgl.defaultmapshader.Vertex.DEBUG_SOURCE :
  55017. ol.renderer.webgl.defaultmapshader.Vertex.OPTIMIZED_SOURCE;
  55018. ol.renderer.webgl.defaultmapshader.vertex = new ol.renderer.webgl.defaultmapshader.Vertex();
  55019. /**
  55020. * @constructor
  55021. * @param {WebGLRenderingContext} gl GL.
  55022. * @param {WebGLProgram} program Program.
  55023. * @struct
  55024. */
  55025. ol.renderer.webgl.defaultmapshader.Locations = function(gl, program) {
  55026. /**
  55027. * @type {WebGLUniformLocation}
  55028. */
  55029. this.u_opacity = gl.getUniformLocation(
  55030. program, ol.DEBUG_WEBGL ? 'u_opacity' : 'f');
  55031. /**
  55032. * @type {WebGLUniformLocation}
  55033. */
  55034. this.u_projectionMatrix = gl.getUniformLocation(
  55035. program, ol.DEBUG_WEBGL ? 'u_projectionMatrix' : 'e');
  55036. /**
  55037. * @type {WebGLUniformLocation}
  55038. */
  55039. this.u_texCoordMatrix = gl.getUniformLocation(
  55040. program, ol.DEBUG_WEBGL ? 'u_texCoordMatrix' : 'd');
  55041. /**
  55042. * @type {WebGLUniformLocation}
  55043. */
  55044. this.u_texture = gl.getUniformLocation(
  55045. program, ol.DEBUG_WEBGL ? 'u_texture' : 'g');
  55046. /**
  55047. * @type {number}
  55048. */
  55049. this.a_position = gl.getAttribLocation(
  55050. program, ol.DEBUG_WEBGL ? 'a_position' : 'b');
  55051. /**
  55052. * @type {number}
  55053. */
  55054. this.a_texCoord = gl.getAttribLocation(
  55055. program, ol.DEBUG_WEBGL ? 'a_texCoord' : 'c');
  55056. };
  55057. }
  55058. goog.provide('ol.renderer.webgl.Layer');
  55059. goog.require('ol');
  55060. goog.require('ol.render.Event');
  55061. goog.require('ol.render.EventType');
  55062. goog.require('ol.render.webgl.Immediate');
  55063. goog.require('ol.renderer.Layer');
  55064. goog.require('ol.renderer.webgl.defaultmapshader');
  55065. goog.require('ol.transform');
  55066. goog.require('ol.vec.Mat4');
  55067. goog.require('ol.webgl');
  55068. goog.require('ol.webgl.Buffer');
  55069. goog.require('ol.webgl.Context');
  55070. if (ol.ENABLE_WEBGL) {
  55071. /**
  55072. * @constructor
  55073. * @abstract
  55074. * @extends {ol.renderer.Layer}
  55075. * @param {ol.renderer.webgl.Map} mapRenderer Map renderer.
  55076. * @param {ol.layer.Layer} layer Layer.
  55077. */
  55078. ol.renderer.webgl.Layer = function(mapRenderer, layer) {
  55079. ol.renderer.Layer.call(this, layer);
  55080. /**
  55081. * @protected
  55082. * @type {ol.renderer.webgl.Map}
  55083. */
  55084. this.mapRenderer = mapRenderer;
  55085. /**
  55086. * @private
  55087. * @type {ol.webgl.Buffer}
  55088. */
  55089. this.arrayBuffer_ = new ol.webgl.Buffer([
  55090. -1, -1, 0, 0,
  55091. 1, -1, 1, 0,
  55092. -1, 1, 0, 1,
  55093. 1, 1, 1, 1
  55094. ]);
  55095. /**
  55096. * @protected
  55097. * @type {WebGLTexture}
  55098. */
  55099. this.texture = null;
  55100. /**
  55101. * @protected
  55102. * @type {WebGLFramebuffer}
  55103. */
  55104. this.framebuffer = null;
  55105. /**
  55106. * @protected
  55107. * @type {number|undefined}
  55108. */
  55109. this.framebufferDimension = undefined;
  55110. /**
  55111. * @protected
  55112. * @type {ol.Transform}
  55113. */
  55114. this.texCoordMatrix = ol.transform.create();
  55115. /**
  55116. * @protected
  55117. * @type {ol.Transform}
  55118. */
  55119. this.projectionMatrix = ol.transform.create();
  55120. /**
  55121. * @type {Array.<number>}
  55122. * @private
  55123. */
  55124. this.tmpMat4_ = ol.vec.Mat4.create();
  55125. /**
  55126. * @private
  55127. * @type {ol.renderer.webgl.defaultmapshader.Locations}
  55128. */
  55129. this.defaultLocations_ = null;
  55130. };
  55131. ol.inherits(ol.renderer.webgl.Layer, ol.renderer.Layer);
  55132. /**
  55133. * @param {olx.FrameState} frameState Frame state.
  55134. * @param {number} framebufferDimension Framebuffer dimension.
  55135. * @protected
  55136. */
  55137. ol.renderer.webgl.Layer.prototype.bindFramebuffer = function(frameState, framebufferDimension) {
  55138. var gl = this.mapRenderer.getGL();
  55139. if (this.framebufferDimension === undefined ||
  55140. this.framebufferDimension != framebufferDimension) {
  55141. /**
  55142. * @param {WebGLRenderingContext} gl GL.
  55143. * @param {WebGLFramebuffer} framebuffer Framebuffer.
  55144. * @param {WebGLTexture} texture Texture.
  55145. */
  55146. var postRenderFunction = function(gl, framebuffer, texture) {
  55147. if (!gl.isContextLost()) {
  55148. gl.deleteFramebuffer(framebuffer);
  55149. gl.deleteTexture(texture);
  55150. }
  55151. }.bind(null, gl, this.framebuffer, this.texture);
  55152. frameState.postRenderFunctions.push(
  55153. /** @type {ol.PostRenderFunction} */ (postRenderFunction)
  55154. );
  55155. var texture = ol.webgl.Context.createEmptyTexture(
  55156. gl, framebufferDimension, framebufferDimension);
  55157. var framebuffer = gl.createFramebuffer();
  55158. gl.bindFramebuffer(ol.webgl.FRAMEBUFFER, framebuffer);
  55159. gl.framebufferTexture2D(ol.webgl.FRAMEBUFFER,
  55160. ol.webgl.COLOR_ATTACHMENT0, ol.webgl.TEXTURE_2D, texture, 0);
  55161. this.texture = texture;
  55162. this.framebuffer = framebuffer;
  55163. this.framebufferDimension = framebufferDimension;
  55164. } else {
  55165. gl.bindFramebuffer(ol.webgl.FRAMEBUFFER, this.framebuffer);
  55166. }
  55167. };
  55168. /**
  55169. * @param {olx.FrameState} frameState Frame state.
  55170. * @param {ol.LayerState} layerState Layer state.
  55171. * @param {ol.webgl.Context} context Context.
  55172. */
  55173. ol.renderer.webgl.Layer.prototype.composeFrame = function(frameState, layerState, context) {
  55174. this.dispatchComposeEvent_(
  55175. ol.render.EventType.PRECOMPOSE, context, frameState);
  55176. context.bindBuffer(ol.webgl.ARRAY_BUFFER, this.arrayBuffer_);
  55177. var gl = context.getGL();
  55178. var fragmentShader = ol.renderer.webgl.defaultmapshader.fragment;
  55179. var vertexShader = ol.renderer.webgl.defaultmapshader.vertex;
  55180. var program = context.getProgram(fragmentShader, vertexShader);
  55181. var locations;
  55182. if (!this.defaultLocations_) {
  55183. // eslint-disable-next-line openlayers-internal/no-missing-requires
  55184. locations = new ol.renderer.webgl.defaultmapshader.Locations(gl, program);
  55185. this.defaultLocations_ = locations;
  55186. } else {
  55187. locations = this.defaultLocations_;
  55188. }
  55189. if (context.useProgram(program)) {
  55190. gl.enableVertexAttribArray(locations.a_position);
  55191. gl.vertexAttribPointer(
  55192. locations.a_position, 2, ol.webgl.FLOAT, false, 16, 0);
  55193. gl.enableVertexAttribArray(locations.a_texCoord);
  55194. gl.vertexAttribPointer(
  55195. locations.a_texCoord, 2, ol.webgl.FLOAT, false, 16, 8);
  55196. gl.uniform1i(locations.u_texture, 0);
  55197. }
  55198. gl.uniformMatrix4fv(locations.u_texCoordMatrix, false,
  55199. ol.vec.Mat4.fromTransform(this.tmpMat4_, this.getTexCoordMatrix()));
  55200. gl.uniformMatrix4fv(locations.u_projectionMatrix, false,
  55201. ol.vec.Mat4.fromTransform(this.tmpMat4_, this.getProjectionMatrix()));
  55202. gl.uniform1f(locations.u_opacity, layerState.opacity);
  55203. gl.bindTexture(ol.webgl.TEXTURE_2D, this.getTexture());
  55204. gl.drawArrays(ol.webgl.TRIANGLE_STRIP, 0, 4);
  55205. this.dispatchComposeEvent_(
  55206. ol.render.EventType.POSTCOMPOSE, context, frameState);
  55207. };
  55208. /**
  55209. * @param {ol.render.EventType} type Event type.
  55210. * @param {ol.webgl.Context} context WebGL context.
  55211. * @param {olx.FrameState} frameState Frame state.
  55212. * @private
  55213. */
  55214. ol.renderer.webgl.Layer.prototype.dispatchComposeEvent_ = function(type, context, frameState) {
  55215. var layer = this.getLayer();
  55216. if (layer.hasListener(type)) {
  55217. var viewState = frameState.viewState;
  55218. var resolution = viewState.resolution;
  55219. var pixelRatio = frameState.pixelRatio;
  55220. var extent = frameState.extent;
  55221. var center = viewState.center;
  55222. var rotation = viewState.rotation;
  55223. var size = frameState.size;
  55224. var render = new ol.render.webgl.Immediate(
  55225. context, center, resolution, rotation, size, extent, pixelRatio);
  55226. var composeEvent = new ol.render.Event(
  55227. type, render, frameState, null, context);
  55228. layer.dispatchEvent(composeEvent);
  55229. }
  55230. };
  55231. /**
  55232. * @return {!ol.Transform} Matrix.
  55233. */
  55234. ol.renderer.webgl.Layer.prototype.getTexCoordMatrix = function() {
  55235. return this.texCoordMatrix;
  55236. };
  55237. /**
  55238. * @return {WebGLTexture} Texture.
  55239. */
  55240. ol.renderer.webgl.Layer.prototype.getTexture = function() {
  55241. return this.texture;
  55242. };
  55243. /**
  55244. * @return {!ol.Transform} Matrix.
  55245. */
  55246. ol.renderer.webgl.Layer.prototype.getProjectionMatrix = function() {
  55247. return this.projectionMatrix;
  55248. };
  55249. /**
  55250. * Handle webglcontextlost.
  55251. */
  55252. ol.renderer.webgl.Layer.prototype.handleWebGLContextLost = function() {
  55253. this.texture = null;
  55254. this.framebuffer = null;
  55255. this.framebufferDimension = undefined;
  55256. };
  55257. /**
  55258. * @abstract
  55259. * @param {olx.FrameState} frameState Frame state.
  55260. * @param {ol.LayerState} layerState Layer state.
  55261. * @param {ol.webgl.Context} context Context.
  55262. * @return {boolean} whether composeFrame should be called.
  55263. */
  55264. ol.renderer.webgl.Layer.prototype.prepareFrame = function(frameState, layerState, context) {};
  55265. /**
  55266. * @abstract
  55267. * @param {ol.Pixel} pixel Pixel.
  55268. * @param {olx.FrameState} frameState FrameState.
  55269. * @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer
  55270. * callback.
  55271. * @param {S} thisArg Value to use as `this` when executing `callback`.
  55272. * @return {T|undefined} Callback result.
  55273. * @template S,T,U
  55274. */
  55275. ol.renderer.webgl.Layer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {};
  55276. }
  55277. goog.provide('ol.renderer.webgl.VectorLayer');
  55278. goog.require('ol');
  55279. goog.require('ol.ViewHint');
  55280. goog.require('ol.extent');
  55281. goog.require('ol.render.webgl.ReplayGroup');
  55282. goog.require('ol.renderer.vector');
  55283. goog.require('ol.renderer.webgl.Layer');
  55284. goog.require('ol.transform');
  55285. if (ol.ENABLE_WEBGL) {
  55286. /**
  55287. * @constructor
  55288. * @extends {ol.renderer.webgl.Layer}
  55289. * @param {ol.renderer.webgl.Map} mapRenderer Map renderer.
  55290. * @param {ol.layer.Vector} vectorLayer Vector layer.
  55291. */
  55292. ol.renderer.webgl.VectorLayer = function(mapRenderer, vectorLayer) {
  55293. ol.renderer.webgl.Layer.call(this, mapRenderer, vectorLayer);
  55294. /**
  55295. * @private
  55296. * @type {boolean}
  55297. */
  55298. this.dirty_ = false;
  55299. /**
  55300. * @private
  55301. * @type {number}
  55302. */
  55303. this.renderedRevision_ = -1;
  55304. /**
  55305. * @private
  55306. * @type {number}
  55307. */
  55308. this.renderedResolution_ = NaN;
  55309. /**
  55310. * @private
  55311. * @type {ol.Extent}
  55312. */
  55313. this.renderedExtent_ = ol.extent.createEmpty();
  55314. /**
  55315. * @private
  55316. * @type {function(ol.Feature, ol.Feature): number|null}
  55317. */
  55318. this.renderedRenderOrder_ = null;
  55319. /**
  55320. * @private
  55321. * @type {ol.render.webgl.ReplayGroup}
  55322. */
  55323. this.replayGroup_ = null;
  55324. /**
  55325. * The last layer state.
  55326. * @private
  55327. * @type {?ol.LayerState}
  55328. */
  55329. this.layerState_ = null;
  55330. };
  55331. ol.inherits(ol.renderer.webgl.VectorLayer, ol.renderer.webgl.Layer);
  55332. /**
  55333. * @inheritDoc
  55334. */
  55335. ol.renderer.webgl.VectorLayer.prototype.composeFrame = function(frameState, layerState, context) {
  55336. this.layerState_ = layerState;
  55337. var viewState = frameState.viewState;
  55338. var replayGroup = this.replayGroup_;
  55339. var size = frameState.size;
  55340. var pixelRatio = frameState.pixelRatio;
  55341. var gl = this.mapRenderer.getGL();
  55342. if (replayGroup && !replayGroup.isEmpty()) {
  55343. gl.enable(gl.SCISSOR_TEST);
  55344. gl.scissor(0, 0, size[0] * pixelRatio, size[1] * pixelRatio);
  55345. replayGroup.replay(context,
  55346. viewState.center, viewState.resolution, viewState.rotation,
  55347. size, pixelRatio, layerState.opacity,
  55348. layerState.managed ? frameState.skippedFeatureUids : {});
  55349. gl.disable(gl.SCISSOR_TEST);
  55350. }
  55351. };
  55352. /**
  55353. * @inheritDoc
  55354. */
  55355. ol.renderer.webgl.VectorLayer.prototype.disposeInternal = function() {
  55356. var replayGroup = this.replayGroup_;
  55357. if (replayGroup) {
  55358. var context = this.mapRenderer.getContext();
  55359. replayGroup.getDeleteResourcesFunction(context)();
  55360. this.replayGroup_ = null;
  55361. }
  55362. ol.renderer.webgl.Layer.prototype.disposeInternal.call(this);
  55363. };
  55364. /**
  55365. * @inheritDoc
  55366. */
  55367. ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
  55368. if (!this.replayGroup_ || !this.layerState_) {
  55369. return undefined;
  55370. } else {
  55371. var context = this.mapRenderer.getContext();
  55372. var viewState = frameState.viewState;
  55373. var layer = this.getLayer();
  55374. var layerState = this.layerState_;
  55375. /** @type {Object.<string, boolean>} */
  55376. var features = {};
  55377. return this.replayGroup_.forEachFeatureAtCoordinate(coordinate,
  55378. context, viewState.center, viewState.resolution, viewState.rotation,
  55379. frameState.size, frameState.pixelRatio, layerState.opacity,
  55380. {},
  55381. /**
  55382. * @param {ol.Feature|ol.render.Feature} feature Feature.
  55383. * @return {?} Callback result.
  55384. */
  55385. function(feature) {
  55386. var key = ol.getUid(feature).toString();
  55387. if (!(key in features)) {
  55388. features[key] = true;
  55389. return callback.call(thisArg, feature, layer);
  55390. }
  55391. });
  55392. }
  55393. };
  55394. /**
  55395. * @inheritDoc
  55396. */
  55397. ol.renderer.webgl.VectorLayer.prototype.hasFeatureAtCoordinate = function(coordinate, frameState) {
  55398. if (!this.replayGroup_ || !this.layerState_) {
  55399. return false;
  55400. } else {
  55401. var context = this.mapRenderer.getContext();
  55402. var viewState = frameState.viewState;
  55403. var layerState = this.layerState_;
  55404. return this.replayGroup_.hasFeatureAtCoordinate(coordinate,
  55405. context, viewState.center, viewState.resolution, viewState.rotation,
  55406. frameState.size, frameState.pixelRatio, layerState.opacity,
  55407. frameState.skippedFeatureUids);
  55408. }
  55409. };
  55410. /**
  55411. * @inheritDoc
  55412. */
  55413. ol.renderer.webgl.VectorLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
  55414. var coordinate = ol.transform.apply(
  55415. frameState.pixelToCoordinateTransform, pixel.slice());
  55416. var hasFeature = this.hasFeatureAtCoordinate(coordinate, frameState);
  55417. if (hasFeature) {
  55418. return callback.call(thisArg, this.getLayer(), null);
  55419. } else {
  55420. return undefined;
  55421. }
  55422. };
  55423. /**
  55424. * Handle changes in image style state.
  55425. * @param {ol.events.Event} event Image style change event.
  55426. * @private
  55427. */
  55428. ol.renderer.webgl.VectorLayer.prototype.handleStyleImageChange_ = function(event) {
  55429. this.renderIfReadyAndVisible();
  55430. };
  55431. /**
  55432. * @inheritDoc
  55433. */
  55434. ol.renderer.webgl.VectorLayer.prototype.prepareFrame = function(frameState, layerState, context) {
  55435. var vectorLayer = /** @type {ol.layer.Vector} */ (this.getLayer());
  55436. var vectorSource = vectorLayer.getSource();
  55437. this.updateAttributions(
  55438. frameState.attributions, vectorSource.getAttributions());
  55439. this.updateLogos(frameState, vectorSource);
  55440. var animating = frameState.viewHints[ol.ViewHint.ANIMATING];
  55441. var interacting = frameState.viewHints[ol.ViewHint.INTERACTING];
  55442. var updateWhileAnimating = vectorLayer.getUpdateWhileAnimating();
  55443. var updateWhileInteracting = vectorLayer.getUpdateWhileInteracting();
  55444. if (!this.dirty_ && (!updateWhileAnimating && animating) ||
  55445. (!updateWhileInteracting && interacting)) {
  55446. return true;
  55447. }
  55448. var frameStateExtent = frameState.extent;
  55449. var viewState = frameState.viewState;
  55450. var projection = viewState.projection;
  55451. var resolution = viewState.resolution;
  55452. var pixelRatio = frameState.pixelRatio;
  55453. var vectorLayerRevision = vectorLayer.getRevision();
  55454. var vectorLayerRenderBuffer = vectorLayer.getRenderBuffer();
  55455. var vectorLayerRenderOrder = vectorLayer.getRenderOrder();
  55456. if (vectorLayerRenderOrder === undefined) {
  55457. vectorLayerRenderOrder = ol.renderer.vector.defaultOrder;
  55458. }
  55459. var extent = ol.extent.buffer(frameStateExtent,
  55460. vectorLayerRenderBuffer * resolution);
  55461. if (!this.dirty_ &&
  55462. this.renderedResolution_ == resolution &&
  55463. this.renderedRevision_ == vectorLayerRevision &&
  55464. this.renderedRenderOrder_ == vectorLayerRenderOrder &&
  55465. ol.extent.containsExtent(this.renderedExtent_, extent)) {
  55466. return true;
  55467. }
  55468. if (this.replayGroup_) {
  55469. frameState.postRenderFunctions.push(
  55470. this.replayGroup_.getDeleteResourcesFunction(context));
  55471. }
  55472. this.dirty_ = false;
  55473. var replayGroup = new ol.render.webgl.ReplayGroup(
  55474. ol.renderer.vector.getTolerance(resolution, pixelRatio),
  55475. extent, vectorLayer.getRenderBuffer());
  55476. vectorSource.loadFeatures(extent, resolution, projection);
  55477. /**
  55478. * @param {ol.Feature} feature Feature.
  55479. * @this {ol.renderer.webgl.VectorLayer}
  55480. */
  55481. var renderFeature = function(feature) {
  55482. var styles;
  55483. var styleFunction = feature.getStyleFunction();
  55484. if (styleFunction) {
  55485. styles = styleFunction.call(feature, resolution);
  55486. } else {
  55487. styleFunction = vectorLayer.getStyleFunction();
  55488. if (styleFunction) {
  55489. styles = styleFunction(feature, resolution);
  55490. }
  55491. }
  55492. if (styles) {
  55493. var dirty = this.renderFeature(
  55494. feature, resolution, pixelRatio, styles, replayGroup);
  55495. this.dirty_ = this.dirty_ || dirty;
  55496. }
  55497. };
  55498. if (vectorLayerRenderOrder) {
  55499. /** @type {Array.<ol.Feature>} */
  55500. var features = [];
  55501. vectorSource.forEachFeatureInExtent(extent,
  55502. /**
  55503. * @param {ol.Feature} feature Feature.
  55504. */
  55505. function(feature) {
  55506. features.push(feature);
  55507. }, this);
  55508. features.sort(vectorLayerRenderOrder);
  55509. features.forEach(renderFeature, this);
  55510. } else {
  55511. vectorSource.forEachFeatureInExtent(extent, renderFeature, this);
  55512. }
  55513. replayGroup.finish(context);
  55514. this.renderedResolution_ = resolution;
  55515. this.renderedRevision_ = vectorLayerRevision;
  55516. this.renderedRenderOrder_ = vectorLayerRenderOrder;
  55517. this.renderedExtent_ = extent;
  55518. this.replayGroup_ = replayGroup;
  55519. return true;
  55520. };
  55521. /**
  55522. * @param {ol.Feature} feature Feature.
  55523. * @param {number} resolution Resolution.
  55524. * @param {number} pixelRatio Pixel ratio.
  55525. * @param {(ol.style.Style|Array.<ol.style.Style>)} styles The style or array of
  55526. * styles.
  55527. * @param {ol.render.webgl.ReplayGroup} replayGroup Replay group.
  55528. * @return {boolean} `true` if an image is loading.
  55529. */
  55530. ol.renderer.webgl.VectorLayer.prototype.renderFeature = function(feature, resolution, pixelRatio, styles, replayGroup) {
  55531. if (!styles) {
  55532. return false;
  55533. }
  55534. var loading = false;
  55535. if (Array.isArray(styles)) {
  55536. for (var i = styles.length - 1, ii = 0; i >= ii; --i) {
  55537. loading = ol.renderer.vector.renderFeature(
  55538. replayGroup, feature, styles[i],
  55539. ol.renderer.vector.getSquaredTolerance(resolution, pixelRatio),
  55540. this.handleStyleImageChange_, this) || loading;
  55541. }
  55542. } else {
  55543. loading = ol.renderer.vector.renderFeature(
  55544. replayGroup, feature, styles,
  55545. ol.renderer.vector.getSquaredTolerance(resolution, pixelRatio),
  55546. this.handleStyleImageChange_, this) || loading;
  55547. }
  55548. return loading;
  55549. };
  55550. }
  55551. goog.provide('ol.layer.Vector');
  55552. goog.require('ol');
  55553. goog.require('ol.layer.Layer');
  55554. goog.require('ol.obj');
  55555. goog.require('ol.renderer.Type');
  55556. goog.require('ol.renderer.canvas.VectorLayer');
  55557. goog.require('ol.renderer.webgl.VectorLayer');
  55558. goog.require('ol.style.Style');
  55559. /**
  55560. * @classdesc
  55561. * Vector data that is rendered client-side.
  55562. * Note that any property set in the options is set as a {@link ol.Object}
  55563. * property on the layer object; for example, setting `title: 'My Title'` in the
  55564. * options means that `title` is observable, and has get/set accessors.
  55565. *
  55566. * @constructor
  55567. * @extends {ol.layer.Layer}
  55568. * @fires ol.render.Event
  55569. * @param {olx.layer.VectorOptions=} opt_options Options.
  55570. * @api
  55571. */
  55572. ol.layer.Vector = function(opt_options) {
  55573. var options = opt_options ?
  55574. opt_options : /** @type {olx.layer.VectorOptions} */ ({});
  55575. var baseOptions = ol.obj.assign({}, options);
  55576. delete baseOptions.style;
  55577. delete baseOptions.renderBuffer;
  55578. delete baseOptions.updateWhileAnimating;
  55579. delete baseOptions.updateWhileInteracting;
  55580. ol.layer.Layer.call(this, /** @type {olx.layer.LayerOptions} */ (baseOptions));
  55581. /**
  55582. * @type {number}
  55583. * @private
  55584. */
  55585. this.renderBuffer_ = options.renderBuffer !== undefined ?
  55586. options.renderBuffer : 100;
  55587. /**
  55588. * User provided style.
  55589. * @type {ol.style.Style|Array.<ol.style.Style>|ol.StyleFunction}
  55590. * @private
  55591. */
  55592. this.style_ = null;
  55593. /**
  55594. * Style function for use within the library.
  55595. * @type {ol.StyleFunction|undefined}
  55596. * @private
  55597. */
  55598. this.styleFunction_ = undefined;
  55599. this.setStyle(options.style);
  55600. /**
  55601. * @type {boolean}
  55602. * @private
  55603. */
  55604. this.updateWhileAnimating_ = options.updateWhileAnimating !== undefined ?
  55605. options.updateWhileAnimating : false;
  55606. /**
  55607. * @type {boolean}
  55608. * @private
  55609. */
  55610. this.updateWhileInteracting_ = options.updateWhileInteracting !== undefined ?
  55611. options.updateWhileInteracting : false;
  55612. };
  55613. ol.inherits(ol.layer.Vector, ol.layer.Layer);
  55614. /**
  55615. * @inheritDoc
  55616. */
  55617. ol.layer.Vector.prototype.createRenderer = function(mapRenderer) {
  55618. var renderer = null;
  55619. var type = mapRenderer.getType();
  55620. if (ol.ENABLE_CANVAS && type === ol.renderer.Type.CANVAS) {
  55621. renderer = new ol.renderer.canvas.VectorLayer(this);
  55622. } else if (ol.ENABLE_WEBGL && type === ol.renderer.Type.WEBGL) {
  55623. renderer = new ol.renderer.webgl.VectorLayer(/** @type {ol.renderer.webgl.Map} */ (mapRenderer), this);
  55624. }
  55625. return renderer;
  55626. };
  55627. /**
  55628. * @return {number|undefined} Render buffer.
  55629. */
  55630. ol.layer.Vector.prototype.getRenderBuffer = function() {
  55631. return this.renderBuffer_;
  55632. };
  55633. /**
  55634. * @return {function(ol.Feature, ol.Feature): number|null|undefined} Render
  55635. * order.
  55636. */
  55637. ol.layer.Vector.prototype.getRenderOrder = function() {
  55638. return /** @type {ol.RenderOrderFunction|null|undefined} */ (
  55639. this.get(ol.layer.Vector.Property_.RENDER_ORDER));
  55640. };
  55641. /**
  55642. * Return the associated {@link ol.source.Vector vectorsource} of the layer.
  55643. * @function
  55644. * @return {ol.source.Vector} Source.
  55645. * @api
  55646. */
  55647. ol.layer.Vector.prototype.getSource;
  55648. /**
  55649. * Get the style for features. This returns whatever was passed to the `style`
  55650. * option at construction or to the `setStyle` method.
  55651. * @return {ol.style.Style|Array.<ol.style.Style>|ol.StyleFunction}
  55652. * Layer style.
  55653. * @api
  55654. */
  55655. ol.layer.Vector.prototype.getStyle = function() {
  55656. return this.style_;
  55657. };
  55658. /**
  55659. * Get the style function.
  55660. * @return {ol.StyleFunction|undefined} Layer style function.
  55661. * @api
  55662. */
  55663. ol.layer.Vector.prototype.getStyleFunction = function() {
  55664. return this.styleFunction_;
  55665. };
  55666. /**
  55667. * @return {boolean} Whether the rendered layer should be updated while
  55668. * animating.
  55669. */
  55670. ol.layer.Vector.prototype.getUpdateWhileAnimating = function() {
  55671. return this.updateWhileAnimating_;
  55672. };
  55673. /**
  55674. * @return {boolean} Whether the rendered layer should be updated while
  55675. * interacting.
  55676. */
  55677. ol.layer.Vector.prototype.getUpdateWhileInteracting = function() {
  55678. return this.updateWhileInteracting_;
  55679. };
  55680. /**
  55681. * @param {ol.RenderOrderFunction|null|undefined} renderOrder
  55682. * Render order.
  55683. */
  55684. ol.layer.Vector.prototype.setRenderOrder = function(renderOrder) {
  55685. this.set(ol.layer.Vector.Property_.RENDER_ORDER, renderOrder);
  55686. };
  55687. /**
  55688. * Set the style for features. This can be a single style object, an array
  55689. * of styles, or a function that takes a feature and resolution and returns
  55690. * an array of styles. If it is `undefined` the default style is used. If
  55691. * it is `null` the layer has no style (a `null` style), so only features
  55692. * that have their own styles will be rendered in the layer. See
  55693. * {@link ol.style} for information on the default style.
  55694. * @param {ol.style.Style|Array.<ol.style.Style>|ol.StyleFunction|null|undefined}
  55695. * style Layer style.
  55696. * @api
  55697. */
  55698. ol.layer.Vector.prototype.setStyle = function(style) {
  55699. this.style_ = style !== undefined ? style : ol.style.Style.defaultFunction;
  55700. this.styleFunction_ = style === null ?
  55701. undefined : ol.style.Style.createFunction(this.style_);
  55702. this.changed();
  55703. };
  55704. /**
  55705. * @enum {string}
  55706. * @private
  55707. */
  55708. ol.layer.Vector.Property_ = {
  55709. RENDER_ORDER: 'renderOrder'
  55710. };
  55711. goog.provide('ol.loadingstrategy');
  55712. /**
  55713. * Strategy function for loading all features with a single request.
  55714. * @param {ol.Extent} extent Extent.
  55715. * @param {number} resolution Resolution.
  55716. * @return {Array.<ol.Extent>} Extents.
  55717. * @api
  55718. */
  55719. ol.loadingstrategy.all = function(extent, resolution) {
  55720. return [[-Infinity, -Infinity, Infinity, Infinity]];
  55721. };
  55722. /**
  55723. * Strategy function for loading features based on the view's extent and
  55724. * resolution.
  55725. * @param {ol.Extent} extent Extent.
  55726. * @param {number} resolution Resolution.
  55727. * @return {Array.<ol.Extent>} Extents.
  55728. * @api
  55729. */
  55730. ol.loadingstrategy.bbox = function(extent, resolution) {
  55731. return [extent];
  55732. };
  55733. /**
  55734. * Creates a strategy function for loading features based on a tile grid.
  55735. * @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
  55736. * @return {function(ol.Extent, number): Array.<ol.Extent>} Loading strategy.
  55737. * @api
  55738. */
  55739. ol.loadingstrategy.tile = function(tileGrid) {
  55740. return (
  55741. /**
  55742. * @param {ol.Extent} extent Extent.
  55743. * @param {number} resolution Resolution.
  55744. * @return {Array.<ol.Extent>} Extents.
  55745. */
  55746. function(extent, resolution) {
  55747. var z = tileGrid.getZForResolution(resolution);
  55748. var tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z);
  55749. /** @type {Array.<ol.Extent>} */
  55750. var extents = [];
  55751. /** @type {ol.TileCoord} */
  55752. var tileCoord = [z, 0, 0];
  55753. for (tileCoord[1] = tileRange.minX; tileCoord[1] <= tileRange.maxX;
  55754. ++tileCoord[1]) {
  55755. for (tileCoord[2] = tileRange.minY; tileCoord[2] <= tileRange.maxY;
  55756. ++tileCoord[2]) {
  55757. extents.push(tileGrid.getTileCoordExtent(tileCoord));
  55758. }
  55759. }
  55760. return extents;
  55761. });
  55762. };
  55763. goog.provide('ol.source.Source');
  55764. goog.require('ol');
  55765. goog.require('ol.Attribution');
  55766. goog.require('ol.Object');
  55767. goog.require('ol.proj');
  55768. goog.require('ol.source.State');
  55769. /**
  55770. * @classdesc
  55771. * Abstract base class; normally only used for creating subclasses and not
  55772. * instantiated in apps.
  55773. * Base class for {@link ol.layer.Layer} sources.
  55774. *
  55775. * A generic `change` event is triggered when the state of the source changes.
  55776. *
  55777. * @constructor
  55778. * @abstract
  55779. * @extends {ol.Object}
  55780. * @param {ol.SourceSourceOptions} options Source options.
  55781. * @api
  55782. */
  55783. ol.source.Source = function(options) {
  55784. ol.Object.call(this);
  55785. /**
  55786. * @private
  55787. * @type {ol.proj.Projection}
  55788. */
  55789. this.projection_ = ol.proj.get(options.projection);
  55790. /**
  55791. * @private
  55792. * @type {Array.<ol.Attribution>}
  55793. */
  55794. this.attributions_ = ol.source.Source.toAttributionsArray_(options.attributions);
  55795. /**
  55796. * @private
  55797. * @type {string|olx.LogoOptions|undefined}
  55798. */
  55799. this.logo_ = options.logo;
  55800. /**
  55801. * @private
  55802. * @type {ol.source.State}
  55803. */
  55804. this.state_ = options.state !== undefined ?
  55805. options.state : ol.source.State.READY;
  55806. /**
  55807. * @private
  55808. * @type {boolean}
  55809. */
  55810. this.wrapX_ = options.wrapX !== undefined ? options.wrapX : false;
  55811. };
  55812. ol.inherits(ol.source.Source, ol.Object);
  55813. /**
  55814. * Turns various ways of defining an attribution to an array of `ol.Attributions`.
  55815. *
  55816. * @param {ol.AttributionLike|undefined}
  55817. * attributionLike The attributions as string, array of strings,
  55818. * `ol.Attribution`, array of `ol.Attribution` or undefined.
  55819. * @return {Array.<ol.Attribution>} The array of `ol.Attribution` or null if
  55820. * `undefined` was given.
  55821. */
  55822. ol.source.Source.toAttributionsArray_ = function(attributionLike) {
  55823. if (typeof attributionLike === 'string') {
  55824. return [new ol.Attribution({html: attributionLike})];
  55825. } else if (attributionLike instanceof ol.Attribution) {
  55826. return [attributionLike];
  55827. } else if (Array.isArray(attributionLike)) {
  55828. var len = attributionLike.length;
  55829. var attributions = new Array(len);
  55830. for (var i = 0; i < len; i++) {
  55831. var item = attributionLike[i];
  55832. if (typeof item === 'string') {
  55833. attributions[i] = new ol.Attribution({html: item});
  55834. } else {
  55835. attributions[i] = item;
  55836. }
  55837. }
  55838. return attributions;
  55839. } else {
  55840. return null;
  55841. }
  55842. };
  55843. /**
  55844. * @param {ol.Coordinate} coordinate Coordinate.
  55845. * @param {number} resolution Resolution.
  55846. * @param {number} rotation Rotation.
  55847. * @param {number} hitTolerance Hit tolerance in pixels.
  55848. * @param {Object.<string, boolean>} skippedFeatureUids Skipped feature uids.
  55849. * @param {function((ol.Feature|ol.render.Feature)): T} callback Feature
  55850. * callback.
  55851. * @return {T|undefined} Callback result.
  55852. * @template T
  55853. */
  55854. ol.source.Source.prototype.forEachFeatureAtCoordinate = ol.nullFunction;
  55855. /**
  55856. * Get the attributions of the source.
  55857. * @return {Array.<ol.Attribution>} Attributions.
  55858. * @api
  55859. */
  55860. ol.source.Source.prototype.getAttributions = function() {
  55861. return this.attributions_;
  55862. };
  55863. /**
  55864. * Get the logo of the source.
  55865. * @return {string|olx.LogoOptions|undefined} Logo.
  55866. * @api
  55867. */
  55868. ol.source.Source.prototype.getLogo = function() {
  55869. return this.logo_;
  55870. };
  55871. /**
  55872. * Get the projection of the source.
  55873. * @return {ol.proj.Projection} Projection.
  55874. * @api
  55875. */
  55876. ol.source.Source.prototype.getProjection = function() {
  55877. return this.projection_;
  55878. };
  55879. /**
  55880. * @abstract
  55881. * @return {Array.<number>|undefined} Resolutions.
  55882. */
  55883. ol.source.Source.prototype.getResolutions = function() {};
  55884. /**
  55885. * Get the state of the source, see {@link ol.source.State} for possible states.
  55886. * @return {ol.source.State} State.
  55887. * @api
  55888. */
  55889. ol.source.Source.prototype.getState = function() {
  55890. return this.state_;
  55891. };
  55892. /**
  55893. * @return {boolean|undefined} Wrap X.
  55894. */
  55895. ol.source.Source.prototype.getWrapX = function() {
  55896. return this.wrapX_;
  55897. };
  55898. /**
  55899. * Refreshes the source and finally dispatches a 'change' event.
  55900. * @api
  55901. */
  55902. ol.source.Source.prototype.refresh = function() {
  55903. this.changed();
  55904. };
  55905. /**
  55906. * Set the attributions of the source.
  55907. * @param {ol.AttributionLike|undefined} attributions Attributions.
  55908. * Can be passed as `string`, `Array<string>`, `{@link ol.Attribution}`,
  55909. * `Array<{@link ol.Attribution}>` or `undefined`.
  55910. * @api
  55911. */
  55912. ol.source.Source.prototype.setAttributions = function(attributions) {
  55913. this.attributions_ = ol.source.Source.toAttributionsArray_(attributions);
  55914. this.changed();
  55915. };
  55916. /**
  55917. * Set the logo of the source.
  55918. * @param {string|olx.LogoOptions|undefined} logo Logo.
  55919. */
  55920. ol.source.Source.prototype.setLogo = function(logo) {
  55921. this.logo_ = logo;
  55922. };
  55923. /**
  55924. * Set the state of the source.
  55925. * @param {ol.source.State} state State.
  55926. * @protected
  55927. */
  55928. ol.source.Source.prototype.setState = function(state) {
  55929. this.state_ = state;
  55930. this.changed();
  55931. };
  55932. goog.provide('ol.source.VectorEventType');
  55933. /**
  55934. * @enum {string}
  55935. */
  55936. ol.source.VectorEventType = {
  55937. /**
  55938. * Triggered when a feature is added to the source.
  55939. * @event ol.source.Vector.Event#addfeature
  55940. * @api
  55941. */
  55942. ADDFEATURE: 'addfeature',
  55943. /**
  55944. * Triggered when a feature is updated.
  55945. * @event ol.source.Vector.Event#changefeature
  55946. * @api
  55947. */
  55948. CHANGEFEATURE: 'changefeature',
  55949. /**
  55950. * Triggered when the clear method is called on the source.
  55951. * @event ol.source.Vector.Event#clear
  55952. * @api
  55953. */
  55954. CLEAR: 'clear',
  55955. /**
  55956. * Triggered when a feature is removed from the source.
  55957. * See {@link ol.source.Vector#clear source.clear()} for exceptions.
  55958. * @event ol.source.Vector.Event#removefeature
  55959. * @api
  55960. */
  55961. REMOVEFEATURE: 'removefeature'
  55962. };
  55963. // FIXME bulk feature upload - suppress events
  55964. // FIXME make change-detection more refined (notably, geometry hint)
  55965. goog.provide('ol.source.Vector');
  55966. goog.require('ol');
  55967. goog.require('ol.Collection');
  55968. goog.require('ol.CollectionEventType');
  55969. goog.require('ol.ObjectEventType');
  55970. goog.require('ol.array');
  55971. goog.require('ol.asserts');
  55972. goog.require('ol.events');
  55973. goog.require('ol.events.Event');
  55974. goog.require('ol.events.EventType');
  55975. goog.require('ol.extent');
  55976. goog.require('ol.featureloader');
  55977. goog.require('ol.functions');
  55978. goog.require('ol.loadingstrategy');
  55979. goog.require('ol.obj');
  55980. goog.require('ol.source.Source');
  55981. goog.require('ol.source.State');
  55982. goog.require('ol.source.VectorEventType');
  55983. goog.require('ol.structs.RBush');
  55984. /**
  55985. * @classdesc
  55986. * Provides a source of features for vector layers. Vector features provided
  55987. * by this source are suitable for editing. See {@link ol.source.VectorTile} for
  55988. * vector data that is optimized for rendering.
  55989. *
  55990. * @constructor
  55991. * @extends {ol.source.Source}
  55992. * @fires ol.source.Vector.Event
  55993. * @param {olx.source.VectorOptions=} opt_options Vector source options.
  55994. * @api
  55995. */
  55996. ol.source.Vector = function(opt_options) {
  55997. var options = opt_options || {};
  55998. ol.source.Source.call(this, {
  55999. attributions: options.attributions,
  56000. logo: options.logo,
  56001. projection: undefined,
  56002. state: ol.source.State.READY,
  56003. wrapX: options.wrapX !== undefined ? options.wrapX : true
  56004. });
  56005. /**
  56006. * @private
  56007. * @type {ol.FeatureLoader}
  56008. */
  56009. this.loader_ = ol.nullFunction;
  56010. /**
  56011. * @private
  56012. * @type {ol.format.Feature|undefined}
  56013. */
  56014. this.format_ = options.format;
  56015. /**
  56016. * @private
  56017. * @type {boolean}
  56018. */
  56019. this.overlaps_ = options.overlaps == undefined ? true : options.overlaps;
  56020. /**
  56021. * @private
  56022. * @type {string|ol.FeatureUrlFunction|undefined}
  56023. */
  56024. this.url_ = options.url;
  56025. if (options.loader !== undefined) {
  56026. this.loader_ = options.loader;
  56027. } else if (this.url_ !== undefined) {
  56028. ol.asserts.assert(this.format_, 7); // `format` must be set when `url` is set
  56029. // create a XHR feature loader for "url" and "format"
  56030. this.loader_ = ol.featureloader.xhr(this.url_, /** @type {ol.format.Feature} */ (this.format_));
  56031. }
  56032. /**
  56033. * @private
  56034. * @type {ol.LoadingStrategy}
  56035. */
  56036. this.strategy_ = options.strategy !== undefined ? options.strategy :
  56037. ol.loadingstrategy.all;
  56038. var useSpatialIndex =
  56039. options.useSpatialIndex !== undefined ? options.useSpatialIndex : true;
  56040. /**
  56041. * @private
  56042. * @type {ol.structs.RBush.<ol.Feature>}
  56043. */
  56044. this.featuresRtree_ = useSpatialIndex ? new ol.structs.RBush() : null;
  56045. /**
  56046. * @private
  56047. * @type {ol.structs.RBush.<{extent: ol.Extent}>}
  56048. */
  56049. this.loadedExtentsRtree_ = new ol.structs.RBush();
  56050. /**
  56051. * @private
  56052. * @type {Object.<string, ol.Feature>}
  56053. */
  56054. this.nullGeometryFeatures_ = {};
  56055. /**
  56056. * A lookup of features by id (the return from feature.getId()).
  56057. * @private
  56058. * @type {Object.<string, ol.Feature>}
  56059. */
  56060. this.idIndex_ = {};
  56061. /**
  56062. * A lookup of features without id (keyed by ol.getUid(feature)).
  56063. * @private
  56064. * @type {Object.<string, ol.Feature>}
  56065. */
  56066. this.undefIdIndex_ = {};
  56067. /**
  56068. * @private
  56069. * @type {Object.<string, Array.<ol.EventsKey>>}
  56070. */
  56071. this.featureChangeKeys_ = {};
  56072. /**
  56073. * @private
  56074. * @type {ol.Collection.<ol.Feature>}
  56075. */
  56076. this.featuresCollection_ = null;
  56077. var collection, features;
  56078. if (options.features instanceof ol.Collection) {
  56079. collection = options.features;
  56080. features = collection.getArray();
  56081. } else if (Array.isArray(options.features)) {
  56082. features = options.features;
  56083. }
  56084. if (!useSpatialIndex && collection === undefined) {
  56085. collection = new ol.Collection(features);
  56086. }
  56087. if (features !== undefined) {
  56088. this.addFeaturesInternal(features);
  56089. }
  56090. if (collection !== undefined) {
  56091. this.bindFeaturesCollection_(collection);
  56092. }
  56093. };
  56094. ol.inherits(ol.source.Vector, ol.source.Source);
  56095. /**
  56096. * Add a single feature to the source. If you want to add a batch of features
  56097. * at once, call {@link ol.source.Vector#addFeatures source.addFeatures()}
  56098. * instead. A feature will not be added to the source if feature with
  56099. * the same id is already there. The reason for this behavior is to avoid
  56100. * feature duplication when using bbox or tile loading strategies.
  56101. * @param {ol.Feature} feature Feature to add.
  56102. * @api
  56103. */
  56104. ol.source.Vector.prototype.addFeature = function(feature) {
  56105. this.addFeatureInternal(feature);
  56106. this.changed();
  56107. };
  56108. /**
  56109. * Add a feature without firing a `change` event.
  56110. * @param {ol.Feature} feature Feature.
  56111. * @protected
  56112. */
  56113. ol.source.Vector.prototype.addFeatureInternal = function(feature) {
  56114. var featureKey = ol.getUid(feature).toString();
  56115. if (!this.addToIndex_(featureKey, feature)) {
  56116. return;
  56117. }
  56118. this.setupChangeEvents_(featureKey, feature);
  56119. var geometry = feature.getGeometry();
  56120. if (geometry) {
  56121. var extent = geometry.getExtent();
  56122. if (this.featuresRtree_) {
  56123. this.featuresRtree_.insert(extent, feature);
  56124. }
  56125. } else {
  56126. this.nullGeometryFeatures_[featureKey] = feature;
  56127. }
  56128. this.dispatchEvent(
  56129. new ol.source.Vector.Event(ol.source.VectorEventType.ADDFEATURE, feature));
  56130. };
  56131. /**
  56132. * @param {string} featureKey Unique identifier for the feature.
  56133. * @param {ol.Feature} feature The feature.
  56134. * @private
  56135. */
  56136. ol.source.Vector.prototype.setupChangeEvents_ = function(featureKey, feature) {
  56137. this.featureChangeKeys_[featureKey] = [
  56138. ol.events.listen(feature, ol.events.EventType.CHANGE,
  56139. this.handleFeatureChange_, this),
  56140. ol.events.listen(feature, ol.ObjectEventType.PROPERTYCHANGE,
  56141. this.handleFeatureChange_, this)
  56142. ];
  56143. };
  56144. /**
  56145. * @param {string} featureKey Unique identifier for the feature.
  56146. * @param {ol.Feature} feature The feature.
  56147. * @return {boolean} The feature is "valid", in the sense that it is also a
  56148. * candidate for insertion into the Rtree.
  56149. * @private
  56150. */
  56151. ol.source.Vector.prototype.addToIndex_ = function(featureKey, feature) {
  56152. var valid = true;
  56153. var id = feature.getId();
  56154. if (id !== undefined) {
  56155. if (!(id.toString() in this.idIndex_)) {
  56156. this.idIndex_[id.toString()] = feature;
  56157. } else {
  56158. valid = false;
  56159. }
  56160. } else {
  56161. ol.asserts.assert(!(featureKey in this.undefIdIndex_),
  56162. 30); // The passed `feature` was already added to the source
  56163. this.undefIdIndex_[featureKey] = feature;
  56164. }
  56165. return valid;
  56166. };
  56167. /**
  56168. * Add a batch of features to the source.
  56169. * @param {Array.<ol.Feature>} features Features to add.
  56170. * @api
  56171. */
  56172. ol.source.Vector.prototype.addFeatures = function(features) {
  56173. this.addFeaturesInternal(features);
  56174. this.changed();
  56175. };
  56176. /**
  56177. * Add features without firing a `change` event.
  56178. * @param {Array.<ol.Feature>} features Features.
  56179. * @protected
  56180. */
  56181. ol.source.Vector.prototype.addFeaturesInternal = function(features) {
  56182. var featureKey, i, length, feature;
  56183. var extents = [];
  56184. var newFeatures = [];
  56185. var geometryFeatures = [];
  56186. for (i = 0, length = features.length; i < length; i++) {
  56187. feature = features[i];
  56188. featureKey = ol.getUid(feature).toString();
  56189. if (this.addToIndex_(featureKey, feature)) {
  56190. newFeatures.push(feature);
  56191. }
  56192. }
  56193. for (i = 0, length = newFeatures.length; i < length; i++) {
  56194. feature = newFeatures[i];
  56195. featureKey = ol.getUid(feature).toString();
  56196. this.setupChangeEvents_(featureKey, feature);
  56197. var geometry = feature.getGeometry();
  56198. if (geometry) {
  56199. var extent = geometry.getExtent();
  56200. extents.push(extent);
  56201. geometryFeatures.push(feature);
  56202. } else {
  56203. this.nullGeometryFeatures_[featureKey] = feature;
  56204. }
  56205. }
  56206. if (this.featuresRtree_) {
  56207. this.featuresRtree_.load(extents, geometryFeatures);
  56208. }
  56209. for (i = 0, length = newFeatures.length; i < length; i++) {
  56210. this.dispatchEvent(new ol.source.Vector.Event(
  56211. ol.source.VectorEventType.ADDFEATURE, newFeatures[i]));
  56212. }
  56213. };
  56214. /**
  56215. * @param {!ol.Collection.<ol.Feature>} collection Collection.
  56216. * @private
  56217. */
  56218. ol.source.Vector.prototype.bindFeaturesCollection_ = function(collection) {
  56219. var modifyingCollection = false;
  56220. ol.events.listen(this, ol.source.VectorEventType.ADDFEATURE,
  56221. function(evt) {
  56222. if (!modifyingCollection) {
  56223. modifyingCollection = true;
  56224. collection.push(evt.feature);
  56225. modifyingCollection = false;
  56226. }
  56227. });
  56228. ol.events.listen(this, ol.source.VectorEventType.REMOVEFEATURE,
  56229. function(evt) {
  56230. if (!modifyingCollection) {
  56231. modifyingCollection = true;
  56232. collection.remove(evt.feature);
  56233. modifyingCollection = false;
  56234. }
  56235. });
  56236. ol.events.listen(collection, ol.CollectionEventType.ADD,
  56237. function(evt) {
  56238. if (!modifyingCollection) {
  56239. modifyingCollection = true;
  56240. this.addFeature(/** @type {ol.Feature} */ (evt.element));
  56241. modifyingCollection = false;
  56242. }
  56243. }, this);
  56244. ol.events.listen(collection, ol.CollectionEventType.REMOVE,
  56245. function(evt) {
  56246. if (!modifyingCollection) {
  56247. modifyingCollection = true;
  56248. this.removeFeature(/** @type {ol.Feature} */ (evt.element));
  56249. modifyingCollection = false;
  56250. }
  56251. }, this);
  56252. this.featuresCollection_ = collection;
  56253. };
  56254. /**
  56255. * Remove all features from the source.
  56256. * @param {boolean=} opt_fast Skip dispatching of {@link removefeature} events.
  56257. * @api
  56258. */
  56259. ol.source.Vector.prototype.clear = function(opt_fast) {
  56260. if (opt_fast) {
  56261. for (var featureId in this.featureChangeKeys_) {
  56262. var keys = this.featureChangeKeys_[featureId];
  56263. keys.forEach(ol.events.unlistenByKey);
  56264. }
  56265. if (!this.featuresCollection_) {
  56266. this.featureChangeKeys_ = {};
  56267. this.idIndex_ = {};
  56268. this.undefIdIndex_ = {};
  56269. }
  56270. } else {
  56271. if (this.featuresRtree_) {
  56272. this.featuresRtree_.forEach(this.removeFeatureInternal, this);
  56273. for (var id in this.nullGeometryFeatures_) {
  56274. this.removeFeatureInternal(this.nullGeometryFeatures_[id]);
  56275. }
  56276. }
  56277. }
  56278. if (this.featuresCollection_) {
  56279. this.featuresCollection_.clear();
  56280. }
  56281. if (this.featuresRtree_) {
  56282. this.featuresRtree_.clear();
  56283. }
  56284. this.loadedExtentsRtree_.clear();
  56285. this.nullGeometryFeatures_ = {};
  56286. var clearEvent = new ol.source.Vector.Event(ol.source.VectorEventType.CLEAR);
  56287. this.dispatchEvent(clearEvent);
  56288. this.changed();
  56289. };
  56290. /**
  56291. * Iterate through all features on the source, calling the provided callback
  56292. * with each one. If the callback returns any "truthy" value, iteration will
  56293. * stop and the function will return the same value.
  56294. *
  56295. * @param {function(this: T, ol.Feature): S} callback Called with each feature
  56296. * on the source. Return a truthy value to stop iteration.
  56297. * @param {T=} opt_this The object to use as `this` in the callback.
  56298. * @return {S|undefined} The return value from the last call to the callback.
  56299. * @template T,S
  56300. * @api
  56301. */
  56302. ol.source.Vector.prototype.forEachFeature = function(callback, opt_this) {
  56303. if (this.featuresRtree_) {
  56304. return this.featuresRtree_.forEach(callback, opt_this);
  56305. } else if (this.featuresCollection_) {
  56306. return this.featuresCollection_.forEach(callback, opt_this);
  56307. }
  56308. };
  56309. /**
  56310. * Iterate through all features whose geometries contain the provided
  56311. * coordinate, calling the callback with each feature. If the callback returns
  56312. * a "truthy" value, iteration will stop and the function will return the same
  56313. * value.
  56314. *
  56315. * @param {ol.Coordinate} coordinate Coordinate.
  56316. * @param {function(this: T, ol.Feature): S} callback Called with each feature
  56317. * whose goemetry contains the provided coordinate.
  56318. * @param {T=} opt_this The object to use as `this` in the callback.
  56319. * @return {S|undefined} The return value from the last call to the callback.
  56320. * @template T,S
  56321. */
  56322. ol.source.Vector.prototype.forEachFeatureAtCoordinateDirect = function(coordinate, callback, opt_this) {
  56323. var extent = [coordinate[0], coordinate[1], coordinate[0], coordinate[1]];
  56324. return this.forEachFeatureInExtent(extent, function(feature) {
  56325. var geometry = feature.getGeometry();
  56326. if (geometry.intersectsCoordinate(coordinate)) {
  56327. return callback.call(opt_this, feature);
  56328. } else {
  56329. return undefined;
  56330. }
  56331. });
  56332. };
  56333. /**
  56334. * Iterate through all features whose bounding box intersects the provided
  56335. * extent (note that the feature's geometry may not intersect the extent),
  56336. * calling the callback with each feature. If the callback returns a "truthy"
  56337. * value, iteration will stop and the function will return the same value.
  56338. *
  56339. * If you are interested in features whose geometry intersects an extent, call
  56340. * the {@link ol.source.Vector#forEachFeatureIntersectingExtent
  56341. * source.forEachFeatureIntersectingExtent()} method instead.
  56342. *
  56343. * When `useSpatialIndex` is set to false, this method will loop through all
  56344. * features, equivalent to {@link ol.source.Vector#forEachFeature}.
  56345. *
  56346. * @param {ol.Extent} extent Extent.
  56347. * @param {function(this: T, ol.Feature): S} callback Called with each feature
  56348. * whose bounding box intersects the provided extent.
  56349. * @param {T=} opt_this The object to use as `this` in the callback.
  56350. * @return {S|undefined} The return value from the last call to the callback.
  56351. * @template T,S
  56352. * @api
  56353. */
  56354. ol.source.Vector.prototype.forEachFeatureInExtent = function(extent, callback, opt_this) {
  56355. if (this.featuresRtree_) {
  56356. return this.featuresRtree_.forEachInExtent(extent, callback, opt_this);
  56357. } else if (this.featuresCollection_) {
  56358. return this.featuresCollection_.forEach(callback, opt_this);
  56359. }
  56360. };
  56361. /**
  56362. * Iterate through all features whose geometry intersects the provided extent,
  56363. * calling the callback with each feature. If the callback returns a "truthy"
  56364. * value, iteration will stop and the function will return the same value.
  56365. *
  56366. * If you only want to test for bounding box intersection, call the
  56367. * {@link ol.source.Vector#forEachFeatureInExtent
  56368. * source.forEachFeatureInExtent()} method instead.
  56369. *
  56370. * @param {ol.Extent} extent Extent.
  56371. * @param {function(this: T, ol.Feature): S} callback Called with each feature
  56372. * whose geometry intersects the provided extent.
  56373. * @param {T=} opt_this The object to use as `this` in the callback.
  56374. * @return {S|undefined} The return value from the last call to the callback.
  56375. * @template T,S
  56376. * @api
  56377. */
  56378. ol.source.Vector.prototype.forEachFeatureIntersectingExtent = function(extent, callback, opt_this) {
  56379. return this.forEachFeatureInExtent(extent,
  56380. /**
  56381. * @param {ol.Feature} feature Feature.
  56382. * @return {S|undefined} The return value from the last call to the callback.
  56383. * @template S
  56384. */
  56385. function(feature) {
  56386. var geometry = feature.getGeometry();
  56387. if (geometry.intersectsExtent(extent)) {
  56388. var result = callback.call(opt_this, feature);
  56389. if (result) {
  56390. return result;
  56391. }
  56392. }
  56393. });
  56394. };
  56395. /**
  56396. * Get the features collection associated with this source. Will be `null`
  56397. * unless the source was configured with `useSpatialIndex` set to `false`, or
  56398. * with an {@link ol.Collection} as `features`.
  56399. * @return {ol.Collection.<ol.Feature>} The collection of features.
  56400. * @api
  56401. */
  56402. ol.source.Vector.prototype.getFeaturesCollection = function() {
  56403. return this.featuresCollection_;
  56404. };
  56405. /**
  56406. * Get all features on the source in random order.
  56407. * @return {Array.<ol.Feature>} Features.
  56408. * @api
  56409. */
  56410. ol.source.Vector.prototype.getFeatures = function() {
  56411. var features;
  56412. if (this.featuresCollection_) {
  56413. features = this.featuresCollection_.getArray();
  56414. } else if (this.featuresRtree_) {
  56415. features = this.featuresRtree_.getAll();
  56416. if (!ol.obj.isEmpty(this.nullGeometryFeatures_)) {
  56417. ol.array.extend(
  56418. features, ol.obj.getValues(this.nullGeometryFeatures_));
  56419. }
  56420. }
  56421. return /** @type {Array.<ol.Feature>} */ (features);
  56422. };
  56423. /**
  56424. * Get all features whose geometry intersects the provided coordinate.
  56425. * @param {ol.Coordinate} coordinate Coordinate.
  56426. * @return {Array.<ol.Feature>} Features.
  56427. * @api
  56428. */
  56429. ol.source.Vector.prototype.getFeaturesAtCoordinate = function(coordinate) {
  56430. var features = [];
  56431. this.forEachFeatureAtCoordinateDirect(coordinate, function(feature) {
  56432. features.push(feature);
  56433. });
  56434. return features;
  56435. };
  56436. /**
  56437. * Get all features in the provided extent. Note that this returns an array of
  56438. * all features intersecting the given extent in random order (so it may include
  56439. * features whose geometries do not intersect the extent).
  56440. *
  56441. * This method is not available when the source is configured with
  56442. * `useSpatialIndex` set to `false`.
  56443. * @param {ol.Extent} extent Extent.
  56444. * @return {Array.<ol.Feature>} Features.
  56445. * @api
  56446. */
  56447. ol.source.Vector.prototype.getFeaturesInExtent = function(extent) {
  56448. return this.featuresRtree_.getInExtent(extent);
  56449. };
  56450. /**
  56451. * Get the closest feature to the provided coordinate.
  56452. *
  56453. * This method is not available when the source is configured with
  56454. * `useSpatialIndex` set to `false`.
  56455. * @param {ol.Coordinate} coordinate Coordinate.
  56456. * @param {function(ol.Feature):boolean=} opt_filter Feature filter function.
  56457. * The filter function will receive one argument, the {@link ol.Feature feature}
  56458. * and it should return a boolean value. By default, no filtering is made.
  56459. * @return {ol.Feature} Closest feature.
  56460. * @api
  56461. */
  56462. ol.source.Vector.prototype.getClosestFeatureToCoordinate = function(coordinate, opt_filter) {
  56463. // Find the closest feature using branch and bound. We start searching an
  56464. // infinite extent, and find the distance from the first feature found. This
  56465. // becomes the closest feature. We then compute a smaller extent which any
  56466. // closer feature must intersect. We continue searching with this smaller
  56467. // extent, trying to find a closer feature. Every time we find a closer
  56468. // feature, we update the extent being searched so that any even closer
  56469. // feature must intersect it. We continue until we run out of features.
  56470. var x = coordinate[0];
  56471. var y = coordinate[1];
  56472. var closestFeature = null;
  56473. var closestPoint = [NaN, NaN];
  56474. var minSquaredDistance = Infinity;
  56475. var extent = [-Infinity, -Infinity, Infinity, Infinity];
  56476. var filter = opt_filter ? opt_filter : ol.functions.TRUE;
  56477. this.featuresRtree_.forEachInExtent(extent,
  56478. /**
  56479. * @param {ol.Feature} feature Feature.
  56480. */
  56481. function(feature) {
  56482. if (filter(feature)) {
  56483. var geometry = feature.getGeometry();
  56484. var previousMinSquaredDistance = minSquaredDistance;
  56485. minSquaredDistance = geometry.closestPointXY(
  56486. x, y, closestPoint, minSquaredDistance);
  56487. if (minSquaredDistance < previousMinSquaredDistance) {
  56488. closestFeature = feature;
  56489. // This is sneaky. Reduce the extent that it is currently being
  56490. // searched while the R-Tree traversal using this same extent object
  56491. // is still in progress. This is safe because the new extent is
  56492. // strictly contained by the old extent.
  56493. var minDistance = Math.sqrt(minSquaredDistance);
  56494. extent[0] = x - minDistance;
  56495. extent[1] = y - minDistance;
  56496. extent[2] = x + minDistance;
  56497. extent[3] = y + minDistance;
  56498. }
  56499. }
  56500. });
  56501. return closestFeature;
  56502. };
  56503. /**
  56504. * Get the extent of the features currently in the source.
  56505. *
  56506. * This method is not available when the source is configured with
  56507. * `useSpatialIndex` set to `false`.
  56508. * @param {ol.Extent=} opt_extent Destination extent. If provided, no new extent
  56509. * will be created. Instead, that extent's coordinates will be overwritten.
  56510. * @return {ol.Extent} Extent.
  56511. * @api
  56512. */
  56513. ol.source.Vector.prototype.getExtent = function(opt_extent) {
  56514. return this.featuresRtree_.getExtent(opt_extent);
  56515. };
  56516. /**
  56517. * Get a feature by its identifier (the value returned by feature.getId()).
  56518. * Note that the index treats string and numeric identifiers as the same. So
  56519. * `source.getFeatureById(2)` will return a feature with id `'2'` or `2`.
  56520. *
  56521. * @param {string|number} id Feature identifier.
  56522. * @return {ol.Feature} The feature (or `null` if not found).
  56523. * @api
  56524. */
  56525. ol.source.Vector.prototype.getFeatureById = function(id) {
  56526. var feature = this.idIndex_[id.toString()];
  56527. return feature !== undefined ? feature : null;
  56528. };
  56529. /**
  56530. * Get the format associated with this source.
  56531. *
  56532. * @return {ol.format.Feature|undefined} The feature format.
  56533. * @api
  56534. */
  56535. ol.source.Vector.prototype.getFormat = function() {
  56536. return this.format_;
  56537. };
  56538. /**
  56539. * @return {boolean} The source can have overlapping geometries.
  56540. */
  56541. ol.source.Vector.prototype.getOverlaps = function() {
  56542. return this.overlaps_;
  56543. };
  56544. /**
  56545. * @override
  56546. */
  56547. ol.source.Vector.prototype.getResolutions = function() {};
  56548. /**
  56549. * Get the url associated with this source.
  56550. *
  56551. * @return {string|ol.FeatureUrlFunction|undefined} The url.
  56552. * @api
  56553. */
  56554. ol.source.Vector.prototype.getUrl = function() {
  56555. return this.url_;
  56556. };
  56557. /**
  56558. * @param {ol.events.Event} event Event.
  56559. * @private
  56560. */
  56561. ol.source.Vector.prototype.handleFeatureChange_ = function(event) {
  56562. var feature = /** @type {ol.Feature} */ (event.target);
  56563. var featureKey = ol.getUid(feature).toString();
  56564. var geometry = feature.getGeometry();
  56565. if (!geometry) {
  56566. if (!(featureKey in this.nullGeometryFeatures_)) {
  56567. if (this.featuresRtree_) {
  56568. this.featuresRtree_.remove(feature);
  56569. }
  56570. this.nullGeometryFeatures_[featureKey] = feature;
  56571. }
  56572. } else {
  56573. var extent = geometry.getExtent();
  56574. if (featureKey in this.nullGeometryFeatures_) {
  56575. delete this.nullGeometryFeatures_[featureKey];
  56576. if (this.featuresRtree_) {
  56577. this.featuresRtree_.insert(extent, feature);
  56578. }
  56579. } else {
  56580. if (this.featuresRtree_) {
  56581. this.featuresRtree_.update(extent, feature);
  56582. }
  56583. }
  56584. }
  56585. var id = feature.getId();
  56586. if (id !== undefined) {
  56587. var sid = id.toString();
  56588. if (featureKey in this.undefIdIndex_) {
  56589. delete this.undefIdIndex_[featureKey];
  56590. this.idIndex_[sid] = feature;
  56591. } else {
  56592. if (this.idIndex_[sid] !== feature) {
  56593. this.removeFromIdIndex_(feature);
  56594. this.idIndex_[sid] = feature;
  56595. }
  56596. }
  56597. } else {
  56598. if (!(featureKey in this.undefIdIndex_)) {
  56599. this.removeFromIdIndex_(feature);
  56600. this.undefIdIndex_[featureKey] = feature;
  56601. }
  56602. }
  56603. this.changed();
  56604. this.dispatchEvent(new ol.source.Vector.Event(
  56605. ol.source.VectorEventType.CHANGEFEATURE, feature));
  56606. };
  56607. /**
  56608. * @return {boolean} Is empty.
  56609. */
  56610. ol.source.Vector.prototype.isEmpty = function() {
  56611. return this.featuresRtree_.isEmpty() &&
  56612. ol.obj.isEmpty(this.nullGeometryFeatures_);
  56613. };
  56614. /**
  56615. * @param {ol.Extent} extent Extent.
  56616. * @param {number} resolution Resolution.
  56617. * @param {ol.proj.Projection} projection Projection.
  56618. */
  56619. ol.source.Vector.prototype.loadFeatures = function(
  56620. extent, resolution, projection) {
  56621. var loadedExtentsRtree = this.loadedExtentsRtree_;
  56622. var extentsToLoad = this.strategy_(extent, resolution);
  56623. var i, ii;
  56624. for (i = 0, ii = extentsToLoad.length; i < ii; ++i) {
  56625. var extentToLoad = extentsToLoad[i];
  56626. var alreadyLoaded = loadedExtentsRtree.forEachInExtent(extentToLoad,
  56627. /**
  56628. * @param {{extent: ol.Extent}} object Object.
  56629. * @return {boolean} Contains.
  56630. */
  56631. function(object) {
  56632. return ol.extent.containsExtent(object.extent, extentToLoad);
  56633. });
  56634. if (!alreadyLoaded) {
  56635. this.loader_.call(this, extentToLoad, resolution, projection);
  56636. loadedExtentsRtree.insert(extentToLoad, {extent: extentToLoad.slice()});
  56637. }
  56638. }
  56639. };
  56640. /**
  56641. * Remove a single feature from the source. If you want to remove all features
  56642. * at once, use the {@link ol.source.Vector#clear source.clear()} method
  56643. * instead.
  56644. * @param {ol.Feature} feature Feature to remove.
  56645. * @api
  56646. */
  56647. ol.source.Vector.prototype.removeFeature = function(feature) {
  56648. var featureKey = ol.getUid(feature).toString();
  56649. if (featureKey in this.nullGeometryFeatures_) {
  56650. delete this.nullGeometryFeatures_[featureKey];
  56651. } else {
  56652. if (this.featuresRtree_) {
  56653. this.featuresRtree_.remove(feature);
  56654. }
  56655. }
  56656. this.removeFeatureInternal(feature);
  56657. this.changed();
  56658. };
  56659. /**
  56660. * Remove feature without firing a `change` event.
  56661. * @param {ol.Feature} feature Feature.
  56662. * @protected
  56663. */
  56664. ol.source.Vector.prototype.removeFeatureInternal = function(feature) {
  56665. var featureKey = ol.getUid(feature).toString();
  56666. this.featureChangeKeys_[featureKey].forEach(ol.events.unlistenByKey);
  56667. delete this.featureChangeKeys_[featureKey];
  56668. var id = feature.getId();
  56669. if (id !== undefined) {
  56670. delete this.idIndex_[id.toString()];
  56671. } else {
  56672. delete this.undefIdIndex_[featureKey];
  56673. }
  56674. this.dispatchEvent(new ol.source.Vector.Event(
  56675. ol.source.VectorEventType.REMOVEFEATURE, feature));
  56676. };
  56677. /**
  56678. * Remove a feature from the id index. Called internally when the feature id
  56679. * may have changed.
  56680. * @param {ol.Feature} feature The feature.
  56681. * @return {boolean} Removed the feature from the index.
  56682. * @private
  56683. */
  56684. ol.source.Vector.prototype.removeFromIdIndex_ = function(feature) {
  56685. var removed = false;
  56686. for (var id in this.idIndex_) {
  56687. if (this.idIndex_[id] === feature) {
  56688. delete this.idIndex_[id];
  56689. removed = true;
  56690. break;
  56691. }
  56692. }
  56693. return removed;
  56694. };
  56695. /**
  56696. * @classdesc
  56697. * Events emitted by {@link ol.source.Vector} instances are instances of this
  56698. * type.
  56699. *
  56700. * @constructor
  56701. * @extends {ol.events.Event}
  56702. * @implements {oli.source.Vector.Event}
  56703. * @param {string} type Type.
  56704. * @param {ol.Feature=} opt_feature Feature.
  56705. */
  56706. ol.source.Vector.Event = function(type, opt_feature) {
  56707. ol.events.Event.call(this, type);
  56708. /**
  56709. * The feature being added or removed.
  56710. * @type {ol.Feature|undefined}
  56711. * @api
  56712. */
  56713. this.feature = opt_feature;
  56714. };
  56715. ol.inherits(ol.source.Vector.Event, ol.events.Event);
  56716. goog.provide('ol.interaction.Draw');
  56717. goog.require('ol');
  56718. goog.require('ol.Feature');
  56719. goog.require('ol.MapBrowserEventType');
  56720. goog.require('ol.Object');
  56721. goog.require('ol.coordinate');
  56722. goog.require('ol.events');
  56723. goog.require('ol.events.Event');
  56724. goog.require('ol.events.condition');
  56725. goog.require('ol.extent');
  56726. goog.require('ol.functions');
  56727. goog.require('ol.geom.Circle');
  56728. goog.require('ol.geom.GeometryType');
  56729. goog.require('ol.geom.LineString');
  56730. goog.require('ol.geom.MultiLineString');
  56731. goog.require('ol.geom.MultiPoint');
  56732. goog.require('ol.geom.MultiPolygon');
  56733. goog.require('ol.geom.Point');
  56734. goog.require('ol.geom.Polygon');
  56735. goog.require('ol.interaction.DrawEventType');
  56736. goog.require('ol.interaction.Pointer');
  56737. goog.require('ol.interaction.Property');
  56738. goog.require('ol.layer.Vector');
  56739. goog.require('ol.source.Vector');
  56740. goog.require('ol.style.Style');
  56741. /**
  56742. * @classdesc
  56743. * Interaction for drawing feature geometries.
  56744. *
  56745. * @constructor
  56746. * @extends {ol.interaction.Pointer}
  56747. * @fires ol.interaction.Draw.Event
  56748. * @param {olx.interaction.DrawOptions} options Options.
  56749. * @api
  56750. */
  56751. ol.interaction.Draw = function(options) {
  56752. ol.interaction.Pointer.call(this, {
  56753. handleDownEvent: ol.interaction.Draw.handleDownEvent_,
  56754. handleEvent: ol.interaction.Draw.handleEvent,
  56755. handleUpEvent: ol.interaction.Draw.handleUpEvent_
  56756. });
  56757. /**
  56758. * @type {boolean}
  56759. * @private
  56760. */
  56761. this.shouldHandle_ = false;
  56762. /**
  56763. * @type {ol.Pixel}
  56764. * @private
  56765. */
  56766. this.downPx_ = null;
  56767. /**
  56768. * @type {boolean}
  56769. * @private
  56770. */
  56771. this.freehand_ = false;
  56772. /**
  56773. * Target source for drawn features.
  56774. * @type {ol.source.Vector}
  56775. * @private
  56776. */
  56777. this.source_ = options.source ? options.source : null;
  56778. /**
  56779. * Target collection for drawn features.
  56780. * @type {ol.Collection.<ol.Feature>}
  56781. * @private
  56782. */
  56783. this.features_ = options.features ? options.features : null;
  56784. /**
  56785. * Pixel distance for snapping.
  56786. * @type {number}
  56787. * @private
  56788. */
  56789. this.snapTolerance_ = options.snapTolerance ? options.snapTolerance : 12;
  56790. /**
  56791. * Geometry type.
  56792. * @type {ol.geom.GeometryType}
  56793. * @private
  56794. */
  56795. this.type_ = options.type;
  56796. /**
  56797. * Drawing mode (derived from geometry type.
  56798. * @type {ol.interaction.Draw.Mode_}
  56799. * @private
  56800. */
  56801. this.mode_ = ol.interaction.Draw.getMode_(this.type_);
  56802. /**
  56803. * The number of points that must be drawn before a polygon ring or line
  56804. * string can be finished. The default is 3 for polygon rings and 2 for
  56805. * line strings.
  56806. * @type {number}
  56807. * @private
  56808. */
  56809. this.minPoints_ = options.minPoints ?
  56810. options.minPoints :
  56811. (this.mode_ === ol.interaction.Draw.Mode_.POLYGON ? 3 : 2);
  56812. /**
  56813. * The number of points that can be drawn before a polygon ring or line string
  56814. * is finished. The default is no restriction.
  56815. * @type {number}
  56816. * @private
  56817. */
  56818. this.maxPoints_ = options.maxPoints ? options.maxPoints : Infinity;
  56819. /**
  56820. * A function to decide if a potential finish coordinate is permissible
  56821. * @private
  56822. * @type {ol.EventsConditionType}
  56823. */
  56824. this.finishCondition_ = options.finishCondition ? options.finishCondition : ol.functions.TRUE;
  56825. var geometryFunction = options.geometryFunction;
  56826. if (!geometryFunction) {
  56827. if (this.type_ === ol.geom.GeometryType.CIRCLE) {
  56828. /**
  56829. * @param {!Array.<ol.Coordinate>} coordinates
  56830. * The coordinates.
  56831. * @param {ol.geom.SimpleGeometry=} opt_geometry Optional geometry.
  56832. * @return {ol.geom.SimpleGeometry} A geometry.
  56833. */
  56834. geometryFunction = function(coordinates, opt_geometry) {
  56835. var circle = opt_geometry ? /** @type {ol.geom.Circle} */ (opt_geometry) :
  56836. new ol.geom.Circle([NaN, NaN]);
  56837. var squaredLength = ol.coordinate.squaredDistance(
  56838. coordinates[0], coordinates[1]);
  56839. circle.setCenterAndRadius(coordinates[0], Math.sqrt(squaredLength));
  56840. return circle;
  56841. };
  56842. } else {
  56843. var Constructor;
  56844. var mode = this.mode_;
  56845. if (mode === ol.interaction.Draw.Mode_.POINT) {
  56846. Constructor = ol.geom.Point;
  56847. } else if (mode === ol.interaction.Draw.Mode_.LINE_STRING) {
  56848. Constructor = ol.geom.LineString;
  56849. } else if (mode === ol.interaction.Draw.Mode_.POLYGON) {
  56850. Constructor = ol.geom.Polygon;
  56851. }
  56852. /**
  56853. * @param {!Array.<ol.Coordinate>} coordinates
  56854. * The coordinates.
  56855. * @param {ol.geom.SimpleGeometry=} opt_geometry Optional geometry.
  56856. * @return {ol.geom.SimpleGeometry} A geometry.
  56857. */
  56858. geometryFunction = function(coordinates, opt_geometry) {
  56859. var geometry = opt_geometry;
  56860. if (geometry) {
  56861. if (mode === ol.interaction.Draw.Mode_.POLYGON) {
  56862. geometry.setCoordinates([coordinates[0].concat([coordinates[0][0]])]);
  56863. } else {
  56864. geometry.setCoordinates(coordinates);
  56865. }
  56866. } else {
  56867. geometry = new Constructor(coordinates);
  56868. }
  56869. return geometry;
  56870. };
  56871. }
  56872. }
  56873. /**
  56874. * @type {ol.DrawGeometryFunctionType}
  56875. * @private
  56876. */
  56877. this.geometryFunction_ = geometryFunction;
  56878. /**
  56879. * Finish coordinate for the feature (first point for polygons, last point for
  56880. * linestrings).
  56881. * @type {ol.Coordinate}
  56882. * @private
  56883. */
  56884. this.finishCoordinate_ = null;
  56885. /**
  56886. * Sketch feature.
  56887. * @type {ol.Feature}
  56888. * @private
  56889. */
  56890. this.sketchFeature_ = null;
  56891. /**
  56892. * Sketch point.
  56893. * @type {ol.Feature}
  56894. * @private
  56895. */
  56896. this.sketchPoint_ = null;
  56897. /**
  56898. * Sketch coordinates. Used when drawing a line or polygon.
  56899. * @type {ol.Coordinate|Array.<ol.Coordinate>|Array.<Array.<ol.Coordinate>>}
  56900. * @private
  56901. */
  56902. this.sketchCoords_ = null;
  56903. /**
  56904. * Sketch line. Used when drawing polygon.
  56905. * @type {ol.Feature}
  56906. * @private
  56907. */
  56908. this.sketchLine_ = null;
  56909. /**
  56910. * Sketch line coordinates. Used when drawing a polygon or circle.
  56911. * @type {Array.<ol.Coordinate>}
  56912. * @private
  56913. */
  56914. this.sketchLineCoords_ = null;
  56915. /**
  56916. * Squared tolerance for handling up events. If the squared distance
  56917. * between a down and up event is greater than this tolerance, up events
  56918. * will not be handled.
  56919. * @type {number}
  56920. * @private
  56921. */
  56922. this.squaredClickTolerance_ = options.clickTolerance ?
  56923. options.clickTolerance * options.clickTolerance : 36;
  56924. /**
  56925. * Draw overlay where our sketch features are drawn.
  56926. * @type {ol.layer.Vector}
  56927. * @private
  56928. */
  56929. this.overlay_ = new ol.layer.Vector({
  56930. source: new ol.source.Vector({
  56931. useSpatialIndex: false,
  56932. wrapX: options.wrapX ? options.wrapX : false
  56933. }),
  56934. style: options.style ? options.style :
  56935. ol.interaction.Draw.getDefaultStyleFunction()
  56936. });
  56937. /**
  56938. * Name of the geometry attribute for newly created features.
  56939. * @type {string|undefined}
  56940. * @private
  56941. */
  56942. this.geometryName_ = options.geometryName;
  56943. /**
  56944. * @private
  56945. * @type {ol.EventsConditionType}
  56946. */
  56947. this.condition_ = options.condition ?
  56948. options.condition : ol.events.condition.noModifierKeys;
  56949. /**
  56950. * @private
  56951. * @type {ol.EventsConditionType}
  56952. */
  56953. this.freehandCondition_;
  56954. if (options.freehand) {
  56955. this.freehandCondition_ = ol.events.condition.always;
  56956. } else {
  56957. this.freehandCondition_ = options.freehandCondition ?
  56958. options.freehandCondition : ol.events.condition.shiftKeyOnly;
  56959. }
  56960. ol.events.listen(this,
  56961. ol.Object.getChangeEventType(ol.interaction.Property.ACTIVE),
  56962. this.updateState_, this);
  56963. };
  56964. ol.inherits(ol.interaction.Draw, ol.interaction.Pointer);
  56965. /**
  56966. * @return {ol.StyleFunction} Styles.
  56967. */
  56968. ol.interaction.Draw.getDefaultStyleFunction = function() {
  56969. var styles = ol.style.Style.createDefaultEditing();
  56970. return function(feature, resolution) {
  56971. return styles[feature.getGeometry().getType()];
  56972. };
  56973. };
  56974. /**
  56975. * @inheritDoc
  56976. */
  56977. ol.interaction.Draw.prototype.setMap = function(map) {
  56978. ol.interaction.Pointer.prototype.setMap.call(this, map);
  56979. this.updateState_();
  56980. };
  56981. /**
  56982. * Handles the {@link ol.MapBrowserEvent map browser event} and may actually
  56983. * draw or finish the drawing.
  56984. * @param {ol.MapBrowserEvent} event Map browser event.
  56985. * @return {boolean} `false` to stop event propagation.
  56986. * @this {ol.interaction.Draw}
  56987. * @api
  56988. */
  56989. ol.interaction.Draw.handleEvent = function(event) {
  56990. this.freehand_ = this.mode_ !== ol.interaction.Draw.Mode_.POINT && this.freehandCondition_(event);
  56991. var pass = !this.freehand_;
  56992. if (this.freehand_ &&
  56993. event.type === ol.MapBrowserEventType.POINTERDRAG && this.sketchFeature_ !== null) {
  56994. this.addToDrawing_(event);
  56995. pass = false;
  56996. } else if (event.type ===
  56997. ol.MapBrowserEventType.POINTERMOVE) {
  56998. pass = this.handlePointerMove_(event);
  56999. } else if (event.type === ol.MapBrowserEventType.DBLCLICK) {
  57000. pass = false;
  57001. }
  57002. return ol.interaction.Pointer.handleEvent.call(this, event) && pass;
  57003. };
  57004. /**
  57005. * @param {ol.MapBrowserPointerEvent} event Event.
  57006. * @return {boolean} Start drag sequence?
  57007. * @this {ol.interaction.Draw}
  57008. * @private
  57009. */
  57010. ol.interaction.Draw.handleDownEvent_ = function(event) {
  57011. this.shouldHandle_ = !this.freehand_;
  57012. if (this.freehand_) {
  57013. this.downPx_ = event.pixel;
  57014. if (!this.finishCoordinate_) {
  57015. this.startDrawing_(event);
  57016. }
  57017. return true;
  57018. } else if (this.condition_(event)) {
  57019. this.downPx_ = event.pixel;
  57020. return true;
  57021. } else {
  57022. return false;
  57023. }
  57024. };
  57025. /**
  57026. * @param {ol.MapBrowserPointerEvent} event Event.
  57027. * @return {boolean} Stop drag sequence?
  57028. * @this {ol.interaction.Draw}
  57029. * @private
  57030. */
  57031. ol.interaction.Draw.handleUpEvent_ = function(event) {
  57032. var pass = true;
  57033. this.handlePointerMove_(event);
  57034. var circleMode = this.mode_ === ol.interaction.Draw.Mode_.CIRCLE;
  57035. if (this.shouldHandle_) {
  57036. if (!this.finishCoordinate_) {
  57037. this.startDrawing_(event);
  57038. if (this.mode_ === ol.interaction.Draw.Mode_.POINT) {
  57039. this.finishDrawing();
  57040. }
  57041. } else if (this.freehand_ || circleMode) {
  57042. this.finishDrawing();
  57043. } else if (this.atFinish_(event)) {
  57044. if (this.finishCondition_(event)) {
  57045. this.finishDrawing();
  57046. }
  57047. } else {
  57048. this.addToDrawing_(event);
  57049. }
  57050. pass = false;
  57051. } else if (this.freehand_) {
  57052. this.finishCoordinate_ = null;
  57053. this.abortDrawing_();
  57054. }
  57055. return pass;
  57056. };
  57057. /**
  57058. * Handle move events.
  57059. * @param {ol.MapBrowserEvent} event A move event.
  57060. * @return {boolean} Pass the event to other interactions.
  57061. * @private
  57062. */
  57063. ol.interaction.Draw.prototype.handlePointerMove_ = function(event) {
  57064. if (this.downPx_ &&
  57065. ((!this.freehand_ && this.shouldHandle_) ||
  57066. (this.freehand_ && !this.shouldHandle_))) {
  57067. var downPx = this.downPx_;
  57068. var clickPx = event.pixel;
  57069. var dx = downPx[0] - clickPx[0];
  57070. var dy = downPx[1] - clickPx[1];
  57071. var squaredDistance = dx * dx + dy * dy;
  57072. this.shouldHandle_ = this.freehand_ ?
  57073. squaredDistance > this.squaredClickTolerance_ :
  57074. squaredDistance <= this.squaredClickTolerance_;
  57075. }
  57076. if (this.finishCoordinate_) {
  57077. this.modifyDrawing_(event);
  57078. } else {
  57079. this.createOrUpdateSketchPoint_(event);
  57080. }
  57081. return true;
  57082. };
  57083. /**
  57084. * Determine if an event is within the snapping tolerance of the start coord.
  57085. * @param {ol.MapBrowserEvent} event Event.
  57086. * @return {boolean} The event is within the snapping tolerance of the start.
  57087. * @private
  57088. */
  57089. ol.interaction.Draw.prototype.atFinish_ = function(event) {
  57090. var at = false;
  57091. if (this.sketchFeature_) {
  57092. var potentiallyDone = false;
  57093. var potentiallyFinishCoordinates = [this.finishCoordinate_];
  57094. if (this.mode_ === ol.interaction.Draw.Mode_.LINE_STRING) {
  57095. potentiallyDone = this.sketchCoords_.length > this.minPoints_;
  57096. } else if (this.mode_ === ol.interaction.Draw.Mode_.POLYGON) {
  57097. potentiallyDone = this.sketchCoords_[0].length >
  57098. this.minPoints_;
  57099. potentiallyFinishCoordinates = [this.sketchCoords_[0][0],
  57100. this.sketchCoords_[0][this.sketchCoords_[0].length - 2]];
  57101. }
  57102. if (potentiallyDone) {
  57103. var map = event.map;
  57104. for (var i = 0, ii = potentiallyFinishCoordinates.length; i < ii; i++) {
  57105. var finishCoordinate = potentiallyFinishCoordinates[i];
  57106. var finishPixel = map.getPixelFromCoordinate(finishCoordinate);
  57107. var pixel = event.pixel;
  57108. var dx = pixel[0] - finishPixel[0];
  57109. var dy = pixel[1] - finishPixel[1];
  57110. var snapTolerance = this.freehand_ ? 1 : this.snapTolerance_;
  57111. at = Math.sqrt(dx * dx + dy * dy) <= snapTolerance;
  57112. if (at) {
  57113. this.finishCoordinate_ = finishCoordinate;
  57114. break;
  57115. }
  57116. }
  57117. }
  57118. }
  57119. return at;
  57120. };
  57121. /**
  57122. * @param {ol.MapBrowserEvent} event Event.
  57123. * @private
  57124. */
  57125. ol.interaction.Draw.prototype.createOrUpdateSketchPoint_ = function(event) {
  57126. var coordinates = event.coordinate.slice();
  57127. if (!this.sketchPoint_) {
  57128. this.sketchPoint_ = new ol.Feature(new ol.geom.Point(coordinates));
  57129. this.updateSketchFeatures_();
  57130. } else {
  57131. var sketchPointGeom = /** @type {ol.geom.Point} */ (this.sketchPoint_.getGeometry());
  57132. sketchPointGeom.setCoordinates(coordinates);
  57133. }
  57134. };
  57135. /**
  57136. * Start the drawing.
  57137. * @param {ol.MapBrowserEvent} event Event.
  57138. * @private
  57139. */
  57140. ol.interaction.Draw.prototype.startDrawing_ = function(event) {
  57141. var start = event.coordinate;
  57142. this.finishCoordinate_ = start;
  57143. if (this.mode_ === ol.interaction.Draw.Mode_.POINT) {
  57144. this.sketchCoords_ = start.slice();
  57145. } else if (this.mode_ === ol.interaction.Draw.Mode_.POLYGON) {
  57146. this.sketchCoords_ = [[start.slice(), start.slice()]];
  57147. this.sketchLineCoords_ = this.sketchCoords_[0];
  57148. } else {
  57149. this.sketchCoords_ = [start.slice(), start.slice()];
  57150. if (this.mode_ === ol.interaction.Draw.Mode_.CIRCLE) {
  57151. this.sketchLineCoords_ = this.sketchCoords_;
  57152. }
  57153. }
  57154. if (this.sketchLineCoords_) {
  57155. this.sketchLine_ = new ol.Feature(
  57156. new ol.geom.LineString(this.sketchLineCoords_));
  57157. }
  57158. var geometry = this.geometryFunction_(this.sketchCoords_);
  57159. this.sketchFeature_ = new ol.Feature();
  57160. if (this.geometryName_) {
  57161. this.sketchFeature_.setGeometryName(this.geometryName_);
  57162. }
  57163. this.sketchFeature_.setGeometry(geometry);
  57164. this.updateSketchFeatures_();
  57165. this.dispatchEvent(new ol.interaction.Draw.Event(
  57166. ol.interaction.DrawEventType.DRAWSTART, this.sketchFeature_));
  57167. };
  57168. /**
  57169. * Modify the drawing.
  57170. * @param {ol.MapBrowserEvent} event Event.
  57171. * @private
  57172. */
  57173. ol.interaction.Draw.prototype.modifyDrawing_ = function(event) {
  57174. var coordinate = event.coordinate;
  57175. var geometry = /** @type {ol.geom.SimpleGeometry} */ (this.sketchFeature_.getGeometry());
  57176. var coordinates, last;
  57177. if (this.mode_ === ol.interaction.Draw.Mode_.POINT) {
  57178. last = this.sketchCoords_;
  57179. } else if (this.mode_ === ol.interaction.Draw.Mode_.POLYGON) {
  57180. coordinates = this.sketchCoords_[0];
  57181. last = coordinates[coordinates.length - 1];
  57182. if (this.atFinish_(event)) {
  57183. // snap to finish
  57184. coordinate = this.finishCoordinate_.slice();
  57185. }
  57186. } else {
  57187. coordinates = this.sketchCoords_;
  57188. last = coordinates[coordinates.length - 1];
  57189. }
  57190. last[0] = coordinate[0];
  57191. last[1] = coordinate[1];
  57192. this.geometryFunction_(/** @type {!Array.<ol.Coordinate>} */ (this.sketchCoords_), geometry);
  57193. if (this.sketchPoint_) {
  57194. var sketchPointGeom = /** @type {ol.geom.Point} */ (this.sketchPoint_.getGeometry());
  57195. sketchPointGeom.setCoordinates(coordinate);
  57196. }
  57197. var sketchLineGeom;
  57198. if (geometry instanceof ol.geom.Polygon &&
  57199. this.mode_ !== ol.interaction.Draw.Mode_.POLYGON) {
  57200. if (!this.sketchLine_) {
  57201. this.sketchLine_ = new ol.Feature(new ol.geom.LineString(null));
  57202. }
  57203. var ring = geometry.getLinearRing(0);
  57204. sketchLineGeom = /** @type {ol.geom.LineString} */ (this.sketchLine_.getGeometry());
  57205. sketchLineGeom.setFlatCoordinates(
  57206. ring.getLayout(), ring.getFlatCoordinates());
  57207. } else if (this.sketchLineCoords_) {
  57208. sketchLineGeom = /** @type {ol.geom.LineString} */ (this.sketchLine_.getGeometry());
  57209. sketchLineGeom.setCoordinates(this.sketchLineCoords_);
  57210. }
  57211. this.updateSketchFeatures_();
  57212. };
  57213. /**
  57214. * Add a new coordinate to the drawing.
  57215. * @param {ol.MapBrowserEvent} event Event.
  57216. * @private
  57217. */
  57218. ol.interaction.Draw.prototype.addToDrawing_ = function(event) {
  57219. var coordinate = event.coordinate;
  57220. var geometry = /** @type {ol.geom.SimpleGeometry} */ (this.sketchFeature_.getGeometry());
  57221. var done;
  57222. var coordinates;
  57223. if (this.mode_ === ol.interaction.Draw.Mode_.LINE_STRING) {
  57224. this.finishCoordinate_ = coordinate.slice();
  57225. coordinates = this.sketchCoords_;
  57226. if (coordinates.length >= this.maxPoints_) {
  57227. if (this.freehand_) {
  57228. coordinates.pop();
  57229. } else {
  57230. done = true;
  57231. }
  57232. }
  57233. coordinates.push(coordinate.slice());
  57234. this.geometryFunction_(coordinates, geometry);
  57235. } else if (this.mode_ === ol.interaction.Draw.Mode_.POLYGON) {
  57236. coordinates = this.sketchCoords_[0];
  57237. if (coordinates.length >= this.maxPoints_) {
  57238. if (this.freehand_) {
  57239. coordinates.pop();
  57240. } else {
  57241. done = true;
  57242. }
  57243. }
  57244. coordinates.push(coordinate.slice());
  57245. if (done) {
  57246. this.finishCoordinate_ = coordinates[0];
  57247. }
  57248. this.geometryFunction_(this.sketchCoords_, geometry);
  57249. }
  57250. this.updateSketchFeatures_();
  57251. if (done) {
  57252. this.finishDrawing();
  57253. }
  57254. };
  57255. /**
  57256. * Remove last point of the feature currently being drawn.
  57257. * @api
  57258. */
  57259. ol.interaction.Draw.prototype.removeLastPoint = function() {
  57260. if (!this.sketchFeature_) {
  57261. return;
  57262. }
  57263. var geometry = /** @type {ol.geom.SimpleGeometry} */ (this.sketchFeature_.getGeometry());
  57264. var coordinates, sketchLineGeom;
  57265. if (this.mode_ === ol.interaction.Draw.Mode_.LINE_STRING) {
  57266. coordinates = this.sketchCoords_;
  57267. coordinates.splice(-2, 1);
  57268. this.geometryFunction_(coordinates, geometry);
  57269. if (coordinates.length >= 2) {
  57270. this.finishCoordinate_ = coordinates[coordinates.length - 2].slice();
  57271. }
  57272. } else if (this.mode_ === ol.interaction.Draw.Mode_.POLYGON) {
  57273. coordinates = this.sketchCoords_[0];
  57274. coordinates.splice(-2, 1);
  57275. sketchLineGeom = /** @type {ol.geom.LineString} */ (this.sketchLine_.getGeometry());
  57276. sketchLineGeom.setCoordinates(coordinates);
  57277. this.geometryFunction_(this.sketchCoords_, geometry);
  57278. }
  57279. if (coordinates.length === 0) {
  57280. this.finishCoordinate_ = null;
  57281. }
  57282. this.updateSketchFeatures_();
  57283. };
  57284. /**
  57285. * Stop drawing and add the sketch feature to the target layer.
  57286. * The {@link ol.interaction.DrawEventType.DRAWEND} event is dispatched before
  57287. * inserting the feature.
  57288. * @api
  57289. */
  57290. ol.interaction.Draw.prototype.finishDrawing = function() {
  57291. var sketchFeature = this.abortDrawing_();
  57292. var coordinates = this.sketchCoords_;
  57293. var geometry = /** @type {ol.geom.SimpleGeometry} */ (sketchFeature.getGeometry());
  57294. if (this.mode_ === ol.interaction.Draw.Mode_.LINE_STRING) {
  57295. // remove the redundant last point
  57296. coordinates.pop();
  57297. this.geometryFunction_(coordinates, geometry);
  57298. } else if (this.mode_ === ol.interaction.Draw.Mode_.POLYGON) {
  57299. // remove the redundant last point in ring
  57300. coordinates[0].pop();
  57301. this.geometryFunction_(coordinates, geometry);
  57302. coordinates = geometry.getCoordinates();
  57303. }
  57304. // cast multi-part geometries
  57305. if (this.type_ === ol.geom.GeometryType.MULTI_POINT) {
  57306. sketchFeature.setGeometry(new ol.geom.MultiPoint([coordinates]));
  57307. } else if (this.type_ === ol.geom.GeometryType.MULTI_LINE_STRING) {
  57308. sketchFeature.setGeometry(new ol.geom.MultiLineString([coordinates]));
  57309. } else if (this.type_ === ol.geom.GeometryType.MULTI_POLYGON) {
  57310. sketchFeature.setGeometry(new ol.geom.MultiPolygon([coordinates]));
  57311. }
  57312. // First dispatch event to allow full set up of feature
  57313. this.dispatchEvent(new ol.interaction.Draw.Event(
  57314. ol.interaction.DrawEventType.DRAWEND, sketchFeature));
  57315. // Then insert feature
  57316. if (this.features_) {
  57317. this.features_.push(sketchFeature);
  57318. }
  57319. if (this.source_) {
  57320. this.source_.addFeature(sketchFeature);
  57321. }
  57322. };
  57323. /**
  57324. * Stop drawing without adding the sketch feature to the target layer.
  57325. * @return {ol.Feature} The sketch feature (or null if none).
  57326. * @private
  57327. */
  57328. ol.interaction.Draw.prototype.abortDrawing_ = function() {
  57329. this.finishCoordinate_ = null;
  57330. var sketchFeature = this.sketchFeature_;
  57331. if (sketchFeature) {
  57332. this.sketchFeature_ = null;
  57333. this.sketchPoint_ = null;
  57334. this.sketchLine_ = null;
  57335. this.overlay_.getSource().clear(true);
  57336. }
  57337. return sketchFeature;
  57338. };
  57339. /**
  57340. * Extend an existing geometry by adding additional points. This only works
  57341. * on features with `LineString` geometries, where the interaction will
  57342. * extend lines by adding points to the end of the coordinates array.
  57343. * @param {!ol.Feature} feature Feature to be extended.
  57344. * @api
  57345. */
  57346. ol.interaction.Draw.prototype.extend = function(feature) {
  57347. var geometry = feature.getGeometry();
  57348. var lineString = /** @type {ol.geom.LineString} */ (geometry);
  57349. this.sketchFeature_ = feature;
  57350. this.sketchCoords_ = lineString.getCoordinates();
  57351. var last = this.sketchCoords_[this.sketchCoords_.length - 1];
  57352. this.finishCoordinate_ = last.slice();
  57353. this.sketchCoords_.push(last.slice());
  57354. this.updateSketchFeatures_();
  57355. this.dispatchEvent(new ol.interaction.Draw.Event(
  57356. ol.interaction.DrawEventType.DRAWSTART, this.sketchFeature_));
  57357. };
  57358. /**
  57359. * @inheritDoc
  57360. */
  57361. ol.interaction.Draw.prototype.shouldStopEvent = ol.functions.FALSE;
  57362. /**
  57363. * Redraw the sketch features.
  57364. * @private
  57365. */
  57366. ol.interaction.Draw.prototype.updateSketchFeatures_ = function() {
  57367. var sketchFeatures = [];
  57368. if (this.sketchFeature_) {
  57369. sketchFeatures.push(this.sketchFeature_);
  57370. }
  57371. if (this.sketchLine_) {
  57372. sketchFeatures.push(this.sketchLine_);
  57373. }
  57374. if (this.sketchPoint_) {
  57375. sketchFeatures.push(this.sketchPoint_);
  57376. }
  57377. var overlaySource = this.overlay_.getSource();
  57378. overlaySource.clear(true);
  57379. overlaySource.addFeatures(sketchFeatures);
  57380. };
  57381. /**
  57382. * @private
  57383. */
  57384. ol.interaction.Draw.prototype.updateState_ = function() {
  57385. var map = this.getMap();
  57386. var active = this.getActive();
  57387. if (!map || !active) {
  57388. this.abortDrawing_();
  57389. }
  57390. this.overlay_.setMap(active ? map : null);
  57391. };
  57392. /**
  57393. * Create a `geometryFunction` for `type: 'Circle'` that will create a regular
  57394. * polygon with a user specified number of sides and start angle instead of an
  57395. * `ol.geom.Circle` geometry.
  57396. * @param {number=} opt_sides Number of sides of the regular polygon. Default is
  57397. * 32.
  57398. * @param {number=} opt_angle Angle of the first point in radians. 0 means East.
  57399. * Default is the angle defined by the heading from the center of the
  57400. * regular polygon to the current pointer position.
  57401. * @return {ol.DrawGeometryFunctionType} Function that draws a
  57402. * polygon.
  57403. * @api
  57404. */
  57405. ol.interaction.Draw.createRegularPolygon = function(opt_sides, opt_angle) {
  57406. return (
  57407. /**
  57408. * @param {ol.Coordinate|Array.<ol.Coordinate>|Array.<Array.<ol.Coordinate>>} coordinates
  57409. * @param {ol.geom.SimpleGeometry=} opt_geometry
  57410. * @return {ol.geom.SimpleGeometry}
  57411. */
  57412. function(coordinates, opt_geometry) {
  57413. var center = coordinates[0];
  57414. var end = coordinates[1];
  57415. var radius = Math.sqrt(
  57416. ol.coordinate.squaredDistance(center, end));
  57417. var geometry = opt_geometry ? /** @type {ol.geom.Polygon} */ (opt_geometry) :
  57418. ol.geom.Polygon.fromCircle(new ol.geom.Circle(center), opt_sides);
  57419. var angle = opt_angle ? opt_angle :
  57420. Math.atan((end[1] - center[1]) / (end[0] - center[0]));
  57421. ol.geom.Polygon.makeRegular(geometry, center, radius, angle);
  57422. return geometry;
  57423. }
  57424. );
  57425. };
  57426. /**
  57427. * Create a `geometryFunction` that will create a box-shaped polygon (aligned
  57428. * with the coordinate system axes). Use this with the draw interaction and
  57429. * `type: 'Circle'` to return a box instead of a circle geometry.
  57430. * @return {ol.DrawGeometryFunctionType} Function that draws a box-shaped polygon.
  57431. * @api
  57432. */
  57433. ol.interaction.Draw.createBox = function() {
  57434. return (
  57435. /**
  57436. * @param {Array.<ol.Coordinate>} coordinates
  57437. * @param {ol.geom.SimpleGeometry=} opt_geometry
  57438. * @return {ol.geom.SimpleGeometry}
  57439. */
  57440. function(coordinates, opt_geometry) {
  57441. var extent = ol.extent.boundingExtent(coordinates);
  57442. var geometry = opt_geometry || new ol.geom.Polygon(null);
  57443. geometry.setCoordinates([[
  57444. ol.extent.getBottomLeft(extent),
  57445. ol.extent.getBottomRight(extent),
  57446. ol.extent.getTopRight(extent),
  57447. ol.extent.getTopLeft(extent),
  57448. ol.extent.getBottomLeft(extent)
  57449. ]]);
  57450. return geometry;
  57451. }
  57452. );
  57453. };
  57454. /**
  57455. * Get the drawing mode. The mode for mult-part geometries is the same as for
  57456. * their single-part cousins.
  57457. * @param {ol.geom.GeometryType} type Geometry type.
  57458. * @return {ol.interaction.Draw.Mode_} Drawing mode.
  57459. * @private
  57460. */
  57461. ol.interaction.Draw.getMode_ = function(type) {
  57462. var mode;
  57463. if (type === ol.geom.GeometryType.POINT ||
  57464. type === ol.geom.GeometryType.MULTI_POINT) {
  57465. mode = ol.interaction.Draw.Mode_.POINT;
  57466. } else if (type === ol.geom.GeometryType.LINE_STRING ||
  57467. type === ol.geom.GeometryType.MULTI_LINE_STRING) {
  57468. mode = ol.interaction.Draw.Mode_.LINE_STRING;
  57469. } else if (type === ol.geom.GeometryType.POLYGON ||
  57470. type === ol.geom.GeometryType.MULTI_POLYGON) {
  57471. mode = ol.interaction.Draw.Mode_.POLYGON;
  57472. } else if (type === ol.geom.GeometryType.CIRCLE) {
  57473. mode = ol.interaction.Draw.Mode_.CIRCLE;
  57474. }
  57475. return /** @type {!ol.interaction.Draw.Mode_} */ (mode);
  57476. };
  57477. /**
  57478. * Draw mode. This collapses multi-part geometry types with their single-part
  57479. * cousins.
  57480. * @enum {string}
  57481. * @private
  57482. */
  57483. ol.interaction.Draw.Mode_ = {
  57484. POINT: 'Point',
  57485. LINE_STRING: 'LineString',
  57486. POLYGON: 'Polygon',
  57487. CIRCLE: 'Circle'
  57488. };
  57489. /**
  57490. * @classdesc
  57491. * Events emitted by {@link ol.interaction.Draw} instances are instances of
  57492. * this type.
  57493. *
  57494. * @constructor
  57495. * @extends {ol.events.Event}
  57496. * @implements {oli.DrawEvent}
  57497. * @param {ol.interaction.DrawEventType} type Type.
  57498. * @param {ol.Feature} feature The feature drawn.
  57499. */
  57500. ol.interaction.Draw.Event = function(type, feature) {
  57501. ol.events.Event.call(this, type);
  57502. /**
  57503. * The feature being drawn.
  57504. * @type {ol.Feature}
  57505. * @api
  57506. */
  57507. this.feature = feature;
  57508. };
  57509. ol.inherits(ol.interaction.Draw.Event, ol.events.Event);
  57510. goog.provide('ol.interaction.ExtentEventType');
  57511. /**
  57512. * @enum {string}
  57513. */
  57514. ol.interaction.ExtentEventType = {
  57515. /**
  57516. * Triggered after the extent is changed
  57517. * @event ol.interaction.Extent.Event#extentchanged
  57518. * @api
  57519. */
  57520. EXTENTCHANGED: 'extentchanged'
  57521. };
  57522. goog.provide('ol.interaction.Extent');
  57523. goog.require('ol');
  57524. goog.require('ol.Feature');
  57525. goog.require('ol.MapBrowserEventType');
  57526. goog.require('ol.MapBrowserPointerEvent');
  57527. goog.require('ol.coordinate');
  57528. goog.require('ol.events.Event');
  57529. goog.require('ol.extent');
  57530. goog.require('ol.geom.GeometryType');
  57531. goog.require('ol.geom.Point');
  57532. goog.require('ol.geom.Polygon');
  57533. goog.require('ol.interaction.ExtentEventType');
  57534. goog.require('ol.interaction.Pointer');
  57535. goog.require('ol.layer.Vector');
  57536. goog.require('ol.source.Vector');
  57537. goog.require('ol.style.Style');
  57538. /**
  57539. * @classdesc
  57540. * Allows the user to draw a vector box by clicking and dragging on the map.
  57541. * Once drawn, the vector box can be modified by dragging its vertices or edges.
  57542. * This interaction is only supported for mouse devices.
  57543. *
  57544. * @constructor
  57545. * @extends {ol.interaction.Pointer}
  57546. * @fires ol.interaction.Extent.Event
  57547. * @param {olx.interaction.ExtentOptions=} opt_options Options.
  57548. * @api
  57549. */
  57550. ol.interaction.Extent = function(opt_options) {
  57551. /**
  57552. * Extent of the drawn box
  57553. * @type {ol.Extent}
  57554. * @private
  57555. */
  57556. this.extent_ = null;
  57557. /**
  57558. * Handler for pointer move events
  57559. * @type {function (ol.Coordinate): ol.Extent|null}
  57560. * @private
  57561. */
  57562. this.pointerHandler_ = null;
  57563. /**
  57564. * Pixel threshold to snap to extent
  57565. * @type {number}
  57566. * @private
  57567. */
  57568. this.pixelTolerance_ = 10;
  57569. /**
  57570. * Is the pointer snapped to an extent vertex
  57571. * @type {boolean}
  57572. * @private
  57573. */
  57574. this.snappedToVertex_ = false;
  57575. /**
  57576. * Feature for displaying the visible extent
  57577. * @type {ol.Feature}
  57578. * @private
  57579. */
  57580. this.extentFeature_ = null;
  57581. /**
  57582. * Feature for displaying the visible pointer
  57583. * @type {ol.Feature}
  57584. * @private
  57585. */
  57586. this.vertexFeature_ = null;
  57587. if (!opt_options) {
  57588. opt_options = {};
  57589. }
  57590. /* Inherit ol.interaction.Pointer */
  57591. ol.interaction.Pointer.call(this, {
  57592. handleDownEvent: ol.interaction.Extent.handleDownEvent_,
  57593. handleDragEvent: ol.interaction.Extent.handleDragEvent_,
  57594. handleEvent: ol.interaction.Extent.handleEvent_,
  57595. handleUpEvent: ol.interaction.Extent.handleUpEvent_
  57596. });
  57597. /**
  57598. * Layer for the extentFeature
  57599. * @type {ol.layer.Vector}
  57600. * @private
  57601. */
  57602. this.extentOverlay_ = new ol.layer.Vector({
  57603. source: new ol.source.Vector({
  57604. useSpatialIndex: false,
  57605. wrapX: !!opt_options.wrapX
  57606. }),
  57607. style: opt_options.boxStyle ? opt_options.boxStyle : ol.interaction.Extent.getDefaultExtentStyleFunction_(),
  57608. updateWhileAnimating: true,
  57609. updateWhileInteracting: true
  57610. });
  57611. /**
  57612. * Layer for the vertexFeature
  57613. * @type {ol.layer.Vector}
  57614. * @private
  57615. */
  57616. this.vertexOverlay_ = new ol.layer.Vector({
  57617. source: new ol.source.Vector({
  57618. useSpatialIndex: false,
  57619. wrapX: !!opt_options.wrapX
  57620. }),
  57621. style: opt_options.pointerStyle ? opt_options.pointerStyle : ol.interaction.Extent.getDefaultPointerStyleFunction_(),
  57622. updateWhileAnimating: true,
  57623. updateWhileInteracting: true
  57624. });
  57625. if (opt_options.extent) {
  57626. this.setExtent(opt_options.extent);
  57627. }
  57628. };
  57629. ol.inherits(ol.interaction.Extent, ol.interaction.Pointer);
  57630. /**
  57631. * @param {ol.MapBrowserEvent} mapBrowserEvent Event.
  57632. * @return {boolean} Propagate event?
  57633. * @this {ol.interaction.Extent}
  57634. * @private
  57635. */
  57636. ol.interaction.Extent.handleEvent_ = function(mapBrowserEvent) {
  57637. if (!(mapBrowserEvent instanceof ol.MapBrowserPointerEvent)) {
  57638. return true;
  57639. }
  57640. //display pointer (if not dragging)
  57641. if (mapBrowserEvent.type == ol.MapBrowserEventType.POINTERMOVE && !this.handlingDownUpSequence) {
  57642. this.handlePointerMove_(mapBrowserEvent);
  57643. }
  57644. //call pointer to determine up/down/drag
  57645. ol.interaction.Pointer.handleEvent.call(this, mapBrowserEvent);
  57646. //return false to stop propagation
  57647. return false;
  57648. };
  57649. /**
  57650. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  57651. * @return {boolean} Event handled?
  57652. * @this {ol.interaction.Extent}
  57653. * @private
  57654. */
  57655. ol.interaction.Extent.handleDownEvent_ = function(mapBrowserEvent) {
  57656. var pixel = mapBrowserEvent.pixel;
  57657. var map = mapBrowserEvent.map;
  57658. var extent = this.getExtent();
  57659. var vertex = this.snapToVertex_(pixel, map);
  57660. //find the extent corner opposite the passed corner
  57661. var getOpposingPoint = function(point) {
  57662. var x_ = null;
  57663. var y_ = null;
  57664. if (point[0] == extent[0]) {
  57665. x_ = extent[2];
  57666. } else if (point[0] == extent[2]) {
  57667. x_ = extent[0];
  57668. }
  57669. if (point[1] == extent[1]) {
  57670. y_ = extent[3];
  57671. } else if (point[1] == extent[3]) {
  57672. y_ = extent[1];
  57673. }
  57674. if (x_ !== null && y_ !== null) {
  57675. return [x_, y_];
  57676. }
  57677. return null;
  57678. };
  57679. if (vertex && extent) {
  57680. var x = (vertex[0] == extent[0] || vertex[0] == extent[2]) ? vertex[0] : null;
  57681. var y = (vertex[1] == extent[1] || vertex[1] == extent[3]) ? vertex[1] : null;
  57682. //snap to point
  57683. if (x !== null && y !== null) {
  57684. this.pointerHandler_ = ol.interaction.Extent.getPointHandler_(getOpposingPoint(vertex));
  57685. //snap to edge
  57686. } else if (x !== null) {
  57687. this.pointerHandler_ = ol.interaction.Extent.getEdgeHandler_(
  57688. getOpposingPoint([x, extent[1]]),
  57689. getOpposingPoint([x, extent[3]])
  57690. );
  57691. } else if (y !== null) {
  57692. this.pointerHandler_ = ol.interaction.Extent.getEdgeHandler_(
  57693. getOpposingPoint([extent[0], y]),
  57694. getOpposingPoint([extent[2], y])
  57695. );
  57696. }
  57697. //no snap - new bbox
  57698. } else {
  57699. vertex = map.getCoordinateFromPixel(pixel);
  57700. this.setExtent([vertex[0], vertex[1], vertex[0], vertex[1]]);
  57701. this.pointerHandler_ = ol.interaction.Extent.getPointHandler_(vertex);
  57702. }
  57703. return true; //event handled; start downup sequence
  57704. };
  57705. /**
  57706. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  57707. * @return {boolean} Event handled?
  57708. * @this {ol.interaction.Extent}
  57709. * @private
  57710. */
  57711. ol.interaction.Extent.handleDragEvent_ = function(mapBrowserEvent) {
  57712. if (this.pointerHandler_) {
  57713. var pixelCoordinate = mapBrowserEvent.coordinate;
  57714. this.setExtent(this.pointerHandler_(pixelCoordinate));
  57715. this.createOrUpdatePointerFeature_(pixelCoordinate);
  57716. }
  57717. return true;
  57718. };
  57719. /**
  57720. * @param {ol.MapBrowserPointerEvent} mapBrowserEvent Event.
  57721. * @return {boolean} Stop drag sequence?
  57722. * @this {ol.interaction.Extent}
  57723. * @private
  57724. */
  57725. ol.interaction.Extent.handleUpEvent_ = function(mapBrowserEvent) {
  57726. this.pointerHandler_ = null;
  57727. //If bbox is zero area, set to null;
  57728. var extent = this.getExtent();
  57729. if (!extent || ol.extent.getArea(extent) === 0) {
  57730. this.setExtent(null);
  57731. }
  57732. return false; //Stop handling downup sequence
  57733. };
  57734. /**
  57735. * Returns the default style for the drawn bbox
  57736. *
  57737. * @return {ol.StyleFunction} Default Extent style
  57738. * @private
  57739. */
  57740. ol.interaction.Extent.getDefaultExtentStyleFunction_ = function() {
  57741. var style = ol.style.Style.createDefaultEditing();
  57742. return function(feature, resolution) {
  57743. return style[ol.geom.GeometryType.POLYGON];
  57744. };
  57745. };
  57746. /**
  57747. * Returns the default style for the pointer
  57748. *
  57749. * @return {ol.StyleFunction} Default pointer style
  57750. * @private
  57751. */
  57752. ol.interaction.Extent.getDefaultPointerStyleFunction_ = function() {
  57753. var style = ol.style.Style.createDefaultEditing();
  57754. return function(feature, resolution) {
  57755. return style[ol.geom.GeometryType.POINT];
  57756. };
  57757. };
  57758. /**
  57759. * @param {ol.Coordinate} fixedPoint corner that will be unchanged in the new extent
  57760. * @returns {function (ol.Coordinate): ol.Extent} event handler
  57761. * @private
  57762. */
  57763. ol.interaction.Extent.getPointHandler_ = function(fixedPoint) {
  57764. return function(point) {
  57765. return ol.extent.boundingExtent([fixedPoint, point]);
  57766. };
  57767. };
  57768. /**
  57769. * @param {ol.Coordinate} fixedP1 first corner that will be unchanged in the new extent
  57770. * @param {ol.Coordinate} fixedP2 second corner that will be unchanged in the new extent
  57771. * @returns {function (ol.Coordinate): ol.Extent|null} event handler
  57772. * @private
  57773. */
  57774. ol.interaction.Extent.getEdgeHandler_ = function(fixedP1, fixedP2) {
  57775. if (fixedP1[0] == fixedP2[0]) {
  57776. return function(point) {
  57777. return ol.extent.boundingExtent([fixedP1, [point[0], fixedP2[1]]]);
  57778. };
  57779. } else if (fixedP1[1] == fixedP2[1]) {
  57780. return function(point) {
  57781. return ol.extent.boundingExtent([fixedP1, [fixedP2[0], point[1]]]);
  57782. };
  57783. } else {
  57784. return null;
  57785. }
  57786. };
  57787. /**
  57788. * @param {ol.Extent} extent extent
  57789. * @returns {Array<Array<ol.Coordinate>>} extent line segments
  57790. * @private
  57791. */
  57792. ol.interaction.Extent.getSegments_ = function(extent) {
  57793. return [
  57794. [[extent[0], extent[1]], [extent[0], extent[3]]],
  57795. [[extent[0], extent[3]], [extent[2], extent[3]]],
  57796. [[extent[2], extent[3]], [extent[2], extent[1]]],
  57797. [[extent[2], extent[1]], [extent[0], extent[1]]]
  57798. ];
  57799. };
  57800. /**
  57801. * @param {ol.Pixel} pixel cursor location
  57802. * @param {ol.Map} map map
  57803. * @returns {ol.Coordinate|null} snapped vertex on extent
  57804. * @private
  57805. */
  57806. ol.interaction.Extent.prototype.snapToVertex_ = function(pixel, map) {
  57807. var pixelCoordinate = map.getCoordinateFromPixel(pixel);
  57808. var sortByDistance = function(a, b) {
  57809. return ol.coordinate.squaredDistanceToSegment(pixelCoordinate, a) -
  57810. ol.coordinate.squaredDistanceToSegment(pixelCoordinate, b);
  57811. };
  57812. var extent = this.getExtent();
  57813. if (extent) {
  57814. //convert extents to line segments and find the segment closest to pixelCoordinate
  57815. var segments = ol.interaction.Extent.getSegments_(extent);
  57816. segments.sort(sortByDistance);
  57817. var closestSegment = segments[0];
  57818. var vertex = (ol.coordinate.closestOnSegment(pixelCoordinate,
  57819. closestSegment));
  57820. var vertexPixel = map.getPixelFromCoordinate(vertex);
  57821. //if the distance is within tolerance, snap to the segment
  57822. if (ol.coordinate.distance(pixel, vertexPixel) <= this.pixelTolerance_) {
  57823. //test if we should further snap to a vertex
  57824. var pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
  57825. var pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
  57826. var squaredDist1 = ol.coordinate.squaredDistance(vertexPixel, pixel1);
  57827. var squaredDist2 = ol.coordinate.squaredDistance(vertexPixel, pixel2);
  57828. var dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
  57829. this.snappedToVertex_ = dist <= this.pixelTolerance_;
  57830. if (this.snappedToVertex_) {
  57831. vertex = squaredDist1 > squaredDist2 ?
  57832. closestSegment[1] : closestSegment[0];
  57833. }
  57834. return vertex;
  57835. }
  57836. }
  57837. return null;
  57838. };
  57839. /**
  57840. * @param {ol.MapBrowserEvent} mapBrowserEvent pointer move event
  57841. * @private
  57842. */
  57843. ol.interaction.Extent.prototype.handlePointerMove_ = function(mapBrowserEvent) {
  57844. var pixel = mapBrowserEvent.pixel;
  57845. var map = mapBrowserEvent.map;
  57846. var vertex = this.snapToVertex_(pixel, map);
  57847. if (!vertex) {
  57848. vertex = map.getCoordinateFromPixel(pixel);
  57849. }
  57850. this.createOrUpdatePointerFeature_(vertex);
  57851. };
  57852. /**
  57853. * @param {ol.Extent} extent extent
  57854. * @returns {ol.Feature} extent as featrue
  57855. * @private
  57856. */
  57857. ol.interaction.Extent.prototype.createOrUpdateExtentFeature_ = function(extent) {
  57858. var extentFeature = this.extentFeature_;
  57859. if (!extentFeature) {
  57860. if (!extent) {
  57861. extentFeature = new ol.Feature({});
  57862. } else {
  57863. extentFeature = new ol.Feature(ol.geom.Polygon.fromExtent(extent));
  57864. }
  57865. this.extentFeature_ = extentFeature;
  57866. this.extentOverlay_.getSource().addFeature(extentFeature);
  57867. } else {
  57868. if (!extent) {
  57869. extentFeature.setGeometry(undefined);
  57870. } else {
  57871. extentFeature.setGeometry(ol.geom.Polygon.fromExtent(extent));
  57872. }
  57873. }
  57874. return extentFeature;
  57875. };
  57876. /**
  57877. * @param {ol.Coordinate} vertex location of feature
  57878. * @returns {ol.Feature} vertex as feature
  57879. * @private
  57880. */
  57881. ol.interaction.Extent.prototype.createOrUpdatePointerFeature_ = function(vertex) {
  57882. var vertexFeature = this.vertexFeature_;
  57883. if (!vertexFeature) {
  57884. vertexFeature = new ol.Feature(new ol.geom.Point(vertex));
  57885. this.vertexFeature_ = vertexFeature;
  57886. this.vertexOverlay_.getSource().addFeature(vertexFeature);
  57887. } else {
  57888. var geometry = /** @type {ol.geom.Point} */ (vertexFeature.getGeometry());
  57889. geometry.setCoordinates(vertex);
  57890. }
  57891. return vertexFeature;
  57892. };
  57893. /**
  57894. * @inheritDoc
  57895. */
  57896. ol.interaction.Extent.prototype.setMap = function(map) {
  57897. this.extentOverlay_.setMap(map);
  57898. this.vertexOverlay_.setMap(map);
  57899. ol.interaction.Pointer.prototype.setMap.call(this, map);
  57900. };
  57901. /**
  57902. * Returns the current drawn extent in the view projection
  57903. *
  57904. * @return {ol.Extent} Drawn extent in the view projection.
  57905. * @api
  57906. */
  57907. ol.interaction.Extent.prototype.getExtent = function() {
  57908. return this.extent_;
  57909. };
  57910. /**
  57911. * Manually sets the drawn extent, using the view projection.
  57912. *
  57913. * @param {ol.Extent} extent Extent
  57914. * @api
  57915. */
  57916. ol.interaction.Extent.prototype.setExtent = function(extent) {
  57917. //Null extent means no bbox
  57918. this.extent_ = extent ? extent : null;
  57919. this.createOrUpdateExtentFeature_(extent);
  57920. this.dispatchEvent(new ol.interaction.Extent.Event(this.extent_));
  57921. };
  57922. /**
  57923. * @classdesc
  57924. * Events emitted by {@link ol.interaction.Extent} instances are instances of
  57925. * this type.
  57926. *
  57927. * @constructor
  57928. * @implements {oli.ExtentEvent}
  57929. * @param {ol.Extent} extent the new extent
  57930. * @extends {ol.events.Event}
  57931. */
  57932. ol.interaction.Extent.Event = function(extent) {
  57933. ol.events.Event.call(this, ol.interaction.ExtentEventType.EXTENTCHANGED);
  57934. /**
  57935. * The current extent.
  57936. * @type {ol.Extent}
  57937. * @api
  57938. */
  57939. this.extent = extent;
  57940. };
  57941. ol.inherits(ol.interaction.Extent.Event, ol.events.Event);
  57942. goog.provide('ol.interaction.ModifyEventType');
  57943. /**
  57944. * @enum {string}
  57945. */
  57946. ol.interaction.ModifyEventType = {
  57947. /**
  57948. * Triggered upon feature modification start
  57949. * @event ol.interaction.Modify.Event#modifystart
  57950. * @api
  57951. */
  57952. MODIFYSTART: 'modifystart',
  57953. /**
  57954. * Triggered upon feature modification end
  57955. * @event ol.interaction.Modify.Event#modifyend
  57956. * @api
  57957. */
  57958. MODIFYEND: 'modifyend'
  57959. };
  57960. goog.provide('ol.interaction.Modify');
  57961. goog.require('ol');
  57962. goog.require('ol.Collection');
  57963. goog.require('ol.CollectionEventType');
  57964. goog.require('ol.Feature');
  57965. goog.require('ol.MapBrowserEventType');
  57966. goog.require('ol.MapBrowserPointerEvent');
  57967. goog.require('ol.ViewHint');
  57968. goog.require('ol.array');
  57969. goog.require('ol.coordinate');
  57970. goog.require('ol.events');
  57971. goog.require('ol.events.Event');
  57972. goog.require('ol.events.EventType');
  57973. goog.require('ol.events.condition');
  57974. goog.require('ol.extent');
  57975. goog.require('ol.geom.GeometryType');
  57976. goog.require('ol.geom.Point');
  57977. goog.require('ol.interaction.ModifyEventType');
  57978. goog.require('ol.interaction.Pointer');
  57979. goog.require('ol.layer.Vector');
  57980. goog.require('ol.source.Vector');
  57981. goog.require('ol.source.VectorEventType');
  57982. goog.require('ol.structs.RBush');
  57983. goog.require('ol.style.Style');
  57984. /**
  57985. * @classdesc
  57986. * Interaction for modifying feature geometries. To modify features that have
  57987. * been added to an existing source, construct the modify interaction with the
  57988. * `source` option. If you want to modify features in a collection (for example,
  57989. * the collection used by a select interaction), construct the interaction with
  57990. * the `features` option. The interaction must be constructed with either a
  57991. * `source` or `features` option.
  57992. *
  57993. * By default, the interaction will allow deletion of vertices when the `alt`
  57994. * key is pressed. To configure the interaction with a different condition
  57995. * for deletion, use the `deleteCondition` option.
  57996. *
  57997. * @constructor
  57998. * @extends {ol.interaction.Pointer}
  57999. * @param {olx.interaction.ModifyOptions} options Options.
  58000. * @fires ol.interaction.Modify.Event
  58001. * @api
  58002. */
  58003. ol.interaction.Modify = function(options) {
  58004. ol.interaction.Pointer.call(this, {
  58005. handleDownEvent: ol.interaction.Modify.handleDownEvent_,
  58006. handleDragEvent: ol.interaction.Modify.handleDragEvent_,
  58007. handleEvent: ol.interaction.Modify.handleEvent,
  58008. handleUpEvent: ol.interaction.Modify.handleUpEvent_
  58009. });
  58010. /**
  58011. * @private
  58012. * @type {ol.EventsConditionType}
  58013. */
  58014. this.condition_ = options.condition ?
  58015. options.condition : ol.events.condition.primaryAction;
  58016. /**
  58017. * @private
  58018. * @param {ol.MapBrowserEvent} mapBrowserEvent Browser event.
  58019. * @return {boolean} Combined condition result.
  58020. */
  58021. this.defaultDeleteCondition_ = function(mapBrowserEvent) {
  58022. return ol.events.condition.altKeyOnly(mapBrowserEvent) &&
  58023. ol.events.condition.singleClick(mapBrowserEvent);
  58024. };
  58025. /**
  58026. * @type {ol.EventsConditionType}
  58027. * @private
  58028. */
  58029. this.deleteCondition_ = options.deleteCondition ?
  58030. options.deleteCondition : this.defaultDeleteCondition_;
  58031. /**
  58032. * @type {ol.EventsConditionType}
  58033. * @private
  58034. */
  58035. this.insertVertexCondition_ = options.insertVertexCondition ?
  58036. options.insertVertexCondition : ol.events.condition.always;
  58037. /**
  58038. * Editing vertex.
  58039. * @type {ol.Feature}
  58040. * @private
  58041. */
  58042. this.vertexFeature_ = null;
  58043. /**
  58044. * Segments intersecting {@link this.vertexFeature_} by segment uid.
  58045. * @type {Object.<string, boolean>}
  58046. * @private
  58047. */
  58048. this.vertexSegments_ = null;
  58049. /**
  58050. * @type {ol.Pixel}
  58051. * @private
  58052. */
  58053. this.lastPixel_ = [0, 0];
  58054. /**
  58055. * Tracks if the next `singleclick` event should be ignored to prevent
  58056. * accidental deletion right after vertex creation.
  58057. * @type {boolean}
  58058. * @private
  58059. */
  58060. this.ignoreNextSingleClick_ = false;
  58061. /**
  58062. * @type {boolean}
  58063. * @private
  58064. */
  58065. this.modified_ = false;
  58066. /**
  58067. * Segment RTree for each layer
  58068. * @type {ol.structs.RBush.<ol.ModifySegmentDataType>}
  58069. * @private
  58070. */
  58071. this.rBush_ = new ol.structs.RBush();
  58072. /**
  58073. * @type {number}
  58074. * @private
  58075. */
  58076. this.pixelTolerance_ = options.pixelTolerance !== undefined ?
  58077. options.pixelTolerance : 10;
  58078. /**
  58079. * @type {boolean}
  58080. * @private
  58081. */
  58082. this.snappedToVertex_ = false;
  58083. /**
  58084. * Indicate whether the interaction is currently changing a feature's
  58085. * coordinates.
  58086. * @type {boolean}
  58087. * @private
  58088. */
  58089. this.changingFeature_ = false;
  58090. /**
  58091. * @type {Array}
  58092. * @private
  58093. */
  58094. this.dragSegments_ = [];
  58095. /**
  58096. * Draw overlay where sketch features are drawn.
  58097. * @type {ol.layer.Vector}
  58098. * @private
  58099. */
  58100. this.overlay_ = new ol.layer.Vector({
  58101. source: new ol.source.Vector({
  58102. useSpatialIndex: false,
  58103. wrapX: !!options.wrapX
  58104. }),
  58105. style: options.style ? options.style :
  58106. ol.interaction.Modify.getDefaultStyleFunction(),
  58107. updateWhileAnimating: true,
  58108. updateWhileInteracting: true
  58109. });
  58110. /**
  58111. * @const
  58112. * @private
  58113. * @type {Object.<string, function(ol.Feature, ol.geom.Geometry)>}
  58114. */
  58115. this.SEGMENT_WRITERS_ = {
  58116. 'Point': this.writePointGeometry_,
  58117. 'LineString': this.writeLineStringGeometry_,
  58118. 'LinearRing': this.writeLineStringGeometry_,
  58119. 'Polygon': this.writePolygonGeometry_,
  58120. 'MultiPoint': this.writeMultiPointGeometry_,
  58121. 'MultiLineString': this.writeMultiLineStringGeometry_,
  58122. 'MultiPolygon': this.writeMultiPolygonGeometry_,
  58123. 'Circle': this.writeCircleGeometry_,
  58124. 'GeometryCollection': this.writeGeometryCollectionGeometry_
  58125. };
  58126. /**
  58127. * @type {ol.source.Vector}
  58128. * @private
  58129. */
  58130. this.source_ = null;
  58131. var features;
  58132. if (options.source) {
  58133. this.source_ = options.source;
  58134. features = new ol.Collection(this.source_.getFeatures());
  58135. ol.events.listen(this.source_, ol.source.VectorEventType.ADDFEATURE,
  58136. this.handleSourceAdd_, this);
  58137. ol.events.listen(this.source_, ol.source.VectorEventType.REMOVEFEATURE,
  58138. this.handleSourceRemove_, this);
  58139. } else {
  58140. features = options.features;
  58141. }
  58142. if (!features) {
  58143. throw new Error('The modify interaction requires features or a source');
  58144. }
  58145. /**
  58146. * @type {ol.Collection.<ol.Feature>}
  58147. * @private
  58148. */
  58149. this.features_ = features;
  58150. this.features_.forEach(this.addFeature_, this);
  58151. ol.events.listen(this.features_, ol.CollectionEventType.ADD,
  58152. this.handleFeatureAdd_, this);
  58153. ol.events.listen(this.features_, ol.CollectionEventType.REMOVE,
  58154. this.handleFeatureRemove_, this);
  58155. /**
  58156. * @type {ol.MapBrowserPointerEvent}
  58157. * @private
  58158. */
  58159. this.lastPointerEvent_ = null;
  58160. };
  58161. ol.inherits(ol.interaction.Modify, ol.interaction.Pointer);
  58162. /**
  58163. * @define {number} The segment index assigned to a circle's center when
  58164. * breaking up a cicrle into ModifySegmentDataType segments.
  58165. */
  58166. ol.interaction.Modify.MODIFY_SEGMENT_CIRCLE_CENTER_INDEX = 0;
  58167. /**
  58168. * @define {number} The segment index assigned to a circle's circumference when
  58169. * breaking up a circle into ModifySegmentDataType segments.
  58170. */
  58171. ol.interaction.Modify.MODIFY_SEGMENT_CIRCLE_CIRCUMFERENCE_INDEX = 1;
  58172. /**
  58173. * @param {ol.Feature} feature Feature.
  58174. * @private
  58175. */
  58176. ol.interaction.Modify.prototype.addFeature_ = function(feature) {
  58177. var geometry = feature.getGeometry();
  58178. if (geometry && geometry.getType() in this.SEGMENT_WRITERS_) {
  58179. this.SEGMENT_WRITERS_[geometry.getType()].call(this, feature, geometry);
  58180. }
  58181. var map = this.getMap();
  58182. if (map && map.isRendered() && this.getActive()) {
  58183. this.handlePointerAtPixel_(this.lastPixel_, map);
  58184. }
  58185. ol.events.listen(feature, ol.events.EventType.CHANGE,
  58186. this.handleFeatureChange_, this);
  58187. };
  58188. /**
  58189. * @param {ol.MapBrowserPointerEvent} evt Map browser event
  58190. * @private
  58191. */
  58192. ol.interaction.Modify.prototype.willModifyFeatures_ = function(evt) {
  58193. if (!this.modified_) {
  58194. this.modified_ = true;
  58195. this.dispatchEvent(new ol.interaction.Modify.Event(
  58196. ol.interaction.ModifyEventType.MODIFYSTART, this.features_, evt));
  58197. }
  58198. };
  58199. /**
  58200. * @param {ol.Feature} feature Feature.
  58201. * @private
  58202. */
  58203. ol.interaction.Modify.prototype.removeFeature_ = function(feature) {
  58204. this.removeFeatureSegmentData_(feature);
  58205. // Remove the vertex feature if the collection of canditate features
  58206. // is empty.
  58207. if (this.vertexFeature_ && this.features_.getLength() === 0) {
  58208. this.overlay_.getSource().removeFeature(this.vertexFeature_);
  58209. this.vertexFeature_ = null;
  58210. }
  58211. ol.events.unlisten(feature, ol.events.EventType.CHANGE,
  58212. this.handleFeatureChange_, this);
  58213. };
  58214. /**
  58215. * @param {ol.Feature} feature Feature.
  58216. * @private
  58217. */
  58218. ol.interaction.Modify.prototype.removeFeatureSegmentData_ = function(feature) {
  58219. var rBush = this.rBush_;
  58220. var /** @type {Array.<ol.ModifySegmentDataType>} */ nodesToRemove = [];
  58221. rBush.forEach(
  58222. /**
  58223. * @param {ol.ModifySegmentDataType} node RTree node.
  58224. */
  58225. function(node) {
  58226. if (feature === node.feature) {
  58227. nodesToRemove.push(node);
  58228. }
  58229. });
  58230. for (var i = nodesToRemove.length - 1; i >= 0; --i) {
  58231. rBush.remove(nodesToRemove[i]);
  58232. }
  58233. };
  58234. /**
  58235. * @inheritDoc
  58236. */
  58237. ol.interaction.Modify.prototype.setActive = function(active) {
  58238. if (this.vertexFeature_ && !active) {
  58239. this.overlay_.getSource().removeFeature(this.vertexFeature_);
  58240. this.vertexFeature_ = null;
  58241. }
  58242. ol.interaction.Pointer.prototype.setActive.call(this, active);
  58243. };
  58244. /**
  58245. * @inheritDoc
  58246. */
  58247. ol.interaction.Modify.prototype.setMap = function(map) {
  58248. this.overlay_.setMap(map);
  58249. ol.interaction.Pointer.prototype.setMap.call(this, map);
  58250. };
  58251. /**
  58252. * @param {ol.source.Vector.Event} event Event.
  58253. * @private
  58254. */
  58255. ol.interaction.Modify.prototype.handleSourceAdd_ = function(event) {
  58256. if (event.feature) {
  58257. this.features_.push(event.feature);
  58258. }
  58259. };
  58260. /**
  58261. * @param {ol.source.Vector.Event} event Event.
  58262. * @private
  58263. */
  58264. ol.interaction.Modify.prototype.handleSourceRemove_ = function(event) {
  58265. if (event.feature) {
  58266. this.features_.remove(event.feature);
  58267. }
  58268. };
  58269. /**
  58270. * @param {ol.Collection.Event} evt Event.
  58271. * @private
  58272. */
  58273. ol.interaction.Modify.prototype.handleFeatureAdd_ = function(evt) {
  58274. this.addFeature_(/** @type {ol.Feature} */ (evt.element));
  58275. };
  58276. /**
  58277. * @param {ol.events.Event} evt Event.
  58278. * @private
  58279. */
  58280. ol.interaction.Modify.prototype.handleFeatureChange_ = function(evt) {
  58281. if (!this.changingFeature_) {
  58282. var feature = /** @type {ol.Feature} */ (evt.target);
  58283. this.removeFeature_(feature);
  58284. this.addFeature_(feature);
  58285. }
  58286. };
  58287. /**
  58288. * @param {ol.Collection.Event} evt Event.
  58289. * @private
  58290. */
  58291. ol.interaction.Modify.prototype.handleFeatureRemove_ = function(evt) {
  58292. var feature = /** @type {ol.Feature} */ (evt.element);
  58293. this.removeFeature_(feature);
  58294. };
  58295. /**
  58296. * @param {ol.Feature} feature Feature
  58297. * @param {ol.geom.Point} geometry Geometry.
  58298. * @private
  58299. */
  58300. ol.interaction.Modify.prototype.writePointGeometry_ = function(feature, geometry) {
  58301. var coordinates = geometry.getCoordinates();
  58302. var segmentData = /** @type {ol.ModifySegmentDataType} */ ({
  58303. feature: feature,
  58304. geometry: geometry,
  58305. segment: [coordinates, coordinates]
  58306. });
  58307. this.rBush_.insert(geometry.getExtent(), segmentData);
  58308. };
  58309. /**
  58310. * @param {ol.Feature} feature Feature
  58311. * @param {ol.geom.MultiPoint} geometry Geometry.
  58312. * @private
  58313. */
  58314. ol.interaction.Modify.prototype.writeMultiPointGeometry_ = function(feature, geometry) {
  58315. var points = geometry.getCoordinates();
  58316. var coordinates, i, ii, segmentData;
  58317. for (i = 0, ii = points.length; i < ii; ++i) {
  58318. coordinates = points[i];
  58319. segmentData = /** @type {ol.ModifySegmentDataType} */ ({
  58320. feature: feature,
  58321. geometry: geometry,
  58322. depth: [i],
  58323. index: i,
  58324. segment: [coordinates, coordinates]
  58325. });
  58326. this.rBush_.insert(geometry.getExtent(), segmentData);
  58327. }
  58328. };
  58329. /**
  58330. * @param {ol.Feature} feature Feature
  58331. * @param {ol.geom.LineString} geometry Geometry.
  58332. * @private
  58333. */
  58334. ol.interaction.Modify.prototype.writeLineStringGeometry_ = function(feature, geometry) {
  58335. var coordinates = geometry.getCoordinates();
  58336. var i, ii, segment, segmentData;
  58337. for (i = 0, ii = coordinates.length - 1; i < ii; ++i) {
  58338. segment = coordinates.slice(i, i + 2);
  58339. segmentData = /** @type {ol.ModifySegmentDataType} */ ({
  58340. feature: feature,
  58341. geometry: geometry,
  58342. index: i,
  58343. segment: segment
  58344. });
  58345. this.rBush_.insert(ol.extent.boundingExtent(segment), segmentData);
  58346. }
  58347. };
  58348. /**
  58349. * @param {ol.Feature} feature Feature
  58350. * @param {ol.geom.MultiLineString} geometry Geometry.
  58351. * @private
  58352. */
  58353. ol.interaction.Modify.prototype.writeMultiLineStringGeometry_ = function(feature, geometry) {
  58354. var lines = geometry.getCoordinates();
  58355. var coordinates, i, ii, j, jj, segment, segmentData;
  58356. for (j = 0, jj = lines.length; j < jj; ++j) {
  58357. coordinates = lines[j];
  58358. for (i = 0, ii = coordinates.length - 1; i < ii; ++i) {
  58359. segment = coordinates.slice(i, i + 2);
  58360. segmentData = /** @type {ol.ModifySegmentDataType} */ ({
  58361. feature: feature,
  58362. geometry: geometry,
  58363. depth: [j],
  58364. index: i,
  58365. segment: segment
  58366. });
  58367. this.rBush_.insert(ol.extent.boundingExtent(segment), segmentData);
  58368. }
  58369. }
  58370. };
  58371. /**
  58372. * @param {ol.Feature} feature Feature
  58373. * @param {ol.geom.Polygon} geometry Geometry.
  58374. * @private
  58375. */
  58376. ol.interaction.Modify.prototype.writePolygonGeometry_ = function(feature, geometry) {
  58377. var rings = geometry.getCoordinates();
  58378. var coordinates, i, ii, j, jj, segment, segmentData;
  58379. for (j = 0, jj = rings.length; j < jj; ++j) {
  58380. coordinates = rings[j];
  58381. for (i = 0, ii = coordinates.length - 1; i < ii; ++i) {
  58382. segment = coordinates.slice(i, i + 2);
  58383. segmentData = /** @type {ol.ModifySegmentDataType} */ ({
  58384. feature: feature,
  58385. geometry: geometry,
  58386. depth: [j],
  58387. index: i,
  58388. segment: segment
  58389. });
  58390. this.rBush_.insert(ol.extent.boundingExtent(segment), segmentData);
  58391. }
  58392. }
  58393. };
  58394. /**
  58395. * @param {ol.Feature} feature Feature
  58396. * @param {ol.geom.MultiPolygon} geometry Geometry.
  58397. * @private
  58398. */
  58399. ol.interaction.Modify.prototype.writeMultiPolygonGeometry_ = function(feature, geometry) {
  58400. var polygons = geometry.getCoordinates();
  58401. var coordinates, i, ii, j, jj, k, kk, rings, segment, segmentData;
  58402. for (k = 0, kk = polygons.length; k < kk; ++k) {
  58403. rings = polygons[k];
  58404. for (j = 0, jj = rings.length; j < jj; ++j) {
  58405. coordinates = rings[j];
  58406. for (i = 0, ii = coordinates.length - 1; i < ii; ++i) {
  58407. segment = coordinates.slice(i, i + 2);
  58408. segmentData = /** @type {ol.ModifySegmentDataType} */ ({
  58409. feature: feature,
  58410. geometry: geometry,
  58411. depth: [j, k],
  58412. index: i,
  58413. segment: segment
  58414. });
  58415. this.rBush_.insert(ol.extent.boundingExtent(segment), segmentData);
  58416. }
  58417. }
  58418. }
  58419. };
  58420. /**
  58421. * We convert a circle into two segments. The segment at index
  58422. * {@link ol.interaction.Modify.MODIFY_SEGMENT_CIRCLE_CENTER_INDEX} is the
  58423. * circle's center (a point). The segment at index
  58424. * {@link ol.interaction.Modify.MODIFY_SEGMENT_CIRCLE_CIRCUMFERENCE_INDEX} is
  58425. * the circumference, and is not a line segment.
  58426. *
  58427. * @param {ol.Feature} feature Feature.
  58428. * @param {ol.geom.Circle} geometry Geometry.
  58429. * @private
  58430. */
  58431. ol.interaction.Modify.prototype.writeCircleGeometry_ = function(feature, geometry) {
  58432. var coordinates = geometry.getCenter();
  58433. var centerSegmentData = /** @type {ol.ModifySegmentDataType} */ ({
  58434. feature: feature,
  58435. geometry: geometry,
  58436. index: ol.interaction.Modify.MODIFY_SEGMENT_CIRCLE_CENTER_INDEX,
  58437. segment: [coordinates, coordinates]
  58438. });
  58439. var circumferenceSegmentData = /** @type {ol.ModifySegmentDataType} */ ({
  58440. feature: feature,
  58441. geometry: geometry,
  58442. index: ol.interaction.Modify.MODIFY_SEGMENT_CIRCLE_CIRCUMFERENCE_INDEX,
  58443. segment: [coordinates, coordinates]
  58444. });
  58445. var featureSegments = [centerSegmentData, circumferenceSegmentData];
  58446. centerSegmentData.featureSegments = circumferenceSegmentData.featureSegments = featureSegments;
  58447. this.rBush_.insert(ol.extent.createOrUpdateFromCoordinate(coordinates), centerSegmentData);
  58448. this.rBush_.insert(geometry.getExtent(), circumferenceSegmentData);
  58449. };
  58450. /**
  58451. * @param {ol.Feature} feature Feature
  58452. * @param {ol.geom.GeometryCollection} geometry Geometry.
  58453. * @private
  58454. */
  58455. ol.interaction.Modify.prototype.writeGeometryCollectionGeometry_ = function(feature, geometry) {
  58456. var i, geometries = geometry.getGeometriesArray();
  58457. for (i = 0; i < geometries.length; ++i) {
  58458. this.SEGMENT_WRITERS_[geometries[i].getType()].call(
  58459. this, feature, geometries[i]);
  58460. }
  58461. };
  58462. /**
  58463. * @param {ol.Coordinate} coordinates Coordinates.
  58464. * @return {ol.Feature} Vertex feature.
  58465. * @private
  58466. */
  58467. ol.interaction.Modify.prototype.createOrUpdateVertexFeature_ = function(coordinates) {
  58468. var vertexFeature = this.vertexFeature_;
  58469. if (!vertexFeature) {
  58470. vertexFeature = new ol.Feature(new ol.geom.Point(coordinates));
  58471. this.vertexFeature_ = vertexFeature;
  58472. this.overlay_.getSource().addFeature(vertexFeature);
  58473. } else {
  58474. var geometry = /** @type {ol.geom.Point} */ (vertexFeature.getGeometry());
  58475. geometry.setCoordinates(coordinates);
  58476. }
  58477. return vertexFeature;
  58478. };
  58479. /**
  58480. * @param {ol.ModifySegmentDataType} a The first segment data.
  58481. * @param {ol.ModifySegmentDataType} b The second segment data.
  58482. * @return {number} The difference in indexes.
  58483. * @private
  58484. */
  58485. ol.interaction.Modify.compareIndexes_ = function(a, b) {
  58486. return a.index - b.index;
  58487. };
  58488. /**
  58489. * @param {ol.MapBrowserPointerEvent} evt Event.
  58490. * @return {boolean} Start drag sequence?
  58491. * @this {ol.interaction.Modify}
  58492. * @private
  58493. */
  58494. ol.interaction.Modify.handleDownEvent_ = function(evt) {
  58495. if (!this.condition_(evt)) {
  58496. return false;
  58497. }
  58498. this.handlePointerAtPixel_(evt.pixel, evt.map);
  58499. var pixelCoordinate = evt.map.getCoordinateFromPixel(evt.pixel);
  58500. this.dragSegments_.length = 0;
  58501. this.modified_ = false;
  58502. var vertexFeature = this.vertexFeature_;
  58503. if (vertexFeature) {
  58504. var insertVertices = [];
  58505. var geometry = /** @type {ol.geom.Point} */ (vertexFeature.getGeometry());
  58506. var vertex = geometry.getCoordinates();
  58507. var vertexExtent = ol.extent.boundingExtent([vertex]);
  58508. var segmentDataMatches = this.rBush_.getInExtent(vertexExtent);
  58509. var componentSegments = {};
  58510. segmentDataMatches.sort(ol.interaction.Modify.compareIndexes_);
  58511. for (var i = 0, ii = segmentDataMatches.length; i < ii; ++i) {
  58512. var segmentDataMatch = segmentDataMatches[i];
  58513. var segment = segmentDataMatch.segment;
  58514. var uid = ol.getUid(segmentDataMatch.feature);
  58515. var depth = segmentDataMatch.depth;
  58516. if (depth) {
  58517. uid += '-' + depth.join('-'); // separate feature components
  58518. }
  58519. if (!componentSegments[uid]) {
  58520. componentSegments[uid] = new Array(2);
  58521. }
  58522. if (segmentDataMatch.geometry.getType() === ol.geom.GeometryType.CIRCLE &&
  58523. segmentDataMatch.index === ol.interaction.Modify.MODIFY_SEGMENT_CIRCLE_CIRCUMFERENCE_INDEX) {
  58524. var closestVertex = ol.interaction.Modify.closestOnSegmentData_(pixelCoordinate, segmentDataMatch);
  58525. if (ol.coordinate.equals(closestVertex, vertex) && !componentSegments[uid][0]) {
  58526. this.dragSegments_.push([segmentDataMatch, 0]);
  58527. componentSegments[uid][0] = segmentDataMatch;
  58528. }
  58529. } else if (ol.coordinate.equals(segment[0], vertex) &&
  58530. !componentSegments[uid][0]) {
  58531. this.dragSegments_.push([segmentDataMatch, 0]);
  58532. componentSegments[uid][0] = segmentDataMatch;
  58533. } else if (ol.coordinate.equals(segment[1], vertex) &&
  58534. !componentSegments[uid][1]) {
  58535. // prevent dragging closed linestrings by the connecting node
  58536. if ((segmentDataMatch.geometry.getType() ===
  58537. ol.geom.GeometryType.LINE_STRING ||
  58538. segmentDataMatch.geometry.getType() ===
  58539. ol.geom.GeometryType.MULTI_LINE_STRING) &&
  58540. componentSegments[uid][0] &&
  58541. componentSegments[uid][0].index === 0) {
  58542. continue;
  58543. }
  58544. this.dragSegments_.push([segmentDataMatch, 1]);
  58545. componentSegments[uid][1] = segmentDataMatch;
  58546. } else if (this.insertVertexCondition_(evt) && ol.getUid(segment) in this.vertexSegments_ &&
  58547. (!componentSegments[uid][0] && !componentSegments[uid][1])) {
  58548. insertVertices.push([segmentDataMatch, vertex]);
  58549. }
  58550. }
  58551. if (insertVertices.length) {
  58552. this.willModifyFeatures_(evt);
  58553. }
  58554. for (var j = insertVertices.length - 1; j >= 0; --j) {
  58555. this.insertVertex_.apply(this, insertVertices[j]);
  58556. }
  58557. }
  58558. return !!this.vertexFeature_;
  58559. };
  58560. /**
  58561. * @param {ol.MapBrowserPointerEvent} evt Event.
  58562. * @this {ol.interaction.Modify}
  58563. * @private
  58564. */
  58565. ol.interaction.Modify.handleDragEvent_ = function(evt) {
  58566. this.ignoreNextSingleClick_ = false;
  58567. this.willModifyFeatures_(evt);
  58568. var vertex = evt.coordinate;
  58569. for (var i = 0, ii = this.dragSegments_.length; i < ii; ++i) {
  58570. var dragSegment = this.dragSegments_[i];
  58571. var segmentData = dragSegment[0];
  58572. var depth = segmentData.depth;
  58573. var geometry = segmentData.geometry;
  58574. var coordinates;
  58575. var segment = segmentData.segment;
  58576. var index = dragSegment[1];
  58577. while (vertex.length < geometry.getStride()) {
  58578. vertex.push(segment[index][vertex.length]);
  58579. }
  58580. switch (geometry.getType()) {
  58581. case ol.geom.GeometryType.POINT:
  58582. coordinates = vertex;
  58583. segment[0] = segment[1] = vertex;
  58584. break;
  58585. case ol.geom.GeometryType.MULTI_POINT:
  58586. coordinates = geometry.getCoordinates();
  58587. coordinates[segmentData.index] = vertex;
  58588. segment[0] = segment[1] = vertex;
  58589. break;
  58590. case ol.geom.GeometryType.LINE_STRING:
  58591. coordinates = geometry.getCoordinates();
  58592. coordinates[segmentData.index + index] = vertex;
  58593. segment[index] = vertex;
  58594. break;
  58595. case ol.geom.GeometryType.MULTI_LINE_STRING:
  58596. coordinates = geometry.getCoordinates();
  58597. coordinates[depth[0]][segmentData.index + index] = vertex;
  58598. segment[index] = vertex;
  58599. break;
  58600. case ol.geom.GeometryType.POLYGON:
  58601. coordinates = geometry.getCoordinates();
  58602. coordinates[depth[0]][segmentData.index + index] = vertex;
  58603. segment[index] = vertex;
  58604. break;
  58605. case ol.geom.GeometryType.MULTI_POLYGON:
  58606. coordinates = geometry.getCoordinates();
  58607. coordinates[depth[1]][depth[0]][segmentData.index + index] = vertex;
  58608. segment[index] = vertex;
  58609. break;
  58610. case ol.geom.GeometryType.CIRCLE:
  58611. segment[0] = segment[1] = vertex;
  58612. if (segmentData.index === ol.interaction.Modify.MODIFY_SEGMENT_CIRCLE_CENTER_INDEX) {
  58613. this.changingFeature_ = true;
  58614. geometry.setCenter(vertex);
  58615. this.changingFeature_ = false;
  58616. } else { // We're dragging the circle's circumference:
  58617. this.changingFeature_ = true;
  58618. geometry.setRadius(ol.coordinate.distance(geometry.getCenter(), vertex));
  58619. this.changingFeature_ = false;
  58620. }
  58621. break;
  58622. default:
  58623. // pass
  58624. }
  58625. if (coordinates) {
  58626. this.setGeometryCoordinates_(geometry, coordinates);
  58627. }
  58628. }
  58629. this.createOrUpdateVertexFeature_(vertex);
  58630. };
  58631. /**
  58632. * @param {ol.MapBrowserPointerEvent} evt Event.
  58633. * @return {boolean} Stop drag sequence?
  58634. * @this {ol.interaction.Modify}
  58635. * @private
  58636. */
  58637. ol.interaction.Modify.handleUpEvent_ = function(evt) {
  58638. var segmentData;
  58639. var geometry;
  58640. for (var i = this.dragSegments_.length - 1; i >= 0; --i) {
  58641. segmentData = this.dragSegments_[i][0];
  58642. geometry = segmentData.geometry;
  58643. if (geometry.getType() === ol.geom.GeometryType.CIRCLE) {
  58644. // Update a circle object in the R* bush:
  58645. var coordinates = geometry.getCenter();
  58646. var centerSegmentData = segmentData.featureSegments[0];
  58647. var circumferenceSegmentData = segmentData.featureSegments[1];
  58648. centerSegmentData.segment[0] = centerSegmentData.segment[1] = coordinates;
  58649. circumferenceSegmentData.segment[0] = circumferenceSegmentData.segment[1] = coordinates;
  58650. this.rBush_.update(ol.extent.createOrUpdateFromCoordinate(coordinates), centerSegmentData);
  58651. this.rBush_.update(geometry.getExtent(), circumferenceSegmentData);
  58652. } else {
  58653. this.rBush_.update(ol.extent.boundingExtent(segmentData.segment),
  58654. segmentData);
  58655. }
  58656. }
  58657. if (this.modified_) {
  58658. this.dispatchEvent(new ol.interaction.Modify.Event(
  58659. ol.interaction.ModifyEventType.MODIFYEND, this.features_, evt));
  58660. this.modified_ = false;
  58661. }
  58662. return false;
  58663. };
  58664. /**
  58665. * Handles the {@link ol.MapBrowserEvent map browser event} and may modify the
  58666. * geometry.
  58667. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  58668. * @return {boolean} `false` to stop event propagation.
  58669. * @this {ol.interaction.Modify}
  58670. * @api
  58671. */
  58672. ol.interaction.Modify.handleEvent = function(mapBrowserEvent) {
  58673. if (!(mapBrowserEvent instanceof ol.MapBrowserPointerEvent)) {
  58674. return true;
  58675. }
  58676. this.lastPointerEvent_ = mapBrowserEvent;
  58677. var handled;
  58678. if (!mapBrowserEvent.map.getView().getHints()[ol.ViewHint.INTERACTING] &&
  58679. mapBrowserEvent.type == ol.MapBrowserEventType.POINTERMOVE &&
  58680. !this.handlingDownUpSequence) {
  58681. this.handlePointerMove_(mapBrowserEvent);
  58682. }
  58683. if (this.vertexFeature_ && this.deleteCondition_(mapBrowserEvent)) {
  58684. if (mapBrowserEvent.type != ol.MapBrowserEventType.SINGLECLICK ||
  58685. !this.ignoreNextSingleClick_) {
  58686. handled = this.removePoint();
  58687. } else {
  58688. handled = true;
  58689. }
  58690. }
  58691. if (mapBrowserEvent.type == ol.MapBrowserEventType.SINGLECLICK) {
  58692. this.ignoreNextSingleClick_ = false;
  58693. }
  58694. return ol.interaction.Pointer.handleEvent.call(this, mapBrowserEvent) &&
  58695. !handled;
  58696. };
  58697. /**
  58698. * @param {ol.MapBrowserEvent} evt Event.
  58699. * @private
  58700. */
  58701. ol.interaction.Modify.prototype.handlePointerMove_ = function(evt) {
  58702. this.lastPixel_ = evt.pixel;
  58703. this.handlePointerAtPixel_(evt.pixel, evt.map);
  58704. };
  58705. /**
  58706. * @param {ol.Pixel} pixel Pixel
  58707. * @param {ol.Map} map Map.
  58708. * @private
  58709. */
  58710. ol.interaction.Modify.prototype.handlePointerAtPixel_ = function(pixel, map) {
  58711. var pixelCoordinate = map.getCoordinateFromPixel(pixel);
  58712. var sortByDistance = function(a, b) {
  58713. return ol.interaction.Modify.pointDistanceToSegmentDataSquared_(pixelCoordinate, a) -
  58714. ol.interaction.Modify.pointDistanceToSegmentDataSquared_(pixelCoordinate, b);
  58715. };
  58716. var box = ol.extent.buffer(
  58717. ol.extent.createOrUpdateFromCoordinate(pixelCoordinate),
  58718. map.getView().getResolution() * this.pixelTolerance_);
  58719. var rBush = this.rBush_;
  58720. var nodes = rBush.getInExtent(box);
  58721. if (nodes.length > 0) {
  58722. nodes.sort(sortByDistance);
  58723. var node = nodes[0];
  58724. var closestSegment = node.segment;
  58725. var vertex = ol.interaction.Modify.closestOnSegmentData_(pixelCoordinate, node);
  58726. var vertexPixel = map.getPixelFromCoordinate(vertex);
  58727. var dist = ol.coordinate.distance(pixel, vertexPixel);
  58728. if (dist <= this.pixelTolerance_) {
  58729. var vertexSegments = {};
  58730. if (node.geometry.getType() === ol.geom.GeometryType.CIRCLE &&
  58731. node.index === ol.interaction.Modify.MODIFY_SEGMENT_CIRCLE_CIRCUMFERENCE_INDEX) {
  58732. this.snappedToVertex_ = true;
  58733. this.createOrUpdateVertexFeature_(vertex);
  58734. } else {
  58735. var pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
  58736. var pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
  58737. var squaredDist1 = ol.coordinate.squaredDistance(vertexPixel, pixel1);
  58738. var squaredDist2 = ol.coordinate.squaredDistance(vertexPixel, pixel2);
  58739. dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
  58740. this.snappedToVertex_ = dist <= this.pixelTolerance_;
  58741. if (this.snappedToVertex_) {
  58742. vertex = squaredDist1 > squaredDist2 ?
  58743. closestSegment[1] : closestSegment[0];
  58744. }
  58745. this.createOrUpdateVertexFeature_(vertex);
  58746. var segment;
  58747. for (var i = 1, ii = nodes.length; i < ii; ++i) {
  58748. segment = nodes[i].segment;
  58749. if ((ol.coordinate.equals(closestSegment[0], segment[0]) &&
  58750. ol.coordinate.equals(closestSegment[1], segment[1]) ||
  58751. (ol.coordinate.equals(closestSegment[0], segment[1]) &&
  58752. ol.coordinate.equals(closestSegment[1], segment[0])))) {
  58753. vertexSegments[ol.getUid(segment)] = true;
  58754. } else {
  58755. break;
  58756. }
  58757. }
  58758. }
  58759. vertexSegments[ol.getUid(closestSegment)] = true;
  58760. this.vertexSegments_ = vertexSegments;
  58761. return;
  58762. }
  58763. }
  58764. if (this.vertexFeature_) {
  58765. this.overlay_.getSource().removeFeature(this.vertexFeature_);
  58766. this.vertexFeature_ = null;
  58767. }
  58768. };
  58769. /**
  58770. * Returns the distance from a point to a line segment.
  58771. *
  58772. * @param {ol.Coordinate} pointCoordinates The coordinates of the point from
  58773. * which to calculate the distance.
  58774. * @param {ol.ModifySegmentDataType} segmentData The object describing the line
  58775. * segment we are calculating the distance to.
  58776. * @return {number} The square of the distance between a point and a line segment.
  58777. */
  58778. ol.interaction.Modify.pointDistanceToSegmentDataSquared_ = function(pointCoordinates, segmentData) {
  58779. var geometry = segmentData.geometry;
  58780. if (geometry.getType() === ol.geom.GeometryType.CIRCLE) {
  58781. var circleGeometry = /** @type {ol.geom.Circle} */ (geometry);
  58782. if (segmentData.index === ol.interaction.Modify.MODIFY_SEGMENT_CIRCLE_CIRCUMFERENCE_INDEX) {
  58783. var distanceToCenterSquared =
  58784. ol.coordinate.squaredDistance(circleGeometry.getCenter(), pointCoordinates);
  58785. var distanceToCircumference =
  58786. Math.sqrt(distanceToCenterSquared) - circleGeometry.getRadius();
  58787. return distanceToCircumference * distanceToCircumference;
  58788. }
  58789. }
  58790. return ol.coordinate.squaredDistanceToSegment(pointCoordinates, segmentData.segment);
  58791. };
  58792. /**
  58793. * Returns the point closest to a given line segment.
  58794. *
  58795. * @param {ol.Coordinate} pointCoordinates The point to which a closest point
  58796. * should be found.
  58797. * @param {ol.ModifySegmentDataType} segmentData The object describing the line
  58798. * segment which should contain the closest point.
  58799. * @return {ol.Coordinate} The point closest to the specified line segment.
  58800. */
  58801. ol.interaction.Modify.closestOnSegmentData_ = function(pointCoordinates, segmentData) {
  58802. var geometry = segmentData.geometry;
  58803. if (geometry.getType() === ol.geom.GeometryType.CIRCLE &&
  58804. segmentData.index === ol.interaction.Modify.MODIFY_SEGMENT_CIRCLE_CIRCUMFERENCE_INDEX) {
  58805. return geometry.getClosestPoint(pointCoordinates);
  58806. }
  58807. return ol.coordinate.closestOnSegment(pointCoordinates, segmentData.segment);
  58808. };
  58809. /**
  58810. * @param {ol.ModifySegmentDataType} segmentData Segment data.
  58811. * @param {ol.Coordinate} vertex Vertex.
  58812. * @private
  58813. */
  58814. ol.interaction.Modify.prototype.insertVertex_ = function(segmentData, vertex) {
  58815. var segment = segmentData.segment;
  58816. var feature = segmentData.feature;
  58817. var geometry = segmentData.geometry;
  58818. var depth = segmentData.depth;
  58819. var index = /** @type {number} */ (segmentData.index);
  58820. var coordinates;
  58821. while (vertex.length < geometry.getStride()) {
  58822. vertex.push(0);
  58823. }
  58824. switch (geometry.getType()) {
  58825. case ol.geom.GeometryType.MULTI_LINE_STRING:
  58826. coordinates = geometry.getCoordinates();
  58827. coordinates[depth[0]].splice(index + 1, 0, vertex);
  58828. break;
  58829. case ol.geom.GeometryType.POLYGON:
  58830. coordinates = geometry.getCoordinates();
  58831. coordinates[depth[0]].splice(index + 1, 0, vertex);
  58832. break;
  58833. case ol.geom.GeometryType.MULTI_POLYGON:
  58834. coordinates = geometry.getCoordinates();
  58835. coordinates[depth[1]][depth[0]].splice(index + 1, 0, vertex);
  58836. break;
  58837. case ol.geom.GeometryType.LINE_STRING:
  58838. coordinates = geometry.getCoordinates();
  58839. coordinates.splice(index + 1, 0, vertex);
  58840. break;
  58841. default:
  58842. return;
  58843. }
  58844. this.setGeometryCoordinates_(geometry, coordinates);
  58845. var rTree = this.rBush_;
  58846. rTree.remove(segmentData);
  58847. this.updateSegmentIndices_(geometry, index, depth, 1);
  58848. var newSegmentData = /** @type {ol.ModifySegmentDataType} */ ({
  58849. segment: [segment[0], vertex],
  58850. feature: feature,
  58851. geometry: geometry,
  58852. depth: depth,
  58853. index: index
  58854. });
  58855. rTree.insert(ol.extent.boundingExtent(newSegmentData.segment),
  58856. newSegmentData);
  58857. this.dragSegments_.push([newSegmentData, 1]);
  58858. var newSegmentData2 = /** @type {ol.ModifySegmentDataType} */ ({
  58859. segment: [vertex, segment[1]],
  58860. feature: feature,
  58861. geometry: geometry,
  58862. depth: depth,
  58863. index: index + 1
  58864. });
  58865. rTree.insert(ol.extent.boundingExtent(newSegmentData2.segment),
  58866. newSegmentData2);
  58867. this.dragSegments_.push([newSegmentData2, 0]);
  58868. this.ignoreNextSingleClick_ = true;
  58869. };
  58870. /**
  58871. * Removes the vertex currently being pointed.
  58872. * @return {boolean} True when a vertex was removed.
  58873. * @api
  58874. */
  58875. ol.interaction.Modify.prototype.removePoint = function() {
  58876. if (this.lastPointerEvent_ && this.lastPointerEvent_.type != ol.MapBrowserEventType.POINTERDRAG) {
  58877. var evt = this.lastPointerEvent_;
  58878. this.willModifyFeatures_(evt);
  58879. this.removeVertex_();
  58880. this.dispatchEvent(new ol.interaction.Modify.Event(
  58881. ol.interaction.ModifyEventType.MODIFYEND, this.features_, evt));
  58882. this.modified_ = false;
  58883. return true;
  58884. }
  58885. return false;
  58886. };
  58887. /**
  58888. * Removes a vertex from all matching features.
  58889. * @return {boolean} True when a vertex was removed.
  58890. * @private
  58891. */
  58892. ol.interaction.Modify.prototype.removeVertex_ = function() {
  58893. var dragSegments = this.dragSegments_;
  58894. var segmentsByFeature = {};
  58895. var deleted = false;
  58896. var component, coordinates, dragSegment, geometry, i, index, left;
  58897. var newIndex, right, segmentData, uid;
  58898. for (i = dragSegments.length - 1; i >= 0; --i) {
  58899. dragSegment = dragSegments[i];
  58900. segmentData = dragSegment[0];
  58901. uid = ol.getUid(segmentData.feature);
  58902. if (segmentData.depth) {
  58903. // separate feature components
  58904. uid += '-' + segmentData.depth.join('-');
  58905. }
  58906. if (!(uid in segmentsByFeature)) {
  58907. segmentsByFeature[uid] = {};
  58908. }
  58909. if (dragSegment[1] === 0) {
  58910. segmentsByFeature[uid].right = segmentData;
  58911. segmentsByFeature[uid].index = segmentData.index;
  58912. } else if (dragSegment[1] == 1) {
  58913. segmentsByFeature[uid].left = segmentData;
  58914. segmentsByFeature[uid].index = segmentData.index + 1;
  58915. }
  58916. }
  58917. for (uid in segmentsByFeature) {
  58918. right = segmentsByFeature[uid].right;
  58919. left = segmentsByFeature[uid].left;
  58920. index = segmentsByFeature[uid].index;
  58921. newIndex = index - 1;
  58922. if (left !== undefined) {
  58923. segmentData = left;
  58924. } else {
  58925. segmentData = right;
  58926. }
  58927. if (newIndex < 0) {
  58928. newIndex = 0;
  58929. }
  58930. geometry = segmentData.geometry;
  58931. coordinates = geometry.getCoordinates();
  58932. component = coordinates;
  58933. deleted = false;
  58934. switch (geometry.getType()) {
  58935. case ol.geom.GeometryType.MULTI_LINE_STRING:
  58936. if (coordinates[segmentData.depth[0]].length > 2) {
  58937. coordinates[segmentData.depth[0]].splice(index, 1);
  58938. deleted = true;
  58939. }
  58940. break;
  58941. case ol.geom.GeometryType.LINE_STRING:
  58942. if (coordinates.length > 2) {
  58943. coordinates.splice(index, 1);
  58944. deleted = true;
  58945. }
  58946. break;
  58947. case ol.geom.GeometryType.MULTI_POLYGON:
  58948. component = component[segmentData.depth[1]];
  58949. /* falls through */
  58950. case ol.geom.GeometryType.POLYGON:
  58951. component = component[segmentData.depth[0]];
  58952. if (component.length > 4) {
  58953. if (index == component.length - 1) {
  58954. index = 0;
  58955. }
  58956. component.splice(index, 1);
  58957. deleted = true;
  58958. if (index === 0) {
  58959. // close the ring again
  58960. component.pop();
  58961. component.push(component[0]);
  58962. newIndex = component.length - 1;
  58963. }
  58964. }
  58965. break;
  58966. default:
  58967. // pass
  58968. }
  58969. if (deleted) {
  58970. this.setGeometryCoordinates_(geometry, coordinates);
  58971. var segments = [];
  58972. if (left !== undefined) {
  58973. this.rBush_.remove(left);
  58974. segments.push(left.segment[0]);
  58975. }
  58976. if (right !== undefined) {
  58977. this.rBush_.remove(right);
  58978. segments.push(right.segment[1]);
  58979. }
  58980. if (left !== undefined && right !== undefined) {
  58981. var newSegmentData = /** @type {ol.ModifySegmentDataType} */ ({
  58982. depth: segmentData.depth,
  58983. feature: segmentData.feature,
  58984. geometry: segmentData.geometry,
  58985. index: newIndex,
  58986. segment: segments
  58987. });
  58988. this.rBush_.insert(ol.extent.boundingExtent(newSegmentData.segment),
  58989. newSegmentData);
  58990. }
  58991. this.updateSegmentIndices_(geometry, index, segmentData.depth, -1);
  58992. if (this.vertexFeature_) {
  58993. this.overlay_.getSource().removeFeature(this.vertexFeature_);
  58994. this.vertexFeature_ = null;
  58995. }
  58996. dragSegments.length = 0;
  58997. }
  58998. }
  58999. return deleted;
  59000. };
  59001. /**
  59002. * @param {ol.geom.SimpleGeometry} geometry Geometry.
  59003. * @param {Array} coordinates Coordinates.
  59004. * @private
  59005. */
  59006. ol.interaction.Modify.prototype.setGeometryCoordinates_ = function(geometry, coordinates) {
  59007. this.changingFeature_ = true;
  59008. geometry.setCoordinates(coordinates);
  59009. this.changingFeature_ = false;
  59010. };
  59011. /**
  59012. * @param {ol.geom.SimpleGeometry} geometry Geometry.
  59013. * @param {number} index Index.
  59014. * @param {Array.<number>|undefined} depth Depth.
  59015. * @param {number} delta Delta (1 or -1).
  59016. * @private
  59017. */
  59018. ol.interaction.Modify.prototype.updateSegmentIndices_ = function(
  59019. geometry, index, depth, delta) {
  59020. this.rBush_.forEachInExtent(geometry.getExtent(), function(segmentDataMatch) {
  59021. if (segmentDataMatch.geometry === geometry &&
  59022. (depth === undefined || segmentDataMatch.depth === undefined ||
  59023. ol.array.equals(segmentDataMatch.depth, depth)) &&
  59024. segmentDataMatch.index > index) {
  59025. segmentDataMatch.index += delta;
  59026. }
  59027. });
  59028. };
  59029. /**
  59030. * @return {ol.StyleFunction} Styles.
  59031. */
  59032. ol.interaction.Modify.getDefaultStyleFunction = function() {
  59033. var style = ol.style.Style.createDefaultEditing();
  59034. return function(feature, resolution) {
  59035. return style[ol.geom.GeometryType.POINT];
  59036. };
  59037. };
  59038. /**
  59039. * @classdesc
  59040. * Events emitted by {@link ol.interaction.Modify} instances are instances of
  59041. * this type.
  59042. *
  59043. * @constructor
  59044. * @extends {ol.events.Event}
  59045. * @implements {oli.ModifyEvent}
  59046. * @param {ol.interaction.ModifyEventType} type Type.
  59047. * @param {ol.Collection.<ol.Feature>} features The features modified.
  59048. * @param {ol.MapBrowserPointerEvent} mapBrowserPointerEvent Associated
  59049. * {@link ol.MapBrowserPointerEvent}.
  59050. */
  59051. ol.interaction.Modify.Event = function(type, features, mapBrowserPointerEvent) {
  59052. ol.events.Event.call(this, type);
  59053. /**
  59054. * The features being modified.
  59055. * @type {ol.Collection.<ol.Feature>}
  59056. * @api
  59057. */
  59058. this.features = features;
  59059. /**
  59060. * Associated {@link ol.MapBrowserEvent}.
  59061. * @type {ol.MapBrowserEvent}
  59062. * @api
  59063. */
  59064. this.mapBrowserEvent = mapBrowserPointerEvent;
  59065. };
  59066. ol.inherits(ol.interaction.Modify.Event, ol.events.Event);
  59067. goog.provide('ol.interaction.Select');
  59068. goog.require('ol');
  59069. goog.require('ol.CollectionEventType');
  59070. goog.require('ol.array');
  59071. goog.require('ol.events');
  59072. goog.require('ol.events.Event');
  59073. goog.require('ol.events.condition');
  59074. goog.require('ol.functions');
  59075. goog.require('ol.geom.GeometryType');
  59076. goog.require('ol.interaction.Interaction');
  59077. goog.require('ol.layer.Vector');
  59078. goog.require('ol.obj');
  59079. goog.require('ol.source.Vector');
  59080. goog.require('ol.style.Style');
  59081. /**
  59082. * @classdesc
  59083. * Interaction for selecting vector features. By default, selected features are
  59084. * styled differently, so this interaction can be used for visual highlighting,
  59085. * as well as selecting features for other actions, such as modification or
  59086. * output. There are three ways of controlling which features are selected:
  59087. * using the browser event as defined by the `condition` and optionally the
  59088. * `toggle`, `add`/`remove`, and `multi` options; a `layers` filter; and a
  59089. * further feature filter using the `filter` option.
  59090. *
  59091. * Selected features are added to an internal unmanaged layer.
  59092. *
  59093. * @constructor
  59094. * @extends {ol.interaction.Interaction}
  59095. * @param {olx.interaction.SelectOptions=} opt_options Options.
  59096. * @fires ol.interaction.Select.Event
  59097. * @api
  59098. */
  59099. ol.interaction.Select = function(opt_options) {
  59100. ol.interaction.Interaction.call(this, {
  59101. handleEvent: ol.interaction.Select.handleEvent
  59102. });
  59103. var options = opt_options ? opt_options : {};
  59104. /**
  59105. * @private
  59106. * @type {ol.EventsConditionType}
  59107. */
  59108. this.condition_ = options.condition ?
  59109. options.condition : ol.events.condition.singleClick;
  59110. /**
  59111. * @private
  59112. * @type {ol.EventsConditionType}
  59113. */
  59114. this.addCondition_ = options.addCondition ?
  59115. options.addCondition : ol.events.condition.never;
  59116. /**
  59117. * @private
  59118. * @type {ol.EventsConditionType}
  59119. */
  59120. this.removeCondition_ = options.removeCondition ?
  59121. options.removeCondition : ol.events.condition.never;
  59122. /**
  59123. * @private
  59124. * @type {ol.EventsConditionType}
  59125. */
  59126. this.toggleCondition_ = options.toggleCondition ?
  59127. options.toggleCondition : ol.events.condition.shiftKeyOnly;
  59128. /**
  59129. * @private
  59130. * @type {boolean}
  59131. */
  59132. this.multi_ = options.multi ? options.multi : false;
  59133. /**
  59134. * @private
  59135. * @type {ol.SelectFilterFunction}
  59136. */
  59137. this.filter_ = options.filter ? options.filter :
  59138. ol.functions.TRUE;
  59139. /**
  59140. * @private
  59141. * @type {number}
  59142. */
  59143. this.hitTolerance_ = options.hitTolerance ? options.hitTolerance : 0;
  59144. var featureOverlay = new ol.layer.Vector({
  59145. source: new ol.source.Vector({
  59146. useSpatialIndex: false,
  59147. features: options.features,
  59148. wrapX: options.wrapX
  59149. }),
  59150. style: options.style ? options.style :
  59151. ol.interaction.Select.getDefaultStyleFunction(),
  59152. updateWhileAnimating: true,
  59153. updateWhileInteracting: true
  59154. });
  59155. /**
  59156. * @private
  59157. * @type {ol.layer.Vector}
  59158. */
  59159. this.featureOverlay_ = featureOverlay;
  59160. /** @type {function(ol.layer.Layer): boolean} */
  59161. var layerFilter;
  59162. if (options.layers) {
  59163. if (typeof options.layers === 'function') {
  59164. layerFilter = options.layers;
  59165. } else {
  59166. var layers = options.layers;
  59167. layerFilter = function(layer) {
  59168. return ol.array.includes(layers, layer);
  59169. };
  59170. }
  59171. } else {
  59172. layerFilter = ol.functions.TRUE;
  59173. }
  59174. /**
  59175. * @private
  59176. * @type {function(ol.layer.Layer): boolean}
  59177. */
  59178. this.layerFilter_ = layerFilter;
  59179. /**
  59180. * An association between selected feature (key)
  59181. * and layer (value)
  59182. * @private
  59183. * @type {Object.<number, ol.layer.Layer>}
  59184. */
  59185. this.featureLayerAssociation_ = {};
  59186. var features = this.featureOverlay_.getSource().getFeaturesCollection();
  59187. ol.events.listen(features, ol.CollectionEventType.ADD,
  59188. this.addFeature_, this);
  59189. ol.events.listen(features, ol.CollectionEventType.REMOVE,
  59190. this.removeFeature_, this);
  59191. };
  59192. ol.inherits(ol.interaction.Select, ol.interaction.Interaction);
  59193. /**
  59194. * @param {ol.Feature|ol.render.Feature} feature Feature.
  59195. * @param {ol.layer.Layer} layer Layer.
  59196. * @private
  59197. */
  59198. ol.interaction.Select.prototype.addFeatureLayerAssociation_ = function(feature, layer) {
  59199. var key = ol.getUid(feature);
  59200. this.featureLayerAssociation_[key] = layer;
  59201. };
  59202. /**
  59203. * Get the selected features.
  59204. * @return {ol.Collection.<ol.Feature>} Features collection.
  59205. * @api
  59206. */
  59207. ol.interaction.Select.prototype.getFeatures = function() {
  59208. return this.featureOverlay_.getSource().getFeaturesCollection();
  59209. };
  59210. /**
  59211. * Returns the Hit-detection tolerance.
  59212. * @returns {number} Hit tolerance in pixels.
  59213. * @api
  59214. */
  59215. ol.interaction.Select.prototype.getHitTolerance = function() {
  59216. return this.hitTolerance_;
  59217. };
  59218. /**
  59219. * Returns the associated {@link ol.layer.Vector vectorlayer} of
  59220. * the (last) selected feature. Note that this will not work with any
  59221. * programmatic method like pushing features to
  59222. * {@link ol.interaction.Select#getFeatures collection}.
  59223. * @param {ol.Feature|ol.render.Feature} feature Feature
  59224. * @return {ol.layer.Vector} Layer.
  59225. * @api
  59226. */
  59227. ol.interaction.Select.prototype.getLayer = function(feature) {
  59228. var key = ol.getUid(feature);
  59229. return /** @type {ol.layer.Vector} */ (this.featureLayerAssociation_[key]);
  59230. };
  59231. /**
  59232. * Handles the {@link ol.MapBrowserEvent map browser event} and may change the
  59233. * selected state of features.
  59234. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
  59235. * @return {boolean} `false` to stop event propagation.
  59236. * @this {ol.interaction.Select}
  59237. * @api
  59238. */
  59239. ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
  59240. if (!this.condition_(mapBrowserEvent)) {
  59241. return true;
  59242. }
  59243. var add = this.addCondition_(mapBrowserEvent);
  59244. var remove = this.removeCondition_(mapBrowserEvent);
  59245. var toggle = this.toggleCondition_(mapBrowserEvent);
  59246. var set = !add && !remove && !toggle;
  59247. var map = mapBrowserEvent.map;
  59248. var features = this.featureOverlay_.getSource().getFeaturesCollection();
  59249. var deselected = [];
  59250. var selected = [];
  59251. if (set) {
  59252. // Replace the currently selected feature(s) with the feature(s) at the
  59253. // pixel, or clear the selected feature(s) if there is no feature at
  59254. // the pixel.
  59255. ol.obj.clear(this.featureLayerAssociation_);
  59256. map.forEachFeatureAtPixel(mapBrowserEvent.pixel,
  59257. (
  59258. /**
  59259. * @param {ol.Feature|ol.render.Feature} feature Feature.
  59260. * @param {ol.layer.Layer} layer Layer.
  59261. * @return {boolean|undefined} Continue to iterate over the features.
  59262. */
  59263. function(feature, layer) {
  59264. if (this.filter_(feature, layer)) {
  59265. selected.push(feature);
  59266. this.addFeatureLayerAssociation_(feature, layer);
  59267. return !this.multi_;
  59268. }
  59269. }).bind(this), {
  59270. layerFilter: this.layerFilter_,
  59271. hitTolerance: this.hitTolerance_
  59272. });
  59273. var i;
  59274. for (i = features.getLength() - 1; i >= 0; --i) {
  59275. var feature = features.item(i);
  59276. var index = selected.indexOf(feature);
  59277. if (index > -1) {
  59278. // feature is already selected
  59279. selected.splice(index, 1);
  59280. } else {
  59281. features.remove(feature);
  59282. deselected.push(feature);
  59283. }
  59284. }
  59285. if (selected.length !== 0) {
  59286. features.extend(selected);
  59287. }
  59288. } else {
  59289. // Modify the currently selected feature(s).
  59290. map.forEachFeatureAtPixel(mapBrowserEvent.pixel,
  59291. (
  59292. /**
  59293. * @param {ol.Feature|ol.render.Feature} feature Feature.
  59294. * @param {ol.layer.Layer} layer Layer.
  59295. * @return {boolean|undefined} Continue to iterate over the features.
  59296. */
  59297. function(feature, layer) {
  59298. if (this.filter_(feature, layer)) {
  59299. if ((add || toggle) &&
  59300. !ol.array.includes(features.getArray(), feature)) {
  59301. selected.push(feature);
  59302. this.addFeatureLayerAssociation_(feature, layer);
  59303. } else if ((remove || toggle) &&
  59304. ol.array.includes(features.getArray(), feature)) {
  59305. deselected.push(feature);
  59306. this.removeFeatureLayerAssociation_(feature);
  59307. }
  59308. return !this.multi_;
  59309. }
  59310. }).bind(this), {
  59311. layerFilter: this.layerFilter_,
  59312. hitTolerance: this.hitTolerance_
  59313. });
  59314. var j;
  59315. for (j = deselected.length - 1; j >= 0; --j) {
  59316. features.remove(deselected[j]);
  59317. }
  59318. features.extend(selected);
  59319. }
  59320. if (selected.length > 0 || deselected.length > 0) {
  59321. this.dispatchEvent(
  59322. new ol.interaction.Select.Event(ol.interaction.Select.EventType_.SELECT,
  59323. selected, deselected, mapBrowserEvent));
  59324. }
  59325. return ol.events.condition.pointerMove(mapBrowserEvent);
  59326. };
  59327. /**
  59328. * Hit-detection tolerance. Pixels inside the radius around the given position
  59329. * will be checked for features. This only works for the canvas renderer and
  59330. * not for WebGL.
  59331. * @param {number} hitTolerance Hit tolerance in pixels.
  59332. * @api
  59333. */
  59334. ol.interaction.Select.prototype.setHitTolerance = function(hitTolerance) {
  59335. this.hitTolerance_ = hitTolerance;
  59336. };
  59337. /**
  59338. * Remove the interaction from its current map, if any, and attach it to a new
  59339. * map, if any. Pass `null` to just remove the interaction from the current map.
  59340. * @param {ol.Map} map Map.
  59341. * @override
  59342. * @api
  59343. */
  59344. ol.interaction.Select.prototype.setMap = function(map) {
  59345. var currentMap = this.getMap();
  59346. var selectedFeatures =
  59347. this.featureOverlay_.getSource().getFeaturesCollection();
  59348. if (currentMap) {
  59349. selectedFeatures.forEach(currentMap.unskipFeature, currentMap);
  59350. }
  59351. ol.interaction.Interaction.prototype.setMap.call(this, map);
  59352. this.featureOverlay_.setMap(map);
  59353. if (map) {
  59354. selectedFeatures.forEach(map.skipFeature, map);
  59355. }
  59356. };
  59357. /**
  59358. * @return {ol.StyleFunction} Styles.
  59359. */
  59360. ol.interaction.Select.getDefaultStyleFunction = function() {
  59361. var styles = ol.style.Style.createDefaultEditing();
  59362. ol.array.extend(styles[ol.geom.GeometryType.POLYGON],
  59363. styles[ol.geom.GeometryType.LINE_STRING]);
  59364. ol.array.extend(styles[ol.geom.GeometryType.GEOMETRY_COLLECTION],
  59365. styles[ol.geom.GeometryType.LINE_STRING]);
  59366. return function(feature, resolution) {
  59367. if (!feature.getGeometry()) {
  59368. return null;
  59369. }
  59370. return styles[feature.getGeometry().getType()];
  59371. };
  59372. };
  59373. /**
  59374. * @param {ol.Collection.Event} evt Event.
  59375. * @private
  59376. */
  59377. ol.interaction.Select.prototype.addFeature_ = function(evt) {
  59378. var map = this.getMap();
  59379. if (map) {
  59380. map.skipFeature(/** @type {ol.Feature} */ (evt.element));
  59381. }
  59382. };
  59383. /**
  59384. * @param {ol.Collection.Event} evt Event.
  59385. * @private
  59386. */
  59387. ol.interaction.Select.prototype.removeFeature_ = function(evt) {
  59388. var map = this.getMap();
  59389. if (map) {
  59390. map.unskipFeature(/** @type {ol.Feature} */ (evt.element));
  59391. }
  59392. };
  59393. /**
  59394. * @param {ol.Feature|ol.render.Feature} feature Feature.
  59395. * @private
  59396. */
  59397. ol.interaction.Select.prototype.removeFeatureLayerAssociation_ = function(feature) {
  59398. var key = ol.getUid(feature);
  59399. delete this.featureLayerAssociation_[key];
  59400. };
  59401. /**
  59402. * @classdesc
  59403. * Events emitted by {@link ol.interaction.Select} instances are instances of
  59404. * this type.
  59405. *
  59406. * @param {ol.interaction.Select.EventType_} type The event type.
  59407. * @param {Array.<ol.Feature>} selected Selected features.
  59408. * @param {Array.<ol.Feature>} deselected Deselected features.
  59409. * @param {ol.MapBrowserEvent} mapBrowserEvent Associated
  59410. * {@link ol.MapBrowserEvent}.
  59411. * @implements {oli.SelectEvent}
  59412. * @extends {ol.events.Event}
  59413. * @constructor
  59414. */
  59415. ol.interaction.Select.Event = function(type, selected, deselected, mapBrowserEvent) {
  59416. ol.events.Event.call(this, type);
  59417. /**
  59418. * Selected features array.
  59419. * @type {Array.<ol.Feature>}
  59420. * @api
  59421. */
  59422. this.selected = selected;
  59423. /**
  59424. * Deselected features array.
  59425. * @type {Array.<ol.Feature>}
  59426. * @api
  59427. */
  59428. this.deselected = deselected;
  59429. /**
  59430. * Associated {@link ol.MapBrowserEvent}.
  59431. * @type {ol.MapBrowserEvent}
  59432. * @api
  59433. */
  59434. this.mapBrowserEvent = mapBrowserEvent;
  59435. };
  59436. ol.inherits(ol.interaction.Select.Event, ol.events.Event);
  59437. /**
  59438. * @enum {string}
  59439. * @private
  59440. */
  59441. ol.interaction.Select.EventType_ = {
  59442. /**
  59443. * Triggered when feature(s) has been (de)selected.
  59444. * @event ol.interaction.Select.Event#select
  59445. * @api
  59446. */
  59447. SELECT: 'select'
  59448. };
  59449. goog.provide('ol.interaction.Snap');
  59450. goog.require('ol');
  59451. goog.require('ol.Collection');
  59452. goog.require('ol.CollectionEventType');
  59453. goog.require('ol.coordinate');
  59454. goog.require('ol.events');
  59455. goog.require('ol.events.EventType');
  59456. goog.require('ol.extent');
  59457. goog.require('ol.functions');
  59458. goog.require('ol.geom.GeometryType');
  59459. goog.require('ol.geom.Polygon');
  59460. goog.require('ol.interaction.Pointer');
  59461. goog.require('ol.obj');
  59462. goog.require('ol.source.Vector');
  59463. goog.require('ol.source.VectorEventType');
  59464. goog.require('ol.structs.RBush');
  59465. /**
  59466. * @classdesc
  59467. * Handles snapping of vector features while modifying or drawing them. The
  59468. * features can come from a {@link ol.source.Vector} or {@link ol.Collection}
  59469. * Any interaction object that allows the user to interact
  59470. * with the features using the mouse can benefit from the snapping, as long
  59471. * as it is added before.
  59472. *
  59473. * The snap interaction modifies map browser event `coordinate` and `pixel`
  59474. * properties to force the snap to occur to any interaction that them.
  59475. *
  59476. * Example:
  59477. *
  59478. * var snap = new ol.interaction.Snap({
  59479. * source: source
  59480. * });
  59481. *
  59482. * @constructor
  59483. * @extends {ol.interaction.Pointer}
  59484. * @param {olx.interaction.SnapOptions=} opt_options Options.
  59485. * @api
  59486. */
  59487. ol.interaction.Snap = function(opt_options) {
  59488. ol.interaction.Pointer.call(this, {
  59489. handleEvent: ol.interaction.Snap.handleEvent_,
  59490. handleDownEvent: ol.functions.TRUE,
  59491. handleUpEvent: ol.interaction.Snap.handleUpEvent_
  59492. });
  59493. var options = opt_options ? opt_options : {};
  59494. /**
  59495. * @type {ol.source.Vector}
  59496. * @private
  59497. */
  59498. this.source_ = options.source ? options.source : null;
  59499. /**
  59500. * @private
  59501. * @type {boolean}
  59502. */
  59503. this.vertex_ = options.vertex !== undefined ? options.vertex : true;
  59504. /**
  59505. * @private
  59506. * @type {boolean}
  59507. */
  59508. this.edge_ = options.edge !== undefined ? options.edge : true;
  59509. /**
  59510. * @type {ol.Collection.<ol.Feature>}
  59511. * @private
  59512. */
  59513. this.features_ = options.features ? options.features : null;
  59514. /**
  59515. * @type {Array.<ol.EventsKey>}
  59516. * @private
  59517. */
  59518. this.featuresListenerKeys_ = [];
  59519. /**
  59520. * @type {Object.<number, ol.EventsKey>}
  59521. * @private
  59522. */
  59523. this.featureChangeListenerKeys_ = {};
  59524. /**
  59525. * Extents are preserved so indexed segment can be quickly removed
  59526. * when its feature geometry changes
  59527. * @type {Object.<number, ol.Extent>}
  59528. * @private
  59529. */
  59530. this.indexedFeaturesExtents_ = {};
  59531. /**
  59532. * If a feature geometry changes while a pointer drag|move event occurs, the
  59533. * feature doesn't get updated right away. It will be at the next 'pointerup'
  59534. * event fired.
  59535. * @type {Object.<number, ol.Feature>}
  59536. * @private
  59537. */
  59538. this.pendingFeatures_ = {};
  59539. /**
  59540. * Used for distance sorting in sortByDistance_
  59541. * @type {ol.Coordinate}
  59542. * @private
  59543. */
  59544. this.pixelCoordinate_ = null;
  59545. /**
  59546. * @type {number}
  59547. * @private
  59548. */
  59549. this.pixelTolerance_ = options.pixelTolerance !== undefined ?
  59550. options.pixelTolerance : 10;
  59551. /**
  59552. * @type {function(ol.SnapSegmentDataType, ol.SnapSegmentDataType): number}
  59553. * @private
  59554. */
  59555. this.sortByDistance_ = ol.interaction.Snap.sortByDistance.bind(this);
  59556. /**
  59557. * Segment RTree for each layer
  59558. * @type {ol.structs.RBush.<ol.SnapSegmentDataType>}
  59559. * @private
  59560. */
  59561. this.rBush_ = new ol.structs.RBush();
  59562. /**
  59563. * @const
  59564. * @private
  59565. * @type {Object.<string, function(ol.Feature, ol.geom.Geometry)>}
  59566. */
  59567. this.SEGMENT_WRITERS_ = {
  59568. 'Point': this.writePointGeometry_,
  59569. 'LineString': this.writeLineStringGeometry_,
  59570. 'LinearRing': this.writeLineStringGeometry_,
  59571. 'Polygon': this.writePolygonGeometry_,
  59572. 'MultiPoint': this.writeMultiPointGeometry_,
  59573. 'MultiLineString': this.writeMultiLineStringGeometry_,
  59574. 'MultiPolygon': this.writeMultiPolygonGeometry_,
  59575. 'GeometryCollection': this.writeGeometryCollectionGeometry_,
  59576. 'Circle': this.writeCircleGeometry_
  59577. };
  59578. };
  59579. ol.inherits(ol.interaction.Snap, ol.interaction.Pointer);
  59580. /**
  59581. * Add a feature to the collection of features that we may snap to.
  59582. * @param {ol.Feature} feature Feature.
  59583. * @param {boolean=} opt_listen Whether to listen to the feature change or not
  59584. * Defaults to `true`.
  59585. * @api
  59586. */
  59587. ol.interaction.Snap.prototype.addFeature = function(feature, opt_listen) {
  59588. var listen = opt_listen !== undefined ? opt_listen : true;
  59589. var feature_uid = ol.getUid(feature);
  59590. var geometry = feature.getGeometry();
  59591. if (geometry) {
  59592. var segmentWriter = this.SEGMENT_WRITERS_[geometry.getType()];
  59593. if (segmentWriter) {
  59594. this.indexedFeaturesExtents_[feature_uid] = geometry.getExtent(
  59595. ol.extent.createEmpty());
  59596. segmentWriter.call(this, feature, geometry);
  59597. }
  59598. }
  59599. if (listen) {
  59600. this.featureChangeListenerKeys_[feature_uid] = ol.events.listen(
  59601. feature,
  59602. ol.events.EventType.CHANGE,
  59603. this.handleFeatureChange_, this);
  59604. }
  59605. };
  59606. /**
  59607. * @param {ol.Feature} feature Feature.
  59608. * @private
  59609. */
  59610. ol.interaction.Snap.prototype.forEachFeatureAdd_ = function(feature) {
  59611. this.addFeature(feature);
  59612. };
  59613. /**
  59614. * @param {ol.Feature} feature Feature.
  59615. * @private
  59616. */
  59617. ol.interaction.Snap.prototype.forEachFeatureRemove_ = function(feature) {
  59618. this.removeFeature(feature);
  59619. };
  59620. /**
  59621. * @return {ol.Collection.<ol.Feature>|Array.<ol.Feature>} Features.
  59622. * @private
  59623. */
  59624. ol.interaction.Snap.prototype.getFeatures_ = function() {
  59625. var features;
  59626. if (this.features_) {
  59627. features = this.features_;
  59628. } else if (this.source_) {
  59629. features = this.source_.getFeatures();
  59630. }
  59631. return /** @type {!Array.<ol.Feature>|!ol.Collection.<ol.Feature>} */ (features);
  59632. };
  59633. /**
  59634. * @param {ol.source.Vector.Event|ol.Collection.Event} evt Event.
  59635. * @private
  59636. */
  59637. ol.interaction.Snap.prototype.handleFeatureAdd_ = function(evt) {
  59638. var feature;
  59639. if (evt instanceof ol.source.Vector.Event) {
  59640. feature = evt.feature;
  59641. } else if (evt instanceof ol.Collection.Event) {
  59642. feature = evt.element;
  59643. }
  59644. this.addFeature(/** @type {ol.Feature} */ (feature));
  59645. };
  59646. /**
  59647. * @param {ol.source.Vector.Event|ol.Collection.Event} evt Event.
  59648. * @private
  59649. */
  59650. ol.interaction.Snap.prototype.handleFeatureRemove_ = function(evt) {
  59651. var feature;
  59652. if (evt instanceof ol.source.Vector.Event) {
  59653. feature = evt.feature;
  59654. } else if (evt instanceof ol.Collection.Event) {
  59655. feature = evt.element;
  59656. }
  59657. this.removeFeature(/** @type {ol.Feature} */ (feature));
  59658. };
  59659. /**
  59660. * @param {ol.events.Event} evt Event.
  59661. * @private
  59662. */
  59663. ol.interaction.Snap.prototype.handleFeatureChange_ = function(evt) {
  59664. var feature = /** @type {ol.Feature} */ (evt.target);
  59665. if (this.handlingDownUpSequence) {
  59666. var uid = ol.getUid(feature);
  59667. if (!(uid in this.pendingFeatures_)) {
  59668. this.pendingFeatures_[uid] = feature;
  59669. }
  59670. } else {
  59671. this.updateFeature_(feature);
  59672. }
  59673. };
  59674. /**
  59675. * Remove a feature from the collection of features that we may snap to.
  59676. * @param {ol.Feature} feature Feature
  59677. * @param {boolean=} opt_unlisten Whether to unlisten to the feature change
  59678. * or not. Defaults to `true`.
  59679. * @api
  59680. */
  59681. ol.interaction.Snap.prototype.removeFeature = function(feature, opt_unlisten) {
  59682. var unlisten = opt_unlisten !== undefined ? opt_unlisten : true;
  59683. var feature_uid = ol.getUid(feature);
  59684. var extent = this.indexedFeaturesExtents_[feature_uid];
  59685. if (extent) {
  59686. var rBush = this.rBush_;
  59687. var i, nodesToRemove = [];
  59688. rBush.forEachInExtent(extent, function(node) {
  59689. if (feature === node.feature) {
  59690. nodesToRemove.push(node);
  59691. }
  59692. });
  59693. for (i = nodesToRemove.length - 1; i >= 0; --i) {
  59694. rBush.remove(nodesToRemove[i]);
  59695. }
  59696. }
  59697. if (unlisten) {
  59698. ol.events.unlistenByKey(this.featureChangeListenerKeys_[feature_uid]);
  59699. delete this.featureChangeListenerKeys_[feature_uid];
  59700. }
  59701. };
  59702. /**
  59703. * @inheritDoc
  59704. */
  59705. ol.interaction.Snap.prototype.setMap = function(map) {
  59706. var currentMap = this.getMap();
  59707. var keys = this.featuresListenerKeys_;
  59708. var features = this.getFeatures_();
  59709. if (currentMap) {
  59710. keys.forEach(ol.events.unlistenByKey);
  59711. keys.length = 0;
  59712. features.forEach(this.forEachFeatureRemove_, this);
  59713. }
  59714. ol.interaction.Pointer.prototype.setMap.call(this, map);
  59715. if (map) {
  59716. if (this.features_) {
  59717. keys.push(
  59718. ol.events.listen(this.features_, ol.CollectionEventType.ADD,
  59719. this.handleFeatureAdd_, this),
  59720. ol.events.listen(this.features_, ol.CollectionEventType.REMOVE,
  59721. this.handleFeatureRemove_, this)
  59722. );
  59723. } else if (this.source_) {
  59724. keys.push(
  59725. ol.events.listen(this.source_, ol.source.VectorEventType.ADDFEATURE,
  59726. this.handleFeatureAdd_, this),
  59727. ol.events.listen(this.source_, ol.source.VectorEventType.REMOVEFEATURE,
  59728. this.handleFeatureRemove_, this)
  59729. );
  59730. }
  59731. features.forEach(this.forEachFeatureAdd_, this);
  59732. }
  59733. };
  59734. /**
  59735. * @inheritDoc
  59736. */
  59737. ol.interaction.Snap.prototype.shouldStopEvent = ol.functions.FALSE;
  59738. /**
  59739. * @param {ol.Pixel} pixel Pixel
  59740. * @param {ol.Coordinate} pixelCoordinate Coordinate
  59741. * @param {ol.Map} map Map.
  59742. * @return {ol.SnapResultType} Snap result
  59743. */
  59744. ol.interaction.Snap.prototype.snapTo = function(pixel, pixelCoordinate, map) {
  59745. var lowerLeft = map.getCoordinateFromPixel(
  59746. [pixel[0] - this.pixelTolerance_, pixel[1] + this.pixelTolerance_]);
  59747. var upperRight = map.getCoordinateFromPixel(
  59748. [pixel[0] + this.pixelTolerance_, pixel[1] - this.pixelTolerance_]);
  59749. var box = ol.extent.boundingExtent([lowerLeft, upperRight]);
  59750. var segments = this.rBush_.getInExtent(box);
  59751. // If snapping on vertices only, don't consider circles
  59752. if (this.vertex_ && !this.edge_) {
  59753. segments = segments.filter(function(segment) {
  59754. return segment.feature.getGeometry().getType() !==
  59755. ol.geom.GeometryType.CIRCLE;
  59756. });
  59757. }
  59758. var snappedToVertex = false;
  59759. var snapped = false;
  59760. var vertex = null;
  59761. var vertexPixel = null;
  59762. var dist, pixel1, pixel2, squaredDist1, squaredDist2;
  59763. if (segments.length > 0) {
  59764. this.pixelCoordinate_ = pixelCoordinate;
  59765. segments.sort(this.sortByDistance_);
  59766. var closestSegment = segments[0].segment;
  59767. var isCircle = segments[0].feature.getGeometry().getType() ===
  59768. ol.geom.GeometryType.CIRCLE;
  59769. if (this.vertex_ && !this.edge_) {
  59770. pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
  59771. pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
  59772. squaredDist1 = ol.coordinate.squaredDistance(pixel, pixel1);
  59773. squaredDist2 = ol.coordinate.squaredDistance(pixel, pixel2);
  59774. dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
  59775. snappedToVertex = dist <= this.pixelTolerance_;
  59776. if (snappedToVertex) {
  59777. snapped = true;
  59778. vertex = squaredDist1 > squaredDist2 ?
  59779. closestSegment[1] : closestSegment[0];
  59780. vertexPixel = map.getPixelFromCoordinate(vertex);
  59781. }
  59782. } else if (this.edge_) {
  59783. if (isCircle) {
  59784. vertex = ol.coordinate.closestOnCircle(pixelCoordinate,
  59785. /** @type {ol.geom.Circle} */ (segments[0].feature.getGeometry()));
  59786. } else {
  59787. vertex = (ol.coordinate.closestOnSegment(pixelCoordinate,
  59788. closestSegment));
  59789. }
  59790. vertexPixel = map.getPixelFromCoordinate(vertex);
  59791. if (ol.coordinate.distance(pixel, vertexPixel) <= this.pixelTolerance_) {
  59792. snapped = true;
  59793. if (this.vertex_ && !isCircle) {
  59794. pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
  59795. pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
  59796. squaredDist1 = ol.coordinate.squaredDistance(vertexPixel, pixel1);
  59797. squaredDist2 = ol.coordinate.squaredDistance(vertexPixel, pixel2);
  59798. dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
  59799. snappedToVertex = dist <= this.pixelTolerance_;
  59800. if (snappedToVertex) {
  59801. vertex = squaredDist1 > squaredDist2 ?
  59802. closestSegment[1] : closestSegment[0];
  59803. vertexPixel = map.getPixelFromCoordinate(vertex);
  59804. }
  59805. }
  59806. }
  59807. }
  59808. if (snapped) {
  59809. vertexPixel = [Math.round(vertexPixel[0]), Math.round(vertexPixel[1])];
  59810. }
  59811. }
  59812. return /** @type {ol.SnapResultType} */ ({
  59813. snapped: snapped,
  59814. vertex: vertex,
  59815. vertexPixel: vertexPixel
  59816. });
  59817. };
  59818. /**
  59819. * @param {ol.Feature} feature Feature
  59820. * @private
  59821. */
  59822. ol.interaction.Snap.prototype.updateFeature_ = function(feature) {
  59823. this.removeFeature(feature, false);
  59824. this.addFeature(feature, false);
  59825. };
  59826. /**
  59827. * @param {ol.Feature} feature Feature
  59828. * @param {ol.geom.Circle} geometry Geometry.
  59829. * @private
  59830. */
  59831. ol.interaction.Snap.prototype.writeCircleGeometry_ = function(feature, geometry) {
  59832. var polygon = ol.geom.Polygon.fromCircle(geometry);
  59833. var coordinates = polygon.getCoordinates()[0];
  59834. var i, ii, segment, segmentData;
  59835. for (i = 0, ii = coordinates.length - 1; i < ii; ++i) {
  59836. segment = coordinates.slice(i, i + 2);
  59837. segmentData = /** @type {ol.SnapSegmentDataType} */ ({
  59838. feature: feature,
  59839. segment: segment
  59840. });
  59841. this.rBush_.insert(ol.extent.boundingExtent(segment), segmentData);
  59842. }
  59843. };
  59844. /**
  59845. * @param {ol.Feature} feature Feature
  59846. * @param {ol.geom.GeometryCollection} geometry Geometry.
  59847. * @private
  59848. */
  59849. ol.interaction.Snap.prototype.writeGeometryCollectionGeometry_ = function(feature, geometry) {
  59850. var i, geometries = geometry.getGeometriesArray();
  59851. for (i = 0; i < geometries.length; ++i) {
  59852. var segmentWriter = this.SEGMENT_WRITERS_[geometries[i].getType()];
  59853. if (segmentWriter) {
  59854. segmentWriter.call(this, feature, geometries[i]);
  59855. }
  59856. }
  59857. };
  59858. /**
  59859. * @param {ol.Feature} feature Feature
  59860. * @param {ol.geom.LineString} geometry Geometry.
  59861. * @private
  59862. */
  59863. ol.interaction.Snap.prototype.writeLineStringGeometry_ = function(feature, geometry) {
  59864. var coordinates = geometry.getCoordinates();
  59865. var i, ii, segment, segmentData;
  59866. for (i = 0, ii = coordinates.length - 1; i < ii; ++i) {
  59867. segment = coordinates.slice(i, i + 2);
  59868. segmentData = /** @type {ol.SnapSegmentDataType} */ ({
  59869. feature: feature,
  59870. segment: segment
  59871. });
  59872. this.rBush_.insert(ol.extent.boundingExtent(segment), segmentData);
  59873. }
  59874. };
  59875. /**
  59876. * @param {ol.Feature} feature Feature
  59877. * @param {ol.geom.MultiLineString} geometry Geometry.
  59878. * @private
  59879. */
  59880. ol.interaction.Snap.prototype.writeMultiLineStringGeometry_ = function(feature, geometry) {
  59881. var lines = geometry.getCoordinates();
  59882. var coordinates, i, ii, j, jj, segment, segmentData;
  59883. for (j = 0, jj = lines.length; j < jj; ++j) {
  59884. coordinates = lines[j];
  59885. for (i = 0, ii = coordinates.length - 1; i < ii; ++i) {
  59886. segment = coordinates.slice(i, i + 2);
  59887. segmentData = /** @type {ol.SnapSegmentDataType} */ ({
  59888. feature: feature,
  59889. segment: segment
  59890. });
  59891. this.rBush_.insert(ol.extent.boundingExtent(segment), segmentData);
  59892. }
  59893. }
  59894. };
  59895. /**
  59896. * @param {ol.Feature} feature Feature
  59897. * @param {ol.geom.MultiPoint} geometry Geometry.
  59898. * @private
  59899. */
  59900. ol.interaction.Snap.prototype.writeMultiPointGeometry_ = function(feature, geometry) {
  59901. var points = geometry.getCoordinates();
  59902. var coordinates, i, ii, segmentData;
  59903. for (i = 0, ii = points.length; i < ii; ++i) {
  59904. coordinates = points[i];
  59905. segmentData = /** @type {ol.SnapSegmentDataType} */ ({
  59906. feature: feature,
  59907. segment: [coordinates, coordinates]
  59908. });
  59909. this.rBush_.insert(geometry.getExtent(), segmentData);
  59910. }
  59911. };
  59912. /**
  59913. * @param {ol.Feature} feature Feature
  59914. * @param {ol.geom.MultiPolygon} geometry Geometry.
  59915. * @private
  59916. */
  59917. ol.interaction.Snap.prototype.writeMultiPolygonGeometry_ = function(feature, geometry) {
  59918. var polygons = geometry.getCoordinates();
  59919. var coordinates, i, ii, j, jj, k, kk, rings, segment, segmentData;
  59920. for (k = 0, kk = polygons.length; k < kk; ++k) {
  59921. rings = polygons[k];
  59922. for (j = 0, jj = rings.length; j < jj; ++j) {
  59923. coordinates = rings[j];
  59924. for (i = 0, ii = coordinates.length - 1; i < ii; ++i) {
  59925. segment = coordinates.slice(i, i + 2);
  59926. segmentData = /** @type {ol.SnapSegmentDataType} */ ({
  59927. feature: feature,
  59928. segment: segment
  59929. });
  59930. this.rBush_.insert(ol.extent.boundingExtent(segment), segmentData);
  59931. }
  59932. }
  59933. }
  59934. };
  59935. /**
  59936. * @param {ol.Feature} feature Feature
  59937. * @param {ol.geom.Point} geometry Geometry.
  59938. * @private
  59939. */
  59940. ol.interaction.Snap.prototype.writePointGeometry_ = function(feature, geometry) {
  59941. var coordinates = geometry.getCoordinates();
  59942. var segmentData = /** @type {ol.SnapSegmentDataType} */ ({
  59943. feature: feature,
  59944. segment: [coordinates, coordinates]
  59945. });
  59946. this.rBush_.insert(geometry.getExtent(), segmentData);
  59947. };
  59948. /**
  59949. * @param {ol.Feature} feature Feature
  59950. * @param {ol.geom.Polygon} geometry Geometry.
  59951. * @private
  59952. */
  59953. ol.interaction.Snap.prototype.writePolygonGeometry_ = function(feature, geometry) {
  59954. var rings = geometry.getCoordinates();
  59955. var coordinates, i, ii, j, jj, segment, segmentData;
  59956. for (j = 0, jj = rings.length; j < jj; ++j) {
  59957. coordinates = rings[j];
  59958. for (i = 0, ii = coordinates.length - 1; i < ii; ++i) {
  59959. segment = coordinates.slice(i, i + 2);
  59960. segmentData = /** @type {ol.SnapSegmentDataType} */ ({
  59961. feature: feature,
  59962. segment: segment
  59963. });
  59964. this.rBush_.insert(ol.extent.boundingExtent(segment), segmentData);
  59965. }
  59966. }
  59967. };
  59968. /**
  59969. * Handle all pointer events events.
  59970. * @param {ol.MapBrowserEvent} evt A move event.
  59971. * @return {boolean} Pass the event to other interactions.
  59972. * @this {ol.interaction.Snap}
  59973. * @private
  59974. */
  59975. ol.interaction.Snap.handleEvent_ = function(evt) {
  59976. var result = this.snapTo(evt.pixel, evt.coordinate, evt.map);
  59977. if (result.snapped) {
  59978. evt.coordinate = result.vertex.slice(0, 2);
  59979. evt.pixel = result.vertexPixel;
  59980. }
  59981. return ol.interaction.Pointer.handleEvent.call(this, evt);
  59982. };
  59983. /**
  59984. * @param {ol.MapBrowserPointerEvent} evt Event.
  59985. * @return {boolean} Stop drag sequence?
  59986. * @this {ol.interaction.Snap}
  59987. * @private
  59988. */
  59989. ol.interaction.Snap.handleUpEvent_ = function(evt) {
  59990. var featuresToUpdate = ol.obj.getValues(this.pendingFeatures_);
  59991. if (featuresToUpdate.length) {
  59992. featuresToUpdate.forEach(this.updateFeature_, this);
  59993. this.pendingFeatures_ = {};
  59994. }
  59995. return false;
  59996. };
  59997. /**
  59998. * Sort segments by distance, helper function
  59999. * @param {ol.SnapSegmentDataType} a The first segment data.
  60000. * @param {ol.SnapSegmentDataType} b The second segment data.
  60001. * @return {number} The difference in distance.
  60002. * @this {ol.interaction.Snap}
  60003. */
  60004. ol.interaction.Snap.sortByDistance = function(a, b) {
  60005. return ol.coordinate.squaredDistanceToSegment(
  60006. this.pixelCoordinate_, a.segment) -
  60007. ol.coordinate.squaredDistanceToSegment(
  60008. this.pixelCoordinate_, b.segment);
  60009. };
  60010. goog.provide('ol.interaction.TranslateEventType');
  60011. /**
  60012. * @enum {string}
  60013. */
  60014. ol.interaction.TranslateEventType = {
  60015. /**
  60016. * Triggered upon feature translation start.
  60017. * @event ol.interaction.Translate.Event#translatestart
  60018. * @api
  60019. */
  60020. TRANSLATESTART: 'translatestart',
  60021. /**
  60022. * Triggered upon feature translation.
  60023. * @event ol.interaction.Translate.Event#translating
  60024. * @api
  60025. */
  60026. TRANSLATING: 'translating',
  60027. /**
  60028. * Triggered upon feature translation end.
  60029. * @event ol.interaction.Translate.Event#translateend
  60030. * @api
  60031. */
  60032. TRANSLATEEND: 'translateend'
  60033. };
  60034. goog.provide('ol.interaction.Translate');
  60035. goog.require('ol');
  60036. goog.require('ol.Collection');
  60037. goog.require('ol.Object');
  60038. goog.require('ol.events');
  60039. goog.require('ol.events.Event');
  60040. goog.require('ol.functions');
  60041. goog.require('ol.array');
  60042. goog.require('ol.interaction.Pointer');
  60043. goog.require('ol.interaction.Property');
  60044. goog.require('ol.interaction.TranslateEventType');
  60045. /**
  60046. * @classdesc
  60047. * Interaction for translating (moving) features.
  60048. *
  60049. * @constructor
  60050. * @extends {ol.interaction.Pointer}
  60051. * @fires ol.interaction.Translate.Event
  60052. * @param {olx.interaction.TranslateOptions=} opt_options Options.
  60053. * @api
  60054. */
  60055. ol.interaction.Translate = function(opt_options) {
  60056. ol.interaction.Pointer.call(this, {
  60057. handleDownEvent: ol.interaction.Translate.handleDownEvent_,
  60058. handleDragEvent: ol.interaction.Translate.handleDragEvent_,
  60059. handleMoveEvent: ol.interaction.Translate.handleMoveEvent_,
  60060. handleUpEvent: ol.interaction.Translate.handleUpEvent_
  60061. });
  60062. var options = opt_options ? opt_options : {};
  60063. /**
  60064. * The last position we translated to.
  60065. * @type {ol.Coordinate}
  60066. * @private
  60067. */
  60068. this.lastCoordinate_ = null;
  60069. /**
  60070. * @type {ol.Collection.<ol.Feature>}
  60071. * @private
  60072. */
  60073. this.features_ = options.features !== undefined ? options.features : null;
  60074. /** @type {function(ol.layer.Layer): boolean} */
  60075. var layerFilter;
  60076. if (options.layers) {
  60077. if (typeof options.layers === 'function') {
  60078. layerFilter = options.layers;
  60079. } else {
  60080. var layers = options.layers;
  60081. layerFilter = function(layer) {
  60082. return ol.array.includes(layers, layer);
  60083. };
  60084. }
  60085. } else {
  60086. layerFilter = ol.functions.TRUE;
  60087. }
  60088. /**
  60089. * @private
  60090. * @type {function(ol.layer.Layer): boolean}
  60091. */
  60092. this.layerFilter_ = layerFilter;
  60093. /**
  60094. * @private
  60095. * @type {number}
  60096. */
  60097. this.hitTolerance_ = options.hitTolerance ? options.hitTolerance : 0;
  60098. /**
  60099. * @type {ol.Feature}
  60100. * @private
  60101. */
  60102. this.lastFeature_ = null;
  60103. ol.events.listen(this,
  60104. ol.Object.getChangeEventType(ol.interaction.Property.ACTIVE),
  60105. this.handleActiveChanged_, this);
  60106. };
  60107. ol.inherits(ol.interaction.Translate, ol.interaction.Pointer);
  60108. /**
  60109. * @param {ol.MapBrowserPointerEvent} event Event.
  60110. * @return {boolean} Start drag sequence?
  60111. * @this {ol.interaction.Translate}
  60112. * @private
  60113. */
  60114. ol.interaction.Translate.handleDownEvent_ = function(event) {
  60115. this.lastFeature_ = this.featuresAtPixel_(event.pixel, event.map);
  60116. if (!this.lastCoordinate_ && this.lastFeature_) {
  60117. this.lastCoordinate_ = event.coordinate;
  60118. ol.interaction.Translate.handleMoveEvent_.call(this, event);
  60119. var features = this.features_ || new ol.Collection([this.lastFeature_]);
  60120. this.dispatchEvent(
  60121. new ol.interaction.Translate.Event(
  60122. ol.interaction.TranslateEventType.TRANSLATESTART, features,
  60123. event.coordinate));
  60124. return true;
  60125. }
  60126. return false;
  60127. };
  60128. /**
  60129. * @param {ol.MapBrowserPointerEvent} event Event.
  60130. * @return {boolean} Stop drag sequence?
  60131. * @this {ol.interaction.Translate}
  60132. * @private
  60133. */
  60134. ol.interaction.Translate.handleUpEvent_ = function(event) {
  60135. if (this.lastCoordinate_) {
  60136. this.lastCoordinate_ = null;
  60137. ol.interaction.Translate.handleMoveEvent_.call(this, event);
  60138. var features = this.features_ || new ol.Collection([this.lastFeature_]);
  60139. this.dispatchEvent(
  60140. new ol.interaction.Translate.Event(
  60141. ol.interaction.TranslateEventType.TRANSLATEEND, features,
  60142. event.coordinate));
  60143. return true;
  60144. }
  60145. return false;
  60146. };
  60147. /**
  60148. * @param {ol.MapBrowserPointerEvent} event Event.
  60149. * @this {ol.interaction.Translate}
  60150. * @private
  60151. */
  60152. ol.interaction.Translate.handleDragEvent_ = function(event) {
  60153. if (this.lastCoordinate_) {
  60154. var newCoordinate = event.coordinate;
  60155. var deltaX = newCoordinate[0] - this.lastCoordinate_[0];
  60156. var deltaY = newCoordinate[1] - this.lastCoordinate_[1];
  60157. var features = this.features_ || new ol.Collection([this.lastFeature_]);
  60158. features.forEach(function(feature) {
  60159. var geom = feature.getGeometry();
  60160. geom.translate(deltaX, deltaY);
  60161. feature.setGeometry(geom);
  60162. });
  60163. this.lastCoordinate_ = newCoordinate;
  60164. this.dispatchEvent(
  60165. new ol.interaction.Translate.Event(
  60166. ol.interaction.TranslateEventType.TRANSLATING, features,
  60167. newCoordinate));
  60168. }
  60169. };
  60170. /**
  60171. * @param {ol.MapBrowserEvent} event Event.
  60172. * @this {ol.interaction.Translate}
  60173. * @private
  60174. */
  60175. ol.interaction.Translate.handleMoveEvent_ = function(event) {
  60176. var elem = event.map.getViewport();
  60177. // Change the cursor to grab/grabbing if hovering any of the features managed
  60178. // by the interaction
  60179. if (this.featuresAtPixel_(event.pixel, event.map)) {
  60180. elem.classList.remove(this.lastCoordinate_ ? 'ol-grab' : 'ol-grabbing');
  60181. elem.classList.add(this.lastCoordinate_ ? 'ol-grabbing' : 'ol-grab');
  60182. } else {
  60183. elem.classList.remove('ol-grab', 'ol-grabbing');
  60184. }
  60185. };
  60186. /**
  60187. * Tests to see if the given coordinates intersects any of our selected
  60188. * features.
  60189. * @param {ol.Pixel} pixel Pixel coordinate to test for intersection.
  60190. * @param {ol.Map} map Map to test the intersection on.
  60191. * @return {ol.Feature} Returns the feature found at the specified pixel
  60192. * coordinates.
  60193. * @private
  60194. */
  60195. ol.interaction.Translate.prototype.featuresAtPixel_ = function(pixel, map) {
  60196. return map.forEachFeatureAtPixel(pixel,
  60197. function(feature) {
  60198. if (!this.features_ ||
  60199. ol.array.includes(this.features_.getArray(), feature)) {
  60200. return feature;
  60201. }
  60202. }.bind(this), {
  60203. layerFilter: this.layerFilter_,
  60204. hitTolerance: this.hitTolerance_
  60205. });
  60206. };
  60207. /**
  60208. * Returns the Hit-detection tolerance.
  60209. * @returns {number} Hit tolerance in pixels.
  60210. * @api
  60211. */
  60212. ol.interaction.Translate.prototype.getHitTolerance = function() {
  60213. return this.hitTolerance_;
  60214. };
  60215. /**
  60216. * Hit-detection tolerance. Pixels inside the radius around the given position
  60217. * will be checked for features. This only works for the canvas renderer and
  60218. * not for WebGL.
  60219. * @param {number} hitTolerance Hit tolerance in pixels.
  60220. * @api
  60221. */
  60222. ol.interaction.Translate.prototype.setHitTolerance = function(hitTolerance) {
  60223. this.hitTolerance_ = hitTolerance;
  60224. };
  60225. /**
  60226. * @inheritDoc
  60227. */
  60228. ol.interaction.Translate.prototype.setMap = function(map) {
  60229. var oldMap = this.getMap();
  60230. ol.interaction.Pointer.prototype.setMap.call(this, map);
  60231. this.updateState_(oldMap);
  60232. };
  60233. /**
  60234. * @private
  60235. */
  60236. ol.interaction.Translate.prototype.handleActiveChanged_ = function() {
  60237. this.updateState_(null);
  60238. };
  60239. /**
  60240. * @param {ol.Map} oldMap Old map.
  60241. * @private
  60242. */
  60243. ol.interaction.Translate.prototype.updateState_ = function(oldMap) {
  60244. var map = this.getMap();
  60245. var active = this.getActive();
  60246. if (!map || !active) {
  60247. map = map || oldMap;
  60248. if (map) {
  60249. var elem = map.getViewport();
  60250. elem.classList.remove('ol-grab', 'ol-grabbing');
  60251. }
  60252. }
  60253. };
  60254. /**
  60255. * @classdesc
  60256. * Events emitted by {@link ol.interaction.Translate} instances are instances of
  60257. * this type.
  60258. *
  60259. * @constructor
  60260. * @extends {ol.events.Event}
  60261. * @implements {oli.interaction.TranslateEvent}
  60262. * @param {ol.interaction.TranslateEventType} type Type.
  60263. * @param {ol.Collection.<ol.Feature>} features The features translated.
  60264. * @param {ol.Coordinate} coordinate The event coordinate.
  60265. */
  60266. ol.interaction.Translate.Event = function(type, features, coordinate) {
  60267. ol.events.Event.call(this, type);
  60268. /**
  60269. * The features being translated.
  60270. * @type {ol.Collection.<ol.Feature>}
  60271. * @api
  60272. */
  60273. this.features = features;
  60274. /**
  60275. * The coordinate of the drag event.
  60276. * @const
  60277. * @type {ol.Coordinate}
  60278. * @api
  60279. */
  60280. this.coordinate = coordinate;
  60281. };
  60282. ol.inherits(ol.interaction.Translate.Event, ol.events.Event);
  60283. goog.provide('ol.layer.Heatmap');
  60284. goog.require('ol.events');
  60285. goog.require('ol');
  60286. goog.require('ol.Object');
  60287. goog.require('ol.dom');
  60288. goog.require('ol.layer.Vector');
  60289. goog.require('ol.math');
  60290. goog.require('ol.obj');
  60291. goog.require('ol.render.EventType');
  60292. goog.require('ol.style.Icon');
  60293. goog.require('ol.style.Style');
  60294. /**
  60295. * @classdesc
  60296. * Layer for rendering vector data as a heatmap.
  60297. * Note that any property set in the options is set as a {@link ol.Object}
  60298. * property on the layer object; for example, setting `title: 'My Title'` in the
  60299. * options means that `title` is observable, and has get/set accessors.
  60300. *
  60301. * @constructor
  60302. * @extends {ol.layer.Vector}
  60303. * @fires ol.render.Event
  60304. * @param {olx.layer.HeatmapOptions=} opt_options Options.
  60305. * @api
  60306. */
  60307. ol.layer.Heatmap = function(opt_options) {
  60308. var options = opt_options ? opt_options : {};
  60309. var baseOptions = ol.obj.assign({}, options);
  60310. delete baseOptions.gradient;
  60311. delete baseOptions.radius;
  60312. delete baseOptions.blur;
  60313. delete baseOptions.shadow;
  60314. delete baseOptions.weight;
  60315. ol.layer.Vector.call(this, /** @type {olx.layer.VectorOptions} */ (baseOptions));
  60316. /**
  60317. * @private
  60318. * @type {Uint8ClampedArray}
  60319. */
  60320. this.gradient_ = null;
  60321. /**
  60322. * @private
  60323. * @type {number}
  60324. */
  60325. this.shadow_ = options.shadow !== undefined ? options.shadow : 250;
  60326. /**
  60327. * @private
  60328. * @type {string|undefined}
  60329. */
  60330. this.circleImage_ = undefined;
  60331. /**
  60332. * @private
  60333. * @type {Array.<Array.<ol.style.Style>>}
  60334. */
  60335. this.styleCache_ = null;
  60336. ol.events.listen(this,
  60337. ol.Object.getChangeEventType(ol.layer.Heatmap.Property_.GRADIENT),
  60338. this.handleGradientChanged_, this);
  60339. this.setGradient(options.gradient ?
  60340. options.gradient : ol.layer.Heatmap.DEFAULT_GRADIENT);
  60341. this.setBlur(options.blur !== undefined ? options.blur : 15);
  60342. this.setRadius(options.radius !== undefined ? options.radius : 8);
  60343. ol.events.listen(this,
  60344. ol.Object.getChangeEventType(ol.layer.Heatmap.Property_.BLUR),
  60345. this.handleStyleChanged_, this);
  60346. ol.events.listen(this,
  60347. ol.Object.getChangeEventType(ol.layer.Heatmap.Property_.RADIUS),
  60348. this.handleStyleChanged_, this);
  60349. this.handleStyleChanged_();
  60350. var weight = options.weight ? options.weight : 'weight';
  60351. var weightFunction;
  60352. if (typeof weight === 'string') {
  60353. weightFunction = function(feature) {
  60354. return feature.get(weight);
  60355. };
  60356. } else {
  60357. weightFunction = weight;
  60358. }
  60359. this.setStyle(function(feature, resolution) {
  60360. var weight = weightFunction(feature);
  60361. var opacity = weight !== undefined ? ol.math.clamp(weight, 0, 1) : 1;
  60362. // cast to 8 bits
  60363. var index = (255 * opacity) | 0;
  60364. var style = this.styleCache_[index];
  60365. if (!style) {
  60366. style = [
  60367. new ol.style.Style({
  60368. image: new ol.style.Icon({
  60369. opacity: opacity,
  60370. src: this.circleImage_
  60371. })
  60372. })
  60373. ];
  60374. this.styleCache_[index] = style;
  60375. }
  60376. return style;
  60377. }.bind(this));
  60378. // For performance reasons, don't sort the features before rendering.
  60379. // The render order is not relevant for a heatmap representation.
  60380. this.setRenderOrder(null);
  60381. ol.events.listen(this, ol.render.EventType.RENDER, this.handleRender_, this);
  60382. };
  60383. ol.inherits(ol.layer.Heatmap, ol.layer.Vector);
  60384. /**
  60385. * @const
  60386. * @type {Array.<string>}
  60387. */
  60388. ol.layer.Heatmap.DEFAULT_GRADIENT = ['#00f', '#0ff', '#0f0', '#ff0', '#f00'];
  60389. /**
  60390. * @param {Array.<string>} colors A list of colored.
  60391. * @return {Uint8ClampedArray} An array.
  60392. * @private
  60393. */
  60394. ol.layer.Heatmap.createGradient_ = function(colors) {
  60395. var width = 1;
  60396. var height = 256;
  60397. var context = ol.dom.createCanvasContext2D(width, height);
  60398. var gradient = context.createLinearGradient(0, 0, width, height);
  60399. var step = 1 / (colors.length - 1);
  60400. for (var i = 0, ii = colors.length; i < ii; ++i) {
  60401. gradient.addColorStop(i * step, colors[i]);
  60402. }
  60403. context.fillStyle = gradient;
  60404. context.fillRect(0, 0, width, height);
  60405. return context.getImageData(0, 0, width, height).data;
  60406. };
  60407. /**
  60408. * @return {string} Data URL for a circle.
  60409. * @private
  60410. */
  60411. ol.layer.Heatmap.prototype.createCircle_ = function() {
  60412. var radius = this.getRadius();
  60413. var blur = this.getBlur();
  60414. var halfSize = radius + blur + 1;
  60415. var size = 2 * halfSize;
  60416. var context = ol.dom.createCanvasContext2D(size, size);
  60417. context.shadowOffsetX = context.shadowOffsetY = this.shadow_;
  60418. context.shadowBlur = blur;
  60419. context.shadowColor = '#000';
  60420. context.beginPath();
  60421. var center = halfSize - this.shadow_;
  60422. context.arc(center, center, radius, 0, Math.PI * 2, true);
  60423. context.fill();
  60424. return context.canvas.toDataURL();
  60425. };
  60426. /**
  60427. * Return the blur size in pixels.
  60428. * @return {number} Blur size in pixels.
  60429. * @api
  60430. * @observable
  60431. */
  60432. ol.layer.Heatmap.prototype.getBlur = function() {
  60433. return /** @type {number} */ (this.get(ol.layer.Heatmap.Property_.BLUR));
  60434. };
  60435. /**
  60436. * Return the gradient colors as array of strings.
  60437. * @return {Array.<string>} Colors.
  60438. * @api
  60439. * @observable
  60440. */
  60441. ol.layer.Heatmap.prototype.getGradient = function() {
  60442. return /** @type {Array.<string>} */ (
  60443. this.get(ol.layer.Heatmap.Property_.GRADIENT));
  60444. };
  60445. /**
  60446. * Return the size of the radius in pixels.
  60447. * @return {number} Radius size in pixel.
  60448. * @api
  60449. * @observable
  60450. */
  60451. ol.layer.Heatmap.prototype.getRadius = function() {
  60452. return /** @type {number} */ (this.get(ol.layer.Heatmap.Property_.RADIUS));
  60453. };
  60454. /**
  60455. * @private
  60456. */
  60457. ol.layer.Heatmap.prototype.handleGradientChanged_ = function() {
  60458. this.gradient_ = ol.layer.Heatmap.createGradient_(this.getGradient());
  60459. };
  60460. /**
  60461. * @private
  60462. */
  60463. ol.layer.Heatmap.prototype.handleStyleChanged_ = function() {
  60464. this.circleImage_ = this.createCircle_();
  60465. this.styleCache_ = new Array(256);
  60466. this.changed();
  60467. };
  60468. /**
  60469. * @param {ol.render.Event} event Post compose event
  60470. * @private
  60471. */
  60472. ol.layer.Heatmap.prototype.handleRender_ = function(event) {
  60473. var context = event.context;
  60474. var canvas = context.canvas;
  60475. var image = context.getImageData(0, 0, canvas.width, canvas.height);
  60476. var view8 = image.data;
  60477. var i, ii, alpha;
  60478. for (i = 0, ii = view8.length; i < ii; i += 4) {
  60479. alpha = view8[i + 3] * 4;
  60480. if (alpha) {
  60481. view8[i] = this.gradient_[alpha];
  60482. view8[i + 1] = this.gradient_[alpha + 1];
  60483. view8[i + 2] = this.gradient_[alpha + 2];
  60484. }
  60485. }
  60486. context.putImageData(image, 0, 0);
  60487. };
  60488. /**
  60489. * Set the blur size in pixels.
  60490. * @param {number} blur Blur size in pixels.
  60491. * @api
  60492. * @observable
  60493. */
  60494. ol.layer.Heatmap.prototype.setBlur = function(blur) {
  60495. this.set(ol.layer.Heatmap.Property_.BLUR, blur);
  60496. };
  60497. /**
  60498. * Set the gradient colors as array of strings.
  60499. * @param {Array.<string>} colors Gradient.
  60500. * @api
  60501. * @observable
  60502. */
  60503. ol.layer.Heatmap.prototype.setGradient = function(colors) {
  60504. this.set(ol.layer.Heatmap.Property_.GRADIENT, colors);
  60505. };
  60506. /**
  60507. * Set the size of the radius in pixels.
  60508. * @param {number} radius Radius size in pixel.
  60509. * @api
  60510. * @observable
  60511. */
  60512. ol.layer.Heatmap.prototype.setRadius = function(radius) {
  60513. this.set(ol.layer.Heatmap.Property_.RADIUS, radius);
  60514. };
  60515. /**
  60516. * @enum {string}
  60517. * @private
  60518. */
  60519. ol.layer.Heatmap.Property_ = {
  60520. BLUR: 'blur',
  60521. GRADIENT: 'gradient',
  60522. RADIUS: 'radius'
  60523. };
  60524. goog.provide('ol.renderer.canvas.IntermediateCanvas');
  60525. goog.require('ol');
  60526. goog.require('ol.coordinate');
  60527. goog.require('ol.dom');
  60528. goog.require('ol.extent');
  60529. goog.require('ol.renderer.canvas.Layer');
  60530. goog.require('ol.transform');
  60531. /**
  60532. * @constructor
  60533. * @abstract
  60534. * @extends {ol.renderer.canvas.Layer}
  60535. * @param {ol.layer.Layer} layer Layer.
  60536. */
  60537. ol.renderer.canvas.IntermediateCanvas = function(layer) {
  60538. ol.renderer.canvas.Layer.call(this, layer);
  60539. /**
  60540. * @protected
  60541. * @type {ol.Transform}
  60542. */
  60543. this.coordinateToCanvasPixelTransform = ol.transform.create();
  60544. /**
  60545. * @private
  60546. * @type {CanvasRenderingContext2D}
  60547. */
  60548. this.hitCanvasContext_ = null;
  60549. };
  60550. ol.inherits(ol.renderer.canvas.IntermediateCanvas, ol.renderer.canvas.Layer);
  60551. /**
  60552. * @inheritDoc
  60553. */
  60554. ol.renderer.canvas.IntermediateCanvas.prototype.composeFrame = function(frameState, layerState, context) {
  60555. this.preCompose(context, frameState);
  60556. var image = this.getImage();
  60557. if (image) {
  60558. // clipped rendering if layer extent is set
  60559. var extent = layerState.extent;
  60560. var clipped = extent !== undefined &&
  60561. !ol.extent.containsExtent(extent, frameState.extent) &&
  60562. ol.extent.intersects(extent, frameState.extent);
  60563. if (clipped) {
  60564. this.clip(context, frameState, /** @type {ol.Extent} */ (extent));
  60565. }
  60566. var imageTransform = this.getImageTransform();
  60567. // for performance reasons, context.save / context.restore is not used
  60568. // to save and restore the transformation matrix and the opacity.
  60569. // see http://jsperf.com/context-save-restore-versus-variable
  60570. var alpha = context.globalAlpha;
  60571. context.globalAlpha = layerState.opacity;
  60572. // for performance reasons, context.setTransform is only used
  60573. // when the view is rotated. see http://jsperf.com/canvas-transform
  60574. var dx = imageTransform[4];
  60575. var dy = imageTransform[5];
  60576. var dw = image.width * imageTransform[0];
  60577. var dh = image.height * imageTransform[3];
  60578. context.drawImage(image, 0, 0, +image.width, +image.height,
  60579. Math.round(dx), Math.round(dy), Math.round(dw), Math.round(dh));
  60580. context.globalAlpha = alpha;
  60581. if (clipped) {
  60582. context.restore();
  60583. }
  60584. }
  60585. this.postCompose(context, frameState, layerState);
  60586. };
  60587. /**
  60588. * @abstract
  60589. * @return {HTMLCanvasElement|HTMLVideoElement|Image} Canvas.
  60590. */
  60591. ol.renderer.canvas.IntermediateCanvas.prototype.getImage = function() {};
  60592. /**
  60593. * @abstract
  60594. * @return {!ol.Transform} Image transform.
  60595. */
  60596. ol.renderer.canvas.IntermediateCanvas.prototype.getImageTransform = function() {};
  60597. /**
  60598. * @inheritDoc
  60599. */
  60600. ol.renderer.canvas.IntermediateCanvas.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
  60601. var layer = this.getLayer();
  60602. var source = layer.getSource();
  60603. var resolution = frameState.viewState.resolution;
  60604. var rotation = frameState.viewState.rotation;
  60605. var skippedFeatureUids = frameState.skippedFeatureUids;
  60606. return source.forEachFeatureAtCoordinate(
  60607. coordinate, resolution, rotation, hitTolerance, skippedFeatureUids,
  60608. /**
  60609. * @param {ol.Feature|ol.render.Feature} feature Feature.
  60610. * @return {?} Callback result.
  60611. */
  60612. function(feature) {
  60613. return callback.call(thisArg, feature, layer);
  60614. });
  60615. };
  60616. /**
  60617. * @inheritDoc
  60618. */
  60619. ol.renderer.canvas.IntermediateCanvas.prototype.forEachLayerAtCoordinate = function(coordinate, frameState, callback, thisArg) {
  60620. if (!this.getImage()) {
  60621. return undefined;
  60622. }
  60623. if (this.getLayer().getSource().forEachFeatureAtCoordinate !== ol.nullFunction) {
  60624. // for ImageVector sources use the original hit-detection logic,
  60625. // so that for example also transparent polygons are detected
  60626. return ol.renderer.canvas.Layer.prototype.forEachLayerAtCoordinate.apply(this, arguments);
  60627. } else {
  60628. var pixel = ol.transform.apply(this.coordinateToCanvasPixelTransform, coordinate.slice());
  60629. ol.coordinate.scale(pixel, frameState.viewState.resolution / this.renderedResolution);
  60630. if (!this.hitCanvasContext_) {
  60631. this.hitCanvasContext_ = ol.dom.createCanvasContext2D(1, 1);
  60632. }
  60633. this.hitCanvasContext_.clearRect(0, 0, 1, 1);
  60634. this.hitCanvasContext_.drawImage(this.getImage(), pixel[0], pixel[1], 1, 1, 0, 0, 1, 1);
  60635. var imageData = this.hitCanvasContext_.getImageData(0, 0, 1, 1).data;
  60636. if (imageData[3] > 0) {
  60637. return callback.call(thisArg, this.getLayer(), imageData);
  60638. } else {
  60639. return undefined;
  60640. }
  60641. }
  60642. };
  60643. goog.provide('ol.renderer.canvas.ImageLayer');
  60644. goog.require('ol');
  60645. goog.require('ol.ViewHint');
  60646. goog.require('ol.extent');
  60647. goog.require('ol.renderer.canvas.IntermediateCanvas');
  60648. goog.require('ol.transform');
  60649. /**
  60650. * @constructor
  60651. * @extends {ol.renderer.canvas.IntermediateCanvas}
  60652. * @param {ol.layer.Image} imageLayer Single image layer.
  60653. */
  60654. ol.renderer.canvas.ImageLayer = function(imageLayer) {
  60655. ol.renderer.canvas.IntermediateCanvas.call(this, imageLayer);
  60656. /**
  60657. * @private
  60658. * @type {?ol.ImageBase}
  60659. */
  60660. this.image_ = null;
  60661. /**
  60662. * @private
  60663. * @type {ol.Transform}
  60664. */
  60665. this.imageTransform_ = ol.transform.create();
  60666. };
  60667. ol.inherits(ol.renderer.canvas.ImageLayer, ol.renderer.canvas.IntermediateCanvas);
  60668. /**
  60669. * @inheritDoc
  60670. */
  60671. ol.renderer.canvas.ImageLayer.prototype.getImage = function() {
  60672. return !this.image_ ? null : this.image_.getImage();
  60673. };
  60674. /**
  60675. * @inheritDoc
  60676. */
  60677. ol.renderer.canvas.ImageLayer.prototype.getImageTransform = function() {
  60678. return this.imageTransform_;
  60679. };
  60680. /**
  60681. * @inheritDoc
  60682. */
  60683. ol.renderer.canvas.ImageLayer.prototype.prepareFrame = function(frameState, layerState) {
  60684. var pixelRatio = frameState.pixelRatio;
  60685. var size = frameState.size;
  60686. var viewState = frameState.viewState;
  60687. var viewCenter = viewState.center;
  60688. var viewResolution = viewState.resolution;
  60689. var image;
  60690. var imageLayer = /** @type {ol.layer.Image} */ (this.getLayer());
  60691. var imageSource = imageLayer.getSource();
  60692. var hints = frameState.viewHints;
  60693. var renderedExtent = frameState.extent;
  60694. if (layerState.extent !== undefined) {
  60695. renderedExtent = ol.extent.getIntersection(
  60696. renderedExtent, layerState.extent);
  60697. }
  60698. if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING] &&
  60699. !ol.extent.isEmpty(renderedExtent)) {
  60700. var projection = viewState.projection;
  60701. if (!ol.ENABLE_RASTER_REPROJECTION) {
  60702. var sourceProjection = imageSource.getProjection();
  60703. if (sourceProjection) {
  60704. projection = sourceProjection;
  60705. }
  60706. }
  60707. image = imageSource.getImage(
  60708. renderedExtent, viewResolution, pixelRatio, projection);
  60709. if (image) {
  60710. var loaded = this.loadImage(image);
  60711. if (loaded) {
  60712. this.image_ = image;
  60713. }
  60714. }
  60715. }
  60716. if (this.image_) {
  60717. image = this.image_;
  60718. var imageExtent = image.getExtent();
  60719. var imageResolution = image.getResolution();
  60720. var imagePixelRatio = image.getPixelRatio();
  60721. var scale = pixelRatio * imageResolution /
  60722. (viewResolution * imagePixelRatio);
  60723. var transform = ol.transform.compose(this.imageTransform_,
  60724. pixelRatio * size[0] / 2, pixelRatio * size[1] / 2,
  60725. scale, scale,
  60726. 0,
  60727. imagePixelRatio * (imageExtent[0] - viewCenter[0]) / imageResolution,
  60728. imagePixelRatio * (viewCenter[1] - imageExtent[3]) / imageResolution);
  60729. ol.transform.compose(this.coordinateToCanvasPixelTransform,
  60730. pixelRatio * size[0] / 2 - transform[4], pixelRatio * size[1] / 2 - transform[5],
  60731. pixelRatio / viewResolution, -pixelRatio / viewResolution,
  60732. 0,
  60733. -viewCenter[0], -viewCenter[1]);
  60734. this.updateAttributions(frameState.attributions, image.getAttributions());
  60735. this.updateLogos(frameState, imageSource);
  60736. this.renderedResolution = viewResolution * pixelRatio / imagePixelRatio;
  60737. }
  60738. return !!this.image_;
  60739. };
  60740. goog.provide('ol.reproj');
  60741. goog.require('ol.dom');
  60742. goog.require('ol.extent');
  60743. goog.require('ol.math');
  60744. goog.require('ol.proj');
  60745. /**
  60746. * Calculates ideal resolution to use from the source in order to achieve
  60747. * pixel mapping as close as possible to 1:1 during reprojection.
  60748. * The resolution is calculated regardless of what resolutions
  60749. * are actually available in the dataset (TileGrid, Image, ...).
  60750. *
  60751. * @param {ol.proj.Projection} sourceProj Source projection.
  60752. * @param {ol.proj.Projection} targetProj Target projection.
  60753. * @param {ol.Coordinate} targetCenter Target center.
  60754. * @param {number} targetResolution Target resolution.
  60755. * @return {number} The best resolution to use. Can be +-Infinity, NaN or 0.
  60756. */
  60757. ol.reproj.calculateSourceResolution = function(sourceProj, targetProj,
  60758. targetCenter, targetResolution) {
  60759. var sourceCenter = ol.proj.transform(targetCenter, targetProj, sourceProj);
  60760. // calculate the ideal resolution of the source data
  60761. var sourceResolution =
  60762. ol.proj.getPointResolution(targetProj, targetResolution, targetCenter);
  60763. var targetMetersPerUnit = targetProj.getMetersPerUnit();
  60764. if (targetMetersPerUnit !== undefined) {
  60765. sourceResolution *= targetMetersPerUnit;
  60766. }
  60767. var sourceMetersPerUnit = sourceProj.getMetersPerUnit();
  60768. if (sourceMetersPerUnit !== undefined) {
  60769. sourceResolution /= sourceMetersPerUnit;
  60770. }
  60771. // Based on the projection properties, the point resolution at the specified
  60772. // coordinates may be slightly different. We need to reverse-compensate this
  60773. // in order to achieve optimal results.
  60774. var sourceExtent = sourceProj.getExtent();
  60775. if (!sourceExtent || ol.extent.containsCoordinate(sourceExtent, sourceCenter)) {
  60776. var compensationFactor =
  60777. ol.proj.getPointResolution(sourceProj, sourceResolution, sourceCenter) /
  60778. sourceResolution;
  60779. if (isFinite(compensationFactor) && compensationFactor > 0) {
  60780. sourceResolution /= compensationFactor;
  60781. }
  60782. }
  60783. return sourceResolution;
  60784. };
  60785. /**
  60786. * Enlarge the clipping triangle point by 1 pixel to ensure the edges overlap
  60787. * in order to mask gaps caused by antialiasing.
  60788. *
  60789. * @param {number} centroidX Centroid of the triangle (x coordinate in pixels).
  60790. * @param {number} centroidY Centroid of the triangle (y coordinate in pixels).
  60791. * @param {number} x X coordinate of the point (in pixels).
  60792. * @param {number} y Y coordinate of the point (in pixels).
  60793. * @return {ol.Coordinate} New point 1 px farther from the centroid.
  60794. * @private
  60795. */
  60796. ol.reproj.enlargeClipPoint_ = function(centroidX, centroidY, x, y) {
  60797. var dX = x - centroidX, dY = y - centroidY;
  60798. var distance = Math.sqrt(dX * dX + dY * dY);
  60799. return [Math.round(x + dX / distance), Math.round(y + dY / distance)];
  60800. };
  60801. /**
  60802. * Renders the source data into new canvas based on the triangulation.
  60803. *
  60804. * @param {number} width Width of the canvas.
  60805. * @param {number} height Height of the canvas.
  60806. * @param {number} pixelRatio Pixel ratio.
  60807. * @param {number} sourceResolution Source resolution.
  60808. * @param {ol.Extent} sourceExtent Extent of the data source.
  60809. * @param {number} targetResolution Target resolution.
  60810. * @param {ol.Extent} targetExtent Target extent.
  60811. * @param {ol.reproj.Triangulation} triangulation Calculated triangulation.
  60812. * @param {Array.<{extent: ol.Extent,
  60813. * image: (HTMLCanvasElement|Image|HTMLVideoElement)}>} sources
  60814. * Array of sources.
  60815. * @param {number} gutter Gutter of the sources.
  60816. * @param {boolean=} opt_renderEdges Render reprojection edges.
  60817. * @return {HTMLCanvasElement} Canvas with reprojected data.
  60818. */
  60819. ol.reproj.render = function(width, height, pixelRatio,
  60820. sourceResolution, sourceExtent, targetResolution, targetExtent,
  60821. triangulation, sources, gutter, opt_renderEdges) {
  60822. var context = ol.dom.createCanvasContext2D(Math.round(pixelRatio * width),
  60823. Math.round(pixelRatio * height));
  60824. if (sources.length === 0) {
  60825. return context.canvas;
  60826. }
  60827. context.scale(pixelRatio, pixelRatio);
  60828. var sourceDataExtent = ol.extent.createEmpty();
  60829. sources.forEach(function(src, i, arr) {
  60830. ol.extent.extend(sourceDataExtent, src.extent);
  60831. });
  60832. var canvasWidthInUnits = ol.extent.getWidth(sourceDataExtent);
  60833. var canvasHeightInUnits = ol.extent.getHeight(sourceDataExtent);
  60834. var stitchContext = ol.dom.createCanvasContext2D(
  60835. Math.round(pixelRatio * canvasWidthInUnits / sourceResolution),
  60836. Math.round(pixelRatio * canvasHeightInUnits / sourceResolution));
  60837. var stitchScale = pixelRatio / sourceResolution;
  60838. sources.forEach(function(src, i, arr) {
  60839. var xPos = src.extent[0] - sourceDataExtent[0];
  60840. var yPos = -(src.extent[3] - sourceDataExtent[3]);
  60841. var srcWidth = ol.extent.getWidth(src.extent);
  60842. var srcHeight = ol.extent.getHeight(src.extent);
  60843. stitchContext.drawImage(
  60844. src.image,
  60845. gutter, gutter,
  60846. src.image.width - 2 * gutter, src.image.height - 2 * gutter,
  60847. xPos * stitchScale, yPos * stitchScale,
  60848. srcWidth * stitchScale, srcHeight * stitchScale);
  60849. });
  60850. var targetTopLeft = ol.extent.getTopLeft(targetExtent);
  60851. triangulation.getTriangles().forEach(function(triangle, i, arr) {
  60852. /* Calculate affine transform (src -> dst)
  60853. * Resulting matrix can be used to transform coordinate
  60854. * from `sourceProjection` to destination pixels.
  60855. *
  60856. * To optimize number of context calls and increase numerical stability,
  60857. * we also do the following operations:
  60858. * trans(-topLeftExtentCorner), scale(1 / targetResolution), scale(1, -1)
  60859. * here before solving the linear system so [ui, vi] are pixel coordinates.
  60860. *
  60861. * Src points: xi, yi
  60862. * Dst points: ui, vi
  60863. * Affine coefficients: aij
  60864. *
  60865. * | x0 y0 1 0 0 0 | |a00| |u0|
  60866. * | x1 y1 1 0 0 0 | |a01| |u1|
  60867. * | x2 y2 1 0 0 0 | x |a02| = |u2|
  60868. * | 0 0 0 x0 y0 1 | |a10| |v0|
  60869. * | 0 0 0 x1 y1 1 | |a11| |v1|
  60870. * | 0 0 0 x2 y2 1 | |a12| |v2|
  60871. */
  60872. var source = triangle.source, target = triangle.target;
  60873. var x0 = source[0][0], y0 = source[0][1],
  60874. x1 = source[1][0], y1 = source[1][1],
  60875. x2 = source[2][0], y2 = source[2][1];
  60876. var u0 = (target[0][0] - targetTopLeft[0]) / targetResolution,
  60877. v0 = -(target[0][1] - targetTopLeft[1]) / targetResolution;
  60878. var u1 = (target[1][0] - targetTopLeft[0]) / targetResolution,
  60879. v1 = -(target[1][1] - targetTopLeft[1]) / targetResolution;
  60880. var u2 = (target[2][0] - targetTopLeft[0]) / targetResolution,
  60881. v2 = -(target[2][1] - targetTopLeft[1]) / targetResolution;
  60882. // Shift all the source points to improve numerical stability
  60883. // of all the subsequent calculations. The [x0, y0] is used here.
  60884. // This is also used to simplify the linear system.
  60885. var sourceNumericalShiftX = x0, sourceNumericalShiftY = y0;
  60886. x0 = 0;
  60887. y0 = 0;
  60888. x1 -= sourceNumericalShiftX;
  60889. y1 -= sourceNumericalShiftY;
  60890. x2 -= sourceNumericalShiftX;
  60891. y2 -= sourceNumericalShiftY;
  60892. var augmentedMatrix = [
  60893. [x1, y1, 0, 0, u1 - u0],
  60894. [x2, y2, 0, 0, u2 - u0],
  60895. [0, 0, x1, y1, v1 - v0],
  60896. [0, 0, x2, y2, v2 - v0]
  60897. ];
  60898. var affineCoefs = ol.math.solveLinearSystem(augmentedMatrix);
  60899. if (!affineCoefs) {
  60900. return;
  60901. }
  60902. context.save();
  60903. context.beginPath();
  60904. var centroidX = (u0 + u1 + u2) / 3, centroidY = (v0 + v1 + v2) / 3;
  60905. var p0 = ol.reproj.enlargeClipPoint_(centroidX, centroidY, u0, v0);
  60906. var p1 = ol.reproj.enlargeClipPoint_(centroidX, centroidY, u1, v1);
  60907. var p2 = ol.reproj.enlargeClipPoint_(centroidX, centroidY, u2, v2);
  60908. context.moveTo(p1[0], p1[1]);
  60909. context.lineTo(p0[0], p0[1]);
  60910. context.lineTo(p2[0], p2[1]);
  60911. context.clip();
  60912. context.transform(
  60913. affineCoefs[0], affineCoefs[2], affineCoefs[1], affineCoefs[3], u0, v0);
  60914. context.translate(sourceDataExtent[0] - sourceNumericalShiftX,
  60915. sourceDataExtent[3] - sourceNumericalShiftY);
  60916. context.scale(sourceResolution / pixelRatio,
  60917. -sourceResolution / pixelRatio);
  60918. context.drawImage(stitchContext.canvas, 0, 0);
  60919. context.restore();
  60920. });
  60921. if (opt_renderEdges) {
  60922. context.save();
  60923. context.strokeStyle = 'black';
  60924. context.lineWidth = 1;
  60925. triangulation.getTriangles().forEach(function(triangle, i, arr) {
  60926. var target = triangle.target;
  60927. var u0 = (target[0][0] - targetTopLeft[0]) / targetResolution,
  60928. v0 = -(target[0][1] - targetTopLeft[1]) / targetResolution;
  60929. var u1 = (target[1][0] - targetTopLeft[0]) / targetResolution,
  60930. v1 = -(target[1][1] - targetTopLeft[1]) / targetResolution;
  60931. var u2 = (target[2][0] - targetTopLeft[0]) / targetResolution,
  60932. v2 = -(target[2][1] - targetTopLeft[1]) / targetResolution;
  60933. context.beginPath();
  60934. context.moveTo(u1, v1);
  60935. context.lineTo(u0, v0);
  60936. context.lineTo(u2, v2);
  60937. context.closePath();
  60938. context.stroke();
  60939. });
  60940. context.restore();
  60941. }
  60942. return context.canvas;
  60943. };
  60944. goog.provide('ol.reproj.Triangulation');
  60945. goog.require('ol');
  60946. goog.require('ol.extent');
  60947. goog.require('ol.math');
  60948. goog.require('ol.proj');
  60949. /**
  60950. * @classdesc
  60951. * Class containing triangulation of the given target extent.
  60952. * Used for determining source data and the reprojection itself.
  60953. *
  60954. * @param {ol.proj.Projection} sourceProj Source projection.
  60955. * @param {ol.proj.Projection} targetProj Target projection.
  60956. * @param {ol.Extent} targetExtent Target extent to triangulate.
  60957. * @param {ol.Extent} maxSourceExtent Maximal source extent that can be used.
  60958. * @param {number} errorThreshold Acceptable error (in source units).
  60959. * @constructor
  60960. */
  60961. ol.reproj.Triangulation = function(sourceProj, targetProj, targetExtent,
  60962. maxSourceExtent, errorThreshold) {
  60963. /**
  60964. * @type {ol.proj.Projection}
  60965. * @private
  60966. */
  60967. this.sourceProj_ = sourceProj;
  60968. /**
  60969. * @type {ol.proj.Projection}
  60970. * @private
  60971. */
  60972. this.targetProj_ = targetProj;
  60973. /** @type {!Object.<string, ol.Coordinate>} */
  60974. var transformInvCache = {};
  60975. var transformInv = ol.proj.getTransform(this.targetProj_, this.sourceProj_);
  60976. /**
  60977. * @param {ol.Coordinate} c A coordinate.
  60978. * @return {ol.Coordinate} Transformed coordinate.
  60979. * @private
  60980. */
  60981. this.transformInv_ = function(c) {
  60982. var key = c[0] + '/' + c[1];
  60983. if (!transformInvCache[key]) {
  60984. transformInvCache[key] = transformInv(c);
  60985. }
  60986. return transformInvCache[key];
  60987. };
  60988. /**
  60989. * @type {ol.Extent}
  60990. * @private
  60991. */
  60992. this.maxSourceExtent_ = maxSourceExtent;
  60993. /**
  60994. * @type {number}
  60995. * @private
  60996. */
  60997. this.errorThresholdSquared_ = errorThreshold * errorThreshold;
  60998. /**
  60999. * @type {Array.<ol.ReprojTriangle>}
  61000. * @private
  61001. */
  61002. this.triangles_ = [];
  61003. /**
  61004. * Indicates that the triangulation crosses edge of the source projection.
  61005. * @type {boolean}
  61006. * @private
  61007. */
  61008. this.wrapsXInSource_ = false;
  61009. /**
  61010. * @type {boolean}
  61011. * @private
  61012. */
  61013. this.canWrapXInSource_ = this.sourceProj_.canWrapX() &&
  61014. !!maxSourceExtent &&
  61015. !!this.sourceProj_.getExtent() &&
  61016. (ol.extent.getWidth(maxSourceExtent) ==
  61017. ol.extent.getWidth(this.sourceProj_.getExtent()));
  61018. /**
  61019. * @type {?number}
  61020. * @private
  61021. */
  61022. this.sourceWorldWidth_ = this.sourceProj_.getExtent() ?
  61023. ol.extent.getWidth(this.sourceProj_.getExtent()) : null;
  61024. /**
  61025. * @type {?number}
  61026. * @private
  61027. */
  61028. this.targetWorldWidth_ = this.targetProj_.getExtent() ?
  61029. ol.extent.getWidth(this.targetProj_.getExtent()) : null;
  61030. var destinationTopLeft = ol.extent.getTopLeft(targetExtent);
  61031. var destinationTopRight = ol.extent.getTopRight(targetExtent);
  61032. var destinationBottomRight = ol.extent.getBottomRight(targetExtent);
  61033. var destinationBottomLeft = ol.extent.getBottomLeft(targetExtent);
  61034. var sourceTopLeft = this.transformInv_(destinationTopLeft);
  61035. var sourceTopRight = this.transformInv_(destinationTopRight);
  61036. var sourceBottomRight = this.transformInv_(destinationBottomRight);
  61037. var sourceBottomLeft = this.transformInv_(destinationBottomLeft);
  61038. this.addQuad_(
  61039. destinationTopLeft, destinationTopRight,
  61040. destinationBottomRight, destinationBottomLeft,
  61041. sourceTopLeft, sourceTopRight, sourceBottomRight, sourceBottomLeft,
  61042. ol.RASTER_REPROJECTION_MAX_SUBDIVISION);
  61043. if (this.wrapsXInSource_) {
  61044. var leftBound = Infinity;
  61045. this.triangles_.forEach(function(triangle, i, arr) {
  61046. leftBound = Math.min(leftBound,
  61047. triangle.source[0][0], triangle.source[1][0], triangle.source[2][0]);
  61048. });
  61049. // Shift triangles to be as close to `leftBound` as possible
  61050. // (if the distance is more than `worldWidth / 2` it can be closer.
  61051. this.triangles_.forEach(function(triangle) {
  61052. if (Math.max(triangle.source[0][0], triangle.source[1][0],
  61053. triangle.source[2][0]) - leftBound > this.sourceWorldWidth_ / 2) {
  61054. var newTriangle = [[triangle.source[0][0], triangle.source[0][1]],
  61055. [triangle.source[1][0], triangle.source[1][1]],
  61056. [triangle.source[2][0], triangle.source[2][1]]];
  61057. if ((newTriangle[0][0] - leftBound) > this.sourceWorldWidth_ / 2) {
  61058. newTriangle[0][0] -= this.sourceWorldWidth_;
  61059. }
  61060. if ((newTriangle[1][0] - leftBound) > this.sourceWorldWidth_ / 2) {
  61061. newTriangle[1][0] -= this.sourceWorldWidth_;
  61062. }
  61063. if ((newTriangle[2][0] - leftBound) > this.sourceWorldWidth_ / 2) {
  61064. newTriangle[2][0] -= this.sourceWorldWidth_;
  61065. }
  61066. // Rarely (if the extent contains both the dateline and prime meridian)
  61067. // the shift can in turn break some triangles.
  61068. // Detect this here and don't shift in such cases.
  61069. var minX = Math.min(
  61070. newTriangle[0][0], newTriangle[1][0], newTriangle[2][0]);
  61071. var maxX = Math.max(
  61072. newTriangle[0][0], newTriangle[1][0], newTriangle[2][0]);
  61073. if ((maxX - minX) < this.sourceWorldWidth_ / 2) {
  61074. triangle.source = newTriangle;
  61075. }
  61076. }
  61077. }, this);
  61078. }
  61079. transformInvCache = {};
  61080. };
  61081. /**
  61082. * Adds triangle to the triangulation.
  61083. * @param {ol.Coordinate} a The target a coordinate.
  61084. * @param {ol.Coordinate} b The target b coordinate.
  61085. * @param {ol.Coordinate} c The target c coordinate.
  61086. * @param {ol.Coordinate} aSrc The source a coordinate.
  61087. * @param {ol.Coordinate} bSrc The source b coordinate.
  61088. * @param {ol.Coordinate} cSrc The source c coordinate.
  61089. * @private
  61090. */
  61091. ol.reproj.Triangulation.prototype.addTriangle_ = function(a, b, c,
  61092. aSrc, bSrc, cSrc) {
  61093. this.triangles_.push({
  61094. source: [aSrc, bSrc, cSrc],
  61095. target: [a, b, c]
  61096. });
  61097. };
  61098. /**
  61099. * Adds quad (points in clock-wise order) to the triangulation
  61100. * (and reprojects the vertices) if valid.
  61101. * Performs quad subdivision if needed to increase precision.
  61102. *
  61103. * @param {ol.Coordinate} a The target a coordinate.
  61104. * @param {ol.Coordinate} b The target b coordinate.
  61105. * @param {ol.Coordinate} c The target c coordinate.
  61106. * @param {ol.Coordinate} d The target d coordinate.
  61107. * @param {ol.Coordinate} aSrc The source a coordinate.
  61108. * @param {ol.Coordinate} bSrc The source b coordinate.
  61109. * @param {ol.Coordinate} cSrc The source c coordinate.
  61110. * @param {ol.Coordinate} dSrc The source d coordinate.
  61111. * @param {number} maxSubdivision Maximal allowed subdivision of the quad.
  61112. * @private
  61113. */
  61114. ol.reproj.Triangulation.prototype.addQuad_ = function(a, b, c, d,
  61115. aSrc, bSrc, cSrc, dSrc, maxSubdivision) {
  61116. var sourceQuadExtent = ol.extent.boundingExtent([aSrc, bSrc, cSrc, dSrc]);
  61117. var sourceCoverageX = this.sourceWorldWidth_ ?
  61118. ol.extent.getWidth(sourceQuadExtent) / this.sourceWorldWidth_ : null;
  61119. var sourceWorldWidth = /** @type {number} */ (this.sourceWorldWidth_);
  61120. // when the quad is wrapped in the source projection
  61121. // it covers most of the projection extent, but not fully
  61122. var wrapsX = this.sourceProj_.canWrapX() &&
  61123. sourceCoverageX > 0.5 && sourceCoverageX < 1;
  61124. var needsSubdivision = false;
  61125. if (maxSubdivision > 0) {
  61126. if (this.targetProj_.isGlobal() && this.targetWorldWidth_) {
  61127. var targetQuadExtent = ol.extent.boundingExtent([a, b, c, d]);
  61128. var targetCoverageX =
  61129. ol.extent.getWidth(targetQuadExtent) / this.targetWorldWidth_;
  61130. needsSubdivision |=
  61131. targetCoverageX > ol.RASTER_REPROJECTION_MAX_TRIANGLE_WIDTH;
  61132. }
  61133. if (!wrapsX && this.sourceProj_.isGlobal() && sourceCoverageX) {
  61134. needsSubdivision |=
  61135. sourceCoverageX > ol.RASTER_REPROJECTION_MAX_TRIANGLE_WIDTH;
  61136. }
  61137. }
  61138. if (!needsSubdivision && this.maxSourceExtent_) {
  61139. if (!ol.extent.intersects(sourceQuadExtent, this.maxSourceExtent_)) {
  61140. // whole quad outside source projection extent -> ignore
  61141. return;
  61142. }
  61143. }
  61144. if (!needsSubdivision) {
  61145. if (!isFinite(aSrc[0]) || !isFinite(aSrc[1]) ||
  61146. !isFinite(bSrc[0]) || !isFinite(bSrc[1]) ||
  61147. !isFinite(cSrc[0]) || !isFinite(cSrc[1]) ||
  61148. !isFinite(dSrc[0]) || !isFinite(dSrc[1])) {
  61149. if (maxSubdivision > 0) {
  61150. needsSubdivision = true;
  61151. } else {
  61152. return;
  61153. }
  61154. }
  61155. }
  61156. if (maxSubdivision > 0) {
  61157. if (!needsSubdivision) {
  61158. var center = [(a[0] + c[0]) / 2, (a[1] + c[1]) / 2];
  61159. var centerSrc = this.transformInv_(center);
  61160. var dx;
  61161. if (wrapsX) {
  61162. var centerSrcEstimX =
  61163. (ol.math.modulo(aSrc[0], sourceWorldWidth) +
  61164. ol.math.modulo(cSrc[0], sourceWorldWidth)) / 2;
  61165. dx = centerSrcEstimX -
  61166. ol.math.modulo(centerSrc[0], sourceWorldWidth);
  61167. } else {
  61168. dx = (aSrc[0] + cSrc[0]) / 2 - centerSrc[0];
  61169. }
  61170. var dy = (aSrc[1] + cSrc[1]) / 2 - centerSrc[1];
  61171. var centerSrcErrorSquared = dx * dx + dy * dy;
  61172. needsSubdivision = centerSrcErrorSquared > this.errorThresholdSquared_;
  61173. }
  61174. if (needsSubdivision) {
  61175. if (Math.abs(a[0] - c[0]) <= Math.abs(a[1] - c[1])) {
  61176. // split horizontally (top & bottom)
  61177. var bc = [(b[0] + c[0]) / 2, (b[1] + c[1]) / 2];
  61178. var bcSrc = this.transformInv_(bc);
  61179. var da = [(d[0] + a[0]) / 2, (d[1] + a[1]) / 2];
  61180. var daSrc = this.transformInv_(da);
  61181. this.addQuad_(
  61182. a, b, bc, da, aSrc, bSrc, bcSrc, daSrc, maxSubdivision - 1);
  61183. this.addQuad_(
  61184. da, bc, c, d, daSrc, bcSrc, cSrc, dSrc, maxSubdivision - 1);
  61185. } else {
  61186. // split vertically (left & right)
  61187. var ab = [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2];
  61188. var abSrc = this.transformInv_(ab);
  61189. var cd = [(c[0] + d[0]) / 2, (c[1] + d[1]) / 2];
  61190. var cdSrc = this.transformInv_(cd);
  61191. this.addQuad_(
  61192. a, ab, cd, d, aSrc, abSrc, cdSrc, dSrc, maxSubdivision - 1);
  61193. this.addQuad_(
  61194. ab, b, c, cd, abSrc, bSrc, cSrc, cdSrc, maxSubdivision - 1);
  61195. }
  61196. return;
  61197. }
  61198. }
  61199. if (wrapsX) {
  61200. if (!this.canWrapXInSource_) {
  61201. return;
  61202. }
  61203. this.wrapsXInSource_ = true;
  61204. }
  61205. this.addTriangle_(a, c, d, aSrc, cSrc, dSrc);
  61206. this.addTriangle_(a, b, c, aSrc, bSrc, cSrc);
  61207. };
  61208. /**
  61209. * Calculates extent of the 'source' coordinates from all the triangles.
  61210. *
  61211. * @return {ol.Extent} Calculated extent.
  61212. */
  61213. ol.reproj.Triangulation.prototype.calculateSourceExtent = function() {
  61214. var extent = ol.extent.createEmpty();
  61215. this.triangles_.forEach(function(triangle, i, arr) {
  61216. var src = triangle.source;
  61217. ol.extent.extendCoordinate(extent, src[0]);
  61218. ol.extent.extendCoordinate(extent, src[1]);
  61219. ol.extent.extendCoordinate(extent, src[2]);
  61220. });
  61221. return extent;
  61222. };
  61223. /**
  61224. * @return {Array.<ol.ReprojTriangle>} Array of the calculated triangles.
  61225. */
  61226. ol.reproj.Triangulation.prototype.getTriangles = function() {
  61227. return this.triangles_;
  61228. };
  61229. goog.provide('ol.reproj.Image');
  61230. goog.require('ol');
  61231. goog.require('ol.ImageBase');
  61232. goog.require('ol.ImageState');
  61233. goog.require('ol.events');
  61234. goog.require('ol.events.EventType');
  61235. goog.require('ol.extent');
  61236. goog.require('ol.reproj');
  61237. goog.require('ol.reproj.Triangulation');
  61238. /**
  61239. * @classdesc
  61240. * Class encapsulating single reprojected image.
  61241. * See {@link ol.source.Image}.
  61242. *
  61243. * @constructor
  61244. * @extends {ol.ImageBase}
  61245. * @param {ol.proj.Projection} sourceProj Source projection (of the data).
  61246. * @param {ol.proj.Projection} targetProj Target projection.
  61247. * @param {ol.Extent} targetExtent Target extent.
  61248. * @param {number} targetResolution Target resolution.
  61249. * @param {number} pixelRatio Pixel ratio.
  61250. * @param {ol.ReprojImageFunctionType} getImageFunction
  61251. * Function returning source images (extent, resolution, pixelRatio).
  61252. */
  61253. ol.reproj.Image = function(sourceProj, targetProj,
  61254. targetExtent, targetResolution, pixelRatio, getImageFunction) {
  61255. /**
  61256. * @private
  61257. * @type {ol.proj.Projection}
  61258. */
  61259. this.targetProj_ = targetProj;
  61260. /**
  61261. * @private
  61262. * @type {ol.Extent}
  61263. */
  61264. this.maxSourceExtent_ = sourceProj.getExtent();
  61265. var maxTargetExtent = targetProj.getExtent();
  61266. var limitedTargetExtent = maxTargetExtent ?
  61267. ol.extent.getIntersection(targetExtent, maxTargetExtent) : targetExtent;
  61268. var targetCenter = ol.extent.getCenter(limitedTargetExtent);
  61269. var sourceResolution = ol.reproj.calculateSourceResolution(
  61270. sourceProj, targetProj, targetCenter, targetResolution);
  61271. var errorThresholdInPixels = ol.DEFAULT_RASTER_REPROJECTION_ERROR_THRESHOLD;
  61272. /**
  61273. * @private
  61274. * @type {!ol.reproj.Triangulation}
  61275. */
  61276. this.triangulation_ = new ol.reproj.Triangulation(
  61277. sourceProj, targetProj, limitedTargetExtent, this.maxSourceExtent_,
  61278. sourceResolution * errorThresholdInPixels);
  61279. /**
  61280. * @private
  61281. * @type {number}
  61282. */
  61283. this.targetResolution_ = targetResolution;
  61284. /**
  61285. * @private
  61286. * @type {ol.Extent}
  61287. */
  61288. this.targetExtent_ = targetExtent;
  61289. var sourceExtent = this.triangulation_.calculateSourceExtent();
  61290. /**
  61291. * @private
  61292. * @type {ol.ImageBase}
  61293. */
  61294. this.sourceImage_ =
  61295. getImageFunction(sourceExtent, sourceResolution, pixelRatio);
  61296. /**
  61297. * @private
  61298. * @type {number}
  61299. */
  61300. this.sourcePixelRatio_ =
  61301. this.sourceImage_ ? this.sourceImage_.getPixelRatio() : 1;
  61302. /**
  61303. * @private
  61304. * @type {HTMLCanvasElement}
  61305. */
  61306. this.canvas_ = null;
  61307. /**
  61308. * @private
  61309. * @type {?ol.EventsKey}
  61310. */
  61311. this.sourceListenerKey_ = null;
  61312. var state = ol.ImageState.LOADED;
  61313. var attributions = [];
  61314. if (this.sourceImage_) {
  61315. state = ol.ImageState.IDLE;
  61316. attributions = this.sourceImage_.getAttributions();
  61317. }
  61318. ol.ImageBase.call(this, targetExtent, targetResolution, this.sourcePixelRatio_,
  61319. state, attributions);
  61320. };
  61321. ol.inherits(ol.reproj.Image, ol.ImageBase);
  61322. /**
  61323. * @inheritDoc
  61324. */
  61325. ol.reproj.Image.prototype.disposeInternal = function() {
  61326. if (this.state == ol.ImageState.LOADING) {
  61327. this.unlistenSource_();
  61328. }
  61329. ol.ImageBase.prototype.disposeInternal.call(this);
  61330. };
  61331. /**
  61332. * @inheritDoc
  61333. */
  61334. ol.reproj.Image.prototype.getImage = function(opt_context) {
  61335. return this.canvas_;
  61336. };
  61337. /**
  61338. * @return {ol.proj.Projection} Projection.
  61339. */
  61340. ol.reproj.Image.prototype.getProjection = function() {
  61341. return this.targetProj_;
  61342. };
  61343. /**
  61344. * @private
  61345. */
  61346. ol.reproj.Image.prototype.reproject_ = function() {
  61347. var sourceState = this.sourceImage_.getState();
  61348. if (sourceState == ol.ImageState.LOADED) {
  61349. var width = ol.extent.getWidth(this.targetExtent_) / this.targetResolution_;
  61350. var height =
  61351. ol.extent.getHeight(this.targetExtent_) / this.targetResolution_;
  61352. this.canvas_ = ol.reproj.render(width, height, this.sourcePixelRatio_,
  61353. this.sourceImage_.getResolution(), this.maxSourceExtent_,
  61354. this.targetResolution_, this.targetExtent_, this.triangulation_, [{
  61355. extent: this.sourceImage_.getExtent(),
  61356. image: this.sourceImage_.getImage()
  61357. }], 0);
  61358. }
  61359. this.state = sourceState;
  61360. this.changed();
  61361. };
  61362. /**
  61363. * @inheritDoc
  61364. */
  61365. ol.reproj.Image.prototype.load = function() {
  61366. if (this.state == ol.ImageState.IDLE) {
  61367. this.state = ol.ImageState.LOADING;
  61368. this.changed();
  61369. var sourceState = this.sourceImage_.getState();
  61370. if (sourceState == ol.ImageState.LOADED ||
  61371. sourceState == ol.ImageState.ERROR) {
  61372. this.reproject_();
  61373. } else {
  61374. this.sourceListenerKey_ = ol.events.listen(this.sourceImage_,
  61375. ol.events.EventType.CHANGE, function(e) {
  61376. var sourceState = this.sourceImage_.getState();
  61377. if (sourceState == ol.ImageState.LOADED ||
  61378. sourceState == ol.ImageState.ERROR) {
  61379. this.unlistenSource_();
  61380. this.reproject_();
  61381. }
  61382. }, this);
  61383. this.sourceImage_.load();
  61384. }
  61385. }
  61386. };
  61387. /**
  61388. * @private
  61389. */
  61390. ol.reproj.Image.prototype.unlistenSource_ = function() {
  61391. ol.events.unlistenByKey(/** @type {!ol.EventsKey} */ (this.sourceListenerKey_));
  61392. this.sourceListenerKey_ = null;
  61393. };
  61394. goog.provide('ol.source.Image');
  61395. goog.require('ol');
  61396. goog.require('ol.ImageState');
  61397. goog.require('ol.array');
  61398. goog.require('ol.events.Event');
  61399. goog.require('ol.extent');
  61400. goog.require('ol.proj');
  61401. goog.require('ol.reproj.Image');
  61402. goog.require('ol.source.Source');
  61403. /**
  61404. * @classdesc
  61405. * Abstract base class; normally only used for creating subclasses and not
  61406. * instantiated in apps.
  61407. * Base class for sources providing a single image.
  61408. *
  61409. * @constructor
  61410. * @abstract
  61411. * @extends {ol.source.Source}
  61412. * @param {ol.SourceImageOptions} options Single image source options.
  61413. * @api
  61414. */
  61415. ol.source.Image = function(options) {
  61416. ol.source.Source.call(this, {
  61417. attributions: options.attributions,
  61418. extent: options.extent,
  61419. logo: options.logo,
  61420. projection: options.projection,
  61421. state: options.state
  61422. });
  61423. /**
  61424. * @private
  61425. * @type {Array.<number>}
  61426. */
  61427. this.resolutions_ = options.resolutions !== undefined ?
  61428. options.resolutions : null;
  61429. /**
  61430. * @private
  61431. * @type {ol.reproj.Image}
  61432. */
  61433. this.reprojectedImage_ = null;
  61434. /**
  61435. * @private
  61436. * @type {number}
  61437. */
  61438. this.reprojectedRevision_ = 0;
  61439. };
  61440. ol.inherits(ol.source.Image, ol.source.Source);
  61441. /**
  61442. * @return {Array.<number>} Resolutions.
  61443. * @override
  61444. */
  61445. ol.source.Image.prototype.getResolutions = function() {
  61446. return this.resolutions_;
  61447. };
  61448. /**
  61449. * @protected
  61450. * @param {number} resolution Resolution.
  61451. * @return {number} Resolution.
  61452. */
  61453. ol.source.Image.prototype.findNearestResolution = function(resolution) {
  61454. if (this.resolutions_) {
  61455. var idx = ol.array.linearFindNearest(this.resolutions_, resolution, 0);
  61456. resolution = this.resolutions_[idx];
  61457. }
  61458. return resolution;
  61459. };
  61460. /**
  61461. * @param {ol.Extent} extent Extent.
  61462. * @param {number} resolution Resolution.
  61463. * @param {number} pixelRatio Pixel ratio.
  61464. * @param {ol.proj.Projection} projection Projection.
  61465. * @return {ol.ImageBase} Single image.
  61466. */
  61467. ol.source.Image.prototype.getImage = function(extent, resolution, pixelRatio, projection) {
  61468. var sourceProjection = this.getProjection();
  61469. if (!ol.ENABLE_RASTER_REPROJECTION ||
  61470. !sourceProjection ||
  61471. !projection ||
  61472. ol.proj.equivalent(sourceProjection, projection)) {
  61473. if (sourceProjection) {
  61474. projection = sourceProjection;
  61475. }
  61476. return this.getImageInternal(extent, resolution, pixelRatio, projection);
  61477. } else {
  61478. if (this.reprojectedImage_) {
  61479. if (this.reprojectedRevision_ == this.getRevision() &&
  61480. ol.proj.equivalent(
  61481. this.reprojectedImage_.getProjection(), projection) &&
  61482. this.reprojectedImage_.getResolution() == resolution &&
  61483. ol.extent.equals(this.reprojectedImage_.getExtent(), extent)) {
  61484. return this.reprojectedImage_;
  61485. }
  61486. this.reprojectedImage_.dispose();
  61487. this.reprojectedImage_ = null;
  61488. }
  61489. this.reprojectedImage_ = new ol.reproj.Image(
  61490. sourceProjection, projection, extent, resolution, pixelRatio,
  61491. function(extent, resolution, pixelRatio) {
  61492. return this.getImageInternal(extent, resolution,
  61493. pixelRatio, sourceProjection);
  61494. }.bind(this));
  61495. this.reprojectedRevision_ = this.getRevision();
  61496. return this.reprojectedImage_;
  61497. }
  61498. };
  61499. /**
  61500. * @abstract
  61501. * @param {ol.Extent} extent Extent.
  61502. * @param {number} resolution Resolution.
  61503. * @param {number} pixelRatio Pixel ratio.
  61504. * @param {ol.proj.Projection} projection Projection.
  61505. * @return {ol.ImageBase} Single image.
  61506. * @protected
  61507. */
  61508. ol.source.Image.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {};
  61509. /**
  61510. * Handle image change events.
  61511. * @param {ol.events.Event} event Event.
  61512. * @protected
  61513. */
  61514. ol.source.Image.prototype.handleImageChange = function(event) {
  61515. var image = /** @type {ol.Image} */ (event.target);
  61516. switch (image.getState()) {
  61517. case ol.ImageState.LOADING:
  61518. this.dispatchEvent(
  61519. new ol.source.Image.Event(ol.source.Image.EventType_.IMAGELOADSTART,
  61520. image));
  61521. break;
  61522. case ol.ImageState.LOADED:
  61523. this.dispatchEvent(
  61524. new ol.source.Image.Event(ol.source.Image.EventType_.IMAGELOADEND,
  61525. image));
  61526. break;
  61527. case ol.ImageState.ERROR:
  61528. this.dispatchEvent(
  61529. new ol.source.Image.Event(ol.source.Image.EventType_.IMAGELOADERROR,
  61530. image));
  61531. break;
  61532. default:
  61533. // pass
  61534. }
  61535. };
  61536. /**
  61537. * Default image load function for image sources that use ol.Image image
  61538. * instances.
  61539. * @param {ol.Image} image Image.
  61540. * @param {string} src Source.
  61541. */
  61542. ol.source.Image.defaultImageLoadFunction = function(image, src) {
  61543. image.getImage().src = src;
  61544. };
  61545. /**
  61546. * @classdesc
  61547. * Events emitted by {@link ol.source.Image} instances are instances of this
  61548. * type.
  61549. *
  61550. * @constructor
  61551. * @extends {ol.events.Event}
  61552. * @implements {oli.source.ImageEvent}
  61553. * @param {string} type Type.
  61554. * @param {ol.Image} image The image.
  61555. */
  61556. ol.source.Image.Event = function(type, image) {
  61557. ol.events.Event.call(this, type);
  61558. /**
  61559. * The image related to the event.
  61560. * @type {ol.Image}
  61561. * @api
  61562. */
  61563. this.image = image;
  61564. };
  61565. ol.inherits(ol.source.Image.Event, ol.events.Event);
  61566. /**
  61567. * @enum {string}
  61568. * @private
  61569. */
  61570. ol.source.Image.EventType_ = {
  61571. /**
  61572. * Triggered when an image starts loading.
  61573. * @event ol.source.Image.Event#imageloadstart
  61574. * @api
  61575. */
  61576. IMAGELOADSTART: 'imageloadstart',
  61577. /**
  61578. * Triggered when an image finishes loading.
  61579. * @event ol.source.Image.Event#imageloadend
  61580. * @api
  61581. */
  61582. IMAGELOADEND: 'imageloadend',
  61583. /**
  61584. * Triggered if image loading results in an error.
  61585. * @event ol.source.Image.Event#imageloaderror
  61586. * @api
  61587. */
  61588. IMAGELOADERROR: 'imageloaderror'
  61589. };
  61590. goog.provide('ol.source.ImageCanvas');
  61591. goog.require('ol');
  61592. goog.require('ol.ImageCanvas');
  61593. goog.require('ol.extent');
  61594. goog.require('ol.source.Image');
  61595. /**
  61596. * @classdesc
  61597. * Base class for image sources where a canvas element is the image.
  61598. *
  61599. * @constructor
  61600. * @extends {ol.source.Image}
  61601. * @param {olx.source.ImageCanvasOptions} options Constructor options.
  61602. * @api
  61603. */
  61604. ol.source.ImageCanvas = function(options) {
  61605. ol.source.Image.call(this, {
  61606. attributions: options.attributions,
  61607. logo: options.logo,
  61608. projection: options.projection,
  61609. resolutions: options.resolutions,
  61610. state: options.state
  61611. });
  61612. /**
  61613. * @private
  61614. * @type {ol.CanvasFunctionType}
  61615. */
  61616. this.canvasFunction_ = options.canvasFunction;
  61617. /**
  61618. * @private
  61619. * @type {ol.ImageCanvas}
  61620. */
  61621. this.canvas_ = null;
  61622. /**
  61623. * @private
  61624. * @type {number}
  61625. */
  61626. this.renderedRevision_ = 0;
  61627. /**
  61628. * @private
  61629. * @type {number}
  61630. */
  61631. this.ratio_ = options.ratio !== undefined ?
  61632. options.ratio : 1.5;
  61633. };
  61634. ol.inherits(ol.source.ImageCanvas, ol.source.Image);
  61635. /**
  61636. * @inheritDoc
  61637. */
  61638. ol.source.ImageCanvas.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
  61639. resolution = this.findNearestResolution(resolution);
  61640. var canvas = this.canvas_;
  61641. if (canvas &&
  61642. this.renderedRevision_ == this.getRevision() &&
  61643. canvas.getResolution() == resolution &&
  61644. canvas.getPixelRatio() == pixelRatio &&
  61645. ol.extent.containsExtent(canvas.getExtent(), extent)) {
  61646. return canvas;
  61647. }
  61648. extent = extent.slice();
  61649. ol.extent.scaleFromCenter(extent, this.ratio_);
  61650. var width = ol.extent.getWidth(extent) / resolution;
  61651. var height = ol.extent.getHeight(extent) / resolution;
  61652. var size = [width * pixelRatio, height * pixelRatio];
  61653. var canvasElement = this.canvasFunction_(
  61654. extent, resolution, pixelRatio, size, projection);
  61655. if (canvasElement) {
  61656. canvas = new ol.ImageCanvas(extent, resolution, pixelRatio,
  61657. this.getAttributions(), canvasElement);
  61658. }
  61659. this.canvas_ = canvas;
  61660. this.renderedRevision_ = this.getRevision();
  61661. return canvas;
  61662. };
  61663. goog.provide('ol.source.ImageVector');
  61664. goog.require('ol');
  61665. goog.require('ol.dom');
  61666. goog.require('ol.events');
  61667. goog.require('ol.events.EventType');
  61668. goog.require('ol.extent');
  61669. goog.require('ol.render.canvas.ReplayGroup');
  61670. goog.require('ol.renderer.vector');
  61671. goog.require('ol.source.ImageCanvas');
  61672. goog.require('ol.style.Style');
  61673. goog.require('ol.transform');
  61674. /**
  61675. * @classdesc
  61676. * An image source whose images are canvas elements into which vector features
  61677. * read from a vector source (`ol.source.Vector`) are drawn. An
  61678. * `ol.source.ImageVector` object is to be used as the `source` of an image
  61679. * layer (`ol.layer.Image`). Image layers are rotated, scaled, and translated,
  61680. * as opposed to being re-rendered, during animations and interactions. So, like
  61681. * any other image layer, an image layer configured with an
  61682. * `ol.source.ImageVector` will exhibit this behaviour. This is in contrast to a
  61683. * vector layer, where vector features are re-drawn during animations and
  61684. * interactions.
  61685. *
  61686. * @constructor
  61687. * @extends {ol.source.ImageCanvas}
  61688. * @param {olx.source.ImageVectorOptions} options Options.
  61689. * @api
  61690. */
  61691. ol.source.ImageVector = function(options) {
  61692. /**
  61693. * @private
  61694. * @type {ol.source.Vector}
  61695. */
  61696. this.source_ = options.source;
  61697. /**
  61698. * @private
  61699. * @type {ol.Transform}
  61700. */
  61701. this.transform_ = ol.transform.create();
  61702. /**
  61703. * @private
  61704. * @type {CanvasRenderingContext2D}
  61705. */
  61706. this.canvasContext_ = ol.dom.createCanvasContext2D();
  61707. /**
  61708. * @private
  61709. * @type {ol.Size}
  61710. */
  61711. this.canvasSize_ = [0, 0];
  61712. /**
  61713. * @private
  61714. * @type {number}
  61715. */
  61716. this.renderBuffer_ = options.renderBuffer == undefined ? 100 : options.renderBuffer;
  61717. /**
  61718. * @private
  61719. * @type {ol.render.canvas.ReplayGroup}
  61720. */
  61721. this.replayGroup_ = null;
  61722. ol.source.ImageCanvas.call(this, {
  61723. attributions: options.attributions,
  61724. canvasFunction: this.canvasFunctionInternal_.bind(this),
  61725. logo: options.logo,
  61726. projection: options.projection,
  61727. ratio: options.ratio,
  61728. resolutions: options.resolutions,
  61729. state: this.source_.getState()
  61730. });
  61731. /**
  61732. * User provided style.
  61733. * @type {ol.style.Style|Array.<ol.style.Style>|ol.StyleFunction}
  61734. * @private
  61735. */
  61736. this.style_ = null;
  61737. /**
  61738. * Style function for use within the library.
  61739. * @type {ol.StyleFunction|undefined}
  61740. * @private
  61741. */
  61742. this.styleFunction_ = undefined;
  61743. this.setStyle(options.style);
  61744. ol.events.listen(this.source_, ol.events.EventType.CHANGE,
  61745. this.handleSourceChange_, this);
  61746. };
  61747. ol.inherits(ol.source.ImageVector, ol.source.ImageCanvas);
  61748. /**
  61749. * @param {ol.Extent} extent Extent.
  61750. * @param {number} resolution Resolution.
  61751. * @param {number} pixelRatio Pixel ratio.
  61752. * @param {ol.Size} size Size.
  61753. * @param {ol.proj.Projection} projection Projection;
  61754. * @return {HTMLCanvasElement} Canvas element.
  61755. * @private
  61756. */
  61757. ol.source.ImageVector.prototype.canvasFunctionInternal_ = function(extent, resolution, pixelRatio, size, projection) {
  61758. var replayGroup = new ol.render.canvas.ReplayGroup(
  61759. ol.renderer.vector.getTolerance(resolution, pixelRatio), extent,
  61760. resolution, this.source_.getOverlaps(), this.renderBuffer_);
  61761. this.source_.loadFeatures(extent, resolution, projection);
  61762. var loading = false;
  61763. this.source_.forEachFeatureInExtent(extent,
  61764. /**
  61765. * @param {ol.Feature} feature Feature.
  61766. */
  61767. function(feature) {
  61768. loading = loading ||
  61769. this.renderFeature_(feature, resolution, pixelRatio, replayGroup);
  61770. }, this);
  61771. replayGroup.finish();
  61772. if (loading) {
  61773. return null;
  61774. }
  61775. if (this.canvasSize_[0] != size[0] || this.canvasSize_[1] != size[1]) {
  61776. this.canvasContext_.canvas.width = size[0];
  61777. this.canvasContext_.canvas.height = size[1];
  61778. this.canvasSize_[0] = size[0];
  61779. this.canvasSize_[1] = size[1];
  61780. } else {
  61781. this.canvasContext_.clearRect(0, 0, size[0], size[1]);
  61782. }
  61783. var transform = this.getTransform_(ol.extent.getCenter(extent),
  61784. resolution, pixelRatio, size);
  61785. replayGroup.replay(this.canvasContext_, pixelRatio, transform, 0, {});
  61786. this.replayGroup_ = replayGroup;
  61787. return this.canvasContext_.canvas;
  61788. };
  61789. /**
  61790. * @inheritDoc
  61791. */
  61792. ol.source.ImageVector.prototype.forEachFeatureAtCoordinate = function(
  61793. coordinate, resolution, rotation, hitTolerance, skippedFeatureUids, callback) {
  61794. if (!this.replayGroup_) {
  61795. return undefined;
  61796. } else {
  61797. /** @type {Object.<string, boolean>} */
  61798. var features = {};
  61799. return this.replayGroup_.forEachFeatureAtCoordinate(
  61800. coordinate, resolution, 0, hitTolerance, skippedFeatureUids,
  61801. /**
  61802. * @param {ol.Feature|ol.render.Feature} feature Feature.
  61803. * @return {?} Callback result.
  61804. */
  61805. function(feature) {
  61806. var key = ol.getUid(feature).toString();
  61807. if (!(key in features)) {
  61808. features[key] = true;
  61809. return callback(feature);
  61810. }
  61811. });
  61812. }
  61813. };
  61814. /**
  61815. * Get a reference to the wrapped source.
  61816. * @return {ol.source.Vector} Source.
  61817. * @api
  61818. */
  61819. ol.source.ImageVector.prototype.getSource = function() {
  61820. return this.source_;
  61821. };
  61822. /**
  61823. * Get the style for features. This returns whatever was passed to the `style`
  61824. * option at construction or to the `setStyle` method.
  61825. * @return {ol.style.Style|Array.<ol.style.Style>|ol.StyleFunction}
  61826. * Layer style.
  61827. * @api
  61828. */
  61829. ol.source.ImageVector.prototype.getStyle = function() {
  61830. return this.style_;
  61831. };
  61832. /**
  61833. * Get the style function.
  61834. * @return {ol.StyleFunction|undefined} Layer style function.
  61835. * @api
  61836. */
  61837. ol.source.ImageVector.prototype.getStyleFunction = function() {
  61838. return this.styleFunction_;
  61839. };
  61840. /**
  61841. * @param {ol.Coordinate} center Center.
  61842. * @param {number} resolution Resolution.
  61843. * @param {number} pixelRatio Pixel ratio.
  61844. * @param {ol.Size} size Size.
  61845. * @return {!ol.Transform} Transform.
  61846. * @private
  61847. */
  61848. ol.source.ImageVector.prototype.getTransform_ = function(center, resolution, pixelRatio, size) {
  61849. var dx1 = size[0] / 2;
  61850. var dy1 = size[1] / 2;
  61851. var sx = pixelRatio / resolution;
  61852. var sy = -sx;
  61853. var dx2 = -center[0];
  61854. var dy2 = -center[1];
  61855. return ol.transform.compose(this.transform_, dx1, dy1, sx, sy, 0, dx2, dy2);
  61856. };
  61857. /**
  61858. * Handle changes in image style state.
  61859. * @param {ol.events.Event} event Image style change event.
  61860. * @private
  61861. */
  61862. ol.source.ImageVector.prototype.handleImageChange_ = function(event) {
  61863. this.changed();
  61864. };
  61865. /**
  61866. * @private
  61867. */
  61868. ol.source.ImageVector.prototype.handleSourceChange_ = function() {
  61869. // setState will trigger a CHANGE event, so we always rely
  61870. // change events by calling setState.
  61871. this.setState(this.source_.getState());
  61872. };
  61873. /**
  61874. * @param {ol.Feature} feature Feature.
  61875. * @param {number} resolution Resolution.
  61876. * @param {number} pixelRatio Pixel ratio.
  61877. * @param {ol.render.canvas.ReplayGroup} replayGroup Replay group.
  61878. * @return {boolean} `true` if an image is loading.
  61879. * @private
  61880. */
  61881. ol.source.ImageVector.prototype.renderFeature_ = function(feature, resolution, pixelRatio, replayGroup) {
  61882. var styles;
  61883. var styleFunction = feature.getStyleFunction();
  61884. if (styleFunction) {
  61885. styles = styleFunction.call(feature, resolution);
  61886. } else if (this.styleFunction_) {
  61887. styles = this.styleFunction_(feature, resolution);
  61888. }
  61889. if (!styles) {
  61890. return false;
  61891. }
  61892. var i, ii, loading = false;
  61893. if (!Array.isArray(styles)) {
  61894. styles = [styles];
  61895. }
  61896. for (i = 0, ii = styles.length; i < ii; ++i) {
  61897. loading = ol.renderer.vector.renderFeature(
  61898. replayGroup, feature, styles[i],
  61899. ol.renderer.vector.getSquaredTolerance(resolution, pixelRatio),
  61900. this.handleImageChange_, this) || loading;
  61901. }
  61902. return loading;
  61903. };
  61904. /**
  61905. * Set the style for features. This can be a single style object, an array
  61906. * of styles, or a function that takes a feature and resolution and returns
  61907. * an array of styles. If it is `undefined` the default style is used. If
  61908. * it is `null` the layer has no style (a `null` style), so only features
  61909. * that have their own styles will be rendered in the layer. See
  61910. * {@link ol.style} for information on the default style.
  61911. * @param {ol.style.Style|Array.<ol.style.Style>|ol.StyleFunction|undefined}
  61912. * style Layer style.
  61913. * @api
  61914. */
  61915. ol.source.ImageVector.prototype.setStyle = function(style) {
  61916. this.style_ = style !== undefined ? style : ol.style.Style.defaultFunction;
  61917. this.styleFunction_ = !style ?
  61918. undefined : ol.style.Style.createFunction(this.style_);
  61919. this.changed();
  61920. };
  61921. goog.provide('ol.renderer.webgl.ImageLayer');
  61922. goog.require('ol');
  61923. goog.require('ol.ViewHint');
  61924. goog.require('ol.dom');
  61925. goog.require('ol.extent');
  61926. goog.require('ol.functions');
  61927. goog.require('ol.renderer.webgl.Layer');
  61928. goog.require('ol.source.ImageVector');
  61929. goog.require('ol.transform');
  61930. goog.require('ol.webgl');
  61931. goog.require('ol.webgl.Context');
  61932. if (ol.ENABLE_WEBGL) {
  61933. /**
  61934. * @constructor
  61935. * @extends {ol.renderer.webgl.Layer}
  61936. * @param {ol.renderer.webgl.Map} mapRenderer Map renderer.
  61937. * @param {ol.layer.Image} imageLayer Tile layer.
  61938. */
  61939. ol.renderer.webgl.ImageLayer = function(mapRenderer, imageLayer) {
  61940. ol.renderer.webgl.Layer.call(this, mapRenderer, imageLayer);
  61941. /**
  61942. * The last rendered image.
  61943. * @private
  61944. * @type {?ol.ImageBase}
  61945. */
  61946. this.image_ = null;
  61947. /**
  61948. * @private
  61949. * @type {CanvasRenderingContext2D}
  61950. */
  61951. this.hitCanvasContext_ = null;
  61952. /**
  61953. * @private
  61954. * @type {?ol.Transform}
  61955. */
  61956. this.hitTransformationMatrix_ = null;
  61957. };
  61958. ol.inherits(ol.renderer.webgl.ImageLayer, ol.renderer.webgl.Layer);
  61959. /**
  61960. * @param {ol.ImageBase} image Image.
  61961. * @private
  61962. * @return {WebGLTexture} Texture.
  61963. */
  61964. ol.renderer.webgl.ImageLayer.prototype.createTexture_ = function(image) {
  61965. // We meet the conditions to work with non-power of two textures.
  61966. // http://www.khronos.org/webgl/wiki/WebGL_and_OpenGL_Differences#Non-Power_of_Two_Texture_Support
  61967. // http://learningwebgl.com/blog/?p=2101
  61968. var imageElement = image.getImage();
  61969. var gl = this.mapRenderer.getGL();
  61970. return ol.webgl.Context.createTexture(
  61971. gl, imageElement, ol.webgl.CLAMP_TO_EDGE, ol.webgl.CLAMP_TO_EDGE);
  61972. };
  61973. /**
  61974. * @inheritDoc
  61975. */
  61976. ol.renderer.webgl.ImageLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
  61977. var layer = this.getLayer();
  61978. var source = layer.getSource();
  61979. var resolution = frameState.viewState.resolution;
  61980. var rotation = frameState.viewState.rotation;
  61981. var skippedFeatureUids = frameState.skippedFeatureUids;
  61982. return source.forEachFeatureAtCoordinate(
  61983. coordinate, resolution, rotation, hitTolerance, skippedFeatureUids,
  61984. /**
  61985. * @param {ol.Feature|ol.render.Feature} feature Feature.
  61986. * @return {?} Callback result.
  61987. */
  61988. function(feature) {
  61989. return callback.call(thisArg, feature, layer);
  61990. });
  61991. };
  61992. /**
  61993. * @inheritDoc
  61994. */
  61995. ol.renderer.webgl.ImageLayer.prototype.prepareFrame = function(frameState, layerState, context) {
  61996. var gl = this.mapRenderer.getGL();
  61997. var pixelRatio = frameState.pixelRatio;
  61998. var viewState = frameState.viewState;
  61999. var viewCenter = viewState.center;
  62000. var viewResolution = viewState.resolution;
  62001. var viewRotation = viewState.rotation;
  62002. var image = this.image_;
  62003. var texture = this.texture;
  62004. var imageLayer = /** @type {ol.layer.Image} */ (this.getLayer());
  62005. var imageSource = imageLayer.getSource();
  62006. var hints = frameState.viewHints;
  62007. var renderedExtent = frameState.extent;
  62008. if (layerState.extent !== undefined) {
  62009. renderedExtent = ol.extent.getIntersection(
  62010. renderedExtent, layerState.extent);
  62011. }
  62012. if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING] &&
  62013. !ol.extent.isEmpty(renderedExtent)) {
  62014. var projection = viewState.projection;
  62015. if (!ol.ENABLE_RASTER_REPROJECTION) {
  62016. var sourceProjection = imageSource.getProjection();
  62017. if (sourceProjection) {
  62018. projection = sourceProjection;
  62019. }
  62020. }
  62021. var image_ = imageSource.getImage(renderedExtent, viewResolution,
  62022. pixelRatio, projection);
  62023. if (image_) {
  62024. var loaded = this.loadImage(image_);
  62025. if (loaded) {
  62026. image = image_;
  62027. texture = this.createTexture_(image_);
  62028. if (this.texture) {
  62029. /**
  62030. * @param {WebGLRenderingContext} gl GL.
  62031. * @param {WebGLTexture} texture Texture.
  62032. */
  62033. var postRenderFunction = function(gl, texture) {
  62034. if (!gl.isContextLost()) {
  62035. gl.deleteTexture(texture);
  62036. }
  62037. }.bind(null, gl, this.texture);
  62038. frameState.postRenderFunctions.push(
  62039. /** @type {ol.PostRenderFunction} */ (postRenderFunction)
  62040. );
  62041. }
  62042. }
  62043. }
  62044. }
  62045. if (image) {
  62046. var canvas = this.mapRenderer.getContext().getCanvas();
  62047. this.updateProjectionMatrix_(canvas.width, canvas.height,
  62048. pixelRatio, viewCenter, viewResolution, viewRotation,
  62049. image.getExtent());
  62050. this.hitTransformationMatrix_ = null;
  62051. // Translate and scale to flip the Y coord.
  62052. var texCoordMatrix = this.texCoordMatrix;
  62053. ol.transform.reset(texCoordMatrix);
  62054. ol.transform.scale(texCoordMatrix, 1, -1);
  62055. ol.transform.translate(texCoordMatrix, 0, -1);
  62056. this.image_ = image;
  62057. this.texture = texture;
  62058. this.updateAttributions(frameState.attributions, image.getAttributions());
  62059. this.updateLogos(frameState, imageSource);
  62060. }
  62061. return !!image;
  62062. };
  62063. /**
  62064. * @param {number} canvasWidth Canvas width.
  62065. * @param {number} canvasHeight Canvas height.
  62066. * @param {number} pixelRatio Pixel ratio.
  62067. * @param {ol.Coordinate} viewCenter View center.
  62068. * @param {number} viewResolution View resolution.
  62069. * @param {number} viewRotation View rotation.
  62070. * @param {ol.Extent} imageExtent Image extent.
  62071. * @private
  62072. */
  62073. ol.renderer.webgl.ImageLayer.prototype.updateProjectionMatrix_ = function(canvasWidth, canvasHeight, pixelRatio,
  62074. viewCenter, viewResolution, viewRotation, imageExtent) {
  62075. var canvasExtentWidth = canvasWidth * viewResolution;
  62076. var canvasExtentHeight = canvasHeight * viewResolution;
  62077. var projectionMatrix = this.projectionMatrix;
  62078. ol.transform.reset(projectionMatrix);
  62079. ol.transform.scale(projectionMatrix,
  62080. pixelRatio * 2 / canvasExtentWidth,
  62081. pixelRatio * 2 / canvasExtentHeight);
  62082. ol.transform.rotate(projectionMatrix, -viewRotation);
  62083. ol.transform.translate(projectionMatrix,
  62084. imageExtent[0] - viewCenter[0],
  62085. imageExtent[1] - viewCenter[1]);
  62086. ol.transform.scale(projectionMatrix,
  62087. (imageExtent[2] - imageExtent[0]) / 2,
  62088. (imageExtent[3] - imageExtent[1]) / 2);
  62089. ol.transform.translate(projectionMatrix, 1, 1);
  62090. };
  62091. /**
  62092. * @inheritDoc
  62093. */
  62094. ol.renderer.webgl.ImageLayer.prototype.hasFeatureAtCoordinate = function(coordinate, frameState) {
  62095. var hasFeature = this.forEachFeatureAtCoordinate(
  62096. coordinate, frameState, 0, ol.functions.TRUE, this);
  62097. return hasFeature !== undefined;
  62098. };
  62099. /**
  62100. * @inheritDoc
  62101. */
  62102. ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
  62103. if (!this.image_ || !this.image_.getImage()) {
  62104. return undefined;
  62105. }
  62106. if (this.getLayer().getSource() instanceof ol.source.ImageVector) {
  62107. // for ImageVector sources use the original hit-detection logic,
  62108. // so that for example also transparent polygons are detected
  62109. var coordinate = ol.transform.apply(
  62110. frameState.pixelToCoordinateTransform, pixel.slice());
  62111. var hasFeature = this.forEachFeatureAtCoordinate(
  62112. coordinate, frameState, 0, ol.functions.TRUE, this);
  62113. if (hasFeature) {
  62114. return callback.call(thisArg, this.getLayer(), null);
  62115. } else {
  62116. return undefined;
  62117. }
  62118. } else {
  62119. var imageSize =
  62120. [this.image_.getImage().width, this.image_.getImage().height];
  62121. if (!this.hitTransformationMatrix_) {
  62122. this.hitTransformationMatrix_ = this.getHitTransformationMatrix_(
  62123. frameState.size, imageSize);
  62124. }
  62125. var pixelOnFrameBuffer = ol.transform.apply(
  62126. this.hitTransformationMatrix_, pixel.slice());
  62127. if (pixelOnFrameBuffer[0] < 0 || pixelOnFrameBuffer[0] > imageSize[0] ||
  62128. pixelOnFrameBuffer[1] < 0 || pixelOnFrameBuffer[1] > imageSize[1]) {
  62129. // outside the image, no need to check
  62130. return undefined;
  62131. }
  62132. if (!this.hitCanvasContext_) {
  62133. this.hitCanvasContext_ = ol.dom.createCanvasContext2D(1, 1);
  62134. }
  62135. this.hitCanvasContext_.clearRect(0, 0, 1, 1);
  62136. this.hitCanvasContext_.drawImage(this.image_.getImage(),
  62137. pixelOnFrameBuffer[0], pixelOnFrameBuffer[1], 1, 1, 0, 0, 1, 1);
  62138. var imageData = this.hitCanvasContext_.getImageData(0, 0, 1, 1).data;
  62139. if (imageData[3] > 0) {
  62140. return callback.call(thisArg, this.getLayer(), imageData);
  62141. } else {
  62142. return undefined;
  62143. }
  62144. }
  62145. };
  62146. /**
  62147. * The transformation matrix to get the pixel on the image for a
  62148. * pixel on the map.
  62149. * @param {ol.Size} mapSize The map size.
  62150. * @param {ol.Size} imageSize The image size.
  62151. * @return {ol.Transform} The transformation matrix.
  62152. * @private
  62153. */
  62154. ol.renderer.webgl.ImageLayer.prototype.getHitTransformationMatrix_ = function(mapSize, imageSize) {
  62155. // the first matrix takes a map pixel, flips the y-axis and scales to
  62156. // a range between -1 ... 1
  62157. var mapCoordTransform = ol.transform.create();
  62158. ol.transform.translate(mapCoordTransform, -1, -1);
  62159. ol.transform.scale(mapCoordTransform, 2 / mapSize[0], 2 / mapSize[1]);
  62160. ol.transform.translate(mapCoordTransform, 0, mapSize[1]);
  62161. ol.transform.scale(mapCoordTransform, 1, -1);
  62162. // the second matrix is the inverse of the projection matrix used in the
  62163. // shader for drawing
  62164. var projectionMatrixInv = ol.transform.invert(this.projectionMatrix.slice());
  62165. // the third matrix scales to the image dimensions and flips the y-axis again
  62166. var transform = ol.transform.create();
  62167. ol.transform.translate(transform, 0, imageSize[1]);
  62168. ol.transform.scale(transform, 1, -1);
  62169. ol.transform.scale(transform, imageSize[0] / 2, imageSize[1] / 2);
  62170. ol.transform.translate(transform, 1, 1);
  62171. ol.transform.multiply(transform, projectionMatrixInv);
  62172. ol.transform.multiply(transform, mapCoordTransform);
  62173. return transform;
  62174. };
  62175. }
  62176. goog.provide('ol.layer.Image');
  62177. goog.require('ol');
  62178. goog.require('ol.layer.Layer');
  62179. goog.require('ol.renderer.Type');
  62180. goog.require('ol.renderer.canvas.ImageLayer');
  62181. goog.require('ol.renderer.webgl.ImageLayer');
  62182. /**
  62183. * @classdesc
  62184. * Server-rendered images that are available for arbitrary extents and
  62185. * resolutions.
  62186. * Note that any property set in the options is set as a {@link ol.Object}
  62187. * property on the layer object; for example, setting `title: 'My Title'` in the
  62188. * options means that `title` is observable, and has get/set accessors.
  62189. *
  62190. * @constructor
  62191. * @extends {ol.layer.Layer}
  62192. * @fires ol.render.Event
  62193. * @param {olx.layer.ImageOptions=} opt_options Layer options.
  62194. * @api
  62195. */
  62196. ol.layer.Image = function(opt_options) {
  62197. var options = opt_options ? opt_options : {};
  62198. ol.layer.Layer.call(this, /** @type {olx.layer.LayerOptions} */ (options));
  62199. };
  62200. ol.inherits(ol.layer.Image, ol.layer.Layer);
  62201. /**
  62202. * @inheritDoc
  62203. */
  62204. ol.layer.Image.prototype.createRenderer = function(mapRenderer) {
  62205. var renderer = null;
  62206. var type = mapRenderer.getType();
  62207. if (ol.ENABLE_CANVAS && type === ol.renderer.Type.CANVAS) {
  62208. renderer = new ol.renderer.canvas.ImageLayer(this);
  62209. } else if (ol.ENABLE_WEBGL && type === ol.renderer.Type.WEBGL) {
  62210. renderer = new ol.renderer.webgl.ImageLayer(/** @type {ol.renderer.webgl.Map} */ (mapRenderer), this);
  62211. }
  62212. return renderer;
  62213. };
  62214. /**
  62215. * Return the associated {@link ol.source.Image source} of the image layer.
  62216. * @function
  62217. * @return {ol.source.Image} Source.
  62218. * @api
  62219. */
  62220. ol.layer.Image.prototype.getSource;
  62221. goog.provide('ol.layer.TileProperty');
  62222. /**
  62223. * @enum {string}
  62224. */
  62225. ol.layer.TileProperty = {
  62226. PRELOAD: 'preload',
  62227. USE_INTERIM_TILES_ON_ERROR: 'useInterimTilesOnError'
  62228. };
  62229. // FIXME find correct globalCompositeOperation
  62230. goog.provide('ol.renderer.canvas.TileLayer');
  62231. goog.require('ol');
  62232. goog.require('ol.TileRange');
  62233. goog.require('ol.TileState');
  62234. goog.require('ol.ViewHint');
  62235. goog.require('ol.array');
  62236. goog.require('ol.dom');
  62237. goog.require('ol.extent');
  62238. goog.require('ol.renderer.canvas.IntermediateCanvas');
  62239. goog.require('ol.transform');
  62240. /**
  62241. * @constructor
  62242. * @extends {ol.renderer.canvas.IntermediateCanvas}
  62243. * @param {ol.layer.Tile|ol.layer.VectorTile} tileLayer Tile layer.
  62244. */
  62245. ol.renderer.canvas.TileLayer = function(tileLayer) {
  62246. ol.renderer.canvas.IntermediateCanvas.call(this, tileLayer);
  62247. /**
  62248. * @protected
  62249. * @type {CanvasRenderingContext2D}
  62250. */
  62251. this.context = this.context === null ? null : ol.dom.createCanvasContext2D();
  62252. /**
  62253. * @private
  62254. * @type {number}
  62255. */
  62256. this.oversampling_;
  62257. /**
  62258. * @private
  62259. * @type {ol.Extent}
  62260. */
  62261. this.renderedExtent_ = null;
  62262. /**
  62263. * @protected
  62264. * @type {number}
  62265. */
  62266. this.renderedRevision;
  62267. /**
  62268. * @protected
  62269. * @type {!Array.<ol.Tile>}
  62270. */
  62271. this.renderedTiles = [];
  62272. /**
  62273. * @protected
  62274. * @type {ol.Extent}
  62275. */
  62276. this.tmpExtent = ol.extent.createEmpty();
  62277. /**
  62278. * @private
  62279. * @type {ol.TileRange}
  62280. */
  62281. this.tmpTileRange_ = new ol.TileRange(0, 0, 0, 0);
  62282. /**
  62283. * @private
  62284. * @type {ol.Transform}
  62285. */
  62286. this.imageTransform_ = ol.transform.create();
  62287. /**
  62288. * @protected
  62289. * @type {number}
  62290. */
  62291. this.zDirection = 0;
  62292. };
  62293. ol.inherits(ol.renderer.canvas.TileLayer, ol.renderer.canvas.IntermediateCanvas);
  62294. /**
  62295. * @private
  62296. * @param {ol.Tile} tile Tile.
  62297. * @return {boolean} Tile is drawable.
  62298. */
  62299. ol.renderer.canvas.TileLayer.prototype.isDrawableTile_ = function(tile) {
  62300. var tileState = tile.getState();
  62301. var useInterimTilesOnError = this.getLayer().getUseInterimTilesOnError();
  62302. return tileState == ol.TileState.LOADED ||
  62303. tileState == ol.TileState.EMPTY ||
  62304. tileState == ol.TileState.ERROR && !useInterimTilesOnError;
  62305. };
  62306. /**
  62307. * @inheritDoc
  62308. */
  62309. ol.renderer.canvas.TileLayer.prototype.prepareFrame = function(frameState, layerState) {
  62310. var pixelRatio = frameState.pixelRatio;
  62311. var size = frameState.size;
  62312. var viewState = frameState.viewState;
  62313. var projection = viewState.projection;
  62314. var viewResolution = viewState.resolution;
  62315. var viewCenter = viewState.center;
  62316. var tileLayer = this.getLayer();
  62317. var tileSource = /** @type {ol.source.Tile} */ (tileLayer.getSource());
  62318. var sourceRevision = tileSource.getRevision();
  62319. var tileGrid = tileSource.getTileGridForProjection(projection);
  62320. var z = tileGrid.getZForResolution(viewResolution, this.zDirection);
  62321. var tileResolution = tileGrid.getResolution(z);
  62322. var oversampling = Math.round(viewResolution / tileResolution) || 1;
  62323. var extent = frameState.extent;
  62324. if (layerState.extent !== undefined) {
  62325. extent = ol.extent.getIntersection(extent, layerState.extent);
  62326. }
  62327. if (ol.extent.isEmpty(extent)) {
  62328. // Return false to prevent the rendering of the layer.
  62329. return false;
  62330. }
  62331. var tileRange = tileGrid.getTileRangeForExtentAndResolution(
  62332. extent, tileResolution);
  62333. var imageExtent = tileGrid.getTileRangeExtent(z, tileRange);
  62334. var tilePixelRatio = tileSource.getTilePixelRatio(pixelRatio);
  62335. /**
  62336. * @type {Object.<number, Object.<string, ol.Tile>>}
  62337. */
  62338. var tilesToDrawByZ = {};
  62339. tilesToDrawByZ[z] = {};
  62340. var findLoadedTiles = this.createLoadedTileFinder(
  62341. tileSource, projection, tilesToDrawByZ);
  62342. var tmpExtent = this.tmpExtent;
  62343. var tmpTileRange = this.tmpTileRange_;
  62344. var newTiles = false;
  62345. var tile, x, y;
  62346. for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
  62347. for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
  62348. tile = tileSource.getTile(z, x, y, pixelRatio, projection);
  62349. if (tile.getState() == ol.TileState.ERROR) {
  62350. if (!tileLayer.getUseInterimTilesOnError()) {
  62351. // When useInterimTilesOnError is false, we consider the error tile as loaded.
  62352. tile.setState(ol.TileState.LOADED);
  62353. } else if (tileLayer.getPreload() > 0) {
  62354. // Preloaded tiles for lower resolutions might have finished loading.
  62355. newTiles = true;
  62356. }
  62357. }
  62358. if (!this.isDrawableTile_(tile)) {
  62359. tile = tile.getInterimTile();
  62360. }
  62361. if (this.isDrawableTile_(tile)) {
  62362. if (tile.getState() == ol.TileState.LOADED) {
  62363. tilesToDrawByZ[z][tile.tileCoord.toString()] = tile;
  62364. if (!newTiles && this.renderedTiles.indexOf(tile) == -1) {
  62365. newTiles = true;
  62366. }
  62367. }
  62368. continue;
  62369. }
  62370. var fullyLoaded = tileGrid.forEachTileCoordParentTileRange(
  62371. tile.tileCoord, findLoadedTiles, null, tmpTileRange, tmpExtent);
  62372. if (!fullyLoaded) {
  62373. var childTileRange = tileGrid.getTileCoordChildTileRange(
  62374. tile.tileCoord, tmpTileRange, tmpExtent);
  62375. if (childTileRange) {
  62376. findLoadedTiles(z + 1, childTileRange);
  62377. }
  62378. }
  62379. }
  62380. }
  62381. var renderedResolution = tileResolution * pixelRatio / tilePixelRatio * oversampling;
  62382. var hints = frameState.viewHints;
  62383. var animatingOrInteracting = hints[ol.ViewHint.ANIMATING] || hints[ol.ViewHint.INTERACTING];
  62384. if (!(this.renderedResolution && Date.now() - frameState.time > 16 && animatingOrInteracting) && (
  62385. newTiles ||
  62386. !(this.renderedExtent_ && ol.extent.containsExtent(this.renderedExtent_, extent)) ||
  62387. this.renderedRevision != sourceRevision ||
  62388. oversampling != this.oversampling_ ||
  62389. !animatingOrInteracting && renderedResolution != this.renderedResolution
  62390. )) {
  62391. var context = this.context;
  62392. if (context) {
  62393. var tilePixelSize = tileSource.getTilePixelSize(z, pixelRatio, projection);
  62394. var width = Math.round(tileRange.getWidth() * tilePixelSize[0] / oversampling);
  62395. var height = Math.round(tileRange.getHeight() * tilePixelSize[1] / oversampling);
  62396. var canvas = context.canvas;
  62397. if (canvas.width != width || canvas.height != height) {
  62398. this.oversampling_ = oversampling;
  62399. canvas.width = width;
  62400. canvas.height = height;
  62401. } else {
  62402. context.clearRect(0, 0, width, height);
  62403. oversampling = this.oversampling_;
  62404. }
  62405. }
  62406. this.renderedTiles.length = 0;
  62407. /** @type {Array.<number>} */
  62408. var zs = Object.keys(tilesToDrawByZ).map(Number);
  62409. zs.sort(ol.array.numberSafeCompareFunction);
  62410. var currentResolution, currentScale, currentTilePixelSize, currentZ, i, ii;
  62411. var tileExtent, tileGutter, tilesToDraw, w, h;
  62412. for (i = 0, ii = zs.length; i < ii; ++i) {
  62413. currentZ = zs[i];
  62414. currentTilePixelSize = tileSource.getTilePixelSize(currentZ, pixelRatio, projection);
  62415. currentResolution = tileGrid.getResolution(currentZ);
  62416. currentScale = currentResolution / tileResolution;
  62417. tileGutter = tilePixelRatio * tileSource.getGutter(projection);
  62418. tilesToDraw = tilesToDrawByZ[currentZ];
  62419. for (var tileCoordKey in tilesToDraw) {
  62420. tile = tilesToDraw[tileCoordKey];
  62421. tileExtent = tileGrid.getTileCoordExtent(tile.getTileCoord(), tmpExtent);
  62422. x = (tileExtent[0] - imageExtent[0]) / tileResolution * tilePixelRatio / oversampling;
  62423. y = (imageExtent[3] - tileExtent[3]) / tileResolution * tilePixelRatio / oversampling;
  62424. w = currentTilePixelSize[0] * currentScale / oversampling;
  62425. h = currentTilePixelSize[1] * currentScale / oversampling;
  62426. this.drawTileImage(tile, frameState, layerState, x, y, w, h, tileGutter);
  62427. this.renderedTiles.push(tile);
  62428. }
  62429. }
  62430. this.renderedRevision = sourceRevision;
  62431. this.renderedResolution = tileResolution * pixelRatio / tilePixelRatio * oversampling;
  62432. this.renderedExtent_ = imageExtent;
  62433. }
  62434. var scale = this.renderedResolution / viewResolution;
  62435. var transform = ol.transform.compose(this.imageTransform_,
  62436. pixelRatio * size[0] / 2, pixelRatio * size[1] / 2,
  62437. scale, scale,
  62438. 0,
  62439. (this.renderedExtent_[0] - viewCenter[0]) / this.renderedResolution * pixelRatio,
  62440. (viewCenter[1] - this.renderedExtent_[3]) / this.renderedResolution * pixelRatio);
  62441. ol.transform.compose(this.coordinateToCanvasPixelTransform,
  62442. pixelRatio * size[0] / 2 - transform[4], pixelRatio * size[1] / 2 - transform[5],
  62443. pixelRatio / viewResolution, -pixelRatio / viewResolution,
  62444. 0,
  62445. -viewCenter[0], -viewCenter[1]);
  62446. this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
  62447. this.manageTilePyramid(frameState, tileSource, tileGrid, pixelRatio,
  62448. projection, extent, z, tileLayer.getPreload());
  62449. this.scheduleExpireCache(frameState, tileSource);
  62450. this.updateLogos(frameState, tileSource);
  62451. return this.renderedTiles.length > 0;
  62452. };
  62453. /**
  62454. * @param {ol.Tile} tile Tile.
  62455. * @param {olx.FrameState} frameState Frame state.
  62456. * @param {ol.LayerState} layerState Layer state.
  62457. * @param {number} x Left of the tile.
  62458. * @param {number} y Top of the tile.
  62459. * @param {number} w Width of the tile.
  62460. * @param {number} h Height of the tile.
  62461. * @param {number} gutter Tile gutter.
  62462. */
  62463. ol.renderer.canvas.TileLayer.prototype.drawTileImage = function(tile, frameState, layerState, x, y, w, h, gutter) {
  62464. if (!this.getLayer().getSource().getOpaque(frameState.viewState.projection)) {
  62465. this.context.clearRect(x, y, w, h);
  62466. }
  62467. var image = tile.getImage(this.getLayer());
  62468. if (image) {
  62469. this.context.drawImage(image, gutter, gutter,
  62470. image.width - 2 * gutter, image.height - 2 * gutter, x, y, w, h);
  62471. }
  62472. };
  62473. /**
  62474. * @inheritDoc
  62475. */
  62476. ol.renderer.canvas.TileLayer.prototype.getImage = function() {
  62477. var context = this.context;
  62478. return context ? context.canvas : null;
  62479. };
  62480. /**
  62481. * @function
  62482. * @return {ol.layer.Tile|ol.layer.VectorTile}
  62483. */
  62484. ol.renderer.canvas.TileLayer.prototype.getLayer;
  62485. /**
  62486. * @inheritDoc
  62487. */
  62488. ol.renderer.canvas.TileLayer.prototype.getImageTransform = function() {
  62489. return this.imageTransform_;
  62490. };
  62491. // This file is automatically generated, do not edit
  62492. /* eslint openlayers-internal/no-missing-requires: 0 */
  62493. goog.provide('ol.renderer.webgl.tilelayershader');
  62494. goog.require('ol');
  62495. goog.require('ol.webgl.Fragment');
  62496. goog.require('ol.webgl.Vertex');
  62497. if (ol.ENABLE_WEBGL) {
  62498. /**
  62499. * @constructor
  62500. * @extends {ol.webgl.Fragment}
  62501. * @struct
  62502. */
  62503. ol.renderer.webgl.tilelayershader.Fragment = function() {
  62504. ol.webgl.Fragment.call(this, ol.renderer.webgl.tilelayershader.Fragment.SOURCE);
  62505. };
  62506. ol.inherits(ol.renderer.webgl.tilelayershader.Fragment, ol.webgl.Fragment);
  62507. /**
  62508. * @const
  62509. * @type {string}
  62510. */
  62511. ol.renderer.webgl.tilelayershader.Fragment.DEBUG_SOURCE = 'precision mediump float;\nvarying vec2 v_texCoord;\n\n\nuniform sampler2D u_texture;\n\nvoid main(void) {\n gl_FragColor = texture2D(u_texture, v_texCoord);\n}\n';
  62512. /**
  62513. * @const
  62514. * @type {string}
  62515. */
  62516. ol.renderer.webgl.tilelayershader.Fragment.OPTIMIZED_SOURCE = 'precision mediump float;varying vec2 a;uniform sampler2D e;void main(void){gl_FragColor=texture2D(e,a);}';
  62517. /**
  62518. * @const
  62519. * @type {string}
  62520. */
  62521. ol.renderer.webgl.tilelayershader.Fragment.SOURCE = ol.DEBUG_WEBGL ?
  62522. ol.renderer.webgl.tilelayershader.Fragment.DEBUG_SOURCE :
  62523. ol.renderer.webgl.tilelayershader.Fragment.OPTIMIZED_SOURCE;
  62524. ol.renderer.webgl.tilelayershader.fragment = new ol.renderer.webgl.tilelayershader.Fragment();
  62525. /**
  62526. * @constructor
  62527. * @extends {ol.webgl.Vertex}
  62528. * @struct
  62529. */
  62530. ol.renderer.webgl.tilelayershader.Vertex = function() {
  62531. ol.webgl.Vertex.call(this, ol.renderer.webgl.tilelayershader.Vertex.SOURCE);
  62532. };
  62533. ol.inherits(ol.renderer.webgl.tilelayershader.Vertex, ol.webgl.Vertex);
  62534. /**
  62535. * @const
  62536. * @type {string}
  62537. */
  62538. ol.renderer.webgl.tilelayershader.Vertex.DEBUG_SOURCE = 'varying vec2 v_texCoord;\n\n\nattribute vec2 a_position;\nattribute vec2 a_texCoord;\nuniform vec4 u_tileOffset;\n\nvoid main(void) {\n gl_Position = vec4(a_position * u_tileOffset.xy + u_tileOffset.zw, 0., 1.);\n v_texCoord = a_texCoord;\n}\n\n\n';
  62539. /**
  62540. * @const
  62541. * @type {string}
  62542. */
  62543. ol.renderer.webgl.tilelayershader.Vertex.OPTIMIZED_SOURCE = 'varying vec2 a;attribute vec2 b;attribute vec2 c;uniform vec4 d;void main(void){gl_Position=vec4(b*d.xy+d.zw,0.,1.);a=c;}';
  62544. /**
  62545. * @const
  62546. * @type {string}
  62547. */
  62548. ol.renderer.webgl.tilelayershader.Vertex.SOURCE = ol.DEBUG_WEBGL ?
  62549. ol.renderer.webgl.tilelayershader.Vertex.DEBUG_SOURCE :
  62550. ol.renderer.webgl.tilelayershader.Vertex.OPTIMIZED_SOURCE;
  62551. ol.renderer.webgl.tilelayershader.vertex = new ol.renderer.webgl.tilelayershader.Vertex();
  62552. /**
  62553. * @constructor
  62554. * @param {WebGLRenderingContext} gl GL.
  62555. * @param {WebGLProgram} program Program.
  62556. * @struct
  62557. */
  62558. ol.renderer.webgl.tilelayershader.Locations = function(gl, program) {
  62559. /**
  62560. * @type {WebGLUniformLocation}
  62561. */
  62562. this.u_texture = gl.getUniformLocation(
  62563. program, ol.DEBUG_WEBGL ? 'u_texture' : 'e');
  62564. /**
  62565. * @type {WebGLUniformLocation}
  62566. */
  62567. this.u_tileOffset = gl.getUniformLocation(
  62568. program, ol.DEBUG_WEBGL ? 'u_tileOffset' : 'd');
  62569. /**
  62570. * @type {number}
  62571. */
  62572. this.a_position = gl.getAttribLocation(
  62573. program, ol.DEBUG_WEBGL ? 'a_position' : 'b');
  62574. /**
  62575. * @type {number}
  62576. */
  62577. this.a_texCoord = gl.getAttribLocation(
  62578. program, ol.DEBUG_WEBGL ? 'a_texCoord' : 'c');
  62579. };
  62580. }
  62581. // FIXME large resolutions lead to too large framebuffers :-(
  62582. // FIXME animated shaders! check in redraw
  62583. goog.provide('ol.renderer.webgl.TileLayer');
  62584. goog.require('ol');
  62585. goog.require('ol.TileState');
  62586. goog.require('ol.TileRange');
  62587. goog.require('ol.array');
  62588. goog.require('ol.extent');
  62589. goog.require('ol.math');
  62590. goog.require('ol.renderer.webgl.Layer');
  62591. goog.require('ol.renderer.webgl.tilelayershader');
  62592. goog.require('ol.size');
  62593. goog.require('ol.transform');
  62594. goog.require('ol.webgl');
  62595. goog.require('ol.webgl.Buffer');
  62596. if (ol.ENABLE_WEBGL) {
  62597. /**
  62598. * @constructor
  62599. * @extends {ol.renderer.webgl.Layer}
  62600. * @param {ol.renderer.webgl.Map} mapRenderer Map renderer.
  62601. * @param {ol.layer.Tile} tileLayer Tile layer.
  62602. */
  62603. ol.renderer.webgl.TileLayer = function(mapRenderer, tileLayer) {
  62604. ol.renderer.webgl.Layer.call(this, mapRenderer, tileLayer);
  62605. /**
  62606. * @private
  62607. * @type {ol.webgl.Fragment}
  62608. */
  62609. this.fragmentShader_ = ol.renderer.webgl.tilelayershader.fragment;
  62610. /**
  62611. * @private
  62612. * @type {ol.webgl.Vertex}
  62613. */
  62614. this.vertexShader_ = ol.renderer.webgl.tilelayershader.vertex;
  62615. /**
  62616. * @private
  62617. * @type {ol.renderer.webgl.tilelayershader.Locations}
  62618. */
  62619. this.locations_ = null;
  62620. /**
  62621. * @private
  62622. * @type {ol.webgl.Buffer}
  62623. */
  62624. this.renderArrayBuffer_ = new ol.webgl.Buffer([
  62625. 0, 0, 0, 1,
  62626. 1, 0, 1, 1,
  62627. 0, 1, 0, 0,
  62628. 1, 1, 1, 0
  62629. ]);
  62630. /**
  62631. * @private
  62632. * @type {ol.TileRange}
  62633. */
  62634. this.renderedTileRange_ = null;
  62635. /**
  62636. * @private
  62637. * @type {ol.Extent}
  62638. */
  62639. this.renderedFramebufferExtent_ = null;
  62640. /**
  62641. * @private
  62642. * @type {number}
  62643. */
  62644. this.renderedRevision_ = -1;
  62645. /**
  62646. * @private
  62647. * @type {ol.Size}
  62648. */
  62649. this.tmpSize_ = [0, 0];
  62650. };
  62651. ol.inherits(ol.renderer.webgl.TileLayer, ol.renderer.webgl.Layer);
  62652. /**
  62653. * @inheritDoc
  62654. */
  62655. ol.renderer.webgl.TileLayer.prototype.disposeInternal = function() {
  62656. var context = this.mapRenderer.getContext();
  62657. context.deleteBuffer(this.renderArrayBuffer_);
  62658. ol.renderer.webgl.Layer.prototype.disposeInternal.call(this);
  62659. };
  62660. /**
  62661. * @inheritDoc
  62662. */
  62663. ol.renderer.webgl.TileLayer.prototype.createLoadedTileFinder = function(source, projection, tiles) {
  62664. var mapRenderer = this.mapRenderer;
  62665. return (
  62666. /**
  62667. * @param {number} zoom Zoom level.
  62668. * @param {ol.TileRange} tileRange Tile range.
  62669. * @return {boolean} The tile range is fully loaded.
  62670. */
  62671. function(zoom, tileRange) {
  62672. function callback(tile) {
  62673. var loaded = mapRenderer.isTileTextureLoaded(tile);
  62674. if (loaded) {
  62675. if (!tiles[zoom]) {
  62676. tiles[zoom] = {};
  62677. }
  62678. tiles[zoom][tile.tileCoord.toString()] = tile;
  62679. }
  62680. return loaded;
  62681. }
  62682. return source.forEachLoadedTile(projection, zoom, tileRange, callback);
  62683. });
  62684. };
  62685. /**
  62686. * @inheritDoc
  62687. */
  62688. ol.renderer.webgl.TileLayer.prototype.handleWebGLContextLost = function() {
  62689. ol.renderer.webgl.Layer.prototype.handleWebGLContextLost.call(this);
  62690. this.locations_ = null;
  62691. };
  62692. /**
  62693. * @inheritDoc
  62694. */
  62695. ol.renderer.webgl.TileLayer.prototype.prepareFrame = function(frameState, layerState, context) {
  62696. var mapRenderer = this.mapRenderer;
  62697. var gl = context.getGL();
  62698. var viewState = frameState.viewState;
  62699. var projection = viewState.projection;
  62700. var tileLayer = /** @type {ol.layer.Tile} */ (this.getLayer());
  62701. var tileSource = tileLayer.getSource();
  62702. var tileGrid = tileSource.getTileGridForProjection(projection);
  62703. var z = tileGrid.getZForResolution(viewState.resolution);
  62704. var tileResolution = tileGrid.getResolution(z);
  62705. var tilePixelSize =
  62706. tileSource.getTilePixelSize(z, frameState.pixelRatio, projection);
  62707. var pixelRatio = tilePixelSize[0] /
  62708. ol.size.toSize(tileGrid.getTileSize(z), this.tmpSize_)[0];
  62709. var tilePixelResolution = tileResolution / pixelRatio;
  62710. var tileGutter = tileSource.getTilePixelRatio(pixelRatio) * tileSource.getGutter(projection);
  62711. var center = viewState.center;
  62712. var extent = frameState.extent;
  62713. var tileRange = tileGrid.getTileRangeForExtentAndResolution(
  62714. extent, tileResolution);
  62715. var framebufferExtent;
  62716. if (this.renderedTileRange_ &&
  62717. this.renderedTileRange_.equals(tileRange) &&
  62718. this.renderedRevision_ == tileSource.getRevision()) {
  62719. framebufferExtent = this.renderedFramebufferExtent_;
  62720. } else {
  62721. var tileRangeSize = tileRange.getSize();
  62722. var maxDimension = Math.max(
  62723. tileRangeSize[0] * tilePixelSize[0],
  62724. tileRangeSize[1] * tilePixelSize[1]);
  62725. var framebufferDimension = ol.math.roundUpToPowerOfTwo(maxDimension);
  62726. var framebufferExtentDimension = tilePixelResolution * framebufferDimension;
  62727. var origin = tileGrid.getOrigin(z);
  62728. var minX = origin[0] +
  62729. tileRange.minX * tilePixelSize[0] * tilePixelResolution;
  62730. var minY = origin[1] +
  62731. tileRange.minY * tilePixelSize[1] * tilePixelResolution;
  62732. framebufferExtent = [
  62733. minX, minY,
  62734. minX + framebufferExtentDimension, minY + framebufferExtentDimension
  62735. ];
  62736. this.bindFramebuffer(frameState, framebufferDimension);
  62737. gl.viewport(0, 0, framebufferDimension, framebufferDimension);
  62738. gl.clearColor(0, 0, 0, 0);
  62739. gl.clear(ol.webgl.COLOR_BUFFER_BIT);
  62740. gl.disable(ol.webgl.BLEND);
  62741. var program = context.getProgram(this.fragmentShader_, this.vertexShader_);
  62742. context.useProgram(program);
  62743. if (!this.locations_) {
  62744. // eslint-disable-next-line openlayers-internal/no-missing-requires
  62745. this.locations_ = new ol.renderer.webgl.tilelayershader.Locations(gl, program);
  62746. }
  62747. context.bindBuffer(ol.webgl.ARRAY_BUFFER, this.renderArrayBuffer_);
  62748. gl.enableVertexAttribArray(this.locations_.a_position);
  62749. gl.vertexAttribPointer(
  62750. this.locations_.a_position, 2, ol.webgl.FLOAT, false, 16, 0);
  62751. gl.enableVertexAttribArray(this.locations_.a_texCoord);
  62752. gl.vertexAttribPointer(
  62753. this.locations_.a_texCoord, 2, ol.webgl.FLOAT, false, 16, 8);
  62754. gl.uniform1i(this.locations_.u_texture, 0);
  62755. /**
  62756. * @type {Object.<number, Object.<string, ol.Tile>>}
  62757. */
  62758. var tilesToDrawByZ = {};
  62759. tilesToDrawByZ[z] = {};
  62760. var findLoadedTiles = this.createLoadedTileFinder(
  62761. tileSource, projection, tilesToDrawByZ);
  62762. var useInterimTilesOnError = tileLayer.getUseInterimTilesOnError();
  62763. var allTilesLoaded = true;
  62764. var tmpExtent = ol.extent.createEmpty();
  62765. var tmpTileRange = new ol.TileRange(0, 0, 0, 0);
  62766. var childTileRange, drawable, fullyLoaded, tile, tileState;
  62767. var x, y, tileExtent;
  62768. for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
  62769. for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
  62770. tile = tileSource.getTile(z, x, y, pixelRatio, projection);
  62771. if (layerState.extent !== undefined) {
  62772. // ignore tiles outside layer extent
  62773. tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord, tmpExtent);
  62774. if (!ol.extent.intersects(tileExtent, layerState.extent)) {
  62775. continue;
  62776. }
  62777. }
  62778. tileState = tile.getState();
  62779. drawable = tileState == ol.TileState.LOADED ||
  62780. tileState == ol.TileState.EMPTY ||
  62781. tileState == ol.TileState.ERROR && !useInterimTilesOnError;
  62782. if (!drawable) {
  62783. tile = tile.getInterimTile();
  62784. }
  62785. tileState = tile.getState();
  62786. if (tileState == ol.TileState.LOADED) {
  62787. if (mapRenderer.isTileTextureLoaded(tile)) {
  62788. tilesToDrawByZ[z][tile.tileCoord.toString()] = tile;
  62789. continue;
  62790. }
  62791. } else if (tileState == ol.TileState.EMPTY ||
  62792. (tileState == ol.TileState.ERROR &&
  62793. !useInterimTilesOnError)) {
  62794. continue;
  62795. }
  62796. allTilesLoaded = false;
  62797. fullyLoaded = tileGrid.forEachTileCoordParentTileRange(
  62798. tile.tileCoord, findLoadedTiles, null, tmpTileRange, tmpExtent);
  62799. if (!fullyLoaded) {
  62800. childTileRange = tileGrid.getTileCoordChildTileRange(
  62801. tile.tileCoord, tmpTileRange, tmpExtent);
  62802. if (childTileRange) {
  62803. findLoadedTiles(z + 1, childTileRange);
  62804. }
  62805. }
  62806. }
  62807. }
  62808. /** @type {Array.<number>} */
  62809. var zs = Object.keys(tilesToDrawByZ).map(Number);
  62810. zs.sort(ol.array.numberSafeCompareFunction);
  62811. var u_tileOffset = new Float32Array(4);
  62812. var i, ii, tileKey, tilesToDraw;
  62813. for (i = 0, ii = zs.length; i < ii; ++i) {
  62814. tilesToDraw = tilesToDrawByZ[zs[i]];
  62815. for (tileKey in tilesToDraw) {
  62816. tile = tilesToDraw[tileKey];
  62817. tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord, tmpExtent);
  62818. u_tileOffset[0] = 2 * (tileExtent[2] - tileExtent[0]) /
  62819. framebufferExtentDimension;
  62820. u_tileOffset[1] = 2 * (tileExtent[3] - tileExtent[1]) /
  62821. framebufferExtentDimension;
  62822. u_tileOffset[2] = 2 * (tileExtent[0] - framebufferExtent[0]) /
  62823. framebufferExtentDimension - 1;
  62824. u_tileOffset[3] = 2 * (tileExtent[1] - framebufferExtent[1]) /
  62825. framebufferExtentDimension - 1;
  62826. gl.uniform4fv(this.locations_.u_tileOffset, u_tileOffset);
  62827. mapRenderer.bindTileTexture(tile, tilePixelSize,
  62828. tileGutter * pixelRatio, ol.webgl.LINEAR, ol.webgl.LINEAR);
  62829. gl.drawArrays(ol.webgl.TRIANGLE_STRIP, 0, 4);
  62830. }
  62831. }
  62832. if (allTilesLoaded) {
  62833. this.renderedTileRange_ = tileRange;
  62834. this.renderedFramebufferExtent_ = framebufferExtent;
  62835. this.renderedRevision_ = tileSource.getRevision();
  62836. } else {
  62837. this.renderedTileRange_ = null;
  62838. this.renderedFramebufferExtent_ = null;
  62839. this.renderedRevision_ = -1;
  62840. frameState.animate = true;
  62841. }
  62842. }
  62843. this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
  62844. var tileTextureQueue = mapRenderer.getTileTextureQueue();
  62845. this.manageTilePyramid(
  62846. frameState, tileSource, tileGrid, pixelRatio, projection, extent, z,
  62847. tileLayer.getPreload(),
  62848. /**
  62849. * @param {ol.Tile} tile Tile.
  62850. */
  62851. function(tile) {
  62852. if (tile.getState() == ol.TileState.LOADED &&
  62853. !mapRenderer.isTileTextureLoaded(tile) &&
  62854. !tileTextureQueue.isKeyQueued(tile.getKey())) {
  62855. tileTextureQueue.enqueue([
  62856. tile,
  62857. tileGrid.getTileCoordCenter(tile.tileCoord),
  62858. tileGrid.getResolution(tile.tileCoord[0]),
  62859. tilePixelSize, tileGutter * pixelRatio
  62860. ]);
  62861. }
  62862. }, this);
  62863. this.scheduleExpireCache(frameState, tileSource);
  62864. this.updateLogos(frameState, tileSource);
  62865. var texCoordMatrix = this.texCoordMatrix;
  62866. ol.transform.reset(texCoordMatrix);
  62867. ol.transform.translate(texCoordMatrix,
  62868. (Math.round(center[0] / tileResolution) * tileResolution - framebufferExtent[0]) /
  62869. (framebufferExtent[2] - framebufferExtent[0]),
  62870. (Math.round(center[1] / tileResolution) * tileResolution - framebufferExtent[1]) /
  62871. (framebufferExtent[3] - framebufferExtent[1]));
  62872. if (viewState.rotation !== 0) {
  62873. ol.transform.rotate(texCoordMatrix, viewState.rotation);
  62874. }
  62875. ol.transform.scale(texCoordMatrix,
  62876. frameState.size[0] * viewState.resolution /
  62877. (framebufferExtent[2] - framebufferExtent[0]),
  62878. frameState.size[1] * viewState.resolution /
  62879. (framebufferExtent[3] - framebufferExtent[1]));
  62880. ol.transform.translate(texCoordMatrix, -0.5, -0.5);
  62881. return true;
  62882. };
  62883. /**
  62884. * @inheritDoc
  62885. */
  62886. ol.renderer.webgl.TileLayer.prototype.forEachLayerAtPixel = function(pixel, frameState, callback, thisArg) {
  62887. if (!this.framebuffer) {
  62888. return undefined;
  62889. }
  62890. var pixelOnMapScaled = [
  62891. pixel[0] / frameState.size[0],
  62892. (frameState.size[1] - pixel[1]) / frameState.size[1]];
  62893. var pixelOnFrameBufferScaled = ol.transform.apply(
  62894. this.texCoordMatrix, pixelOnMapScaled.slice());
  62895. var pixelOnFrameBuffer = [
  62896. pixelOnFrameBufferScaled[0] * this.framebufferDimension,
  62897. pixelOnFrameBufferScaled[1] * this.framebufferDimension];
  62898. var gl = this.mapRenderer.getContext().getGL();
  62899. gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
  62900. var imageData = new Uint8Array(4);
  62901. gl.readPixels(pixelOnFrameBuffer[0], pixelOnFrameBuffer[1], 1, 1,
  62902. gl.RGBA, gl.UNSIGNED_BYTE, imageData);
  62903. if (imageData[3] > 0) {
  62904. return callback.call(thisArg, this.getLayer(), imageData);
  62905. } else {
  62906. return undefined;
  62907. }
  62908. };
  62909. }
  62910. goog.provide('ol.layer.Tile');
  62911. goog.require('ol');
  62912. goog.require('ol.layer.Layer');
  62913. goog.require('ol.layer.TileProperty');
  62914. goog.require('ol.obj');
  62915. goog.require('ol.renderer.Type');
  62916. goog.require('ol.renderer.canvas.TileLayer');
  62917. goog.require('ol.renderer.webgl.TileLayer');
  62918. /**
  62919. * @classdesc
  62920. * For layer sources that provide pre-rendered, tiled images in grids that are
  62921. * organized by zoom levels for specific resolutions.
  62922. * Note that any property set in the options is set as a {@link ol.Object}
  62923. * property on the layer object; for example, setting `title: 'My Title'` in the
  62924. * options means that `title` is observable, and has get/set accessors.
  62925. *
  62926. * @constructor
  62927. * @extends {ol.layer.Layer}
  62928. * @fires ol.render.Event
  62929. * @param {olx.layer.TileOptions=} opt_options Tile layer options.
  62930. * @api
  62931. */
  62932. ol.layer.Tile = function(opt_options) {
  62933. var options = opt_options ? opt_options : {};
  62934. var baseOptions = ol.obj.assign({}, options);
  62935. delete baseOptions.preload;
  62936. delete baseOptions.useInterimTilesOnError;
  62937. ol.layer.Layer.call(this, /** @type {olx.layer.LayerOptions} */ (baseOptions));
  62938. this.setPreload(options.preload !== undefined ? options.preload : 0);
  62939. this.setUseInterimTilesOnError(options.useInterimTilesOnError !== undefined ?
  62940. options.useInterimTilesOnError : true);
  62941. };
  62942. ol.inherits(ol.layer.Tile, ol.layer.Layer);
  62943. /**
  62944. * @inheritDoc
  62945. */
  62946. ol.layer.Tile.prototype.createRenderer = function(mapRenderer) {
  62947. var renderer = null;
  62948. var type = mapRenderer.getType();
  62949. if (ol.ENABLE_CANVAS && type === ol.renderer.Type.CANVAS) {
  62950. renderer = new ol.renderer.canvas.TileLayer(this);
  62951. } else if (ol.ENABLE_WEBGL && type === ol.renderer.Type.WEBGL) {
  62952. renderer = new ol.renderer.webgl.TileLayer(/** @type {ol.renderer.webgl.Map} */ (mapRenderer), this);
  62953. }
  62954. return renderer;
  62955. };
  62956. /**
  62957. * Return the level as number to which we will preload tiles up to.
  62958. * @return {number} The level to preload tiles up to.
  62959. * @observable
  62960. * @api
  62961. */
  62962. ol.layer.Tile.prototype.getPreload = function() {
  62963. return /** @type {number} */ (this.get(ol.layer.TileProperty.PRELOAD));
  62964. };
  62965. /**
  62966. * Return the associated {@link ol.source.Tile tilesource} of the layer.
  62967. * @function
  62968. * @return {ol.source.Tile} Source.
  62969. * @api
  62970. */
  62971. ol.layer.Tile.prototype.getSource;
  62972. /**
  62973. * Set the level as number to which we will preload tiles up to.
  62974. * @param {number} preload The level to preload tiles up to.
  62975. * @observable
  62976. * @api
  62977. */
  62978. ol.layer.Tile.prototype.setPreload = function(preload) {
  62979. this.set(ol.layer.TileProperty.PRELOAD, preload);
  62980. };
  62981. /**
  62982. * Whether we use interim tiles on error.
  62983. * @return {boolean} Use interim tiles on error.
  62984. * @observable
  62985. * @api
  62986. */
  62987. ol.layer.Tile.prototype.getUseInterimTilesOnError = function() {
  62988. return /** @type {boolean} */ (
  62989. this.get(ol.layer.TileProperty.USE_INTERIM_TILES_ON_ERROR));
  62990. };
  62991. /**
  62992. * Set whether we use interim tiles on error.
  62993. * @param {boolean} useInterimTilesOnError Use interim tiles on error.
  62994. * @observable
  62995. * @api
  62996. */
  62997. ol.layer.Tile.prototype.setUseInterimTilesOnError = function(useInterimTilesOnError) {
  62998. this.set(
  62999. ol.layer.TileProperty.USE_INTERIM_TILES_ON_ERROR, useInterimTilesOnError);
  63000. };
  63001. goog.provide('ol.layer.VectorTileRenderType');
  63002. /**
  63003. * @enum {string}
  63004. * Render mode for vector tiles:
  63005. * * `'image'`: Vector tiles are rendered as images. Great performance, but
  63006. * point symbols and texts are always rotated with the view and pixels are
  63007. * scaled during zoom animations.
  63008. * * `'hybrid'`: Polygon and line elements are rendered as images, so pixels
  63009. * are scaled during zoom animations. Point symbols and texts are accurately
  63010. * rendered as vectors and can stay upright on rotated views.
  63011. * * `'vector'`: Vector tiles are rendered as vectors. Most accurate rendering
  63012. * even during animations, but slower performance than the other options.
  63013. * @api
  63014. */
  63015. ol.layer.VectorTileRenderType = {
  63016. IMAGE: 'image',
  63017. HYBRID: 'hybrid',
  63018. VECTOR: 'vector'
  63019. };
  63020. goog.provide('ol.renderer.canvas.VectorTileLayer');
  63021. goog.require('ol');
  63022. goog.require('ol.TileState');
  63023. goog.require('ol.dom');
  63024. goog.require('ol.extent');
  63025. goog.require('ol.proj');
  63026. goog.require('ol.proj.Units');
  63027. goog.require('ol.layer.VectorTileRenderType');
  63028. goog.require('ol.render.ReplayType');
  63029. goog.require('ol.render.canvas');
  63030. goog.require('ol.render.canvas.ReplayGroup');
  63031. goog.require('ol.render.replay');
  63032. goog.require('ol.renderer.canvas.TileLayer');
  63033. goog.require('ol.renderer.vector');
  63034. goog.require('ol.size');
  63035. goog.require('ol.transform');
  63036. /**
  63037. * @constructor
  63038. * @extends {ol.renderer.canvas.TileLayer}
  63039. * @param {ol.layer.VectorTile} layer VectorTile layer.
  63040. */
  63041. ol.renderer.canvas.VectorTileLayer = function(layer) {
  63042. /**
  63043. * @type {CanvasRenderingContext2D}
  63044. */
  63045. this.context = null;
  63046. ol.renderer.canvas.TileLayer.call(this, layer);
  63047. /**
  63048. * @private
  63049. * @type {boolean}
  63050. */
  63051. this.dirty_ = false;
  63052. /**
  63053. * @private
  63054. * @type {number}
  63055. */
  63056. this.renderedLayerRevision_;
  63057. /**
  63058. * @private
  63059. * @type {ol.Transform}
  63060. */
  63061. this.tmpTransform_ = ol.transform.create();
  63062. // Use lower resolution for pure vector rendering. Closest resolution otherwise.
  63063. this.zDirection =
  63064. layer.getRenderMode() == ol.layer.VectorTileRenderType.VECTOR ? 1 : 0;
  63065. };
  63066. ol.inherits(ol.renderer.canvas.VectorTileLayer, ol.renderer.canvas.TileLayer);
  63067. /**
  63068. * @const
  63069. * @type {!Object.<string, Array.<ol.render.ReplayType>>}
  63070. */
  63071. ol.renderer.canvas.VectorTileLayer.IMAGE_REPLAYS = {
  63072. 'image': [ol.render.ReplayType.POLYGON, ol.render.ReplayType.CIRCLE,
  63073. ol.render.ReplayType.LINE_STRING, ol.render.ReplayType.IMAGE, ol.render.ReplayType.TEXT],
  63074. 'hybrid': [ol.render.ReplayType.POLYGON, ol.render.ReplayType.LINE_STRING]
  63075. };
  63076. /**
  63077. * @const
  63078. * @type {!Object.<string, Array.<ol.render.ReplayType>>}
  63079. */
  63080. ol.renderer.canvas.VectorTileLayer.VECTOR_REPLAYS = {
  63081. 'image': [ol.render.ReplayType.DEFAULT],
  63082. 'hybrid': [ol.render.ReplayType.IMAGE, ol.render.ReplayType.TEXT, ol.render.ReplayType.DEFAULT],
  63083. 'vector': ol.render.replay.ORDER
  63084. };
  63085. /**
  63086. * @inheritDoc
  63087. */
  63088. ol.renderer.canvas.VectorTileLayer.prototype.prepareFrame = function(frameState, layerState) {
  63089. var layer = this.getLayer();
  63090. var layerRevision = layer.getRevision();
  63091. if (this.renderedLayerRevision_ != layerRevision) {
  63092. this.renderedTiles.length = 0;
  63093. var renderMode = layer.getRenderMode();
  63094. if (!this.context && renderMode != ol.layer.VectorTileRenderType.VECTOR) {
  63095. this.context = ol.dom.createCanvasContext2D();
  63096. }
  63097. if (this.context && renderMode == ol.layer.VectorTileRenderType.VECTOR) {
  63098. this.context = null;
  63099. }
  63100. }
  63101. this.renderedLayerRevision_ = layerRevision;
  63102. return ol.renderer.canvas.TileLayer.prototype.prepareFrame.apply(this, arguments);
  63103. };
  63104. /**
  63105. * @param {ol.VectorImageTile} tile Tile.
  63106. * @param {olx.FrameState} frameState Frame state.
  63107. * @private
  63108. */
  63109. ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup_ = function(
  63110. tile, frameState) {
  63111. var layer = this.getLayer();
  63112. var pixelRatio = frameState.pixelRatio;
  63113. var projection = frameState.viewState.projection;
  63114. var revision = layer.getRevision();
  63115. var renderOrder = /** @type {ol.RenderOrderFunction} */
  63116. (layer.getRenderOrder()) || null;
  63117. var replayState = tile.getReplayState(layer);
  63118. if (!replayState.dirty && replayState.renderedRevision == revision &&
  63119. replayState.renderedRenderOrder == renderOrder) {
  63120. return;
  63121. }
  63122. var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
  63123. var sourceTileGrid = source.getTileGrid();
  63124. var tileGrid = source.getTileGridForProjection(projection);
  63125. var resolution = tileGrid.getResolution(tile.tileCoord[0]);
  63126. var tileExtent = tileGrid.getTileCoordExtent(tile.wrappedTileCoord);
  63127. for (var t = 0, tt = tile.tileKeys.length; t < tt; ++t) {
  63128. var sourceTile = tile.getTile(tile.tileKeys[t]);
  63129. replayState.dirty = false;
  63130. var sourceTileCoord = sourceTile.tileCoord;
  63131. var tileProjection = sourceTile.getProjection();
  63132. var sourceTileResolution = sourceTileGrid.getResolution(sourceTile.tileCoord[0]);
  63133. var sourceTileExtent = sourceTileGrid.getTileCoordExtent(sourceTileCoord);
  63134. var sharedExtent = ol.extent.getIntersection(tileExtent, sourceTileExtent);
  63135. var extent, reproject, tileResolution;
  63136. if (tileProjection.getUnits() == ol.proj.Units.TILE_PIXELS) {
  63137. var tilePixelRatio = tileResolution = this.getTilePixelRatio_(source, sourceTile);
  63138. var transform = ol.transform.compose(this.tmpTransform_,
  63139. 0, 0,
  63140. 1 / sourceTileResolution * tilePixelRatio, -1 / sourceTileResolution * tilePixelRatio,
  63141. 0,
  63142. -sourceTileExtent[0], -sourceTileExtent[3]);
  63143. extent = (ol.transform.apply(transform, [sharedExtent[0], sharedExtent[3]])
  63144. .concat(ol.transform.apply(transform, [sharedExtent[2], sharedExtent[1]])));
  63145. } else {
  63146. tileResolution = resolution;
  63147. extent = sharedExtent;
  63148. if (!ol.proj.equivalent(projection, tileProjection)) {
  63149. reproject = true;
  63150. sourceTile.setProjection(projection);
  63151. }
  63152. }
  63153. replayState.dirty = false;
  63154. var replayGroup = new ol.render.canvas.ReplayGroup(0, extent,
  63155. tileResolution, source.getOverlaps(), layer.getRenderBuffer());
  63156. var squaredTolerance = ol.renderer.vector.getSquaredTolerance(
  63157. tileResolution, pixelRatio);
  63158. /**
  63159. * @param {ol.Feature|ol.render.Feature} feature Feature.
  63160. * @this {ol.renderer.canvas.VectorTileLayer}
  63161. */
  63162. var renderFeature = function(feature) {
  63163. var styles;
  63164. var styleFunction = feature.getStyleFunction();
  63165. if (styleFunction) {
  63166. styles = styleFunction.call(/** @type {ol.Feature} */ (feature), resolution);
  63167. } else {
  63168. styleFunction = layer.getStyleFunction();
  63169. if (styleFunction) {
  63170. styles = styleFunction(feature, resolution);
  63171. }
  63172. }
  63173. if (styles) {
  63174. if (!Array.isArray(styles)) {
  63175. styles = [styles];
  63176. }
  63177. var dirty = this.renderFeature(feature, squaredTolerance, styles,
  63178. replayGroup);
  63179. this.dirty_ = this.dirty_ || dirty;
  63180. replayState.dirty = replayState.dirty || dirty;
  63181. }
  63182. };
  63183. var features = sourceTile.getFeatures();
  63184. if (renderOrder && renderOrder !== replayState.renderedRenderOrder) {
  63185. features.sort(renderOrder);
  63186. }
  63187. var feature;
  63188. for (var i = 0, ii = features.length; i < ii; ++i) {
  63189. feature = features[i];
  63190. if (reproject) {
  63191. feature.getGeometry().transform(tileProjection, projection);
  63192. }
  63193. renderFeature.call(this, feature);
  63194. }
  63195. replayGroup.finish();
  63196. sourceTile.setReplayGroup(layer, tile.tileCoord.toString(), replayGroup);
  63197. }
  63198. replayState.renderedRevision = revision;
  63199. replayState.renderedRenderOrder = renderOrder;
  63200. };
  63201. /**
  63202. * @inheritDoc
  63203. */
  63204. ol.renderer.canvas.VectorTileLayer.prototype.drawTileImage = function(
  63205. tile, frameState, layerState, x, y, w, h, gutter) {
  63206. var vectorImageTile = /** @type {ol.VectorImageTile} */ (tile);
  63207. this.createReplayGroup_(vectorImageTile, frameState);
  63208. if (this.context) {
  63209. this.renderTileImage_(vectorImageTile, frameState, layerState);
  63210. ol.renderer.canvas.TileLayer.prototype.drawTileImage.apply(this, arguments);
  63211. }
  63212. };
  63213. /**
  63214. * @inheritDoc
  63215. */
  63216. ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
  63217. var resolution = frameState.viewState.resolution;
  63218. var rotation = frameState.viewState.rotation;
  63219. hitTolerance = hitTolerance == undefined ? 0 : hitTolerance;
  63220. var layer = this.getLayer();
  63221. /** @type {Object.<string, boolean>} */
  63222. var features = {};
  63223. /** @type {Array.<ol.VectorImageTile>} */
  63224. var renderedTiles = this.renderedTiles;
  63225. var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
  63226. var tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
  63227. var sourceTileGrid = source.getTileGrid();
  63228. var bufferedExtent, found, tileSpaceCoordinate;
  63229. var i, ii, origin, replayGroup;
  63230. var tile, tileCoord, tileExtent, tilePixelRatio, tileRenderResolution;
  63231. for (i = 0, ii = renderedTiles.length; i < ii; ++i) {
  63232. tile = renderedTiles[i];
  63233. tileCoord = tile.tileCoord;
  63234. tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent);
  63235. bufferedExtent = ol.extent.buffer(tileExtent, hitTolerance * resolution, bufferedExtent);
  63236. if (!ol.extent.containsCoordinate(bufferedExtent, coordinate)) {
  63237. continue;
  63238. }
  63239. for (var t = 0, tt = tile.tileKeys.length; t < tt; ++t) {
  63240. var sourceTile = tile.getTile(tile.tileKeys[t]);
  63241. if (sourceTile.getProjection().getUnits() === ol.proj.Units.TILE_PIXELS) {
  63242. var sourceTileCoord = sourceTile.tileCoord;
  63243. var sourceTileExtent = sourceTileGrid.getTileCoordExtent(sourceTileCoord, this.tmpExtent);
  63244. origin = ol.extent.getTopLeft(sourceTileExtent);
  63245. tilePixelRatio = this.getTilePixelRatio_(source, sourceTile);
  63246. var sourceTileResolution = sourceTileGrid.getResolution(sourceTileCoord[0]);
  63247. tileRenderResolution = sourceTileResolution / tilePixelRatio;
  63248. tileSpaceCoordinate = [
  63249. (coordinate[0] - origin[0]) / tileRenderResolution,
  63250. (origin[1] - coordinate[1]) / tileRenderResolution
  63251. ];
  63252. var upscaling = tileGrid.getResolution(tileCoord[0]) / sourceTileResolution;
  63253. resolution = tilePixelRatio * upscaling;
  63254. } else {
  63255. tileSpaceCoordinate = coordinate;
  63256. }
  63257. replayGroup = sourceTile.getReplayGroup(layer, tile.tileCoord.toString());
  63258. found = found || replayGroup.forEachFeatureAtCoordinate(
  63259. tileSpaceCoordinate, resolution, rotation, hitTolerance, {},
  63260. /**
  63261. * @param {ol.Feature|ol.render.Feature} feature Feature.
  63262. * @return {?} Callback result.
  63263. */
  63264. function(feature) {
  63265. var key = ol.getUid(feature).toString();
  63266. if (!(key in features)) {
  63267. features[key] = true;
  63268. return callback.call(thisArg, feature, layer);
  63269. }
  63270. });
  63271. }
  63272. }
  63273. return found;
  63274. };
  63275. /**
  63276. * @param {ol.VectorTile} tile Tile.
  63277. * @param {olx.FrameState} frameState Frame state.
  63278. * @return {ol.Transform} transform Transform.
  63279. * @private
  63280. */
  63281. ol.renderer.canvas.VectorTileLayer.prototype.getReplayTransform_ = function(tile, frameState) {
  63282. if (tile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS) {
  63283. var layer = this.getLayer();
  63284. var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
  63285. var tileGrid = source.getTileGrid();
  63286. var tileCoord = tile.tileCoord;
  63287. var tileResolution =
  63288. tileGrid.getResolution(tileCoord[0]) / this.getTilePixelRatio_(source, tile);
  63289. var viewState = frameState.viewState;
  63290. var pixelRatio = frameState.pixelRatio;
  63291. var renderResolution = viewState.resolution / pixelRatio;
  63292. var tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent);
  63293. var center = viewState.center;
  63294. var origin = ol.extent.getTopLeft(tileExtent);
  63295. var size = frameState.size;
  63296. var offsetX = Math.round(pixelRatio * size[0] / 2);
  63297. var offsetY = Math.round(pixelRatio * size[1] / 2);
  63298. return ol.transform.compose(this.tmpTransform_,
  63299. offsetX, offsetY,
  63300. tileResolution / renderResolution, tileResolution / renderResolution,
  63301. viewState.rotation,
  63302. (origin[0] - center[0]) / tileResolution,
  63303. (center[1] - origin[1]) / tileResolution);
  63304. } else {
  63305. return this.getTransform(frameState, 0);
  63306. }
  63307. };
  63308. /**
  63309. * @private
  63310. * @param {ol.source.VectorTile} source Source.
  63311. * @param {ol.VectorTile} tile Tile.
  63312. * @return {number} The tile's pixel ratio.
  63313. */
  63314. ol.renderer.canvas.VectorTileLayer.prototype.getTilePixelRatio_ = function(source, tile) {
  63315. return ol.extent.getWidth(tile.getExtent()) /
  63316. ol.size.toSize(source.getTileGrid().getTileSize(tile.tileCoord[0]))[0];
  63317. };
  63318. /**
  63319. * Handle changes in image style state.
  63320. * @param {ol.events.Event} event Image style change event.
  63321. * @private
  63322. */
  63323. ol.renderer.canvas.VectorTileLayer.prototype.handleStyleImageChange_ = function(event) {
  63324. this.renderIfReadyAndVisible();
  63325. };
  63326. /**
  63327. * @inheritDoc
  63328. */
  63329. ol.renderer.canvas.VectorTileLayer.prototype.postCompose = function(context, frameState, layerState) {
  63330. var layer = this.getLayer();
  63331. var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
  63332. var renderMode = layer.getRenderMode();
  63333. var replays = ol.renderer.canvas.VectorTileLayer.VECTOR_REPLAYS[renderMode];
  63334. var pixelRatio = frameState.pixelRatio;
  63335. var rotation = frameState.viewState.rotation;
  63336. var size = frameState.size;
  63337. var offsetX = Math.round(pixelRatio * size[0] / 2);
  63338. var offsetY = Math.round(pixelRatio * size[1] / 2);
  63339. var tiles = this.renderedTiles;
  63340. var sourceTileGrid = source.getTileGrid();
  63341. var tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
  63342. var clips = [];
  63343. var zs = [];
  63344. for (var i = tiles.length - 1; i >= 0; --i) {
  63345. var tile = /** @type {ol.VectorImageTile} */ (tiles[i]);
  63346. if (tile.getState() == ol.TileState.ABORT) {
  63347. continue;
  63348. }
  63349. var tileCoord = tile.tileCoord;
  63350. var worldOffset = tileGrid.getTileCoordExtent(tileCoord)[0] -
  63351. tileGrid.getTileCoordExtent(tile.wrappedTileCoord)[0];
  63352. for (var t = 0, tt = tile.tileKeys.length; t < tt; ++t) {
  63353. var sourceTile = tile.getTile(tile.tileKeys[t]);
  63354. var tilePixelRatio = this.getTilePixelRatio_(source, sourceTile);
  63355. var replayGroup = sourceTile.getReplayGroup(layer, tileCoord.toString());
  63356. if (renderMode != ol.layer.VectorTileRenderType.VECTOR && !replayGroup.hasReplays(replays)) {
  63357. continue;
  63358. }
  63359. var currentZ = sourceTile.tileCoord[0];
  63360. var sourceResolution = sourceTileGrid.getResolution(currentZ);
  63361. var transform = this.getReplayTransform_(sourceTile, frameState);
  63362. ol.transform.translate(transform, worldOffset * tilePixelRatio / sourceResolution, 0);
  63363. var currentClip = replayGroup.getClipCoords(transform);
  63364. context.save();
  63365. context.globalAlpha = layerState.opacity;
  63366. ol.render.canvas.rotateAtOffset(context, -rotation, offsetX, offsetY);
  63367. // Create a clip mask for regions in this low resolution tile that are
  63368. // already filled by a higher resolution tile
  63369. for (var j = 0, jj = clips.length; j < jj; ++j) {
  63370. var clip = clips[j];
  63371. if (currentZ < zs[j]) {
  63372. context.beginPath();
  63373. // counter-clockwise (outer ring) for current tile
  63374. context.moveTo(currentClip[0], currentClip[1]);
  63375. context.lineTo(currentClip[2], currentClip[3]);
  63376. context.lineTo(currentClip[4], currentClip[5]);
  63377. context.lineTo(currentClip[6], currentClip[7]);
  63378. // clockwise (inner ring) for higher resolution tile
  63379. context.moveTo(clip[6], clip[7]);
  63380. context.lineTo(clip[4], clip[5]);
  63381. context.lineTo(clip[2], clip[3]);
  63382. context.lineTo(clip[0], clip[1]);
  63383. context.clip();
  63384. }
  63385. }
  63386. replayGroup.replay(context, pixelRatio, transform, rotation, {}, replays);
  63387. context.restore();
  63388. clips.push(currentClip);
  63389. zs.push(currentZ);
  63390. }
  63391. }
  63392. ol.renderer.canvas.TileLayer.prototype.postCompose.apply(this, arguments);
  63393. };
  63394. /**
  63395. * @param {ol.Feature|ol.render.Feature} feature Feature.
  63396. * @param {number} squaredTolerance Squared tolerance.
  63397. * @param {(ol.style.Style|Array.<ol.style.Style>)} styles The style or array of
  63398. * styles.
  63399. * @param {ol.render.canvas.ReplayGroup} replayGroup Replay group.
  63400. * @return {boolean} `true` if an image is loading.
  63401. */
  63402. ol.renderer.canvas.VectorTileLayer.prototype.renderFeature = function(feature, squaredTolerance, styles, replayGroup) {
  63403. if (!styles) {
  63404. return false;
  63405. }
  63406. var loading = false;
  63407. if (Array.isArray(styles)) {
  63408. for (var i = 0, ii = styles.length; i < ii; ++i) {
  63409. loading = ol.renderer.vector.renderFeature(
  63410. replayGroup, feature, styles[i], squaredTolerance,
  63411. this.handleStyleImageChange_, this) || loading;
  63412. }
  63413. } else {
  63414. loading = ol.renderer.vector.renderFeature(
  63415. replayGroup, feature, styles, squaredTolerance,
  63416. this.handleStyleImageChange_, this) || loading;
  63417. }
  63418. return loading;
  63419. };
  63420. /**
  63421. * @param {ol.VectorImageTile} tile Tile.
  63422. * @param {olx.FrameState} frameState Frame state.
  63423. * @param {ol.LayerState} layerState Layer state.
  63424. * @private
  63425. */
  63426. ol.renderer.canvas.VectorTileLayer.prototype.renderTileImage_ = function(
  63427. tile, frameState, layerState) {
  63428. var layer = this.getLayer();
  63429. var replayState = tile.getReplayState(layer);
  63430. var revision = layer.getRevision();
  63431. var replays = ol.renderer.canvas.VectorTileLayer.IMAGE_REPLAYS[layer.getRenderMode()];
  63432. if (replays && replayState.renderedTileRevision !== revision) {
  63433. replayState.renderedTileRevision = revision;
  63434. var tileCoord = tile.wrappedTileCoord;
  63435. var z = tileCoord[0];
  63436. var pixelRatio = frameState.pixelRatio;
  63437. var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
  63438. var sourceTileGrid = source.getTileGrid();
  63439. var tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
  63440. var resolution = tileGrid.getResolution(z);
  63441. var context = tile.getContext(layer);
  63442. var size = source.getTilePixelSize(z, pixelRatio, frameState.viewState.projection);
  63443. context.canvas.width = size[0];
  63444. context.canvas.height = size[1];
  63445. var tileExtent = tileGrid.getTileCoordExtent(tileCoord);
  63446. for (var i = 0, ii = tile.tileKeys.length; i < ii; ++i) {
  63447. var sourceTile = tile.getTile(tile.tileKeys[i]);
  63448. var tilePixelRatio = this.getTilePixelRatio_(source, sourceTile);
  63449. var sourceTileCoord = sourceTile.tileCoord;
  63450. var pixelScale = pixelRatio / resolution;
  63451. var transform = ol.transform.reset(this.tmpTransform_);
  63452. if (sourceTile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS) {
  63453. var sourceTileExtent = sourceTileGrid.getTileCoordExtent(sourceTileCoord, this.tmpExtent);
  63454. var sourceResolution = sourceTileGrid.getResolution(sourceTileCoord[0]);
  63455. var renderPixelRatio = pixelRatio / tilePixelRatio * sourceResolution / resolution;
  63456. ol.transform.scale(transform, renderPixelRatio, renderPixelRatio);
  63457. var offsetX = (sourceTileExtent[0] - tileExtent[0]) / sourceResolution * tilePixelRatio;
  63458. var offsetY = (tileExtent[3] - sourceTileExtent[3]) / sourceResolution * tilePixelRatio;
  63459. ol.transform.translate(transform, Math.round(offsetX), Math.round(offsetY));
  63460. } else {
  63461. ol.transform.scale(transform, pixelScale, -pixelScale);
  63462. ol.transform.translate(transform, -tileExtent[0], -tileExtent[3]);
  63463. }
  63464. var replayGroup = sourceTile.getReplayGroup(layer, tile.tileCoord.toString());
  63465. replayGroup.replay(context, pixelRatio, transform, 0, {}, replays, true);
  63466. }
  63467. }
  63468. };
  63469. goog.provide('ol.layer.VectorTile');
  63470. goog.require('ol');
  63471. goog.require('ol.asserts');
  63472. goog.require('ol.layer.TileProperty');
  63473. goog.require('ol.layer.Vector');
  63474. goog.require('ol.layer.VectorTileRenderType');
  63475. goog.require('ol.obj');
  63476. goog.require('ol.renderer.Type');
  63477. goog.require('ol.renderer.canvas.VectorTileLayer');
  63478. /**
  63479. * @classdesc
  63480. * Layer for vector tile data that is rendered client-side.
  63481. * Note that any property set in the options is set as a {@link ol.Object}
  63482. * property on the layer object; for example, setting `title: 'My Title'` in the
  63483. * options means that `title` is observable, and has get/set accessors.
  63484. *
  63485. * @constructor
  63486. * @extends {ol.layer.Vector}
  63487. * @param {olx.layer.VectorTileOptions=} opt_options Options.
  63488. * @api
  63489. */
  63490. ol.layer.VectorTile = function(opt_options) {
  63491. var options = opt_options ? opt_options : {};
  63492. var baseOptions = ol.obj.assign({}, options);
  63493. delete baseOptions.preload;
  63494. delete baseOptions.useInterimTilesOnError;
  63495. ol.layer.Vector.call(this, /** @type {olx.layer.VectorOptions} */ (baseOptions));
  63496. this.setPreload(options.preload ? options.preload : 0);
  63497. this.setUseInterimTilesOnError(options.useInterimTilesOnError ?
  63498. options.useInterimTilesOnError : true);
  63499. ol.asserts.assert(options.renderMode == undefined ||
  63500. options.renderMode == ol.layer.VectorTileRenderType.IMAGE ||
  63501. options.renderMode == ol.layer.VectorTileRenderType.HYBRID ||
  63502. options.renderMode == ol.layer.VectorTileRenderType.VECTOR,
  63503. 28); // `renderMode` must be `'image'`, `'hybrid'` or `'vector'`
  63504. /**
  63505. * @private
  63506. * @type {ol.layer.VectorTileRenderType|string}
  63507. */
  63508. this.renderMode_ = options.renderMode || ol.layer.VectorTileRenderType.HYBRID;
  63509. };
  63510. ol.inherits(ol.layer.VectorTile, ol.layer.Vector);
  63511. /**
  63512. * @inheritDoc
  63513. */
  63514. ol.layer.VectorTile.prototype.createRenderer = function(mapRenderer) {
  63515. var renderer = null;
  63516. var type = mapRenderer.getType();
  63517. if (ol.ENABLE_CANVAS && type === ol.renderer.Type.CANVAS) {
  63518. renderer = new ol.renderer.canvas.VectorTileLayer(this);
  63519. }
  63520. return renderer;
  63521. };
  63522. /**
  63523. * Return the level as number to which we will preload tiles up to.
  63524. * @return {number} The level to preload tiles up to.
  63525. * @observable
  63526. * @api
  63527. */
  63528. ol.layer.VectorTile.prototype.getPreload = function() {
  63529. return /** @type {number} */ (this.get(ol.layer.TileProperty.PRELOAD));
  63530. };
  63531. /**
  63532. * @return {ol.layer.VectorTileRenderType|string} The render mode.
  63533. */
  63534. ol.layer.VectorTile.prototype.getRenderMode = function() {
  63535. return this.renderMode_;
  63536. };
  63537. /**
  63538. * Whether we use interim tiles on error.
  63539. * @return {boolean} Use interim tiles on error.
  63540. * @observable
  63541. * @api
  63542. */
  63543. ol.layer.VectorTile.prototype.getUseInterimTilesOnError = function() {
  63544. return /** @type {boolean} */ (
  63545. this.get(ol.layer.TileProperty.USE_INTERIM_TILES_ON_ERROR));
  63546. };
  63547. /**
  63548. * Set the level as number to which we will preload tiles up to.
  63549. * @param {number} preload The level to preload tiles up to.
  63550. * @observable
  63551. * @api
  63552. */
  63553. ol.layer.VectorTile.prototype.setPreload = function(preload) {
  63554. this.set(ol.layer.TileProperty.PRELOAD, preload);
  63555. };
  63556. /**
  63557. * Set whether we use interim tiles on error.
  63558. * @param {boolean} useInterimTilesOnError Use interim tiles on error.
  63559. * @observable
  63560. * @api
  63561. */
  63562. ol.layer.VectorTile.prototype.setUseInterimTilesOnError = function(useInterimTilesOnError) {
  63563. this.set(
  63564. ol.layer.TileProperty.USE_INTERIM_TILES_ON_ERROR, useInterimTilesOnError);
  63565. };
  63566. /**
  63567. * Return the associated {@link ol.source.VectorTile vectortilesource} of the layer.
  63568. * @function
  63569. * @return {ol.source.VectorTile} Source.
  63570. * @api
  63571. */
  63572. ol.layer.VectorTile.prototype.getSource;
  63573. goog.provide('ol.net');
  63574. goog.require('ol');
  63575. /**
  63576. * Simple JSONP helper. Supports error callbacks and a custom callback param.
  63577. * The error callback will be called when no JSONP is executed after 10 seconds.
  63578. *
  63579. * @param {string} url Request url. A 'callback' query parameter will be
  63580. * appended.
  63581. * @param {Function} callback Callback on success.
  63582. * @param {function()=} opt_errback Callback on error.
  63583. * @param {string=} opt_callbackParam Custom query parameter for the JSONP
  63584. * callback. Default is 'callback'.
  63585. */
  63586. ol.net.jsonp = function(url, callback, opt_errback, opt_callbackParam) {
  63587. var script = document.createElement('script');
  63588. var key = 'olc_' + ol.getUid(callback);
  63589. function cleanup() {
  63590. delete window[key];
  63591. script.parentNode.removeChild(script);
  63592. }
  63593. script.async = true;
  63594. script.src = url + (url.indexOf('?') == -1 ? '?' : '&') +
  63595. (opt_callbackParam || 'callback') + '=' + key;
  63596. var timer = setTimeout(function() {
  63597. cleanup();
  63598. if (opt_errback) {
  63599. opt_errback();
  63600. }
  63601. }, 10000);
  63602. window[key] = function(data) {
  63603. clearTimeout(timer);
  63604. cleanup();
  63605. callback(data);
  63606. };
  63607. document.getElementsByTagName('head')[0].appendChild(script);
  63608. };
  63609. goog.provide('ol.proj.common');
  63610. goog.require('ol.proj');
  63611. /**
  63612. * Deprecated. Transforms between EPSG:4326 and EPSG:3857 are now included by
  63613. * default. There is no need to call this function in application code and it
  63614. * will be removed in a future major release.
  63615. * @deprecated This function is no longer necessary.
  63616. * @api
  63617. */
  63618. ol.proj.common.add = ol.proj.addCommon;
  63619. goog.provide('ol.render');
  63620. goog.require('ol.has');
  63621. goog.require('ol.transform');
  63622. goog.require('ol.render.canvas.Immediate');
  63623. /**
  63624. * Binds a Canvas Immediate API to a canvas context, to allow drawing geometries
  63625. * to the context's canvas.
  63626. *
  63627. * The units for geometry coordinates are css pixels relative to the top left
  63628. * corner of the canvas element.
  63629. * ```js
  63630. * var canvas = document.createElement('canvas');
  63631. * var render = ol.render.toContext(canvas.getContext('2d'),
  63632. * { size: [100, 100] });
  63633. * render.setFillStrokeStyle(new ol.style.Fill({ color: blue }));
  63634. * render.drawPolygon(
  63635. * new ol.geom.Polygon([[[0, 0], [100, 100], [100, 0], [0, 0]]]));
  63636. * ```
  63637. *
  63638. * @param {CanvasRenderingContext2D} context Canvas context.
  63639. * @param {olx.render.ToContextOptions=} opt_options Options.
  63640. * @return {ol.render.canvas.Immediate} Canvas Immediate.
  63641. * @api
  63642. */
  63643. ol.render.toContext = function(context, opt_options) {
  63644. var canvas = context.canvas;
  63645. var options = opt_options ? opt_options : {};
  63646. var pixelRatio = options.pixelRatio || ol.has.DEVICE_PIXEL_RATIO;
  63647. var size = options.size;
  63648. if (size) {
  63649. canvas.width = size[0] * pixelRatio;
  63650. canvas.height = size[1] * pixelRatio;
  63651. canvas.style.width = size[0] + 'px';
  63652. canvas.style.height = size[1] + 'px';
  63653. }
  63654. var extent = [0, 0, canvas.width, canvas.height];
  63655. var transform = ol.transform.scale(ol.transform.create(), pixelRatio, pixelRatio);
  63656. return new ol.render.canvas.Immediate(context, pixelRatio, extent, transform,
  63657. 0);
  63658. };
  63659. goog.provide('ol.reproj.Tile');
  63660. goog.require('ol');
  63661. goog.require('ol.Tile');
  63662. goog.require('ol.TileState');
  63663. goog.require('ol.events');
  63664. goog.require('ol.events.EventType');
  63665. goog.require('ol.extent');
  63666. goog.require('ol.math');
  63667. goog.require('ol.reproj');
  63668. goog.require('ol.reproj.Triangulation');
  63669. /**
  63670. * @classdesc
  63671. * Class encapsulating single reprojected tile.
  63672. * See {@link ol.source.TileImage}.
  63673. *
  63674. * @constructor
  63675. * @extends {ol.Tile}
  63676. * @param {ol.proj.Projection} sourceProj Source projection.
  63677. * @param {ol.tilegrid.TileGrid} sourceTileGrid Source tile grid.
  63678. * @param {ol.proj.Projection} targetProj Target projection.
  63679. * @param {ol.tilegrid.TileGrid} targetTileGrid Target tile grid.
  63680. * @param {ol.TileCoord} tileCoord Coordinate of the tile.
  63681. * @param {ol.TileCoord} wrappedTileCoord Coordinate of the tile wrapped in X.
  63682. * @param {number} pixelRatio Pixel ratio.
  63683. * @param {number} gutter Gutter of the source tiles.
  63684. * @param {ol.ReprojTileFunctionType} getTileFunction
  63685. * Function returning source tiles (z, x, y, pixelRatio).
  63686. * @param {number=} opt_errorThreshold Acceptable reprojection error (in px).
  63687. * @param {boolean=} opt_renderEdges Render reprojection edges.
  63688. */
  63689. ol.reproj.Tile = function(sourceProj, sourceTileGrid,
  63690. targetProj, targetTileGrid, tileCoord, wrappedTileCoord,
  63691. pixelRatio, gutter, getTileFunction,
  63692. opt_errorThreshold,
  63693. opt_renderEdges) {
  63694. ol.Tile.call(this, tileCoord, ol.TileState.IDLE);
  63695. /**
  63696. * @private
  63697. * @type {boolean}
  63698. */
  63699. this.renderEdges_ = opt_renderEdges !== undefined ? opt_renderEdges : false;
  63700. /**
  63701. * @private
  63702. * @type {number}
  63703. */
  63704. this.pixelRatio_ = pixelRatio;
  63705. /**
  63706. * @private
  63707. * @type {number}
  63708. */
  63709. this.gutter_ = gutter;
  63710. /**
  63711. * @private
  63712. * @type {HTMLCanvasElement}
  63713. */
  63714. this.canvas_ = null;
  63715. /**
  63716. * @private
  63717. * @type {ol.tilegrid.TileGrid}
  63718. */
  63719. this.sourceTileGrid_ = sourceTileGrid;
  63720. /**
  63721. * @private
  63722. * @type {ol.tilegrid.TileGrid}
  63723. */
  63724. this.targetTileGrid_ = targetTileGrid;
  63725. /**
  63726. * @private
  63727. * @type {ol.TileCoord}
  63728. */
  63729. this.wrappedTileCoord_ = wrappedTileCoord ? wrappedTileCoord : tileCoord;
  63730. /**
  63731. * @private
  63732. * @type {!Array.<ol.Tile>}
  63733. */
  63734. this.sourceTiles_ = [];
  63735. /**
  63736. * @private
  63737. * @type {Array.<ol.EventsKey>}
  63738. */
  63739. this.sourcesListenerKeys_ = null;
  63740. /**
  63741. * @private
  63742. * @type {number}
  63743. */
  63744. this.sourceZ_ = 0;
  63745. var targetExtent = targetTileGrid.getTileCoordExtent(this.wrappedTileCoord_);
  63746. var maxTargetExtent = this.targetTileGrid_.getExtent();
  63747. var maxSourceExtent = this.sourceTileGrid_.getExtent();
  63748. var limitedTargetExtent = maxTargetExtent ?
  63749. ol.extent.getIntersection(targetExtent, maxTargetExtent) : targetExtent;
  63750. if (ol.extent.getArea(limitedTargetExtent) === 0) {
  63751. // Tile is completely outside range -> EMPTY
  63752. // TODO: is it actually correct that the source even creates the tile ?
  63753. this.state = ol.TileState.EMPTY;
  63754. return;
  63755. }
  63756. var sourceProjExtent = sourceProj.getExtent();
  63757. if (sourceProjExtent) {
  63758. if (!maxSourceExtent) {
  63759. maxSourceExtent = sourceProjExtent;
  63760. } else {
  63761. maxSourceExtent = ol.extent.getIntersection(
  63762. maxSourceExtent, sourceProjExtent);
  63763. }
  63764. }
  63765. var targetResolution = targetTileGrid.getResolution(
  63766. this.wrappedTileCoord_[0]);
  63767. var targetCenter = ol.extent.getCenter(limitedTargetExtent);
  63768. var sourceResolution = ol.reproj.calculateSourceResolution(
  63769. sourceProj, targetProj, targetCenter, targetResolution);
  63770. if (!isFinite(sourceResolution) || sourceResolution <= 0) {
  63771. // invalid sourceResolution -> EMPTY
  63772. // probably edges of the projections when no extent is defined
  63773. this.state = ol.TileState.EMPTY;
  63774. return;
  63775. }
  63776. var errorThresholdInPixels = opt_errorThreshold !== undefined ?
  63777. opt_errorThreshold : ol.DEFAULT_RASTER_REPROJECTION_ERROR_THRESHOLD;
  63778. /**
  63779. * @private
  63780. * @type {!ol.reproj.Triangulation}
  63781. */
  63782. this.triangulation_ = new ol.reproj.Triangulation(
  63783. sourceProj, targetProj, limitedTargetExtent, maxSourceExtent,
  63784. sourceResolution * errorThresholdInPixels);
  63785. if (this.triangulation_.getTriangles().length === 0) {
  63786. // no valid triangles -> EMPTY
  63787. this.state = ol.TileState.EMPTY;
  63788. return;
  63789. }
  63790. this.sourceZ_ = sourceTileGrid.getZForResolution(sourceResolution);
  63791. var sourceExtent = this.triangulation_.calculateSourceExtent();
  63792. if (maxSourceExtent) {
  63793. if (sourceProj.canWrapX()) {
  63794. sourceExtent[1] = ol.math.clamp(
  63795. sourceExtent[1], maxSourceExtent[1], maxSourceExtent[3]);
  63796. sourceExtent[3] = ol.math.clamp(
  63797. sourceExtent[3], maxSourceExtent[1], maxSourceExtent[3]);
  63798. } else {
  63799. sourceExtent = ol.extent.getIntersection(sourceExtent, maxSourceExtent);
  63800. }
  63801. }
  63802. if (!ol.extent.getArea(sourceExtent)) {
  63803. this.state = ol.TileState.EMPTY;
  63804. } else {
  63805. var sourceRange = sourceTileGrid.getTileRangeForExtentAndZ(
  63806. sourceExtent, this.sourceZ_);
  63807. for (var srcX = sourceRange.minX; srcX <= sourceRange.maxX; srcX++) {
  63808. for (var srcY = sourceRange.minY; srcY <= sourceRange.maxY; srcY++) {
  63809. var tile = getTileFunction(this.sourceZ_, srcX, srcY, pixelRatio);
  63810. if (tile) {
  63811. this.sourceTiles_.push(tile);
  63812. }
  63813. }
  63814. }
  63815. if (this.sourceTiles_.length === 0) {
  63816. this.state = ol.TileState.EMPTY;
  63817. }
  63818. }
  63819. };
  63820. ol.inherits(ol.reproj.Tile, ol.Tile);
  63821. /**
  63822. * @inheritDoc
  63823. */
  63824. ol.reproj.Tile.prototype.disposeInternal = function() {
  63825. if (this.state == ol.TileState.LOADING) {
  63826. this.unlistenSources_();
  63827. }
  63828. ol.Tile.prototype.disposeInternal.call(this);
  63829. };
  63830. /**
  63831. * Get the HTML Canvas element for this tile.
  63832. * @return {HTMLCanvasElement} Canvas.
  63833. */
  63834. ol.reproj.Tile.prototype.getImage = function() {
  63835. return this.canvas_;
  63836. };
  63837. /**
  63838. * @private
  63839. */
  63840. ol.reproj.Tile.prototype.reproject_ = function() {
  63841. var sources = [];
  63842. this.sourceTiles_.forEach(function(tile, i, arr) {
  63843. if (tile && tile.getState() == ol.TileState.LOADED) {
  63844. sources.push({
  63845. extent: this.sourceTileGrid_.getTileCoordExtent(tile.tileCoord),
  63846. image: tile.getImage()
  63847. });
  63848. }
  63849. }, this);
  63850. this.sourceTiles_.length = 0;
  63851. if (sources.length === 0) {
  63852. this.state = ol.TileState.ERROR;
  63853. } else {
  63854. var z = this.wrappedTileCoord_[0];
  63855. var size = this.targetTileGrid_.getTileSize(z);
  63856. var width = typeof size === 'number' ? size : size[0];
  63857. var height = typeof size === 'number' ? size : size[1];
  63858. var targetResolution = this.targetTileGrid_.getResolution(z);
  63859. var sourceResolution = this.sourceTileGrid_.getResolution(this.sourceZ_);
  63860. var targetExtent = this.targetTileGrid_.getTileCoordExtent(
  63861. this.wrappedTileCoord_);
  63862. this.canvas_ = ol.reproj.render(width, height, this.pixelRatio_,
  63863. sourceResolution, this.sourceTileGrid_.getExtent(),
  63864. targetResolution, targetExtent, this.triangulation_, sources,
  63865. this.gutter_, this.renderEdges_);
  63866. this.state = ol.TileState.LOADED;
  63867. }
  63868. this.changed();
  63869. };
  63870. /**
  63871. * @inheritDoc
  63872. */
  63873. ol.reproj.Tile.prototype.load = function() {
  63874. if (this.state == ol.TileState.IDLE) {
  63875. this.state = ol.TileState.LOADING;
  63876. this.changed();
  63877. var leftToLoad = 0;
  63878. this.sourcesListenerKeys_ = [];
  63879. this.sourceTiles_.forEach(function(tile, i, arr) {
  63880. var state = tile.getState();
  63881. if (state == ol.TileState.IDLE || state == ol.TileState.LOADING) {
  63882. leftToLoad++;
  63883. var sourceListenKey;
  63884. sourceListenKey = ol.events.listen(tile, ol.events.EventType.CHANGE,
  63885. function(e) {
  63886. var state = tile.getState();
  63887. if (state == ol.TileState.LOADED ||
  63888. state == ol.TileState.ERROR ||
  63889. state == ol.TileState.EMPTY) {
  63890. ol.events.unlistenByKey(sourceListenKey);
  63891. leftToLoad--;
  63892. if (leftToLoad === 0) {
  63893. this.unlistenSources_();
  63894. this.reproject_();
  63895. }
  63896. }
  63897. }, this);
  63898. this.sourcesListenerKeys_.push(sourceListenKey);
  63899. }
  63900. }, this);
  63901. this.sourceTiles_.forEach(function(tile, i, arr) {
  63902. var state = tile.getState();
  63903. if (state == ol.TileState.IDLE) {
  63904. tile.load();
  63905. }
  63906. });
  63907. if (leftToLoad === 0) {
  63908. setTimeout(this.reproject_.bind(this), 0);
  63909. }
  63910. }
  63911. };
  63912. /**
  63913. * @private
  63914. */
  63915. ol.reproj.Tile.prototype.unlistenSources_ = function() {
  63916. this.sourcesListenerKeys_.forEach(ol.events.unlistenByKey);
  63917. this.sourcesListenerKeys_ = null;
  63918. };
  63919. goog.provide('ol.TileUrlFunction');
  63920. goog.require('ol.asserts');
  63921. goog.require('ol.math');
  63922. goog.require('ol.tilecoord');
  63923. /**
  63924. * @param {string} template Template.
  63925. * @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
  63926. * @return {ol.TileUrlFunctionType} Tile URL function.
  63927. */
  63928. ol.TileUrlFunction.createFromTemplate = function(template, tileGrid) {
  63929. var zRegEx = /\{z\}/g;
  63930. var xRegEx = /\{x\}/g;
  63931. var yRegEx = /\{y\}/g;
  63932. var dashYRegEx = /\{-y\}/g;
  63933. return (
  63934. /**
  63935. * @param {ol.TileCoord} tileCoord Tile Coordinate.
  63936. * @param {number} pixelRatio Pixel ratio.
  63937. * @param {ol.proj.Projection} projection Projection.
  63938. * @return {string|undefined} Tile URL.
  63939. */
  63940. function(tileCoord, pixelRatio, projection) {
  63941. if (!tileCoord) {
  63942. return undefined;
  63943. } else {
  63944. return template.replace(zRegEx, tileCoord[0].toString())
  63945. .replace(xRegEx, tileCoord[1].toString())
  63946. .replace(yRegEx, function() {
  63947. var y = -tileCoord[2] - 1;
  63948. return y.toString();
  63949. })
  63950. .replace(dashYRegEx, function() {
  63951. var z = tileCoord[0];
  63952. var range = tileGrid.getFullTileRange(z);
  63953. ol.asserts.assert(range, 55); // The {-y} placeholder requires a tile grid with extent
  63954. var y = range.getHeight() + tileCoord[2];
  63955. return y.toString();
  63956. });
  63957. }
  63958. });
  63959. };
  63960. /**
  63961. * @param {Array.<string>} templates Templates.
  63962. * @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
  63963. * @return {ol.TileUrlFunctionType} Tile URL function.
  63964. */
  63965. ol.TileUrlFunction.createFromTemplates = function(templates, tileGrid) {
  63966. var len = templates.length;
  63967. var tileUrlFunctions = new Array(len);
  63968. for (var i = 0; i < len; ++i) {
  63969. tileUrlFunctions[i] = ol.TileUrlFunction.createFromTemplate(
  63970. templates[i], tileGrid);
  63971. }
  63972. return ol.TileUrlFunction.createFromTileUrlFunctions(tileUrlFunctions);
  63973. };
  63974. /**
  63975. * @param {Array.<ol.TileUrlFunctionType>} tileUrlFunctions Tile URL Functions.
  63976. * @return {ol.TileUrlFunctionType} Tile URL function.
  63977. */
  63978. ol.TileUrlFunction.createFromTileUrlFunctions = function(tileUrlFunctions) {
  63979. if (tileUrlFunctions.length === 1) {
  63980. return tileUrlFunctions[0];
  63981. }
  63982. return (
  63983. /**
  63984. * @param {ol.TileCoord} tileCoord Tile Coordinate.
  63985. * @param {number} pixelRatio Pixel ratio.
  63986. * @param {ol.proj.Projection} projection Projection.
  63987. * @return {string|undefined} Tile URL.
  63988. */
  63989. function(tileCoord, pixelRatio, projection) {
  63990. if (!tileCoord) {
  63991. return undefined;
  63992. } else {
  63993. var h = ol.tilecoord.hash(tileCoord);
  63994. var index = ol.math.modulo(h, tileUrlFunctions.length);
  63995. return tileUrlFunctions[index](tileCoord, pixelRatio, projection);
  63996. }
  63997. });
  63998. };
  63999. /**
  64000. * @param {ol.TileCoord} tileCoord Tile coordinate.
  64001. * @param {number} pixelRatio Pixel ratio.
  64002. * @param {ol.proj.Projection} projection Projection.
  64003. * @return {string|undefined} Tile URL.
  64004. */
  64005. ol.TileUrlFunction.nullTileUrlFunction = function(tileCoord, pixelRatio, projection) {
  64006. return undefined;
  64007. };
  64008. /**
  64009. * @param {string} url URL.
  64010. * @return {Array.<string>} Array of urls.
  64011. */
  64012. ol.TileUrlFunction.expandUrl = function(url) {
  64013. var urls = [];
  64014. var match = /\{([a-z])-([a-z])\}/.exec(url);
  64015. if (match) {
  64016. // char range
  64017. var startCharCode = match[1].charCodeAt(0);
  64018. var stopCharCode = match[2].charCodeAt(0);
  64019. var charCode;
  64020. for (charCode = startCharCode; charCode <= stopCharCode; ++charCode) {
  64021. urls.push(url.replace(match[0], String.fromCharCode(charCode)));
  64022. }
  64023. return urls;
  64024. }
  64025. match = match = /\{(\d+)-(\d+)\}/.exec(url);
  64026. if (match) {
  64027. // number range
  64028. var stop = parseInt(match[2], 10);
  64029. for (var i = parseInt(match[1], 10); i <= stop; i++) {
  64030. urls.push(url.replace(match[0], i.toString()));
  64031. }
  64032. return urls;
  64033. }
  64034. urls.push(url);
  64035. return urls;
  64036. };
  64037. goog.provide('ol.TileCache');
  64038. goog.require('ol');
  64039. goog.require('ol.structs.LRUCache');
  64040. /**
  64041. * @constructor
  64042. * @extends {ol.structs.LRUCache.<ol.Tile>}
  64043. * @param {number=} opt_highWaterMark High water mark.
  64044. * @struct
  64045. */
  64046. ol.TileCache = function(opt_highWaterMark) {
  64047. ol.structs.LRUCache.call(this);
  64048. /**
  64049. * @type {number}
  64050. */
  64051. this.highWaterMark = opt_highWaterMark !== undefined ? opt_highWaterMark : 2048;
  64052. };
  64053. ol.inherits(ol.TileCache, ol.structs.LRUCache);
  64054. /**
  64055. * @return {boolean} Can expire cache.
  64056. */
  64057. ol.TileCache.prototype.canExpireCache = function() {
  64058. return this.getCount() > this.highWaterMark;
  64059. };
  64060. /**
  64061. * @param {Object.<string, ol.TileRange>} usedTiles Used tiles.
  64062. */
  64063. ol.TileCache.prototype.expireCache = function(usedTiles) {
  64064. var tile, zKey;
  64065. while (this.canExpireCache()) {
  64066. tile = this.peekLast();
  64067. zKey = tile.tileCoord[0].toString();
  64068. if (zKey in usedTiles && usedTiles[zKey].contains(tile.tileCoord)) {
  64069. break;
  64070. } else {
  64071. this.pop().dispose();
  64072. }
  64073. }
  64074. };
  64075. goog.provide('ol.source.Tile');
  64076. goog.require('ol');
  64077. goog.require('ol.TileCache');
  64078. goog.require('ol.TileState');
  64079. goog.require('ol.events.Event');
  64080. goog.require('ol.proj');
  64081. goog.require('ol.size');
  64082. goog.require('ol.source.Source');
  64083. goog.require('ol.tilecoord');
  64084. goog.require('ol.tilegrid');
  64085. /**
  64086. * @classdesc
  64087. * Abstract base class; normally only used for creating subclasses and not
  64088. * instantiated in apps.
  64089. * Base class for sources providing images divided into a tile grid.
  64090. *
  64091. * @constructor
  64092. * @abstract
  64093. * @extends {ol.source.Source}
  64094. * @param {ol.SourceTileOptions} options Tile source options.
  64095. * @api
  64096. */
  64097. ol.source.Tile = function(options) {
  64098. ol.source.Source.call(this, {
  64099. attributions: options.attributions,
  64100. extent: options.extent,
  64101. logo: options.logo,
  64102. projection: options.projection,
  64103. state: options.state,
  64104. wrapX: options.wrapX
  64105. });
  64106. /**
  64107. * @private
  64108. * @type {boolean}
  64109. */
  64110. this.opaque_ = options.opaque !== undefined ? options.opaque : false;
  64111. /**
  64112. * @private
  64113. * @type {number}
  64114. */
  64115. this.tilePixelRatio_ = options.tilePixelRatio !== undefined ?
  64116. options.tilePixelRatio : 1;
  64117. /**
  64118. * @protected
  64119. * @type {ol.tilegrid.TileGrid}
  64120. */
  64121. this.tileGrid = options.tileGrid !== undefined ? options.tileGrid : null;
  64122. /**
  64123. * @protected
  64124. * @type {ol.TileCache}
  64125. */
  64126. this.tileCache = new ol.TileCache(options.cacheSize);
  64127. /**
  64128. * @protected
  64129. * @type {ol.Size}
  64130. */
  64131. this.tmpSize = [0, 0];
  64132. /**
  64133. * @private
  64134. * @type {string}
  64135. */
  64136. this.key_ = '';
  64137. };
  64138. ol.inherits(ol.source.Tile, ol.source.Source);
  64139. /**
  64140. * @return {boolean} Can expire cache.
  64141. */
  64142. ol.source.Tile.prototype.canExpireCache = function() {
  64143. return this.tileCache.canExpireCache();
  64144. };
  64145. /**
  64146. * @param {ol.proj.Projection} projection Projection.
  64147. * @param {Object.<string, ol.TileRange>} usedTiles Used tiles.
  64148. */
  64149. ol.source.Tile.prototype.expireCache = function(projection, usedTiles) {
  64150. var tileCache = this.getTileCacheForProjection(projection);
  64151. if (tileCache) {
  64152. tileCache.expireCache(usedTiles);
  64153. }
  64154. };
  64155. /**
  64156. * @param {ol.proj.Projection} projection Projection.
  64157. * @param {number} z Zoom level.
  64158. * @param {ol.TileRange} tileRange Tile range.
  64159. * @param {function(ol.Tile):(boolean|undefined)} callback Called with each
  64160. * loaded tile. If the callback returns `false`, the tile will not be
  64161. * considered loaded.
  64162. * @return {boolean} The tile range is fully covered with loaded tiles.
  64163. */
  64164. ol.source.Tile.prototype.forEachLoadedTile = function(projection, z, tileRange, callback) {
  64165. var tileCache = this.getTileCacheForProjection(projection);
  64166. if (!tileCache) {
  64167. return false;
  64168. }
  64169. var covered = true;
  64170. var tile, tileCoordKey, loaded;
  64171. for (var x = tileRange.minX; x <= tileRange.maxX; ++x) {
  64172. for (var y = tileRange.minY; y <= tileRange.maxY; ++y) {
  64173. tileCoordKey = this.getKeyZXY(z, x, y);
  64174. loaded = false;
  64175. if (tileCache.containsKey(tileCoordKey)) {
  64176. tile = /** @type {!ol.Tile} */ (tileCache.get(tileCoordKey));
  64177. loaded = tile.getState() === ol.TileState.LOADED;
  64178. if (loaded) {
  64179. loaded = (callback(tile) !== false);
  64180. }
  64181. }
  64182. if (!loaded) {
  64183. covered = false;
  64184. }
  64185. }
  64186. }
  64187. return covered;
  64188. };
  64189. /**
  64190. * @param {ol.proj.Projection} projection Projection.
  64191. * @return {number} Gutter.
  64192. */
  64193. ol.source.Tile.prototype.getGutter = function(projection) {
  64194. return 0;
  64195. };
  64196. /**
  64197. * Return the key to be used for all tiles in the source.
  64198. * @return {string} The key for all tiles.
  64199. * @protected
  64200. */
  64201. ol.source.Tile.prototype.getKey = function() {
  64202. return this.key_;
  64203. };
  64204. /**
  64205. * Set the value to be used as the key for all tiles in the source.
  64206. * @param {string} key The key for tiles.
  64207. * @protected
  64208. */
  64209. ol.source.Tile.prototype.setKey = function(key) {
  64210. if (this.key_ !== key) {
  64211. this.key_ = key;
  64212. this.changed();
  64213. }
  64214. };
  64215. /**
  64216. * @param {number} z Z.
  64217. * @param {number} x X.
  64218. * @param {number} y Y.
  64219. * @return {string} Key.
  64220. * @protected
  64221. */
  64222. ol.source.Tile.prototype.getKeyZXY = ol.tilecoord.getKeyZXY;
  64223. /**
  64224. * @param {ol.proj.Projection} projection Projection.
  64225. * @return {boolean} Opaque.
  64226. */
  64227. ol.source.Tile.prototype.getOpaque = function(projection) {
  64228. return this.opaque_;
  64229. };
  64230. /**
  64231. * @inheritDoc
  64232. */
  64233. ol.source.Tile.prototype.getResolutions = function() {
  64234. return this.tileGrid.getResolutions();
  64235. };
  64236. /**
  64237. * @abstract
  64238. * @param {number} z Tile coordinate z.
  64239. * @param {number} x Tile coordinate x.
  64240. * @param {number} y Tile coordinate y.
  64241. * @param {number} pixelRatio Pixel ratio.
  64242. * @param {ol.proj.Projection} projection Projection.
  64243. * @return {!ol.Tile} Tile.
  64244. */
  64245. ol.source.Tile.prototype.getTile = function(z, x, y, pixelRatio, projection) {};
  64246. /**
  64247. * Return the tile grid of the tile source.
  64248. * @return {ol.tilegrid.TileGrid} Tile grid.
  64249. * @api
  64250. */
  64251. ol.source.Tile.prototype.getTileGrid = function() {
  64252. return this.tileGrid;
  64253. };
  64254. /**
  64255. * @param {ol.proj.Projection} projection Projection.
  64256. * @return {!ol.tilegrid.TileGrid} Tile grid.
  64257. */
  64258. ol.source.Tile.prototype.getTileGridForProjection = function(projection) {
  64259. if (!this.tileGrid) {
  64260. return ol.tilegrid.getForProjection(projection);
  64261. } else {
  64262. return this.tileGrid;
  64263. }
  64264. };
  64265. /**
  64266. * @param {ol.proj.Projection} projection Projection.
  64267. * @return {ol.TileCache} Tile cache.
  64268. * @protected
  64269. */
  64270. ol.source.Tile.prototype.getTileCacheForProjection = function(projection) {
  64271. var thisProj = this.getProjection();
  64272. if (thisProj && !ol.proj.equivalent(thisProj, projection)) {
  64273. return null;
  64274. } else {
  64275. return this.tileCache;
  64276. }
  64277. };
  64278. /**
  64279. * Get the tile pixel ratio for this source. Subclasses may override this
  64280. * method, which is meant to return a supported pixel ratio that matches the
  64281. * provided `pixelRatio` as close as possible.
  64282. * @param {number} pixelRatio Pixel ratio.
  64283. * @return {number} Tile pixel ratio.
  64284. */
  64285. ol.source.Tile.prototype.getTilePixelRatio = function(pixelRatio) {
  64286. return this.tilePixelRatio_;
  64287. };
  64288. /**
  64289. * @param {number} z Z.
  64290. * @param {number} pixelRatio Pixel ratio.
  64291. * @param {ol.proj.Projection} projection Projection.
  64292. * @return {ol.Size} Tile size.
  64293. */
  64294. ol.source.Tile.prototype.getTilePixelSize = function(z, pixelRatio, projection) {
  64295. var tileGrid = this.getTileGridForProjection(projection);
  64296. var tilePixelRatio = this.getTilePixelRatio(pixelRatio);
  64297. var tileSize = ol.size.toSize(tileGrid.getTileSize(z), this.tmpSize);
  64298. if (tilePixelRatio == 1) {
  64299. return tileSize;
  64300. } else {
  64301. return ol.size.scale(tileSize, tilePixelRatio, this.tmpSize);
  64302. }
  64303. };
  64304. /**
  64305. * Returns a tile coordinate wrapped around the x-axis. When the tile coordinate
  64306. * is outside the resolution and extent range of the tile grid, `null` will be
  64307. * returned.
  64308. * @param {ol.TileCoord} tileCoord Tile coordinate.
  64309. * @param {ol.proj.Projection=} opt_projection Projection.
  64310. * @return {ol.TileCoord} Tile coordinate to be passed to the tileUrlFunction or
  64311. * null if no tile URL should be created for the passed `tileCoord`.
  64312. */
  64313. ol.source.Tile.prototype.getTileCoordForTileUrlFunction = function(tileCoord, opt_projection) {
  64314. var projection = opt_projection !== undefined ?
  64315. opt_projection : this.getProjection();
  64316. var tileGrid = this.getTileGridForProjection(projection);
  64317. if (this.getWrapX() && projection.isGlobal()) {
  64318. tileCoord = ol.tilegrid.wrapX(tileGrid, tileCoord, projection);
  64319. }
  64320. return ol.tilecoord.withinExtentAndZ(tileCoord, tileGrid) ? tileCoord : null;
  64321. };
  64322. /**
  64323. * @inheritDoc
  64324. */
  64325. ol.source.Tile.prototype.refresh = function() {
  64326. this.tileCache.clear();
  64327. this.changed();
  64328. };
  64329. /**
  64330. * Marks a tile coord as being used, without triggering a load.
  64331. * @param {number} z Tile coordinate z.
  64332. * @param {number} x Tile coordinate x.
  64333. * @param {number} y Tile coordinate y.
  64334. * @param {ol.proj.Projection} projection Projection.
  64335. */
  64336. ol.source.Tile.prototype.useTile = ol.nullFunction;
  64337. /**
  64338. * @classdesc
  64339. * Events emitted by {@link ol.source.Tile} instances are instances of this
  64340. * type.
  64341. *
  64342. * @constructor
  64343. * @extends {ol.events.Event}
  64344. * @implements {oli.source.Tile.Event}
  64345. * @param {string} type Type.
  64346. * @param {ol.Tile} tile The tile.
  64347. */
  64348. ol.source.Tile.Event = function(type, tile) {
  64349. ol.events.Event.call(this, type);
  64350. /**
  64351. * The tile related to the event.
  64352. * @type {ol.Tile}
  64353. * @api
  64354. */
  64355. this.tile = tile;
  64356. };
  64357. ol.inherits(ol.source.Tile.Event, ol.events.Event);
  64358. goog.provide('ol.source.TileEventType');
  64359. /**
  64360. * @enum {string}
  64361. */
  64362. ol.source.TileEventType = {
  64363. /**
  64364. * Triggered when a tile starts loading.
  64365. * @event ol.source.Tile.Event#tileloadstart
  64366. * @api
  64367. */
  64368. TILELOADSTART: 'tileloadstart',
  64369. /**
  64370. * Triggered when a tile finishes loading.
  64371. * @event ol.source.Tile.Event#tileloadend
  64372. * @api
  64373. */
  64374. TILELOADEND: 'tileloadend',
  64375. /**
  64376. * Triggered if tile loading results in an error.
  64377. * @event ol.source.Tile.Event#tileloaderror
  64378. * @api
  64379. */
  64380. TILELOADERROR: 'tileloaderror'
  64381. };
  64382. goog.provide('ol.source.UrlTile');
  64383. goog.require('ol');
  64384. goog.require('ol.TileState');
  64385. goog.require('ol.TileUrlFunction');
  64386. goog.require('ol.source.Tile');
  64387. goog.require('ol.source.TileEventType');
  64388. /**
  64389. * @classdesc
  64390. * Base class for sources providing tiles divided into a tile grid over http.
  64391. *
  64392. * @constructor
  64393. * @abstract
  64394. * @fires ol.source.Tile.Event
  64395. * @extends {ol.source.Tile}
  64396. * @param {ol.SourceUrlTileOptions} options Image tile options.
  64397. */
  64398. ol.source.UrlTile = function(options) {
  64399. ol.source.Tile.call(this, {
  64400. attributions: options.attributions,
  64401. cacheSize: options.cacheSize,
  64402. extent: options.extent,
  64403. logo: options.logo,
  64404. opaque: options.opaque,
  64405. projection: options.projection,
  64406. state: options.state,
  64407. tileGrid: options.tileGrid,
  64408. tilePixelRatio: options.tilePixelRatio,
  64409. wrapX: options.wrapX
  64410. });
  64411. /**
  64412. * @protected
  64413. * @type {ol.TileLoadFunctionType}
  64414. */
  64415. this.tileLoadFunction = options.tileLoadFunction;
  64416. /**
  64417. * @protected
  64418. * @type {ol.TileUrlFunctionType}
  64419. */
  64420. this.tileUrlFunction = this.fixedTileUrlFunction ?
  64421. this.fixedTileUrlFunction.bind(this) :
  64422. ol.TileUrlFunction.nullTileUrlFunction;
  64423. /**
  64424. * @protected
  64425. * @type {!Array.<string>|null}
  64426. */
  64427. this.urls = null;
  64428. if (options.urls) {
  64429. this.setUrls(options.urls);
  64430. } else if (options.url) {
  64431. this.setUrl(options.url);
  64432. }
  64433. if (options.tileUrlFunction) {
  64434. this.setTileUrlFunction(options.tileUrlFunction);
  64435. }
  64436. };
  64437. ol.inherits(ol.source.UrlTile, ol.source.Tile);
  64438. /**
  64439. * @type {ol.TileUrlFunctionType|undefined}
  64440. * @protected
  64441. */
  64442. ol.source.UrlTile.prototype.fixedTileUrlFunction;
  64443. /**
  64444. * Return the tile load function of the source.
  64445. * @return {ol.TileLoadFunctionType} TileLoadFunction
  64446. * @api
  64447. */
  64448. ol.source.UrlTile.prototype.getTileLoadFunction = function() {
  64449. return this.tileLoadFunction;
  64450. };
  64451. /**
  64452. * Return the tile URL function of the source.
  64453. * @return {ol.TileUrlFunctionType} TileUrlFunction
  64454. * @api
  64455. */
  64456. ol.source.UrlTile.prototype.getTileUrlFunction = function() {
  64457. return this.tileUrlFunction;
  64458. };
  64459. /**
  64460. * Return the URLs used for this source.
  64461. * When a tileUrlFunction is used instead of url or urls,
  64462. * null will be returned.
  64463. * @return {!Array.<string>|null} URLs.
  64464. * @api
  64465. */
  64466. ol.source.UrlTile.prototype.getUrls = function() {
  64467. return this.urls;
  64468. };
  64469. /**
  64470. * Handle tile change events.
  64471. * @param {ol.events.Event} event Event.
  64472. * @protected
  64473. */
  64474. ol.source.UrlTile.prototype.handleTileChange = function(event) {
  64475. var tile = /** @type {ol.Tile} */ (event.target);
  64476. switch (tile.getState()) {
  64477. case ol.TileState.LOADING:
  64478. this.dispatchEvent(
  64479. new ol.source.Tile.Event(ol.source.TileEventType.TILELOADSTART, tile));
  64480. break;
  64481. case ol.TileState.LOADED:
  64482. this.dispatchEvent(
  64483. new ol.source.Tile.Event(ol.source.TileEventType.TILELOADEND, tile));
  64484. break;
  64485. case ol.TileState.ERROR:
  64486. this.dispatchEvent(
  64487. new ol.source.Tile.Event(ol.source.TileEventType.TILELOADERROR, tile));
  64488. break;
  64489. default:
  64490. // pass
  64491. }
  64492. };
  64493. /**
  64494. * Set the tile load function of the source.
  64495. * @param {ol.TileLoadFunctionType} tileLoadFunction Tile load function.
  64496. * @api
  64497. */
  64498. ol.source.UrlTile.prototype.setTileLoadFunction = function(tileLoadFunction) {
  64499. this.tileCache.clear();
  64500. this.tileLoadFunction = tileLoadFunction;
  64501. this.changed();
  64502. };
  64503. /**
  64504. * Set the tile URL function of the source.
  64505. * @param {ol.TileUrlFunctionType} tileUrlFunction Tile URL function.
  64506. * @param {string=} opt_key Optional new tile key for the source.
  64507. * @api
  64508. */
  64509. ol.source.UrlTile.prototype.setTileUrlFunction = function(tileUrlFunction, opt_key) {
  64510. this.tileUrlFunction = tileUrlFunction;
  64511. if (typeof opt_key !== 'undefined') {
  64512. this.setKey(opt_key);
  64513. } else {
  64514. this.changed();
  64515. }
  64516. };
  64517. /**
  64518. * Set the URL to use for requests.
  64519. * @param {string} url URL.
  64520. * @api
  64521. */
  64522. ol.source.UrlTile.prototype.setUrl = function(url) {
  64523. var urls = this.urls = ol.TileUrlFunction.expandUrl(url);
  64524. this.setTileUrlFunction(this.fixedTileUrlFunction ?
  64525. this.fixedTileUrlFunction.bind(this) :
  64526. ol.TileUrlFunction.createFromTemplates(urls, this.tileGrid), url);
  64527. };
  64528. /**
  64529. * Set the URLs to use for requests.
  64530. * @param {Array.<string>} urls URLs.
  64531. * @api
  64532. */
  64533. ol.source.UrlTile.prototype.setUrls = function(urls) {
  64534. this.urls = urls;
  64535. var key = urls.join('\n');
  64536. this.setTileUrlFunction(this.fixedTileUrlFunction ?
  64537. this.fixedTileUrlFunction.bind(this) :
  64538. ol.TileUrlFunction.createFromTemplates(urls, this.tileGrid), key);
  64539. };
  64540. /**
  64541. * @inheritDoc
  64542. */
  64543. ol.source.UrlTile.prototype.useTile = function(z, x, y) {
  64544. var tileCoordKey = this.getKeyZXY(z, x, y);
  64545. if (this.tileCache.containsKey(tileCoordKey)) {
  64546. this.tileCache.get(tileCoordKey);
  64547. }
  64548. };
  64549. goog.provide('ol.source.TileImage');
  64550. goog.require('ol');
  64551. goog.require('ol.ImageTile');
  64552. goog.require('ol.TileCache');
  64553. goog.require('ol.TileState');
  64554. goog.require('ol.events');
  64555. goog.require('ol.events.EventType');
  64556. goog.require('ol.proj');
  64557. goog.require('ol.reproj.Tile');
  64558. goog.require('ol.source.UrlTile');
  64559. goog.require('ol.tilegrid');
  64560. /**
  64561. * @classdesc
  64562. * Base class for sources providing images divided into a tile grid.
  64563. *
  64564. * @constructor
  64565. * @fires ol.source.Tile.Event
  64566. * @extends {ol.source.UrlTile}
  64567. * @param {olx.source.TileImageOptions} options Image tile options.
  64568. * @api
  64569. */
  64570. ol.source.TileImage = function(options) {
  64571. ol.source.UrlTile.call(this, {
  64572. attributions: options.attributions,
  64573. cacheSize: options.cacheSize,
  64574. extent: options.extent,
  64575. logo: options.logo,
  64576. opaque: options.opaque,
  64577. projection: options.projection,
  64578. state: options.state,
  64579. tileGrid: options.tileGrid,
  64580. tileLoadFunction: options.tileLoadFunction ?
  64581. options.tileLoadFunction : ol.source.TileImage.defaultTileLoadFunction,
  64582. tilePixelRatio: options.tilePixelRatio,
  64583. tileUrlFunction: options.tileUrlFunction,
  64584. url: options.url,
  64585. urls: options.urls,
  64586. wrapX: options.wrapX
  64587. });
  64588. /**
  64589. * @protected
  64590. * @type {?string}
  64591. */
  64592. this.crossOrigin =
  64593. options.crossOrigin !== undefined ? options.crossOrigin : null;
  64594. /**
  64595. * @protected
  64596. * @type {function(new: ol.ImageTile, ol.TileCoord, ol.TileState, string,
  64597. * ?string, ol.TileLoadFunctionType)}
  64598. */
  64599. this.tileClass = options.tileClass !== undefined ?
  64600. options.tileClass : ol.ImageTile;
  64601. /**
  64602. * @protected
  64603. * @type {Object.<string, ol.TileCache>}
  64604. */
  64605. this.tileCacheForProjection = {};
  64606. /**
  64607. * @protected
  64608. * @type {Object.<string, ol.tilegrid.TileGrid>}
  64609. */
  64610. this.tileGridForProjection = {};
  64611. /**
  64612. * @private
  64613. * @type {number|undefined}
  64614. */
  64615. this.reprojectionErrorThreshold_ = options.reprojectionErrorThreshold;
  64616. /**
  64617. * @private
  64618. * @type {boolean}
  64619. */
  64620. this.renderReprojectionEdges_ = false;
  64621. };
  64622. ol.inherits(ol.source.TileImage, ol.source.UrlTile);
  64623. /**
  64624. * @inheritDoc
  64625. */
  64626. ol.source.TileImage.prototype.canExpireCache = function() {
  64627. if (!ol.ENABLE_RASTER_REPROJECTION) {
  64628. return ol.source.UrlTile.prototype.canExpireCache.call(this);
  64629. }
  64630. if (this.tileCache.canExpireCache()) {
  64631. return true;
  64632. } else {
  64633. for (var key in this.tileCacheForProjection) {
  64634. if (this.tileCacheForProjection[key].canExpireCache()) {
  64635. return true;
  64636. }
  64637. }
  64638. }
  64639. return false;
  64640. };
  64641. /**
  64642. * @inheritDoc
  64643. */
  64644. ol.source.TileImage.prototype.expireCache = function(projection, usedTiles) {
  64645. if (!ol.ENABLE_RASTER_REPROJECTION) {
  64646. ol.source.UrlTile.prototype.expireCache.call(this, projection, usedTiles);
  64647. return;
  64648. }
  64649. var usedTileCache = this.getTileCacheForProjection(projection);
  64650. this.tileCache.expireCache(this.tileCache == usedTileCache ? usedTiles : {});
  64651. for (var id in this.tileCacheForProjection) {
  64652. var tileCache = this.tileCacheForProjection[id];
  64653. tileCache.expireCache(tileCache == usedTileCache ? usedTiles : {});
  64654. }
  64655. };
  64656. /**
  64657. * @inheritDoc
  64658. */
  64659. ol.source.TileImage.prototype.getGutter = function(projection) {
  64660. if (ol.ENABLE_RASTER_REPROJECTION &&
  64661. this.getProjection() && projection &&
  64662. !ol.proj.equivalent(this.getProjection(), projection)) {
  64663. return 0;
  64664. } else {
  64665. return this.getGutterInternal();
  64666. }
  64667. };
  64668. /**
  64669. * @protected
  64670. * @return {number} Gutter.
  64671. */
  64672. ol.source.TileImage.prototype.getGutterInternal = function() {
  64673. return 0;
  64674. };
  64675. /**
  64676. * @inheritDoc
  64677. */
  64678. ol.source.TileImage.prototype.getOpaque = function(projection) {
  64679. if (ol.ENABLE_RASTER_REPROJECTION &&
  64680. this.getProjection() && projection &&
  64681. !ol.proj.equivalent(this.getProjection(), projection)) {
  64682. return false;
  64683. } else {
  64684. return ol.source.UrlTile.prototype.getOpaque.call(this, projection);
  64685. }
  64686. };
  64687. /**
  64688. * @inheritDoc
  64689. */
  64690. ol.source.TileImage.prototype.getTileGridForProjection = function(projection) {
  64691. if (!ol.ENABLE_RASTER_REPROJECTION) {
  64692. return ol.source.UrlTile.prototype.getTileGridForProjection.call(this, projection);
  64693. }
  64694. var thisProj = this.getProjection();
  64695. if (this.tileGrid &&
  64696. (!thisProj || ol.proj.equivalent(thisProj, projection))) {
  64697. return this.tileGrid;
  64698. } else {
  64699. var projKey = ol.getUid(projection).toString();
  64700. if (!(projKey in this.tileGridForProjection)) {
  64701. this.tileGridForProjection[projKey] =
  64702. ol.tilegrid.getForProjection(projection);
  64703. }
  64704. return /** @type {!ol.tilegrid.TileGrid} */ (this.tileGridForProjection[projKey]);
  64705. }
  64706. };
  64707. /**
  64708. * @inheritDoc
  64709. */
  64710. ol.source.TileImage.prototype.getTileCacheForProjection = function(projection) {
  64711. if (!ol.ENABLE_RASTER_REPROJECTION) {
  64712. return ol.source.UrlTile.prototype.getTileCacheForProjection.call(this, projection);
  64713. }
  64714. var thisProj = this.getProjection();
  64715. if (!thisProj || ol.proj.equivalent(thisProj, projection)) {
  64716. return this.tileCache;
  64717. } else {
  64718. var projKey = ol.getUid(projection).toString();
  64719. if (!(projKey in this.tileCacheForProjection)) {
  64720. this.tileCacheForProjection[projKey] = new ol.TileCache(this.tileCache.highWaterMark);
  64721. }
  64722. return this.tileCacheForProjection[projKey];
  64723. }
  64724. };
  64725. /**
  64726. * @param {number} z Tile coordinate z.
  64727. * @param {number} x Tile coordinate x.
  64728. * @param {number} y Tile coordinate y.
  64729. * @param {number} pixelRatio Pixel ratio.
  64730. * @param {ol.proj.Projection} projection Projection.
  64731. * @param {string} key The key set on the tile.
  64732. * @return {!ol.Tile} Tile.
  64733. * @private
  64734. */
  64735. ol.source.TileImage.prototype.createTile_ = function(z, x, y, pixelRatio, projection, key) {
  64736. var tileCoord = [z, x, y];
  64737. var urlTileCoord = this.getTileCoordForTileUrlFunction(
  64738. tileCoord, projection);
  64739. var tileUrl = urlTileCoord ?
  64740. this.tileUrlFunction(urlTileCoord, pixelRatio, projection) : undefined;
  64741. var tile = new this.tileClass(
  64742. tileCoord,
  64743. tileUrl !== undefined ? ol.TileState.IDLE : ol.TileState.EMPTY,
  64744. tileUrl !== undefined ? tileUrl : '',
  64745. this.crossOrigin,
  64746. this.tileLoadFunction);
  64747. tile.key = key;
  64748. ol.events.listen(tile, ol.events.EventType.CHANGE,
  64749. this.handleTileChange, this);
  64750. return tile;
  64751. };
  64752. /**
  64753. * @inheritDoc
  64754. */
  64755. ol.source.TileImage.prototype.getTile = function(z, x, y, pixelRatio, projection) {
  64756. if (!ol.ENABLE_RASTER_REPROJECTION ||
  64757. !this.getProjection() ||
  64758. !projection ||
  64759. ol.proj.equivalent(this.getProjection(), projection)) {
  64760. return this.getTileInternal(z, x, y, pixelRatio, /** @type {!ol.proj.Projection} */ (projection));
  64761. } else {
  64762. var cache = this.getTileCacheForProjection(projection);
  64763. var tileCoord = [z, x, y];
  64764. var tile;
  64765. var tileCoordKey = this.getKeyZXY.apply(this, tileCoord);
  64766. if (cache.containsKey(tileCoordKey)) {
  64767. tile = /** @type {!ol.Tile} */ (cache.get(tileCoordKey));
  64768. }
  64769. var key = this.getKey();
  64770. if (tile && tile.key == key) {
  64771. return tile;
  64772. } else {
  64773. var sourceProjection = /** @type {!ol.proj.Projection} */ (this.getProjection());
  64774. var sourceTileGrid = this.getTileGridForProjection(sourceProjection);
  64775. var targetTileGrid = this.getTileGridForProjection(projection);
  64776. var wrappedTileCoord =
  64777. this.getTileCoordForTileUrlFunction(tileCoord, projection);
  64778. var newTile = new ol.reproj.Tile(
  64779. sourceProjection, sourceTileGrid,
  64780. projection, targetTileGrid,
  64781. tileCoord, wrappedTileCoord, this.getTilePixelRatio(pixelRatio),
  64782. this.getGutterInternal(),
  64783. function(z, x, y, pixelRatio) {
  64784. return this.getTileInternal(z, x, y, pixelRatio, sourceProjection);
  64785. }.bind(this), this.reprojectionErrorThreshold_,
  64786. this.renderReprojectionEdges_);
  64787. newTile.key = key;
  64788. if (tile) {
  64789. newTile.interimTile = tile;
  64790. newTile.refreshInterimChain();
  64791. cache.replace(tileCoordKey, newTile);
  64792. } else {
  64793. cache.set(tileCoordKey, newTile);
  64794. }
  64795. return newTile;
  64796. }
  64797. }
  64798. };
  64799. /**
  64800. * @param {number} z Tile coordinate z.
  64801. * @param {number} x Tile coordinate x.
  64802. * @param {number} y Tile coordinate y.
  64803. * @param {number} pixelRatio Pixel ratio.
  64804. * @param {!ol.proj.Projection} projection Projection.
  64805. * @return {!ol.Tile} Tile.
  64806. * @protected
  64807. */
  64808. ol.source.TileImage.prototype.getTileInternal = function(z, x, y, pixelRatio, projection) {
  64809. var tile = null;
  64810. var tileCoordKey = this.getKeyZXY(z, x, y);
  64811. var key = this.getKey();
  64812. if (!this.tileCache.containsKey(tileCoordKey)) {
  64813. tile = this.createTile_(z, x, y, pixelRatio, projection, key);
  64814. this.tileCache.set(tileCoordKey, tile);
  64815. } else {
  64816. tile = this.tileCache.get(tileCoordKey);
  64817. if (tile.key != key) {
  64818. // The source's params changed. If the tile has an interim tile and if we
  64819. // can use it then we use it. Otherwise we create a new tile. In both
  64820. // cases we attempt to assign an interim tile to the new tile.
  64821. var interimTile = tile;
  64822. tile = this.createTile_(z, x, y, pixelRatio, projection, key);
  64823. //make the new tile the head of the list,
  64824. if (interimTile.getState() == ol.TileState.IDLE) {
  64825. //the old tile hasn't begun loading yet, and is now outdated, so we can simply discard it
  64826. tile.interimTile = interimTile.interimTile;
  64827. } else {
  64828. tile.interimTile = interimTile;
  64829. }
  64830. tile.refreshInterimChain();
  64831. this.tileCache.replace(tileCoordKey, tile);
  64832. }
  64833. }
  64834. return tile;
  64835. };
  64836. /**
  64837. * Sets whether to render reprojection edges or not (usually for debugging).
  64838. * @param {boolean} render Render the edges.
  64839. * @api
  64840. */
  64841. ol.source.TileImage.prototype.setRenderReprojectionEdges = function(render) {
  64842. if (!ol.ENABLE_RASTER_REPROJECTION ||
  64843. this.renderReprojectionEdges_ == render) {
  64844. return;
  64845. }
  64846. this.renderReprojectionEdges_ = render;
  64847. for (var id in this.tileCacheForProjection) {
  64848. this.tileCacheForProjection[id].clear();
  64849. }
  64850. this.changed();
  64851. };
  64852. /**
  64853. * Sets the tile grid to use when reprojecting the tiles to the given
  64854. * projection instead of the default tile grid for the projection.
  64855. *
  64856. * This can be useful when the default tile grid cannot be created
  64857. * (e.g. projection has no extent defined) or
  64858. * for optimization reasons (custom tile size, resolutions, ...).
  64859. *
  64860. * @param {ol.ProjectionLike} projection Projection.
  64861. * @param {ol.tilegrid.TileGrid} tilegrid Tile grid to use for the projection.
  64862. * @api
  64863. */
  64864. ol.source.TileImage.prototype.setTileGridForProjection = function(projection, tilegrid) {
  64865. if (ol.ENABLE_RASTER_REPROJECTION) {
  64866. var proj = ol.proj.get(projection);
  64867. if (proj) {
  64868. var projKey = ol.getUid(proj).toString();
  64869. if (!(projKey in this.tileGridForProjection)) {
  64870. this.tileGridForProjection[projKey] = tilegrid;
  64871. }
  64872. }
  64873. }
  64874. };
  64875. /**
  64876. * @param {ol.ImageTile} imageTile Image tile.
  64877. * @param {string} src Source.
  64878. */
  64879. ol.source.TileImage.defaultTileLoadFunction = function(imageTile, src) {
  64880. imageTile.getImage().src = src;
  64881. };
  64882. goog.provide('ol.source.BingMaps');
  64883. goog.require('ol');
  64884. goog.require('ol.Attribution');
  64885. goog.require('ol.TileUrlFunction');
  64886. goog.require('ol.extent');
  64887. goog.require('ol.net');
  64888. goog.require('ol.proj');
  64889. goog.require('ol.source.State');
  64890. goog.require('ol.source.TileImage');
  64891. goog.require('ol.tilecoord');
  64892. goog.require('ol.tilegrid');
  64893. /**
  64894. * @classdesc
  64895. * Layer source for Bing Maps tile data.
  64896. *
  64897. * @constructor
  64898. * @extends {ol.source.TileImage}
  64899. * @param {olx.source.BingMapsOptions} options Bing Maps options.
  64900. * @api
  64901. */
  64902. ol.source.BingMaps = function(options) {
  64903. /**
  64904. * @private
  64905. * @type {boolean}
  64906. */
  64907. this.hidpi_ = options.hidpi !== undefined ? options.hidpi : false;
  64908. ol.source.TileImage.call(this, {
  64909. cacheSize: options.cacheSize,
  64910. crossOrigin: 'anonymous',
  64911. opaque: true,
  64912. projection: ol.proj.get('EPSG:3857'),
  64913. reprojectionErrorThreshold: options.reprojectionErrorThreshold,
  64914. state: ol.source.State.LOADING,
  64915. tileLoadFunction: options.tileLoadFunction,
  64916. tilePixelRatio: this.hidpi_ ? 2 : 1,
  64917. wrapX: options.wrapX !== undefined ? options.wrapX : true
  64918. });
  64919. /**
  64920. * @private
  64921. * @type {string}
  64922. */
  64923. this.culture_ = options.culture !== undefined ? options.culture : 'en-us';
  64924. /**
  64925. * @private
  64926. * @type {number}
  64927. */
  64928. this.maxZoom_ = options.maxZoom !== undefined ? options.maxZoom : -1;
  64929. /**
  64930. * @private
  64931. * @type {string}
  64932. */
  64933. this.apiKey_ = options.key;
  64934. /**
  64935. * @private
  64936. * @type {string}
  64937. */
  64938. this.imagerySet_ = options.imagerySet;
  64939. var url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/' +
  64940. this.imagerySet_ +
  64941. '?uriScheme=https&include=ImageryProviders&key=' + this.apiKey_;
  64942. ol.net.jsonp(url, this.handleImageryMetadataResponse.bind(this), undefined,
  64943. 'jsonp');
  64944. };
  64945. ol.inherits(ol.source.BingMaps, ol.source.TileImage);
  64946. /**
  64947. * The attribution containing a link to the Microsoft® Bing™ Maps Platform APIs’
  64948. * Terms Of Use.
  64949. * @const
  64950. * @type {ol.Attribution}
  64951. * @api
  64952. */
  64953. ol.source.BingMaps.TOS_ATTRIBUTION = new ol.Attribution({
  64954. html: '<a class="ol-attribution-bing-tos" ' +
  64955. 'href="https://www.microsoft.com/maps/product/terms.html">' +
  64956. 'Terms of Use</a>'
  64957. });
  64958. /**
  64959. * Get the api key used for this source.
  64960. *
  64961. * @return {string} The api key.
  64962. * @api
  64963. */
  64964. ol.source.BingMaps.prototype.getApiKey = function() {
  64965. return this.apiKey_;
  64966. };
  64967. /**
  64968. * Get the imagery set associated with this source.
  64969. *
  64970. * @return {string} The imagery set.
  64971. * @api
  64972. */
  64973. ol.source.BingMaps.prototype.getImagerySet = function() {
  64974. return this.imagerySet_;
  64975. };
  64976. /**
  64977. * @param {BingMapsImageryMetadataResponse} response Response.
  64978. */
  64979. ol.source.BingMaps.prototype.handleImageryMetadataResponse = function(response) {
  64980. if (response.statusCode != 200 ||
  64981. response.statusDescription != 'OK' ||
  64982. response.authenticationResultCode != 'ValidCredentials' ||
  64983. response.resourceSets.length != 1 ||
  64984. response.resourceSets[0].resources.length != 1) {
  64985. this.setState(ol.source.State.ERROR);
  64986. return;
  64987. }
  64988. var brandLogoUri = response.brandLogoUri;
  64989. if (brandLogoUri.indexOf('https') == -1) {
  64990. brandLogoUri = brandLogoUri.replace('http', 'https');
  64991. }
  64992. //var copyright = response.copyright; // FIXME do we need to display this?
  64993. var resource = response.resourceSets[0].resources[0];
  64994. var maxZoom = this.maxZoom_ == -1 ? resource.zoomMax : this.maxZoom_;
  64995. var sourceProjection = this.getProjection();
  64996. var extent = ol.tilegrid.extentFromProjection(sourceProjection);
  64997. var tileSize = resource.imageWidth == resource.imageHeight ?
  64998. resource.imageWidth : [resource.imageWidth, resource.imageHeight];
  64999. var tileGrid = ol.tilegrid.createXYZ({
  65000. extent: extent,
  65001. minZoom: resource.zoomMin,
  65002. maxZoom: maxZoom,
  65003. tileSize: tileSize / (this.hidpi_ ? 2 : 1)
  65004. });
  65005. this.tileGrid = tileGrid;
  65006. var culture = this.culture_;
  65007. var hidpi = this.hidpi_;
  65008. this.tileUrlFunction = ol.TileUrlFunction.createFromTileUrlFunctions(
  65009. resource.imageUrlSubdomains.map(function(subdomain) {
  65010. var quadKeyTileCoord = [0, 0, 0];
  65011. var imageUrl = resource.imageUrl
  65012. .replace('{subdomain}', subdomain)
  65013. .replace('{culture}', culture);
  65014. return (
  65015. /**
  65016. * @param {ol.TileCoord} tileCoord Tile coordinate.
  65017. * @param {number} pixelRatio Pixel ratio.
  65018. * @param {ol.proj.Projection} projection Projection.
  65019. * @return {string|undefined} Tile URL.
  65020. */
  65021. function(tileCoord, pixelRatio, projection) {
  65022. if (!tileCoord) {
  65023. return undefined;
  65024. } else {
  65025. ol.tilecoord.createOrUpdate(tileCoord[0], tileCoord[1],
  65026. -tileCoord[2] - 1, quadKeyTileCoord);
  65027. var url = imageUrl;
  65028. if (hidpi) {
  65029. url += '&dpi=d1&device=mobile';
  65030. }
  65031. return url.replace('{quadkey}', ol.tilecoord.quadKey(
  65032. quadKeyTileCoord));
  65033. }
  65034. });
  65035. }));
  65036. if (resource.imageryProviders) {
  65037. var transform = ol.proj.getTransformFromProjections(
  65038. ol.proj.get('EPSG:4326'), this.getProjection());
  65039. var attributions = resource.imageryProviders.map(function(imageryProvider) {
  65040. var html = imageryProvider.attribution;
  65041. /** @type {Object.<string, Array.<ol.TileRange>>} */
  65042. var tileRanges = {};
  65043. imageryProvider.coverageAreas.forEach(function(coverageArea) {
  65044. var minZ = coverageArea.zoomMin;
  65045. var maxZ = Math.min(coverageArea.zoomMax, maxZoom);
  65046. var bbox = coverageArea.bbox;
  65047. var epsg4326Extent = [bbox[1], bbox[0], bbox[3], bbox[2]];
  65048. var extent = ol.extent.applyTransform(epsg4326Extent, transform);
  65049. var tileRange, z, zKey;
  65050. for (z = minZ; z <= maxZ; ++z) {
  65051. zKey = z.toString();
  65052. tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z);
  65053. if (zKey in tileRanges) {
  65054. tileRanges[zKey].push(tileRange);
  65055. } else {
  65056. tileRanges[zKey] = [tileRange];
  65057. }
  65058. }
  65059. });
  65060. return new ol.Attribution({html: html, tileRanges: tileRanges});
  65061. });
  65062. attributions.push(ol.source.BingMaps.TOS_ATTRIBUTION);
  65063. this.setAttributions(attributions);
  65064. }
  65065. this.setLogo(brandLogoUri);
  65066. this.setState(ol.source.State.READY);
  65067. };
  65068. goog.provide('ol.source.XYZ');
  65069. goog.require('ol');
  65070. goog.require('ol.source.TileImage');
  65071. goog.require('ol.tilegrid');
  65072. /**
  65073. * @classdesc
  65074. * Layer source for tile data with URLs in a set XYZ format that are
  65075. * defined in a URL template. By default, this follows the widely-used
  65076. * Google grid where `x` 0 and `y` 0 are in the top left. Grids like
  65077. * TMS where `x` 0 and `y` 0 are in the bottom left can be used by
  65078. * using the `{-y}` placeholder in the URL template, so long as the
  65079. * source does not have a custom tile grid. In this case,
  65080. * {@link ol.source.TileImage} can be used with a `tileUrlFunction`
  65081. * such as:
  65082. *
  65083. * tileUrlFunction: function(coordinate) {
  65084. * return 'http://mapserver.com/' + coordinate[0] + '/' +
  65085. * coordinate[1] + '/' + coordinate[2] + '.png';
  65086. * }
  65087. *
  65088. *
  65089. * @constructor
  65090. * @extends {ol.source.TileImage}
  65091. * @param {olx.source.XYZOptions=} opt_options XYZ options.
  65092. * @api
  65093. */
  65094. ol.source.XYZ = function(opt_options) {
  65095. var options = opt_options || {};
  65096. var projection = options.projection !== undefined ?
  65097. options.projection : 'EPSG:3857';
  65098. var tileGrid = options.tileGrid !== undefined ? options.tileGrid :
  65099. ol.tilegrid.createXYZ({
  65100. extent: ol.tilegrid.extentFromProjection(projection),
  65101. maxZoom: options.maxZoom,
  65102. minZoom: options.minZoom,
  65103. tileSize: options.tileSize
  65104. });
  65105. ol.source.TileImage.call(this, {
  65106. attributions: options.attributions,
  65107. cacheSize: options.cacheSize,
  65108. crossOrigin: options.crossOrigin,
  65109. logo: options.logo,
  65110. opaque: options.opaque,
  65111. projection: projection,
  65112. reprojectionErrorThreshold: options.reprojectionErrorThreshold,
  65113. tileGrid: tileGrid,
  65114. tileLoadFunction: options.tileLoadFunction,
  65115. tilePixelRatio: options.tilePixelRatio,
  65116. tileUrlFunction: options.tileUrlFunction,
  65117. url: options.url,
  65118. urls: options.urls,
  65119. wrapX: options.wrapX !== undefined ? options.wrapX : true
  65120. });
  65121. };
  65122. ol.inherits(ol.source.XYZ, ol.source.TileImage);
  65123. goog.provide('ol.source.CartoDB');
  65124. goog.require('ol');
  65125. goog.require('ol.obj');
  65126. goog.require('ol.source.State');
  65127. goog.require('ol.source.XYZ');
  65128. /**
  65129. * @classdesc
  65130. * Layer source for the CartoDB tiles.
  65131. *
  65132. * @constructor
  65133. * @extends {ol.source.XYZ}
  65134. * @param {olx.source.CartoDBOptions} options CartoDB options.
  65135. * @api
  65136. */
  65137. ol.source.CartoDB = function(options) {
  65138. /**
  65139. * @type {string}
  65140. * @private
  65141. */
  65142. this.account_ = options.account;
  65143. /**
  65144. * @type {string}
  65145. * @private
  65146. */
  65147. this.mapId_ = options.map || '';
  65148. /**
  65149. * @type {!Object}
  65150. * @private
  65151. */
  65152. this.config_ = options.config || {};
  65153. /**
  65154. * @type {!Object.<string, CartoDBLayerInfo>}
  65155. * @private
  65156. */
  65157. this.templateCache_ = {};
  65158. ol.source.XYZ.call(this, {
  65159. attributions: options.attributions,
  65160. cacheSize: options.cacheSize,
  65161. crossOrigin: options.crossOrigin,
  65162. logo: options.logo,
  65163. maxZoom: options.maxZoom !== undefined ? options.maxZoom : 18,
  65164. minZoom: options.minZoom,
  65165. projection: options.projection,
  65166. state: ol.source.State.LOADING,
  65167. wrapX: options.wrapX
  65168. });
  65169. this.initializeMap_();
  65170. };
  65171. ol.inherits(ol.source.CartoDB, ol.source.XYZ);
  65172. /**
  65173. * Returns the current config.
  65174. * @return {!Object} The current configuration.
  65175. * @api
  65176. */
  65177. ol.source.CartoDB.prototype.getConfig = function() {
  65178. return this.config_;
  65179. };
  65180. /**
  65181. * Updates the carto db config.
  65182. * @param {Object} config a key-value lookup. Values will replace current values
  65183. * in the config.
  65184. * @api
  65185. */
  65186. ol.source.CartoDB.prototype.updateConfig = function(config) {
  65187. ol.obj.assign(this.config_, config);
  65188. this.initializeMap_();
  65189. };
  65190. /**
  65191. * Sets the CartoDB config
  65192. * @param {Object} config In the case of anonymous maps, a CartoDB configuration
  65193. * object.
  65194. * If using named maps, a key-value lookup with the template parameters.
  65195. * @api
  65196. */
  65197. ol.source.CartoDB.prototype.setConfig = function(config) {
  65198. this.config_ = config || {};
  65199. this.initializeMap_();
  65200. };
  65201. /**
  65202. * Issue a request to initialize the CartoDB map.
  65203. * @private
  65204. */
  65205. ol.source.CartoDB.prototype.initializeMap_ = function() {
  65206. var paramHash = JSON.stringify(this.config_);
  65207. if (this.templateCache_[paramHash]) {
  65208. this.applyTemplate_(this.templateCache_[paramHash]);
  65209. return;
  65210. }
  65211. var mapUrl = 'https://' + this.account_ + '.cartodb.com/api/v1/map';
  65212. if (this.mapId_) {
  65213. mapUrl += '/named/' + this.mapId_;
  65214. }
  65215. var client = new XMLHttpRequest();
  65216. client.addEventListener('load', this.handleInitResponse_.bind(this, paramHash));
  65217. client.addEventListener('error', this.handleInitError_.bind(this));
  65218. client.open('POST', mapUrl);
  65219. client.setRequestHeader('Content-type', 'application/json');
  65220. client.send(JSON.stringify(this.config_));
  65221. };
  65222. /**
  65223. * Handle map initialization response.
  65224. * @param {string} paramHash a hash representing the parameter set that was used
  65225. * for the request
  65226. * @param {Event} event Event.
  65227. * @private
  65228. */
  65229. ol.source.CartoDB.prototype.handleInitResponse_ = function(paramHash, event) {
  65230. var client = /** @type {XMLHttpRequest} */ (event.target);
  65231. // status will be 0 for file:// urls
  65232. if (!client.status || client.status >= 200 && client.status < 300) {
  65233. var response;
  65234. try {
  65235. response = /** @type {CartoDBLayerInfo} */(JSON.parse(client.responseText));
  65236. } catch (err) {
  65237. this.setState(ol.source.State.ERROR);
  65238. return;
  65239. }
  65240. this.applyTemplate_(response);
  65241. this.templateCache_[paramHash] = response;
  65242. this.setState(ol.source.State.READY);
  65243. } else {
  65244. this.setState(ol.source.State.ERROR);
  65245. }
  65246. };
  65247. /**
  65248. * @private
  65249. * @param {Event} event Event.
  65250. */
  65251. ol.source.CartoDB.prototype.handleInitError_ = function(event) {
  65252. this.setState(ol.source.State.ERROR);
  65253. };
  65254. /**
  65255. * Apply the new tile urls returned by carto db
  65256. * @param {CartoDBLayerInfo} data Result of carto db call.
  65257. * @private
  65258. */
  65259. ol.source.CartoDB.prototype.applyTemplate_ = function(data) {
  65260. var tilesUrl = 'https://' + data.cdn_url.https + '/' + this.account_ +
  65261. '/api/v1/map/' + data.layergroupid + '/{z}/{x}/{y}.png';
  65262. this.setUrl(tilesUrl);
  65263. };
  65264. // FIXME keep cluster cache by resolution ?
  65265. // FIXME distance not respected because of the centroid
  65266. goog.provide('ol.source.Cluster');
  65267. goog.require('ol');
  65268. goog.require('ol.asserts');
  65269. goog.require('ol.Feature');
  65270. goog.require('ol.coordinate');
  65271. goog.require('ol.events.EventType');
  65272. goog.require('ol.extent');
  65273. goog.require('ol.geom.Point');
  65274. goog.require('ol.source.Vector');
  65275. /**
  65276. * @classdesc
  65277. * Layer source to cluster vector data. Works out of the box with point
  65278. * geometries. For other geometry types, or if not all geometries should be
  65279. * considered for clustering, a custom `geometryFunction` can be defined.
  65280. *
  65281. * @constructor
  65282. * @param {olx.source.ClusterOptions} options Constructor options.
  65283. * @extends {ol.source.Vector}
  65284. * @api
  65285. */
  65286. ol.source.Cluster = function(options) {
  65287. ol.source.Vector.call(this, {
  65288. attributions: options.attributions,
  65289. extent: options.extent,
  65290. logo: options.logo,
  65291. projection: options.projection,
  65292. wrapX: options.wrapX
  65293. });
  65294. /**
  65295. * @type {number|undefined}
  65296. * @protected
  65297. */
  65298. this.resolution = undefined;
  65299. /**
  65300. * @type {number}
  65301. * @protected
  65302. */
  65303. this.distance = options.distance !== undefined ? options.distance : 20;
  65304. /**
  65305. * @type {Array.<ol.Feature>}
  65306. * @protected
  65307. */
  65308. this.features = [];
  65309. /**
  65310. * @param {ol.Feature} feature Feature.
  65311. * @return {ol.geom.Point} Cluster calculation point.
  65312. * @protected
  65313. */
  65314. this.geometryFunction = options.geometryFunction || function(feature) {
  65315. var geometry = /** @type {ol.geom.Point} */ (feature.getGeometry());
  65316. ol.asserts.assert(geometry instanceof ol.geom.Point,
  65317. 10); // The default `geometryFunction` can only handle `ol.geom.Point` geometries
  65318. return geometry;
  65319. };
  65320. /**
  65321. * @type {ol.source.Vector}
  65322. * @protected
  65323. */
  65324. this.source = options.source;
  65325. this.source.on(ol.events.EventType.CHANGE,
  65326. ol.source.Cluster.prototype.refresh, this);
  65327. };
  65328. ol.inherits(ol.source.Cluster, ol.source.Vector);
  65329. /**
  65330. * Get the distance in pixels between clusters.
  65331. * @return {number} Distance.
  65332. * @api
  65333. */
  65334. ol.source.Cluster.prototype.getDistance = function() {
  65335. return this.distance;
  65336. };
  65337. /**
  65338. * Get a reference to the wrapped source.
  65339. * @return {ol.source.Vector} Source.
  65340. * @api
  65341. */
  65342. ol.source.Cluster.prototype.getSource = function() {
  65343. return this.source;
  65344. };
  65345. /**
  65346. * @inheritDoc
  65347. */
  65348. ol.source.Cluster.prototype.loadFeatures = function(extent, resolution,
  65349. projection) {
  65350. this.source.loadFeatures(extent, resolution, projection);
  65351. if (resolution !== this.resolution) {
  65352. this.clear();
  65353. this.resolution = resolution;
  65354. this.cluster();
  65355. this.addFeatures(this.features);
  65356. }
  65357. };
  65358. /**
  65359. * Set the distance in pixels between clusters.
  65360. * @param {number} distance The distance in pixels.
  65361. * @api
  65362. */
  65363. ol.source.Cluster.prototype.setDistance = function(distance) {
  65364. this.distance = distance;
  65365. this.refresh();
  65366. };
  65367. /**
  65368. * handle the source changing
  65369. * @override
  65370. */
  65371. ol.source.Cluster.prototype.refresh = function() {
  65372. this.clear();
  65373. this.cluster();
  65374. this.addFeatures(this.features);
  65375. ol.source.Vector.prototype.refresh.call(this);
  65376. };
  65377. /**
  65378. * @protected
  65379. */
  65380. ol.source.Cluster.prototype.cluster = function() {
  65381. if (this.resolution === undefined) {
  65382. return;
  65383. }
  65384. this.features.length = 0;
  65385. var extent = ol.extent.createEmpty();
  65386. var mapDistance = this.distance * this.resolution;
  65387. var features = this.source.getFeatures();
  65388. /**
  65389. * @type {!Object.<string, boolean>}
  65390. */
  65391. var clustered = {};
  65392. for (var i = 0, ii = features.length; i < ii; i++) {
  65393. var feature = features[i];
  65394. if (!(ol.getUid(feature).toString() in clustered)) {
  65395. var geometry = this.geometryFunction(feature);
  65396. if (geometry) {
  65397. var coordinates = geometry.getCoordinates();
  65398. ol.extent.createOrUpdateFromCoordinate(coordinates, extent);
  65399. ol.extent.buffer(extent, mapDistance, extent);
  65400. var neighbors = this.source.getFeaturesInExtent(extent);
  65401. neighbors = neighbors.filter(function(neighbor) {
  65402. var uid = ol.getUid(neighbor).toString();
  65403. if (!(uid in clustered)) {
  65404. clustered[uid] = true;
  65405. return true;
  65406. } else {
  65407. return false;
  65408. }
  65409. });
  65410. this.features.push(this.createCluster(neighbors));
  65411. }
  65412. }
  65413. }
  65414. };
  65415. /**
  65416. * @param {Array.<ol.Feature>} features Features
  65417. * @return {ol.Feature} The cluster feature.
  65418. * @protected
  65419. */
  65420. ol.source.Cluster.prototype.createCluster = function(features) {
  65421. var centroid = [0, 0];
  65422. for (var i = features.length - 1; i >= 0; --i) {
  65423. var geometry = this.geometryFunction(features[i]);
  65424. if (geometry) {
  65425. ol.coordinate.add(centroid, geometry.getCoordinates());
  65426. } else {
  65427. features.splice(i, 1);
  65428. }
  65429. }
  65430. ol.coordinate.scale(centroid, 1 / features.length);
  65431. var cluster = new ol.Feature(new ol.geom.Point(centroid));
  65432. cluster.set('features', features);
  65433. return cluster;
  65434. };
  65435. goog.provide('ol.uri');
  65436. /**
  65437. * Appends query parameters to a URI.
  65438. *
  65439. * @param {string} uri The original URI, which may already have query data.
  65440. * @param {!Object} params An object where keys are URI-encoded parameter keys,
  65441. * and the values are arbitrary types or arrays.
  65442. * @return {string} The new URI.
  65443. */
  65444. ol.uri.appendParams = function(uri, params) {
  65445. var keyParams = [];
  65446. // Skip any null or undefined parameter values
  65447. Object.keys(params).forEach(function(k) {
  65448. if (params[k] !== null && params[k] !== undefined) {
  65449. keyParams.push(k + '=' + encodeURIComponent(params[k]));
  65450. }
  65451. });
  65452. var qs = keyParams.join('&');
  65453. // remove any trailing ? or &
  65454. uri = uri.replace(/[?&]$/, '');
  65455. // append ? or & depending on whether uri has existing parameters
  65456. uri = uri.indexOf('?') === -1 ? uri + '?' : uri + '&';
  65457. return uri + qs;
  65458. };
  65459. goog.provide('ol.source.ImageArcGISRest');
  65460. goog.require('ol');
  65461. goog.require('ol.Image');
  65462. goog.require('ol.asserts');
  65463. goog.require('ol.events');
  65464. goog.require('ol.events.EventType');
  65465. goog.require('ol.extent');
  65466. goog.require('ol.obj');
  65467. goog.require('ol.source.Image');
  65468. goog.require('ol.uri');
  65469. /**
  65470. * @classdesc
  65471. * Source for data from ArcGIS Rest services providing single, untiled images.
  65472. * Useful when underlying map service has labels.
  65473. *
  65474. * If underlying map service is not using labels,
  65475. * take advantage of ol image caching and use
  65476. * {@link ol.source.TileArcGISRest} data source.
  65477. *
  65478. * @constructor
  65479. * @fires ol.source.Image.Event
  65480. * @extends {ol.source.Image}
  65481. * @param {olx.source.ImageArcGISRestOptions=} opt_options Image ArcGIS Rest Options.
  65482. * @api
  65483. */
  65484. ol.source.ImageArcGISRest = function(opt_options) {
  65485. var options = opt_options || {};
  65486. ol.source.Image.call(this, {
  65487. attributions: options.attributions,
  65488. logo: options.logo,
  65489. projection: options.projection,
  65490. resolutions: options.resolutions
  65491. });
  65492. /**
  65493. * @private
  65494. * @type {?string}
  65495. */
  65496. this.crossOrigin_ =
  65497. options.crossOrigin !== undefined ? options.crossOrigin : null;
  65498. /**
  65499. * @private
  65500. * @type {boolean}
  65501. */
  65502. this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
  65503. /**
  65504. * @private
  65505. * @type {string|undefined}
  65506. */
  65507. this.url_ = options.url;
  65508. /**
  65509. * @private
  65510. * @type {ol.ImageLoadFunctionType}
  65511. */
  65512. this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
  65513. options.imageLoadFunction : ol.source.Image.defaultImageLoadFunction;
  65514. /**
  65515. * @private
  65516. * @type {!Object}
  65517. */
  65518. this.params_ = options.params || {};
  65519. /**
  65520. * @private
  65521. * @type {ol.Image}
  65522. */
  65523. this.image_ = null;
  65524. /**
  65525. * @private
  65526. * @type {ol.Size}
  65527. */
  65528. this.imageSize_ = [0, 0];
  65529. /**
  65530. * @private
  65531. * @type {number}
  65532. */
  65533. this.renderedRevision_ = 0;
  65534. /**
  65535. * @private
  65536. * @type {number}
  65537. */
  65538. this.ratio_ = options.ratio !== undefined ? options.ratio : 1.5;
  65539. };
  65540. ol.inherits(ol.source.ImageArcGISRest, ol.source.Image);
  65541. /**
  65542. * Get the user-provided params, i.e. those passed to the constructor through
  65543. * the "params" option, and possibly updated using the updateParams method.
  65544. * @return {Object} Params.
  65545. * @api
  65546. */
  65547. ol.source.ImageArcGISRest.prototype.getParams = function() {
  65548. return this.params_;
  65549. };
  65550. /**
  65551. * @inheritDoc
  65552. */
  65553. ol.source.ImageArcGISRest.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
  65554. if (this.url_ === undefined) {
  65555. return null;
  65556. }
  65557. resolution = this.findNearestResolution(resolution);
  65558. pixelRatio = this.hidpi_ ? pixelRatio : 1;
  65559. var image = this.image_;
  65560. if (image &&
  65561. this.renderedRevision_ == this.getRevision() &&
  65562. image.getResolution() == resolution &&
  65563. image.getPixelRatio() == pixelRatio &&
  65564. ol.extent.containsExtent(image.getExtent(), extent)) {
  65565. return image;
  65566. }
  65567. var params = {
  65568. 'F': 'image',
  65569. 'FORMAT': 'PNG32',
  65570. 'TRANSPARENT': true
  65571. };
  65572. ol.obj.assign(params, this.params_);
  65573. extent = extent.slice();
  65574. var centerX = (extent[0] + extent[2]) / 2;
  65575. var centerY = (extent[1] + extent[3]) / 2;
  65576. if (this.ratio_ != 1) {
  65577. var halfWidth = this.ratio_ * ol.extent.getWidth(extent) / 2;
  65578. var halfHeight = this.ratio_ * ol.extent.getHeight(extent) / 2;
  65579. extent[0] = centerX - halfWidth;
  65580. extent[1] = centerY - halfHeight;
  65581. extent[2] = centerX + halfWidth;
  65582. extent[3] = centerY + halfHeight;
  65583. }
  65584. var imageResolution = resolution / pixelRatio;
  65585. // Compute an integer width and height.
  65586. var width = Math.ceil(ol.extent.getWidth(extent) / imageResolution);
  65587. var height = Math.ceil(ol.extent.getHeight(extent) / imageResolution);
  65588. // Modify the extent to match the integer width and height.
  65589. extent[0] = centerX - imageResolution * width / 2;
  65590. extent[2] = centerX + imageResolution * width / 2;
  65591. extent[1] = centerY - imageResolution * height / 2;
  65592. extent[3] = centerY + imageResolution * height / 2;
  65593. this.imageSize_[0] = width;
  65594. this.imageSize_[1] = height;
  65595. var url = this.getRequestUrl_(extent, this.imageSize_, pixelRatio,
  65596. projection, params);
  65597. this.image_ = new ol.Image(extent, resolution, pixelRatio,
  65598. this.getAttributions(), url, this.crossOrigin_, this.imageLoadFunction_);
  65599. this.renderedRevision_ = this.getRevision();
  65600. ol.events.listen(this.image_, ol.events.EventType.CHANGE,
  65601. this.handleImageChange, this);
  65602. return this.image_;
  65603. };
  65604. /**
  65605. * Return the image load function of the source.
  65606. * @return {ol.ImageLoadFunctionType} The image load function.
  65607. * @api
  65608. */
  65609. ol.source.ImageArcGISRest.prototype.getImageLoadFunction = function() {
  65610. return this.imageLoadFunction_;
  65611. };
  65612. /**
  65613. * @param {ol.Extent} extent Extent.
  65614. * @param {ol.Size} size Size.
  65615. * @param {number} pixelRatio Pixel ratio.
  65616. * @param {ol.proj.Projection} projection Projection.
  65617. * @param {Object} params Params.
  65618. * @return {string} Request URL.
  65619. * @private
  65620. */
  65621. ol.source.ImageArcGISRest.prototype.getRequestUrl_ = function(extent, size, pixelRatio, projection, params) {
  65622. // ArcGIS Server only wants the numeric portion of the projection ID.
  65623. var srid = projection.getCode().split(':').pop();
  65624. params['SIZE'] = size[0] + ',' + size[1];
  65625. params['BBOX'] = extent.join(',');
  65626. params['BBOXSR'] = srid;
  65627. params['IMAGESR'] = srid;
  65628. params['DPI'] = Math.round(90 * pixelRatio);
  65629. var url = this.url_;
  65630. var modifiedUrl = url
  65631. .replace(/MapServer\/?$/, 'MapServer/export')
  65632. .replace(/ImageServer\/?$/, 'ImageServer/exportImage');
  65633. if (modifiedUrl == url) {
  65634. ol.asserts.assert(false, 50); // `options.featureTypes` should be an Array
  65635. }
  65636. return ol.uri.appendParams(modifiedUrl, params);
  65637. };
  65638. /**
  65639. * Return the URL used for this ArcGIS source.
  65640. * @return {string|undefined} URL.
  65641. * @api
  65642. */
  65643. ol.source.ImageArcGISRest.prototype.getUrl = function() {
  65644. return this.url_;
  65645. };
  65646. /**
  65647. * Set the image load function of the source.
  65648. * @param {ol.ImageLoadFunctionType} imageLoadFunction Image load function.
  65649. * @api
  65650. */
  65651. ol.source.ImageArcGISRest.prototype.setImageLoadFunction = function(imageLoadFunction) {
  65652. this.image_ = null;
  65653. this.imageLoadFunction_ = imageLoadFunction;
  65654. this.changed();
  65655. };
  65656. /**
  65657. * Set the URL to use for requests.
  65658. * @param {string|undefined} url URL.
  65659. * @api
  65660. */
  65661. ol.source.ImageArcGISRest.prototype.setUrl = function(url) {
  65662. if (url != this.url_) {
  65663. this.url_ = url;
  65664. this.image_ = null;
  65665. this.changed();
  65666. }
  65667. };
  65668. /**
  65669. * Update the user-provided params.
  65670. * @param {Object} params Params.
  65671. * @api
  65672. */
  65673. ol.source.ImageArcGISRest.prototype.updateParams = function(params) {
  65674. ol.obj.assign(this.params_, params);
  65675. this.image_ = null;
  65676. this.changed();
  65677. };
  65678. goog.provide('ol.source.ImageMapGuide');
  65679. goog.require('ol');
  65680. goog.require('ol.Image');
  65681. goog.require('ol.events');
  65682. goog.require('ol.events.EventType');
  65683. goog.require('ol.extent');
  65684. goog.require('ol.obj');
  65685. goog.require('ol.source.Image');
  65686. goog.require('ol.uri');
  65687. /**
  65688. * @classdesc
  65689. * Source for images from Mapguide servers
  65690. *
  65691. * @constructor
  65692. * @fires ol.source.Image.Event
  65693. * @extends {ol.source.Image}
  65694. * @param {olx.source.ImageMapGuideOptions} options Options.
  65695. * @api
  65696. */
  65697. ol.source.ImageMapGuide = function(options) {
  65698. ol.source.Image.call(this, {
  65699. projection: options.projection,
  65700. resolutions: options.resolutions
  65701. });
  65702. /**
  65703. * @private
  65704. * @type {?string}
  65705. */
  65706. this.crossOrigin_ =
  65707. options.crossOrigin !== undefined ? options.crossOrigin : null;
  65708. /**
  65709. * @private
  65710. * @type {number}
  65711. */
  65712. this.displayDpi_ = options.displayDpi !== undefined ?
  65713. options.displayDpi : 96;
  65714. /**
  65715. * @private
  65716. * @type {!Object}
  65717. */
  65718. this.params_ = options.params || {};
  65719. /**
  65720. * @private
  65721. * @type {string|undefined}
  65722. */
  65723. this.url_ = options.url;
  65724. /**
  65725. * @private
  65726. * @type {ol.ImageLoadFunctionType}
  65727. */
  65728. this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
  65729. options.imageLoadFunction : ol.source.Image.defaultImageLoadFunction;
  65730. /**
  65731. * @private
  65732. * @type {boolean}
  65733. */
  65734. this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
  65735. /**
  65736. * @private
  65737. * @type {number}
  65738. */
  65739. this.metersPerUnit_ = options.metersPerUnit !== undefined ?
  65740. options.metersPerUnit : 1;
  65741. /**
  65742. * @private
  65743. * @type {number}
  65744. */
  65745. this.ratio_ = options.ratio !== undefined ? options.ratio : 1;
  65746. /**
  65747. * @private
  65748. * @type {boolean}
  65749. */
  65750. this.useOverlay_ = options.useOverlay !== undefined ?
  65751. options.useOverlay : false;
  65752. /**
  65753. * @private
  65754. * @type {ol.Image}
  65755. */
  65756. this.image_ = null;
  65757. /**
  65758. * @private
  65759. * @type {number}
  65760. */
  65761. this.renderedRevision_ = 0;
  65762. };
  65763. ol.inherits(ol.source.ImageMapGuide, ol.source.Image);
  65764. /**
  65765. * Get the user-provided params, i.e. those passed to the constructor through
  65766. * the "params" option, and possibly updated using the updateParams method.
  65767. * @return {Object} Params.
  65768. * @api
  65769. */
  65770. ol.source.ImageMapGuide.prototype.getParams = function() {
  65771. return this.params_;
  65772. };
  65773. /**
  65774. * @inheritDoc
  65775. */
  65776. ol.source.ImageMapGuide.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
  65777. resolution = this.findNearestResolution(resolution);
  65778. pixelRatio = this.hidpi_ ? pixelRatio : 1;
  65779. var image = this.image_;
  65780. if (image &&
  65781. this.renderedRevision_ == this.getRevision() &&
  65782. image.getResolution() == resolution &&
  65783. image.getPixelRatio() == pixelRatio &&
  65784. ol.extent.containsExtent(image.getExtent(), extent)) {
  65785. return image;
  65786. }
  65787. if (this.ratio_ != 1) {
  65788. extent = extent.slice();
  65789. ol.extent.scaleFromCenter(extent, this.ratio_);
  65790. }
  65791. var width = ol.extent.getWidth(extent) / resolution;
  65792. var height = ol.extent.getHeight(extent) / resolution;
  65793. var size = [width * pixelRatio, height * pixelRatio];
  65794. if (this.url_ !== undefined) {
  65795. var imageUrl = this.getUrl(this.url_, this.params_, extent, size,
  65796. projection);
  65797. image = new ol.Image(extent, resolution, pixelRatio,
  65798. this.getAttributions(), imageUrl, this.crossOrigin_,
  65799. this.imageLoadFunction_);
  65800. ol.events.listen(image, ol.events.EventType.CHANGE,
  65801. this.handleImageChange, this);
  65802. } else {
  65803. image = null;
  65804. }
  65805. this.image_ = image;
  65806. this.renderedRevision_ = this.getRevision();
  65807. return image;
  65808. };
  65809. /**
  65810. * Return the image load function of the source.
  65811. * @return {ol.ImageLoadFunctionType} The image load function.
  65812. * @api
  65813. */
  65814. ol.source.ImageMapGuide.prototype.getImageLoadFunction = function() {
  65815. return this.imageLoadFunction_;
  65816. };
  65817. /**
  65818. * @param {ol.Extent} extent The map extents.
  65819. * @param {ol.Size} size The viewport size.
  65820. * @param {number} metersPerUnit The meters-per-unit value.
  65821. * @param {number} dpi The display resolution.
  65822. * @return {number} The computed map scale.
  65823. */
  65824. ol.source.ImageMapGuide.getScale = function(extent, size, metersPerUnit, dpi) {
  65825. var mcsW = ol.extent.getWidth(extent);
  65826. var mcsH = ol.extent.getHeight(extent);
  65827. var devW = size[0];
  65828. var devH = size[1];
  65829. var mpp = 0.0254 / dpi;
  65830. if (devH * mcsW > devW * mcsH) {
  65831. return mcsW * metersPerUnit / (devW * mpp); // width limited
  65832. } else {
  65833. return mcsH * metersPerUnit / (devH * mpp); // height limited
  65834. }
  65835. };
  65836. /**
  65837. * Update the user-provided params.
  65838. * @param {Object} params Params.
  65839. * @api
  65840. */
  65841. ol.source.ImageMapGuide.prototype.updateParams = function(params) {
  65842. ol.obj.assign(this.params_, params);
  65843. this.changed();
  65844. };
  65845. /**
  65846. * @param {string} baseUrl The mapagent url.
  65847. * @param {Object.<string, string|number>} params Request parameters.
  65848. * @param {ol.Extent} extent Extent.
  65849. * @param {ol.Size} size Size.
  65850. * @param {ol.proj.Projection} projection Projection.
  65851. * @return {string} The mapagent map image request URL.
  65852. */
  65853. ol.source.ImageMapGuide.prototype.getUrl = function(baseUrl, params, extent, size, projection) {
  65854. var scale = ol.source.ImageMapGuide.getScale(extent, size,
  65855. this.metersPerUnit_, this.displayDpi_);
  65856. var center = ol.extent.getCenter(extent);
  65857. var baseParams = {
  65858. 'OPERATION': this.useOverlay_ ? 'GETDYNAMICMAPOVERLAYIMAGE' : 'GETMAPIMAGE',
  65859. 'VERSION': '2.0.0',
  65860. 'LOCALE': 'en',
  65861. 'CLIENTAGENT': 'ol.source.ImageMapGuide source',
  65862. 'CLIP': '1',
  65863. 'SETDISPLAYDPI': this.displayDpi_,
  65864. 'SETDISPLAYWIDTH': Math.round(size[0]),
  65865. 'SETDISPLAYHEIGHT': Math.round(size[1]),
  65866. 'SETVIEWSCALE': scale,
  65867. 'SETVIEWCENTERX': center[0],
  65868. 'SETVIEWCENTERY': center[1]
  65869. };
  65870. ol.obj.assign(baseParams, params);
  65871. return ol.uri.appendParams(baseUrl, baseParams);
  65872. };
  65873. /**
  65874. * Set the image load function of the MapGuide source.
  65875. * @param {ol.ImageLoadFunctionType} imageLoadFunction Image load function.
  65876. * @api
  65877. */
  65878. ol.source.ImageMapGuide.prototype.setImageLoadFunction = function(
  65879. imageLoadFunction) {
  65880. this.image_ = null;
  65881. this.imageLoadFunction_ = imageLoadFunction;
  65882. this.changed();
  65883. };
  65884. goog.provide('ol.source.ImageStatic');
  65885. goog.require('ol');
  65886. goog.require('ol.Image');
  65887. goog.require('ol.ImageState');
  65888. goog.require('ol.dom');
  65889. goog.require('ol.events');
  65890. goog.require('ol.events.EventType');
  65891. goog.require('ol.extent');
  65892. goog.require('ol.proj');
  65893. goog.require('ol.source.Image');
  65894. /**
  65895. * @classdesc
  65896. * A layer source for displaying a single, static image.
  65897. *
  65898. * @constructor
  65899. * @extends {ol.source.Image}
  65900. * @param {olx.source.ImageStaticOptions} options Options.
  65901. * @api
  65902. */
  65903. ol.source.ImageStatic = function(options) {
  65904. var imageExtent = options.imageExtent;
  65905. var crossOrigin = options.crossOrigin !== undefined ?
  65906. options.crossOrigin : null;
  65907. var /** @type {ol.ImageLoadFunctionType} */ imageLoadFunction =
  65908. options.imageLoadFunction !== undefined ?
  65909. options.imageLoadFunction : ol.source.Image.defaultImageLoadFunction;
  65910. ol.source.Image.call(this, {
  65911. attributions: options.attributions,
  65912. logo: options.logo,
  65913. projection: ol.proj.get(options.projection)
  65914. });
  65915. /**
  65916. * @private
  65917. * @type {ol.Image}
  65918. */
  65919. this.image_ = new ol.Image(imageExtent, undefined, 1, this.getAttributions(),
  65920. options.url, crossOrigin, imageLoadFunction);
  65921. /**
  65922. * @private
  65923. * @type {ol.Size}
  65924. */
  65925. this.imageSize_ = options.imageSize ? options.imageSize : null;
  65926. ol.events.listen(this.image_, ol.events.EventType.CHANGE,
  65927. this.handleImageChange, this);
  65928. };
  65929. ol.inherits(ol.source.ImageStatic, ol.source.Image);
  65930. /**
  65931. * @inheritDoc
  65932. */
  65933. ol.source.ImageStatic.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
  65934. if (ol.extent.intersects(extent, this.image_.getExtent())) {
  65935. return this.image_;
  65936. }
  65937. return null;
  65938. };
  65939. /**
  65940. * @inheritDoc
  65941. */
  65942. ol.source.ImageStatic.prototype.handleImageChange = function(evt) {
  65943. if (this.image_.getState() == ol.ImageState.LOADED) {
  65944. var imageExtent = this.image_.getExtent();
  65945. var image = this.image_.getImage();
  65946. var imageWidth, imageHeight;
  65947. if (this.imageSize_) {
  65948. imageWidth = this.imageSize_[0];
  65949. imageHeight = this.imageSize_[1];
  65950. } else {
  65951. imageWidth = image.width;
  65952. imageHeight = image.height;
  65953. }
  65954. var resolution = ol.extent.getHeight(imageExtent) / imageHeight;
  65955. var targetWidth = Math.ceil(ol.extent.getWidth(imageExtent) / resolution);
  65956. if (targetWidth != imageWidth) {
  65957. var context = ol.dom.createCanvasContext2D(targetWidth, imageHeight);
  65958. var canvas = context.canvas;
  65959. context.drawImage(image, 0, 0, imageWidth, imageHeight,
  65960. 0, 0, canvas.width, canvas.height);
  65961. this.image_.setImage(canvas);
  65962. }
  65963. }
  65964. ol.source.Image.prototype.handleImageChange.call(this, evt);
  65965. };
  65966. goog.provide('ol.source.WMSServerType');
  65967. /**
  65968. * Available server types: `'carmentaserver'`, `'geoserver'`, `'mapserver'`,
  65969. * `'qgis'`. These are servers that have vendor parameters beyond the WMS
  65970. * specification that OpenLayers can make use of.
  65971. * @enum {string}
  65972. */
  65973. ol.source.WMSServerType = {
  65974. CARMENTA_SERVER: 'carmentaserver',
  65975. GEOSERVER: 'geoserver',
  65976. MAPSERVER: 'mapserver',
  65977. QGIS: 'qgis'
  65978. };
  65979. // FIXME cannot be shared between maps with different projections
  65980. goog.provide('ol.source.ImageWMS');
  65981. goog.require('ol');
  65982. goog.require('ol.Image');
  65983. goog.require('ol.asserts');
  65984. goog.require('ol.events');
  65985. goog.require('ol.events.EventType');
  65986. goog.require('ol.extent');
  65987. goog.require('ol.obj');
  65988. goog.require('ol.proj');
  65989. goog.require('ol.source.Image');
  65990. goog.require('ol.source.WMSServerType');
  65991. goog.require('ol.string');
  65992. goog.require('ol.uri');
  65993. /**
  65994. * @classdesc
  65995. * Source for WMS servers providing single, untiled images.
  65996. *
  65997. * @constructor
  65998. * @fires ol.source.Image.Event
  65999. * @extends {ol.source.Image}
  66000. * @param {olx.source.ImageWMSOptions=} opt_options Options.
  66001. * @api
  66002. */
  66003. ol.source.ImageWMS = function(opt_options) {
  66004. var options = opt_options || {};
  66005. ol.source.Image.call(this, {
  66006. attributions: options.attributions,
  66007. logo: options.logo,
  66008. projection: options.projection,
  66009. resolutions: options.resolutions
  66010. });
  66011. /**
  66012. * @private
  66013. * @type {?string}
  66014. */
  66015. this.crossOrigin_ =
  66016. options.crossOrigin !== undefined ? options.crossOrigin : null;
  66017. /**
  66018. * @private
  66019. * @type {string|undefined}
  66020. */
  66021. this.url_ = options.url;
  66022. /**
  66023. * @private
  66024. * @type {ol.ImageLoadFunctionType}
  66025. */
  66026. this.imageLoadFunction_ = options.imageLoadFunction !== undefined ?
  66027. options.imageLoadFunction : ol.source.Image.defaultImageLoadFunction;
  66028. /**
  66029. * @private
  66030. * @type {!Object}
  66031. */
  66032. this.params_ = options.params || {};
  66033. /**
  66034. * @private
  66035. * @type {boolean}
  66036. */
  66037. this.v13_ = true;
  66038. this.updateV13_();
  66039. /**
  66040. * @private
  66041. * @type {ol.source.WMSServerType|undefined}
  66042. */
  66043. this.serverType_ = /** @type {ol.source.WMSServerType|undefined} */ (options.serverType);
  66044. /**
  66045. * @private
  66046. * @type {boolean}
  66047. */
  66048. this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
  66049. /**
  66050. * @private
  66051. * @type {ol.Image}
  66052. */
  66053. this.image_ = null;
  66054. /**
  66055. * @private
  66056. * @type {ol.Size}
  66057. */
  66058. this.imageSize_ = [0, 0];
  66059. /**
  66060. * @private
  66061. * @type {number}
  66062. */
  66063. this.renderedRevision_ = 0;
  66064. /**
  66065. * @private
  66066. * @type {number}
  66067. */
  66068. this.ratio_ = options.ratio !== undefined ? options.ratio : 1.5;
  66069. };
  66070. ol.inherits(ol.source.ImageWMS, ol.source.Image);
  66071. /**
  66072. * @const
  66073. * @type {ol.Size}
  66074. * @private
  66075. */
  66076. ol.source.ImageWMS.GETFEATUREINFO_IMAGE_SIZE_ = [101, 101];
  66077. /**
  66078. * Return the GetFeatureInfo URL for the passed coordinate, resolution, and
  66079. * projection. Return `undefined` if the GetFeatureInfo URL cannot be
  66080. * constructed.
  66081. * @param {ol.Coordinate} coordinate Coordinate.
  66082. * @param {number} resolution Resolution.
  66083. * @param {ol.ProjectionLike} projection Projection.
  66084. * @param {!Object} params GetFeatureInfo params. `INFO_FORMAT` at least should
  66085. * be provided. If `QUERY_LAYERS` is not provided then the layers specified
  66086. * in the `LAYERS` parameter will be used. `VERSION` should not be
  66087. * specified here.
  66088. * @return {string|undefined} GetFeatureInfo URL.
  66089. * @api
  66090. */
  66091. ol.source.ImageWMS.prototype.getGetFeatureInfoUrl = function(coordinate, resolution, projection, params) {
  66092. if (this.url_ === undefined) {
  66093. return undefined;
  66094. }
  66095. var extent = ol.extent.getForViewAndSize(
  66096. coordinate, resolution, 0,
  66097. ol.source.ImageWMS.GETFEATUREINFO_IMAGE_SIZE_);
  66098. var baseParams = {
  66099. 'SERVICE': 'WMS',
  66100. 'VERSION': ol.DEFAULT_WMS_VERSION,
  66101. 'REQUEST': 'GetFeatureInfo',
  66102. 'FORMAT': 'image/png',
  66103. 'TRANSPARENT': true,
  66104. 'QUERY_LAYERS': this.params_['LAYERS']
  66105. };
  66106. ol.obj.assign(baseParams, this.params_, params);
  66107. var x = Math.floor((coordinate[0] - extent[0]) / resolution);
  66108. var y = Math.floor((extent[3] - coordinate[1]) / resolution);
  66109. baseParams[this.v13_ ? 'I' : 'X'] = x;
  66110. baseParams[this.v13_ ? 'J' : 'Y'] = y;
  66111. return this.getRequestUrl_(
  66112. extent, ol.source.ImageWMS.GETFEATUREINFO_IMAGE_SIZE_,
  66113. 1, ol.proj.get(projection), baseParams);
  66114. };
  66115. /**
  66116. * Get the user-provided params, i.e. those passed to the constructor through
  66117. * the "params" option, and possibly updated using the updateParams method.
  66118. * @return {Object} Params.
  66119. * @api
  66120. */
  66121. ol.source.ImageWMS.prototype.getParams = function() {
  66122. return this.params_;
  66123. };
  66124. /**
  66125. * @inheritDoc
  66126. */
  66127. ol.source.ImageWMS.prototype.getImageInternal = function(extent, resolution, pixelRatio, projection) {
  66128. if (this.url_ === undefined) {
  66129. return null;
  66130. }
  66131. resolution = this.findNearestResolution(resolution);
  66132. if (pixelRatio != 1 && (!this.hidpi_ || this.serverType_ === undefined)) {
  66133. pixelRatio = 1;
  66134. }
  66135. var imageResolution = resolution / pixelRatio;
  66136. var center = ol.extent.getCenter(extent);
  66137. var viewWidth = Math.ceil(ol.extent.getWidth(extent) / imageResolution);
  66138. var viewHeight = Math.ceil(ol.extent.getHeight(extent) / imageResolution);
  66139. var viewExtent = ol.extent.getForViewAndSize(center, imageResolution, 0,
  66140. [viewWidth, viewHeight]);
  66141. var requestWidth = Math.ceil(this.ratio_ * ol.extent.getWidth(extent) / imageResolution);
  66142. var requestHeight = Math.ceil(this.ratio_ * ol.extent.getHeight(extent) / imageResolution);
  66143. var requestExtent = ol.extent.getForViewAndSize(center, imageResolution, 0,
  66144. [requestWidth, requestHeight]);
  66145. var image = this.image_;
  66146. if (image &&
  66147. this.renderedRevision_ == this.getRevision() &&
  66148. image.getResolution() == resolution &&
  66149. image.getPixelRatio() == pixelRatio &&
  66150. ol.extent.containsExtent(image.getExtent(), viewExtent)) {
  66151. return image;
  66152. }
  66153. var params = {
  66154. 'SERVICE': 'WMS',
  66155. 'VERSION': ol.DEFAULT_WMS_VERSION,
  66156. 'REQUEST': 'GetMap',
  66157. 'FORMAT': 'image/png',
  66158. 'TRANSPARENT': true
  66159. };
  66160. ol.obj.assign(params, this.params_);
  66161. this.imageSize_[0] = Math.round(ol.extent.getWidth(requestExtent) / imageResolution);
  66162. this.imageSize_[1] = Math.round(ol.extent.getHeight(requestExtent) / imageResolution);
  66163. var url = this.getRequestUrl_(requestExtent, this.imageSize_, pixelRatio,
  66164. projection, params);
  66165. this.image_ = new ol.Image(requestExtent, resolution, pixelRatio,
  66166. this.getAttributions(), url, this.crossOrigin_, this.imageLoadFunction_);
  66167. this.renderedRevision_ = this.getRevision();
  66168. ol.events.listen(this.image_, ol.events.EventType.CHANGE,
  66169. this.handleImageChange, this);
  66170. return this.image_;
  66171. };
  66172. /**
  66173. * Return the image load function of the source.
  66174. * @return {ol.ImageLoadFunctionType} The image load function.
  66175. * @api
  66176. */
  66177. ol.source.ImageWMS.prototype.getImageLoadFunction = function() {
  66178. return this.imageLoadFunction_;
  66179. };
  66180. /**
  66181. * @param {ol.Extent} extent Extent.
  66182. * @param {ol.Size} size Size.
  66183. * @param {number} pixelRatio Pixel ratio.
  66184. * @param {ol.proj.Projection} projection Projection.
  66185. * @param {Object} params Params.
  66186. * @return {string} Request URL.
  66187. * @private
  66188. */
  66189. ol.source.ImageWMS.prototype.getRequestUrl_ = function(extent, size, pixelRatio, projection, params) {
  66190. ol.asserts.assert(this.url_ !== undefined, 9); // `url` must be configured or set using `#setUrl()`
  66191. params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode();
  66192. if (!('STYLES' in this.params_)) {
  66193. params['STYLES'] = '';
  66194. }
  66195. if (pixelRatio != 1) {
  66196. switch (this.serverType_) {
  66197. case ol.source.WMSServerType.GEOSERVER:
  66198. var dpi = (90 * pixelRatio + 0.5) | 0;
  66199. if ('FORMAT_OPTIONS' in params) {
  66200. params['FORMAT_OPTIONS'] += ';dpi:' + dpi;
  66201. } else {
  66202. params['FORMAT_OPTIONS'] = 'dpi:' + dpi;
  66203. }
  66204. break;
  66205. case ol.source.WMSServerType.MAPSERVER:
  66206. params['MAP_RESOLUTION'] = 90 * pixelRatio;
  66207. break;
  66208. case ol.source.WMSServerType.CARMENTA_SERVER:
  66209. case ol.source.WMSServerType.QGIS:
  66210. params['DPI'] = 90 * pixelRatio;
  66211. break;
  66212. default:
  66213. ol.asserts.assert(false, 8); // Unknown `serverType` configured
  66214. break;
  66215. }
  66216. }
  66217. params['WIDTH'] = size[0];
  66218. params['HEIGHT'] = size[1];
  66219. var axisOrientation = projection.getAxisOrientation();
  66220. var bbox;
  66221. if (this.v13_ && axisOrientation.substr(0, 2) == 'ne') {
  66222. bbox = [extent[1], extent[0], extent[3], extent[2]];
  66223. } else {
  66224. bbox = extent;
  66225. }
  66226. params['BBOX'] = bbox.join(',');
  66227. return ol.uri.appendParams(/** @type {string} */ (this.url_), params);
  66228. };
  66229. /**
  66230. * Return the URL used for this WMS source.
  66231. * @return {string|undefined} URL.
  66232. * @api
  66233. */
  66234. ol.source.ImageWMS.prototype.getUrl = function() {
  66235. return this.url_;
  66236. };
  66237. /**
  66238. * Set the image load function of the source.
  66239. * @param {ol.ImageLoadFunctionType} imageLoadFunction Image load function.
  66240. * @api
  66241. */
  66242. ol.source.ImageWMS.prototype.setImageLoadFunction = function(
  66243. imageLoadFunction) {
  66244. this.image_ = null;
  66245. this.imageLoadFunction_ = imageLoadFunction;
  66246. this.changed();
  66247. };
  66248. /**
  66249. * Set the URL to use for requests.
  66250. * @param {string|undefined} url URL.
  66251. * @api
  66252. */
  66253. ol.source.ImageWMS.prototype.setUrl = function(url) {
  66254. if (url != this.url_) {
  66255. this.url_ = url;
  66256. this.image_ = null;
  66257. this.changed();
  66258. }
  66259. };
  66260. /**
  66261. * Update the user-provided params.
  66262. * @param {Object} params Params.
  66263. * @api
  66264. */
  66265. ol.source.ImageWMS.prototype.updateParams = function(params) {
  66266. ol.obj.assign(this.params_, params);
  66267. this.updateV13_();
  66268. this.image_ = null;
  66269. this.changed();
  66270. };
  66271. /**
  66272. * @private
  66273. */
  66274. ol.source.ImageWMS.prototype.updateV13_ = function() {
  66275. var version = this.params_['VERSION'] || ol.DEFAULT_WMS_VERSION;
  66276. this.v13_ = ol.string.compareVersions(version, '1.3') >= 0;
  66277. };
  66278. goog.provide('ol.source.OSM');
  66279. goog.require('ol');
  66280. goog.require('ol.Attribution');
  66281. goog.require('ol.source.XYZ');
  66282. /**
  66283. * @classdesc
  66284. * Layer source for the OpenStreetMap tile server.
  66285. *
  66286. * @constructor
  66287. * @extends {ol.source.XYZ}
  66288. * @param {olx.source.OSMOptions=} opt_options Open Street Map options.
  66289. * @api
  66290. */
  66291. ol.source.OSM = function(opt_options) {
  66292. var options = opt_options || {};
  66293. var attributions;
  66294. if (options.attributions !== undefined) {
  66295. attributions = options.attributions;
  66296. } else {
  66297. attributions = [ol.source.OSM.ATTRIBUTION];
  66298. }
  66299. var crossOrigin = options.crossOrigin !== undefined ?
  66300. options.crossOrigin : 'anonymous';
  66301. var url = options.url !== undefined ?
  66302. options.url : 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png';
  66303. ol.source.XYZ.call(this, {
  66304. attributions: attributions,
  66305. cacheSize: options.cacheSize,
  66306. crossOrigin: crossOrigin,
  66307. opaque: options.opaque !== undefined ? options.opaque : true,
  66308. maxZoom: options.maxZoom !== undefined ? options.maxZoom : 19,
  66309. reprojectionErrorThreshold: options.reprojectionErrorThreshold,
  66310. tileLoadFunction: options.tileLoadFunction,
  66311. url: url,
  66312. wrapX: options.wrapX
  66313. });
  66314. };
  66315. ol.inherits(ol.source.OSM, ol.source.XYZ);
  66316. /**
  66317. * The attribution containing a link to the OpenStreetMap Copyright and License
  66318. * page.
  66319. * @const
  66320. * @type {ol.Attribution}
  66321. * @api
  66322. */
  66323. ol.source.OSM.ATTRIBUTION = new ol.Attribution({
  66324. html: '&copy; ' +
  66325. '<a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> ' +
  66326. 'contributors.'
  66327. });
  66328. /**
  66329. * @fileoverview
  66330. * @suppress {accessControls, ambiguousFunctionDecl, checkDebuggerStatement, checkRegExp, checkTypes, checkVars, const, constantProperty, deprecated, duplicate, es5Strict, fileoverviewTags, missingProperties, nonStandardJsDocs, strictModuleDepCheck, suspiciousCode, undefinedNames, undefinedVars, unknownDefines, unusedLocalVariables, uselessCode, visibility}
  66331. */
  66332. goog.provide('ol.ext.pixelworks.Processor');
  66333. /** @typedef {function(*)} */
  66334. ol.ext.pixelworks.Processor = function() {};
  66335. (function() {(function (exports) {
  66336. 'use strict';
  66337. var hasImageData = true;
  66338. try {
  66339. new ImageData(10, 10);
  66340. } catch (_) {
  66341. hasImageData = false;
  66342. }
  66343. var context = document.createElement('canvas').getContext('2d');
  66344. function newImageData$1(data, width, height) {
  66345. if (hasImageData) {
  66346. return new ImageData(data, width, height);
  66347. } else {
  66348. var imageData = context.createImageData(width, height);
  66349. imageData.data.set(data);
  66350. return imageData;
  66351. }
  66352. }
  66353. var newImageData_1 = newImageData$1;
  66354. var util = {
  66355. newImageData: newImageData_1
  66356. };
  66357. var newImageData = util.newImageData;
  66358. function createMinion(operation) {
  66359. var workerHasImageData = true;
  66360. try {
  66361. new ImageData(10, 10);
  66362. } catch (_) {
  66363. workerHasImageData = false;
  66364. }
  66365. function newWorkerImageData(data, width, height) {
  66366. if (workerHasImageData) {
  66367. return new ImageData(data, width, height);
  66368. } else {
  66369. return {data: data, width: width, height: height};
  66370. }
  66371. }
  66372. return function(data) {
  66373. var buffers = data['buffers'];
  66374. var meta = data['meta'];
  66375. var imageOps = data['imageOps'];
  66376. var width = data['width'];
  66377. var height = data['height'];
  66378. var numBuffers = buffers.length;
  66379. var numBytes = buffers[0].byteLength;
  66380. var output, b;
  66381. if (imageOps) {
  66382. var images = new Array(numBuffers);
  66383. for (b = 0; b < numBuffers; ++b) {
  66384. images[b] = newWorkerImageData(
  66385. new Uint8ClampedArray(buffers[b]), width, height);
  66386. }
  66387. output = operation(images, meta).data;
  66388. } else {
  66389. output = new Uint8ClampedArray(numBytes);
  66390. var arrays = new Array(numBuffers);
  66391. var pixels = new Array(numBuffers);
  66392. for (b = 0; b < numBuffers; ++b) {
  66393. arrays[b] = new Uint8ClampedArray(buffers[b]);
  66394. pixels[b] = [0, 0, 0, 0];
  66395. }
  66396. for (var i = 0; i < numBytes; i += 4) {
  66397. for (var j = 0; j < numBuffers; ++j) {
  66398. var array = arrays[j];
  66399. pixels[j][0] = array[i];
  66400. pixels[j][1] = array[i + 1];
  66401. pixels[j][2] = array[i + 2];
  66402. pixels[j][3] = array[i + 3];
  66403. }
  66404. var pixel = operation(pixels, meta);
  66405. output[i] = pixel[0];
  66406. output[i + 1] = pixel[1];
  66407. output[i + 2] = pixel[2];
  66408. output[i + 3] = pixel[3];
  66409. }
  66410. }
  66411. return output.buffer;
  66412. };
  66413. }
  66414. function createWorker(config, onMessage) {
  66415. var lib = Object.keys(config.lib || {}).map(function(name) {
  66416. return 'var ' + name + ' = ' + config.lib[name].toString() + ';';
  66417. });
  66418. var lines = lib.concat([
  66419. 'var __minion__ = (' + createMinion.toString() + ')(', config.operation.toString(), ');',
  66420. 'self.addEventListener("message", function(event) {',
  66421. ' var buffer = __minion__(event.data);',
  66422. ' self.postMessage({buffer: buffer, meta: event.data.meta}, [buffer]);',
  66423. '});'
  66424. ]);
  66425. var blob = new Blob(lines, {type: 'text/javascript'});
  66426. var source = URL.createObjectURL(blob);
  66427. var worker = new Worker(source);
  66428. worker.addEventListener('message', onMessage);
  66429. return worker;
  66430. }
  66431. function createFauxWorker(config, onMessage) {
  66432. var minion = createMinion(config.operation);
  66433. return {
  66434. postMessage: function(data) {
  66435. setTimeout(function() {
  66436. onMessage({'data': {'buffer': minion(data), 'meta': data['meta']}});
  66437. }, 0);
  66438. }
  66439. };
  66440. }
  66441. function Processor(config) {
  66442. this._imageOps = !!config.imageOps;
  66443. var threads;
  66444. if (config.threads === 0) {
  66445. threads = 0;
  66446. } else if (this._imageOps) {
  66447. threads = 1;
  66448. } else {
  66449. threads = config.threads || 1;
  66450. }
  66451. var workers = [];
  66452. if (threads) {
  66453. for (var i = 0; i < threads; ++i) {
  66454. workers[i] = createWorker(config, this._onWorkerMessage.bind(this, i));
  66455. }
  66456. } else {
  66457. workers[0] = createFauxWorker(config, this._onWorkerMessage.bind(this, 0));
  66458. }
  66459. this._workers = workers;
  66460. this._queue = [];
  66461. this._maxQueueLength = config.queue || Infinity;
  66462. this._running = 0;
  66463. this._dataLookup = {};
  66464. this._job = null;
  66465. }
  66466. Processor.prototype.process = function(inputs, meta, callback) {
  66467. this._enqueue({
  66468. inputs: inputs,
  66469. meta: meta,
  66470. callback: callback
  66471. });
  66472. this._dispatch();
  66473. };
  66474. Processor.prototype.destroy = function() {
  66475. for (var key in this) {
  66476. this[key] = null;
  66477. }
  66478. this._destroyed = true;
  66479. };
  66480. Processor.prototype._enqueue = function(job) {
  66481. this._queue.push(job);
  66482. while (this._queue.length > this._maxQueueLength) {
  66483. this._queue.shift().callback(null, null);
  66484. }
  66485. };
  66486. Processor.prototype._dispatch = function() {
  66487. if (this._running === 0 && this._queue.length > 0) {
  66488. var job = this._job = this._queue.shift();
  66489. var width = job.inputs[0].width;
  66490. var height = job.inputs[0].height;
  66491. var buffers = job.inputs.map(function(input) {
  66492. return input.data.buffer;
  66493. });
  66494. var threads = this._workers.length;
  66495. this._running = threads;
  66496. if (threads === 1) {
  66497. this._workers[0].postMessage({
  66498. 'buffers': buffers,
  66499. 'meta': job.meta,
  66500. 'imageOps': this._imageOps,
  66501. 'width': width,
  66502. 'height': height
  66503. }, buffers);
  66504. } else {
  66505. var length = job.inputs[0].data.length;
  66506. var segmentLength = 4 * Math.ceil(length / 4 / threads);
  66507. for (var i = 0; i < threads; ++i) {
  66508. var offset = i * segmentLength;
  66509. var slices = [];
  66510. for (var j = 0, jj = buffers.length; j < jj; ++j) {
  66511. slices.push(buffers[i].slice(offset, offset + segmentLength));
  66512. }
  66513. this._workers[i].postMessage({
  66514. 'buffers': slices,
  66515. 'meta': job.meta,
  66516. 'imageOps': this._imageOps,
  66517. 'width': width,
  66518. 'height': height
  66519. }, slices);
  66520. }
  66521. }
  66522. }
  66523. };
  66524. Processor.prototype._onWorkerMessage = function(index, event) {
  66525. if (this._destroyed) {
  66526. return;
  66527. }
  66528. this._dataLookup[index] = event.data;
  66529. --this._running;
  66530. if (this._running === 0) {
  66531. this._resolveJob();
  66532. }
  66533. };
  66534. Processor.prototype._resolveJob = function() {
  66535. var job = this._job;
  66536. var threads = this._workers.length;
  66537. var data, meta;
  66538. if (threads === 1) {
  66539. data = new Uint8ClampedArray(this._dataLookup[0]['buffer']);
  66540. meta = this._dataLookup[0]['meta'];
  66541. } else {
  66542. var length = job.inputs[0].data.length;
  66543. data = new Uint8ClampedArray(length);
  66544. meta = new Array(length);
  66545. var segmentLength = 4 * Math.ceil(length / 4 / threads);
  66546. for (var i = 0; i < threads; ++i) {
  66547. var buffer = this._dataLookup[i]['buffer'];
  66548. var offset = i * segmentLength;
  66549. data.set(new Uint8ClampedArray(buffer), offset);
  66550. meta[i] = this._dataLookup[i]['meta'];
  66551. }
  66552. }
  66553. this._job = null;
  66554. this._dataLookup = {};
  66555. job.callback(null,
  66556. newImageData(data, job.inputs[0].width, job.inputs[0].height), meta);
  66557. this._dispatch();
  66558. };
  66559. var processor = Processor;
  66560. var Processor_1 = processor;
  66561. var lib = {
  66562. Processor: Processor_1
  66563. };
  66564. exports['default'] = lib;
  66565. exports.Processor = Processor_1;
  66566. }((this.pixelworks = this.pixelworks || {})));}).call(ol.ext);
  66567. goog.provide('ol.source.RasterOperationType');
  66568. /**
  66569. * Raster operation type. Supported values are `'pixel'` and `'image'`.
  66570. * @enum {string}
  66571. */
  66572. ol.source.RasterOperationType = {
  66573. PIXEL: 'pixel',
  66574. IMAGE: 'image'
  66575. };
  66576. goog.provide('ol.source.Raster');
  66577. goog.require('ol');
  66578. goog.require('ol.ImageCanvas');
  66579. goog.require('ol.TileQueue');
  66580. goog.require('ol.dom');
  66581. goog.require('ol.events');
  66582. goog.require('ol.events.Event');
  66583. goog.require('ol.events.EventType');
  66584. goog.require('ol.ext.pixelworks.Processor');
  66585. goog.require('ol.extent');
  66586. goog.require('ol.layer.Image');
  66587. goog.require('ol.layer.Tile');
  66588. goog.require('ol.obj');
  66589. goog.require('ol.renderer.canvas.ImageLayer');
  66590. goog.require('ol.renderer.canvas.TileLayer');
  66591. goog.require('ol.source.Image');
  66592. goog.require('ol.source.RasterOperationType');
  66593. goog.require('ol.source.State');
  66594. goog.require('ol.source.Tile');
  66595. goog.require('ol.transform');
  66596. /**
  66597. * @classdesc
  66598. * A source that transforms data from any number of input sources using an array
  66599. * of {@link ol.RasterOperation} functions to transform input pixel values into
  66600. * output pixel values.
  66601. *
  66602. * @constructor
  66603. * @extends {ol.source.Image}
  66604. * @fires ol.source.Raster.Event
  66605. * @param {olx.source.RasterOptions} options Options.
  66606. * @api
  66607. */
  66608. ol.source.Raster = function(options) {
  66609. /**
  66610. * @private
  66611. * @type {*}
  66612. */
  66613. this.worker_ = null;
  66614. /**
  66615. * @private
  66616. * @type {ol.source.RasterOperationType}
  66617. */
  66618. this.operationType_ = options.operationType !== undefined ?
  66619. options.operationType : ol.source.RasterOperationType.PIXEL;
  66620. /**
  66621. * @private
  66622. * @type {number}
  66623. */
  66624. this.threads_ = options.threads !== undefined ? options.threads : 1;
  66625. /**
  66626. * @private
  66627. * @type {Array.<ol.renderer.canvas.Layer>}
  66628. */
  66629. this.renderers_ = ol.source.Raster.createRenderers_(options.sources);
  66630. for (var r = 0, rr = this.renderers_.length; r < rr; ++r) {
  66631. ol.events.listen(this.renderers_[r], ol.events.EventType.CHANGE,
  66632. this.changed, this);
  66633. }
  66634. /**
  66635. * @private
  66636. * @type {ol.TileQueue}
  66637. */
  66638. this.tileQueue_ = new ol.TileQueue(
  66639. function() {
  66640. return 1;
  66641. },
  66642. this.changed.bind(this));
  66643. var layerStatesArray = ol.source.Raster.getLayerStatesArray_(this.renderers_);
  66644. var layerStates = {};
  66645. for (var i = 0, ii = layerStatesArray.length; i < ii; ++i) {
  66646. layerStates[ol.getUid(layerStatesArray[i].layer)] = layerStatesArray[i];
  66647. }
  66648. /**
  66649. * The most recently requested frame state.
  66650. * @type {olx.FrameState}
  66651. * @private
  66652. */
  66653. this.requestedFrameState_;
  66654. /**
  66655. * The most recently rendered image canvas.
  66656. * @type {ol.ImageCanvas}
  66657. * @private
  66658. */
  66659. this.renderedImageCanvas_ = null;
  66660. /**
  66661. * The most recently rendered revision.
  66662. * @type {number}
  66663. */
  66664. this.renderedRevision_;
  66665. /**
  66666. * @private
  66667. * @type {olx.FrameState}
  66668. */
  66669. this.frameState_ = {
  66670. animate: false,
  66671. attributions: {},
  66672. coordinateToPixelTransform: ol.transform.create(),
  66673. extent: null,
  66674. focus: null,
  66675. index: 0,
  66676. layerStates: layerStates,
  66677. layerStatesArray: layerStatesArray,
  66678. logos: {},
  66679. pixelRatio: 1,
  66680. pixelToCoordinateTransform: ol.transform.create(),
  66681. postRenderFunctions: [],
  66682. size: [0, 0],
  66683. skippedFeatureUids: {},
  66684. tileQueue: this.tileQueue_,
  66685. time: Date.now(),
  66686. usedTiles: {},
  66687. viewState: /** @type {olx.ViewState} */ ({
  66688. rotation: 0
  66689. }),
  66690. viewHints: [],
  66691. wantedTiles: {}
  66692. };
  66693. ol.source.Image.call(this, {});
  66694. if (options.operation !== undefined) {
  66695. this.setOperation(options.operation, options.lib);
  66696. }
  66697. };
  66698. ol.inherits(ol.source.Raster, ol.source.Image);
  66699. /**
  66700. * Set the operation.
  66701. * @param {ol.RasterOperation} operation New operation.
  66702. * @param {Object=} opt_lib Functions that will be available to operations run
  66703. * in a worker.
  66704. * @api
  66705. */
  66706. ol.source.Raster.prototype.setOperation = function(operation, opt_lib) {
  66707. this.worker_ = new ol.ext.pixelworks.Processor({
  66708. operation: operation,
  66709. imageOps: this.operationType_ === ol.source.RasterOperationType.IMAGE,
  66710. queue: 1,
  66711. lib: opt_lib,
  66712. threads: this.threads_
  66713. });
  66714. this.changed();
  66715. };
  66716. /**
  66717. * Update the stored frame state.
  66718. * @param {ol.Extent} extent The view extent (in map units).
  66719. * @param {number} resolution The view resolution.
  66720. * @param {ol.proj.Projection} projection The view projection.
  66721. * @return {olx.FrameState} The updated frame state.
  66722. * @private
  66723. */
  66724. ol.source.Raster.prototype.updateFrameState_ = function(extent, resolution, projection) {
  66725. var frameState = /** @type {olx.FrameState} */ (
  66726. ol.obj.assign({}, this.frameState_));
  66727. frameState.viewState = /** @type {olx.ViewState} */ (
  66728. ol.obj.assign({}, frameState.viewState));
  66729. var center = ol.extent.getCenter(extent);
  66730. frameState.extent = extent.slice();
  66731. frameState.focus = center;
  66732. frameState.size[0] = Math.round(ol.extent.getWidth(extent) / resolution);
  66733. frameState.size[1] = Math.round(ol.extent.getHeight(extent) / resolution);
  66734. var viewState = frameState.viewState;
  66735. viewState.center = center;
  66736. viewState.projection = projection;
  66737. viewState.resolution = resolution;
  66738. return frameState;
  66739. };
  66740. /**
  66741. * Determine if all sources are ready.
  66742. * @return {boolean} All sources are ready.
  66743. * @private
  66744. */
  66745. ol.source.Raster.prototype.allSourcesReady_ = function() {
  66746. var ready = true;
  66747. var source;
  66748. for (var i = 0, ii = this.renderers_.length; i < ii; ++i) {
  66749. source = this.renderers_[i].getLayer().getSource();
  66750. if (source.getState() !== ol.source.State.READY) {
  66751. ready = false;
  66752. break;
  66753. }
  66754. }
  66755. return ready;
  66756. };
  66757. /**
  66758. * @inheritDoc
  66759. */
  66760. ol.source.Raster.prototype.getImage = function(extent, resolution, pixelRatio, projection) {
  66761. if (!this.allSourcesReady_()) {
  66762. return null;
  66763. }
  66764. var frameState = this.updateFrameState_(extent, resolution, projection);
  66765. this.requestedFrameState_ = frameState;
  66766. // check if we can't reuse the existing ol.ImageCanvas
  66767. if (this.renderedImageCanvas_) {
  66768. var renderedResolution = this.renderedImageCanvas_.getResolution();
  66769. var renderedExtent = this.renderedImageCanvas_.getExtent();
  66770. if (resolution !== renderedResolution || !ol.extent.equals(extent, renderedExtent)) {
  66771. this.renderedImageCanvas_ = null;
  66772. }
  66773. }
  66774. if (!this.renderedImageCanvas_ || this.getRevision() !== this.renderedRevision_) {
  66775. this.processSources_();
  66776. }
  66777. frameState.tileQueue.loadMoreTiles(16, 16);
  66778. return this.renderedImageCanvas_;
  66779. };
  66780. /**
  66781. * Start processing source data.
  66782. * @private
  66783. */
  66784. ol.source.Raster.prototype.processSources_ = function() {
  66785. var frameState = this.requestedFrameState_;
  66786. var len = this.renderers_.length;
  66787. var imageDatas = new Array(len);
  66788. for (var i = 0; i < len; ++i) {
  66789. var imageData = ol.source.Raster.getImageData_(
  66790. this.renderers_[i], frameState, frameState.layerStatesArray[i]);
  66791. if (imageData) {
  66792. imageDatas[i] = imageData;
  66793. } else {
  66794. return;
  66795. }
  66796. }
  66797. var data = {};
  66798. this.dispatchEvent(new ol.source.Raster.Event(
  66799. ol.source.Raster.EventType_.BEFOREOPERATIONS, frameState, data));
  66800. this.worker_.process(imageDatas, data,
  66801. this.onWorkerComplete_.bind(this, frameState));
  66802. };
  66803. /**
  66804. * Called when pixel processing is complete.
  66805. * @param {olx.FrameState} frameState The frame state.
  66806. * @param {Error} err Any error during processing.
  66807. * @param {ImageData} output The output image data.
  66808. * @param {Object} data The user data.
  66809. * @private
  66810. */
  66811. ol.source.Raster.prototype.onWorkerComplete_ = function(frameState, err, output, data) {
  66812. if (err || !output) {
  66813. return;
  66814. }
  66815. // do nothing if extent or resolution changed
  66816. var extent = frameState.extent;
  66817. var resolution = frameState.viewState.resolution;
  66818. if (resolution !== this.requestedFrameState_.viewState.resolution ||
  66819. !ol.extent.equals(extent, this.requestedFrameState_.extent)) {
  66820. return;
  66821. }
  66822. var context;
  66823. if (this.renderedImageCanvas_) {
  66824. context = this.renderedImageCanvas_.getImage().getContext('2d');
  66825. } else {
  66826. var width = Math.round(ol.extent.getWidth(extent) / resolution);
  66827. var height = Math.round(ol.extent.getHeight(extent) / resolution);
  66828. context = ol.dom.createCanvasContext2D(width, height);
  66829. this.renderedImageCanvas_ = new ol.ImageCanvas(
  66830. extent, resolution, 1, this.getAttributions(), context.canvas);
  66831. }
  66832. context.putImageData(output, 0, 0);
  66833. this.changed();
  66834. this.renderedRevision_ = this.getRevision();
  66835. this.dispatchEvent(new ol.source.Raster.Event(
  66836. ol.source.Raster.EventType_.AFTEROPERATIONS, frameState, data));
  66837. };
  66838. /**
  66839. * Get image data from a renderer.
  66840. * @param {ol.renderer.canvas.Layer} renderer Layer renderer.
  66841. * @param {olx.FrameState} frameState The frame state.
  66842. * @param {ol.LayerState} layerState The layer state.
  66843. * @return {ImageData} The image data.
  66844. * @private
  66845. */
  66846. ol.source.Raster.getImageData_ = function(renderer, frameState, layerState) {
  66847. if (!renderer.prepareFrame(frameState, layerState)) {
  66848. return null;
  66849. }
  66850. var width = frameState.size[0];
  66851. var height = frameState.size[1];
  66852. if (!ol.source.Raster.context_) {
  66853. ol.source.Raster.context_ = ol.dom.createCanvasContext2D(width, height);
  66854. } else {
  66855. var canvas = ol.source.Raster.context_.canvas;
  66856. if (canvas.width !== width || canvas.height !== height) {
  66857. ol.source.Raster.context_ = ol.dom.createCanvasContext2D(width, height);
  66858. } else {
  66859. ol.source.Raster.context_.clearRect(0, 0, width, height);
  66860. }
  66861. }
  66862. renderer.composeFrame(frameState, layerState, ol.source.Raster.context_);
  66863. return ol.source.Raster.context_.getImageData(0, 0, width, height);
  66864. };
  66865. /**
  66866. * A reusable canvas context.
  66867. * @type {CanvasRenderingContext2D}
  66868. * @private
  66869. */
  66870. ol.source.Raster.context_ = null;
  66871. /**
  66872. * Get a list of layer states from a list of renderers.
  66873. * @param {Array.<ol.renderer.canvas.Layer>} renderers Layer renderers.
  66874. * @return {Array.<ol.LayerState>} The layer states.
  66875. * @private
  66876. */
  66877. ol.source.Raster.getLayerStatesArray_ = function(renderers) {
  66878. return renderers.map(function(renderer) {
  66879. return renderer.getLayer().getLayerState();
  66880. });
  66881. };
  66882. /**
  66883. * Create renderers for all sources.
  66884. * @param {Array.<ol.source.Source>} sources The sources.
  66885. * @return {Array.<ol.renderer.canvas.Layer>} Array of layer renderers.
  66886. * @private
  66887. */
  66888. ol.source.Raster.createRenderers_ = function(sources) {
  66889. var len = sources.length;
  66890. var renderers = new Array(len);
  66891. for (var i = 0; i < len; ++i) {
  66892. renderers[i] = ol.source.Raster.createRenderer_(sources[i]);
  66893. }
  66894. return renderers;
  66895. };
  66896. /**
  66897. * Create a renderer for the provided source.
  66898. * @param {ol.source.Source} source The source.
  66899. * @return {ol.renderer.canvas.Layer} The renderer.
  66900. * @private
  66901. */
  66902. ol.source.Raster.createRenderer_ = function(source) {
  66903. var renderer = null;
  66904. if (source instanceof ol.source.Tile) {
  66905. renderer = ol.source.Raster.createTileRenderer_(source);
  66906. } else if (source instanceof ol.source.Image) {
  66907. renderer = ol.source.Raster.createImageRenderer_(source);
  66908. }
  66909. return renderer;
  66910. };
  66911. /**
  66912. * Create an image renderer for the provided source.
  66913. * @param {ol.source.Image} source The source.
  66914. * @return {ol.renderer.canvas.Layer} The renderer.
  66915. * @private
  66916. */
  66917. ol.source.Raster.createImageRenderer_ = function(source) {
  66918. var layer = new ol.layer.Image({source: source});
  66919. return new ol.renderer.canvas.ImageLayer(layer);
  66920. };
  66921. /**
  66922. * Create a tile renderer for the provided source.
  66923. * @param {ol.source.Tile} source The source.
  66924. * @return {ol.renderer.canvas.Layer} The renderer.
  66925. * @private
  66926. */
  66927. ol.source.Raster.createTileRenderer_ = function(source) {
  66928. var layer = new ol.layer.Tile({source: source});
  66929. return new ol.renderer.canvas.TileLayer(layer);
  66930. };
  66931. /**
  66932. * @classdesc
  66933. * Events emitted by {@link ol.source.Raster} instances are instances of this
  66934. * type.
  66935. *
  66936. * @constructor
  66937. * @extends {ol.events.Event}
  66938. * @implements {oli.source.RasterEvent}
  66939. * @param {string} type Type.
  66940. * @param {olx.FrameState} frameState The frame state.
  66941. * @param {Object} data An object made available to operations.
  66942. */
  66943. ol.source.Raster.Event = function(type, frameState, data) {
  66944. ol.events.Event.call(this, type);
  66945. /**
  66946. * The raster extent.
  66947. * @type {ol.Extent}
  66948. * @api
  66949. */
  66950. this.extent = frameState.extent;
  66951. /**
  66952. * The pixel resolution (map units per pixel).
  66953. * @type {number}
  66954. * @api
  66955. */
  66956. this.resolution = frameState.viewState.resolution / frameState.pixelRatio;
  66957. /**
  66958. * An object made available to all operations. This can be used by operations
  66959. * as a storage object (e.g. for calculating statistics).
  66960. * @type {Object}
  66961. * @api
  66962. */
  66963. this.data = data;
  66964. };
  66965. ol.inherits(ol.source.Raster.Event, ol.events.Event);
  66966. /**
  66967. * @override
  66968. */
  66969. ol.source.Raster.prototype.getImageInternal = function() {
  66970. return null; // not implemented
  66971. };
  66972. /**
  66973. * @enum {string}
  66974. * @private
  66975. */
  66976. ol.source.Raster.EventType_ = {
  66977. /**
  66978. * Triggered before operations are run.
  66979. * @event ol.source.Raster.Event#beforeoperations
  66980. * @api
  66981. */
  66982. BEFOREOPERATIONS: 'beforeoperations',
  66983. /**
  66984. * Triggered after operations are run.
  66985. * @event ol.source.Raster.Event#afteroperations
  66986. * @api
  66987. */
  66988. AFTEROPERATIONS: 'afteroperations'
  66989. };
  66990. goog.provide('ol.source.Stamen');
  66991. goog.require('ol');
  66992. goog.require('ol.Attribution');
  66993. goog.require('ol.source.OSM');
  66994. goog.require('ol.source.XYZ');
  66995. /**
  66996. * @classdesc
  66997. * Layer source for the Stamen tile server.
  66998. *
  66999. * @constructor
  67000. * @extends {ol.source.XYZ}
  67001. * @param {olx.source.StamenOptions} options Stamen options.
  67002. * @api
  67003. */
  67004. ol.source.Stamen = function(options) {
  67005. var i = options.layer.indexOf('-');
  67006. var provider = i == -1 ? options.layer : options.layer.slice(0, i);
  67007. var providerConfig = ol.source.Stamen.ProviderConfig[provider];
  67008. var layerConfig = ol.source.Stamen.LayerConfig[options.layer];
  67009. var url = options.url !== undefined ? options.url :
  67010. 'https://stamen-tiles-{a-d}.a.ssl.fastly.net/' + options.layer +
  67011. '/{z}/{x}/{y}.' + layerConfig.extension;
  67012. ol.source.XYZ.call(this, {
  67013. attributions: ol.source.Stamen.ATTRIBUTIONS,
  67014. cacheSize: options.cacheSize,
  67015. crossOrigin: 'anonymous',
  67016. maxZoom: options.maxZoom != undefined ? options.maxZoom : providerConfig.maxZoom,
  67017. minZoom: options.minZoom != undefined ? options.minZoom : providerConfig.minZoom,
  67018. opaque: layerConfig.opaque,
  67019. reprojectionErrorThreshold: options.reprojectionErrorThreshold,
  67020. tileLoadFunction: options.tileLoadFunction,
  67021. url: url,
  67022. wrapX: options.wrapX
  67023. });
  67024. };
  67025. ol.inherits(ol.source.Stamen, ol.source.XYZ);
  67026. /**
  67027. * @const
  67028. * @type {Array.<ol.Attribution>}
  67029. */
  67030. ol.source.Stamen.ATTRIBUTIONS = [
  67031. new ol.Attribution({
  67032. html: 'Map tiles by <a href="https://stamen.com/">Stamen Design</a>, ' +
  67033. 'under <a href="https://creativecommons.org/licenses/by/3.0/">CC BY' +
  67034. ' 3.0</a>.'
  67035. }),
  67036. ol.source.OSM.ATTRIBUTION
  67037. ];
  67038. /**
  67039. * @type {Object.<string, {extension: string, opaque: boolean}>}
  67040. */
  67041. ol.source.Stamen.LayerConfig = {
  67042. 'terrain': {
  67043. extension: 'jpg',
  67044. opaque: true
  67045. },
  67046. 'terrain-background': {
  67047. extension: 'jpg',
  67048. opaque: true
  67049. },
  67050. 'terrain-labels': {
  67051. extension: 'png',
  67052. opaque: false
  67053. },
  67054. 'terrain-lines': {
  67055. extension: 'png',
  67056. opaque: false
  67057. },
  67058. 'toner-background': {
  67059. extension: 'png',
  67060. opaque: true
  67061. },
  67062. 'toner': {
  67063. extension: 'png',
  67064. opaque: true
  67065. },
  67066. 'toner-hybrid': {
  67067. extension: 'png',
  67068. opaque: false
  67069. },
  67070. 'toner-labels': {
  67071. extension: 'png',
  67072. opaque: false
  67073. },
  67074. 'toner-lines': {
  67075. extension: 'png',
  67076. opaque: false
  67077. },
  67078. 'toner-lite': {
  67079. extension: 'png',
  67080. opaque: true
  67081. },
  67082. 'watercolor': {
  67083. extension: 'jpg',
  67084. opaque: true
  67085. }
  67086. };
  67087. /**
  67088. * @type {Object.<string, {minZoom: number, maxZoom: number}>}
  67089. */
  67090. ol.source.Stamen.ProviderConfig = {
  67091. 'terrain': {
  67092. minZoom: 4,
  67093. maxZoom: 18
  67094. },
  67095. 'toner': {
  67096. minZoom: 0,
  67097. maxZoom: 20
  67098. },
  67099. 'watercolor': {
  67100. minZoom: 1,
  67101. maxZoom: 16
  67102. }
  67103. };
  67104. goog.provide('ol.source.TileArcGISRest');
  67105. goog.require('ol');
  67106. goog.require('ol.extent');
  67107. goog.require('ol.math');
  67108. goog.require('ol.obj');
  67109. goog.require('ol.size');
  67110. goog.require('ol.source.TileImage');
  67111. goog.require('ol.tilecoord');
  67112. goog.require('ol.uri');
  67113. /**
  67114. * @classdesc
  67115. * Layer source for tile data from ArcGIS Rest services. Map and Image
  67116. * Services are supported.
  67117. *
  67118. * For cached ArcGIS services, better performance is available using the
  67119. * {@link ol.source.XYZ} data source.
  67120. *
  67121. * @constructor
  67122. * @extends {ol.source.TileImage}
  67123. * @param {olx.source.TileArcGISRestOptions=} opt_options Tile ArcGIS Rest
  67124. * options.
  67125. * @api
  67126. */
  67127. ol.source.TileArcGISRest = function(opt_options) {
  67128. var options = opt_options || {};
  67129. ol.source.TileImage.call(this, {
  67130. attributions: options.attributions,
  67131. cacheSize: options.cacheSize,
  67132. crossOrigin: options.crossOrigin,
  67133. logo: options.logo,
  67134. projection: options.projection,
  67135. reprojectionErrorThreshold: options.reprojectionErrorThreshold,
  67136. tileGrid: options.tileGrid,
  67137. tileLoadFunction: options.tileLoadFunction,
  67138. url: options.url,
  67139. urls: options.urls,
  67140. wrapX: options.wrapX !== undefined ? options.wrapX : true
  67141. });
  67142. /**
  67143. * @private
  67144. * @type {!Object}
  67145. */
  67146. this.params_ = options.params || {};
  67147. /**
  67148. * @private
  67149. * @type {ol.Extent}
  67150. */
  67151. this.tmpExtent_ = ol.extent.createEmpty();
  67152. this.setKey(this.getKeyForParams_());
  67153. };
  67154. ol.inherits(ol.source.TileArcGISRest, ol.source.TileImage);
  67155. /**
  67156. * @private
  67157. * @return {string} The key for the current params.
  67158. */
  67159. ol.source.TileArcGISRest.prototype.getKeyForParams_ = function() {
  67160. var i = 0;
  67161. var res = [];
  67162. for (var key in this.params_) {
  67163. res[i++] = key + '-' + this.params_[key];
  67164. }
  67165. return res.join('/');
  67166. };
  67167. /**
  67168. * Get the user-provided params, i.e. those passed to the constructor through
  67169. * the "params" option, and possibly updated using the updateParams method.
  67170. * @return {Object} Params.
  67171. * @api
  67172. */
  67173. ol.source.TileArcGISRest.prototype.getParams = function() {
  67174. return this.params_;
  67175. };
  67176. /**
  67177. * @param {ol.TileCoord} tileCoord Tile coordinate.
  67178. * @param {ol.Size} tileSize Tile size.
  67179. * @param {ol.Extent} tileExtent Tile extent.
  67180. * @param {number} pixelRatio Pixel ratio.
  67181. * @param {ol.proj.Projection} projection Projection.
  67182. * @param {Object} params Params.
  67183. * @return {string|undefined} Request URL.
  67184. * @private
  67185. */
  67186. ol.source.TileArcGISRest.prototype.getRequestUrl_ = function(tileCoord, tileSize, tileExtent,
  67187. pixelRatio, projection, params) {
  67188. var urls = this.urls;
  67189. if (!urls) {
  67190. return undefined;
  67191. }
  67192. // ArcGIS Server only wants the numeric portion of the projection ID.
  67193. var srid = projection.getCode().split(':').pop();
  67194. params['SIZE'] = tileSize[0] + ',' + tileSize[1];
  67195. params['BBOX'] = tileExtent.join(',');
  67196. params['BBOXSR'] = srid;
  67197. params['IMAGESR'] = srid;
  67198. params['DPI'] = Math.round(
  67199. params['DPI'] ? params['DPI'] * pixelRatio : 90 * pixelRatio
  67200. );
  67201. var url;
  67202. if (urls.length == 1) {
  67203. url = urls[0];
  67204. } else {
  67205. var index = ol.math.modulo(ol.tilecoord.hash(tileCoord), urls.length);
  67206. url = urls[index];
  67207. }
  67208. var modifiedUrl = url
  67209. .replace(/MapServer\/?$/, 'MapServer/export')
  67210. .replace(/ImageServer\/?$/, 'ImageServer/exportImage');
  67211. return ol.uri.appendParams(modifiedUrl, params);
  67212. };
  67213. /**
  67214. * @inheritDoc
  67215. */
  67216. ol.source.TileArcGISRest.prototype.getTilePixelRatio = function(pixelRatio) {
  67217. return /** @type {number} */ (pixelRatio);
  67218. };
  67219. /**
  67220. * @inheritDoc
  67221. */
  67222. ol.source.TileArcGISRest.prototype.fixedTileUrlFunction = function(tileCoord, pixelRatio, projection) {
  67223. var tileGrid = this.getTileGrid();
  67224. if (!tileGrid) {
  67225. tileGrid = this.getTileGridForProjection(projection);
  67226. }
  67227. if (tileGrid.getResolutions().length <= tileCoord[0]) {
  67228. return undefined;
  67229. }
  67230. var tileExtent = tileGrid.getTileCoordExtent(
  67231. tileCoord, this.tmpExtent_);
  67232. var tileSize = ol.size.toSize(
  67233. tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
  67234. if (pixelRatio != 1) {
  67235. tileSize = ol.size.scale(tileSize, pixelRatio, this.tmpSize);
  67236. }
  67237. // Apply default params and override with user specified values.
  67238. var baseParams = {
  67239. 'F': 'image',
  67240. 'FORMAT': 'PNG32',
  67241. 'TRANSPARENT': true
  67242. };
  67243. ol.obj.assign(baseParams, this.params_);
  67244. return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
  67245. pixelRatio, projection, baseParams);
  67246. };
  67247. /**
  67248. * Update the user-provided params.
  67249. * @param {Object} params Params.
  67250. * @api
  67251. */
  67252. ol.source.TileArcGISRest.prototype.updateParams = function(params) {
  67253. ol.obj.assign(this.params_, params);
  67254. this.setKey(this.getKeyForParams_());
  67255. };
  67256. goog.provide('ol.source.TileDebug');
  67257. goog.require('ol');
  67258. goog.require('ol.Tile');
  67259. goog.require('ol.TileState');
  67260. goog.require('ol.dom');
  67261. goog.require('ol.size');
  67262. goog.require('ol.source.Tile');
  67263. /**
  67264. * @classdesc
  67265. * A pseudo tile source, which does not fetch tiles from a server, but renders
  67266. * a grid outline for the tile grid/projection along with the coordinates for
  67267. * each tile. See examples/canvas-tiles for an example.
  67268. *
  67269. * Uses Canvas context2d, so requires Canvas support.
  67270. *
  67271. * @constructor
  67272. * @extends {ol.source.Tile}
  67273. * @param {olx.source.TileDebugOptions} options Debug tile options.
  67274. * @api
  67275. */
  67276. ol.source.TileDebug = function(options) {
  67277. ol.source.Tile.call(this, {
  67278. opaque: false,
  67279. projection: options.projection,
  67280. tileGrid: options.tileGrid,
  67281. wrapX: options.wrapX !== undefined ? options.wrapX : true
  67282. });
  67283. };
  67284. ol.inherits(ol.source.TileDebug, ol.source.Tile);
  67285. /**
  67286. * @inheritDoc
  67287. */
  67288. ol.source.TileDebug.prototype.getTile = function(z, x, y) {
  67289. var tileCoordKey = this.getKeyZXY(z, x, y);
  67290. if (this.tileCache.containsKey(tileCoordKey)) {
  67291. return /** @type {!ol.source.TileDebug.Tile_} */ (this.tileCache.get(tileCoordKey));
  67292. } else {
  67293. var tileSize = ol.size.toSize(this.tileGrid.getTileSize(z));
  67294. var tileCoord = [z, x, y];
  67295. var textTileCoord = this.getTileCoordForTileUrlFunction(tileCoord);
  67296. var text = !textTileCoord ? '' :
  67297. this.getTileCoordForTileUrlFunction(textTileCoord).toString();
  67298. var tile = new ol.source.TileDebug.Tile_(tileCoord, tileSize, text);
  67299. this.tileCache.set(tileCoordKey, tile);
  67300. return tile;
  67301. }
  67302. };
  67303. /**
  67304. * @constructor
  67305. * @extends {ol.Tile}
  67306. * @param {ol.TileCoord} tileCoord Tile coordinate.
  67307. * @param {ol.Size} tileSize Tile size.
  67308. * @param {string} text Text.
  67309. * @private
  67310. */
  67311. ol.source.TileDebug.Tile_ = function(tileCoord, tileSize, text) {
  67312. ol.Tile.call(this, tileCoord, ol.TileState.LOADED);
  67313. /**
  67314. * @private
  67315. * @type {ol.Size}
  67316. */
  67317. this.tileSize_ = tileSize;
  67318. /**
  67319. * @private
  67320. * @type {string}
  67321. */
  67322. this.text_ = text;
  67323. /**
  67324. * @private
  67325. * @type {HTMLCanvasElement}
  67326. */
  67327. this.canvas_ = null;
  67328. };
  67329. ol.inherits(ol.source.TileDebug.Tile_, ol.Tile);
  67330. /**
  67331. * Get the image element for this tile.
  67332. * @return {HTMLCanvasElement} Image.
  67333. */
  67334. ol.source.TileDebug.Tile_.prototype.getImage = function() {
  67335. if (this.canvas_) {
  67336. return this.canvas_;
  67337. } else {
  67338. var tileSize = this.tileSize_;
  67339. var context = ol.dom.createCanvasContext2D(tileSize[0], tileSize[1]);
  67340. context.strokeStyle = 'black';
  67341. context.strokeRect(0.5, 0.5, tileSize[0] + 0.5, tileSize[1] + 0.5);
  67342. context.fillStyle = 'black';
  67343. context.textAlign = 'center';
  67344. context.textBaseline = 'middle';
  67345. context.font = '24px sans-serif';
  67346. context.fillText(this.text_, tileSize[0] / 2, tileSize[1] / 2);
  67347. this.canvas_ = context.canvas;
  67348. return context.canvas;
  67349. }
  67350. };
  67351. /**
  67352. * @override
  67353. */
  67354. ol.source.TileDebug.Tile_.prototype.load = function() {};
  67355. // FIXME check order of async callbacks
  67356. /**
  67357. * @see http://mapbox.com/developers/api/
  67358. */
  67359. goog.provide('ol.source.TileJSON');
  67360. goog.require('ol');
  67361. goog.require('ol.Attribution');
  67362. goog.require('ol.TileUrlFunction');
  67363. goog.require('ol.asserts');
  67364. goog.require('ol.extent');
  67365. goog.require('ol.net');
  67366. goog.require('ol.proj');
  67367. goog.require('ol.source.State');
  67368. goog.require('ol.source.TileImage');
  67369. goog.require('ol.tilegrid');
  67370. /**
  67371. * @classdesc
  67372. * Layer source for tile data in TileJSON format.
  67373. *
  67374. * @constructor
  67375. * @extends {ol.source.TileImage}
  67376. * @param {olx.source.TileJSONOptions} options TileJSON options.
  67377. * @api
  67378. */
  67379. ol.source.TileJSON = function(options) {
  67380. /**
  67381. * @type {TileJSON}
  67382. * @private
  67383. */
  67384. this.tileJSON_ = null;
  67385. ol.source.TileImage.call(this, {
  67386. attributions: options.attributions,
  67387. cacheSize: options.cacheSize,
  67388. crossOrigin: options.crossOrigin,
  67389. projection: ol.proj.get('EPSG:3857'),
  67390. reprojectionErrorThreshold: options.reprojectionErrorThreshold,
  67391. state: ol.source.State.LOADING,
  67392. tileLoadFunction: options.tileLoadFunction,
  67393. wrapX: options.wrapX !== undefined ? options.wrapX : true
  67394. });
  67395. if (options.url) {
  67396. if (options.jsonp) {
  67397. ol.net.jsonp(options.url, this.handleTileJSONResponse.bind(this),
  67398. this.handleTileJSONError.bind(this));
  67399. } else {
  67400. var client = new XMLHttpRequest();
  67401. client.addEventListener('load', this.onXHRLoad_.bind(this));
  67402. client.addEventListener('error', this.onXHRError_.bind(this));
  67403. client.open('GET', options.url);
  67404. client.send();
  67405. }
  67406. } else if (options.tileJSON) {
  67407. this.handleTileJSONResponse(options.tileJSON);
  67408. } else {
  67409. ol.asserts.assert(false, 51); // Either `url` or `tileJSON` options must be provided
  67410. }
  67411. };
  67412. ol.inherits(ol.source.TileJSON, ol.source.TileImage);
  67413. /**
  67414. * @private
  67415. * @param {Event} event The load event.
  67416. */
  67417. ol.source.TileJSON.prototype.onXHRLoad_ = function(event) {
  67418. var client = /** @type {XMLHttpRequest} */ (event.target);
  67419. // status will be 0 for file:// urls
  67420. if (!client.status || client.status >= 200 && client.status < 300) {
  67421. var response;
  67422. try {
  67423. response = /** @type {TileJSON} */(JSON.parse(client.responseText));
  67424. } catch (err) {
  67425. this.handleTileJSONError();
  67426. return;
  67427. }
  67428. this.handleTileJSONResponse(response);
  67429. } else {
  67430. this.handleTileJSONError();
  67431. }
  67432. };
  67433. /**
  67434. * @private
  67435. * @param {Event} event The error event.
  67436. */
  67437. ol.source.TileJSON.prototype.onXHRError_ = function(event) {
  67438. this.handleTileJSONError();
  67439. };
  67440. /**
  67441. * @return {TileJSON} The tilejson object.
  67442. * @api
  67443. */
  67444. ol.source.TileJSON.prototype.getTileJSON = function() {
  67445. return this.tileJSON_;
  67446. };
  67447. /**
  67448. * @protected
  67449. * @param {TileJSON} tileJSON Tile JSON.
  67450. */
  67451. ol.source.TileJSON.prototype.handleTileJSONResponse = function(tileJSON) {
  67452. var epsg4326Projection = ol.proj.get('EPSG:4326');
  67453. var sourceProjection = this.getProjection();
  67454. var extent;
  67455. if (tileJSON.bounds !== undefined) {
  67456. var transform = ol.proj.getTransformFromProjections(
  67457. epsg4326Projection, sourceProjection);
  67458. extent = ol.extent.applyTransform(tileJSON.bounds, transform);
  67459. }
  67460. var minZoom = tileJSON.minzoom || 0;
  67461. var maxZoom = tileJSON.maxzoom || 22;
  67462. var tileGrid = ol.tilegrid.createXYZ({
  67463. extent: ol.tilegrid.extentFromProjection(sourceProjection),
  67464. maxZoom: maxZoom,
  67465. minZoom: minZoom
  67466. });
  67467. this.tileGrid = tileGrid;
  67468. this.tileUrlFunction =
  67469. ol.TileUrlFunction.createFromTemplates(tileJSON.tiles, tileGrid);
  67470. if (tileJSON.attribution !== undefined && !this.getAttributions()) {
  67471. var attributionExtent = extent !== undefined ?
  67472. extent : epsg4326Projection.getExtent();
  67473. /** @type {Object.<string, Array.<ol.TileRange>>} */
  67474. var tileRanges = {};
  67475. var z, zKey;
  67476. for (z = minZoom; z <= maxZoom; ++z) {
  67477. zKey = z.toString();
  67478. tileRanges[zKey] =
  67479. [tileGrid.getTileRangeForExtentAndZ(attributionExtent, z)];
  67480. }
  67481. this.setAttributions([
  67482. new ol.Attribution({
  67483. html: tileJSON.attribution,
  67484. tileRanges: tileRanges
  67485. })
  67486. ]);
  67487. }
  67488. this.tileJSON_ = tileJSON;
  67489. this.setState(ol.source.State.READY);
  67490. };
  67491. /**
  67492. * @protected
  67493. */
  67494. ol.source.TileJSON.prototype.handleTileJSONError = function() {
  67495. this.setState(ol.source.State.ERROR);
  67496. };
  67497. goog.provide('ol.source.TileUTFGrid');
  67498. goog.require('ol');
  67499. goog.require('ol.Attribution');
  67500. goog.require('ol.Tile');
  67501. goog.require('ol.TileState');
  67502. goog.require('ol.TileUrlFunction');
  67503. goog.require('ol.asserts');
  67504. goog.require('ol.events');
  67505. goog.require('ol.events.EventType');
  67506. goog.require('ol.extent');
  67507. goog.require('ol.net');
  67508. goog.require('ol.proj');
  67509. goog.require('ol.source.State');
  67510. goog.require('ol.source.Tile');
  67511. goog.require('ol.tilegrid');
  67512. /**
  67513. * @classdesc
  67514. * Layer source for UTFGrid interaction data loaded from TileJSON format.
  67515. *
  67516. * @constructor
  67517. * @extends {ol.source.Tile}
  67518. * @param {olx.source.TileUTFGridOptions} options Source options.
  67519. * @api
  67520. */
  67521. ol.source.TileUTFGrid = function(options) {
  67522. ol.source.Tile.call(this, {
  67523. projection: ol.proj.get('EPSG:3857'),
  67524. state: ol.source.State.LOADING
  67525. });
  67526. /**
  67527. * @private
  67528. * @type {boolean}
  67529. */
  67530. this.preemptive_ = options.preemptive !== undefined ?
  67531. options.preemptive : true;
  67532. /**
  67533. * @private
  67534. * @type {!ol.TileUrlFunctionType}
  67535. */
  67536. this.tileUrlFunction_ = ol.TileUrlFunction.nullTileUrlFunction;
  67537. /**
  67538. * @private
  67539. * @type {string|undefined}
  67540. */
  67541. this.template_ = undefined;
  67542. /**
  67543. * @private
  67544. * @type {boolean}
  67545. */
  67546. this.jsonp_ = options.jsonp || false;
  67547. if (options.url) {
  67548. if (this.jsonp_) {
  67549. ol.net.jsonp(options.url, this.handleTileJSONResponse.bind(this),
  67550. this.handleTileJSONError.bind(this));
  67551. } else {
  67552. var client = new XMLHttpRequest();
  67553. client.addEventListener('load', this.onXHRLoad_.bind(this));
  67554. client.addEventListener('error', this.onXHRError_.bind(this));
  67555. client.open('GET', options.url);
  67556. client.send();
  67557. }
  67558. } else if (options.tileJSON) {
  67559. this.handleTileJSONResponse(options.tileJSON);
  67560. } else {
  67561. ol.asserts.assert(false, 51); // Either `url` or `tileJSON` options must be provided
  67562. }
  67563. };
  67564. ol.inherits(ol.source.TileUTFGrid, ol.source.Tile);
  67565. /**
  67566. * @private
  67567. * @param {Event} event The load event.
  67568. */
  67569. ol.source.TileUTFGrid.prototype.onXHRLoad_ = function(event) {
  67570. var client = /** @type {XMLHttpRequest} */ (event.target);
  67571. // status will be 0 for file:// urls
  67572. if (!client.status || client.status >= 200 && client.status < 300) {
  67573. var response;
  67574. try {
  67575. response = /** @type {TileJSON} */(JSON.parse(client.responseText));
  67576. } catch (err) {
  67577. this.handleTileJSONError();
  67578. return;
  67579. }
  67580. this.handleTileJSONResponse(response);
  67581. } else {
  67582. this.handleTileJSONError();
  67583. }
  67584. };
  67585. /**
  67586. * @private
  67587. * @param {Event} event The error event.
  67588. */
  67589. ol.source.TileUTFGrid.prototype.onXHRError_ = function(event) {
  67590. this.handleTileJSONError();
  67591. };
  67592. /**
  67593. * Return the template from TileJSON.
  67594. * @return {string|undefined} The template from TileJSON.
  67595. * @api
  67596. */
  67597. ol.source.TileUTFGrid.prototype.getTemplate = function() {
  67598. return this.template_;
  67599. };
  67600. /**
  67601. * Calls the callback (synchronously by default) with the available data
  67602. * for given coordinate and resolution (or `null` if not yet loaded or
  67603. * in case of an error).
  67604. * @param {ol.Coordinate} coordinate Coordinate.
  67605. * @param {number} resolution Resolution.
  67606. * @param {function(this: T, *)} callback Callback.
  67607. * @param {T=} opt_this The object to use as `this` in the callback.
  67608. * @param {boolean=} opt_request If `true` the callback is always async.
  67609. * The tile data is requested if not yet loaded.
  67610. * @template T
  67611. * @api
  67612. */
  67613. ol.source.TileUTFGrid.prototype.forDataAtCoordinateAndResolution = function(
  67614. coordinate, resolution, callback, opt_this, opt_request) {
  67615. if (this.tileGrid) {
  67616. var tileCoord = this.tileGrid.getTileCoordForCoordAndResolution(
  67617. coordinate, resolution);
  67618. var tile = /** @type {!ol.source.TileUTFGrid.Tile_} */(this.getTile(
  67619. tileCoord[0], tileCoord[1], tileCoord[2], 1, this.getProjection()));
  67620. tile.forDataAtCoordinate(coordinate, callback, opt_this, opt_request);
  67621. } else {
  67622. if (opt_request === true) {
  67623. setTimeout(function() {
  67624. callback.call(opt_this, null);
  67625. }, 0);
  67626. } else {
  67627. callback.call(opt_this, null);
  67628. }
  67629. }
  67630. };
  67631. /**
  67632. * @protected
  67633. */
  67634. ol.source.TileUTFGrid.prototype.handleTileJSONError = function() {
  67635. this.setState(ol.source.State.ERROR);
  67636. };
  67637. /**
  67638. * TODO: very similar to ol.source.TileJSON#handleTileJSONResponse
  67639. * @protected
  67640. * @param {TileJSON} tileJSON Tile JSON.
  67641. */
  67642. ol.source.TileUTFGrid.prototype.handleTileJSONResponse = function(tileJSON) {
  67643. var epsg4326Projection = ol.proj.get('EPSG:4326');
  67644. var sourceProjection = this.getProjection();
  67645. var extent;
  67646. if (tileJSON.bounds !== undefined) {
  67647. var transform = ol.proj.getTransformFromProjections(
  67648. epsg4326Projection, sourceProjection);
  67649. extent = ol.extent.applyTransform(tileJSON.bounds, transform);
  67650. }
  67651. var minZoom = tileJSON.minzoom || 0;
  67652. var maxZoom = tileJSON.maxzoom || 22;
  67653. var tileGrid = ol.tilegrid.createXYZ({
  67654. extent: ol.tilegrid.extentFromProjection(sourceProjection),
  67655. maxZoom: maxZoom,
  67656. minZoom: minZoom
  67657. });
  67658. this.tileGrid = tileGrid;
  67659. this.template_ = tileJSON.template;
  67660. var grids = tileJSON.grids;
  67661. if (!grids) {
  67662. this.setState(ol.source.State.ERROR);
  67663. return;
  67664. }
  67665. this.tileUrlFunction_ =
  67666. ol.TileUrlFunction.createFromTemplates(grids, tileGrid);
  67667. if (tileJSON.attribution !== undefined) {
  67668. var attributionExtent = extent !== undefined ?
  67669. extent : epsg4326Projection.getExtent();
  67670. /** @type {Object.<string, Array.<ol.TileRange>>} */
  67671. var tileRanges = {};
  67672. var z, zKey;
  67673. for (z = minZoom; z <= maxZoom; ++z) {
  67674. zKey = z.toString();
  67675. tileRanges[zKey] =
  67676. [tileGrid.getTileRangeForExtentAndZ(attributionExtent, z)];
  67677. }
  67678. this.setAttributions([
  67679. new ol.Attribution({
  67680. html: tileJSON.attribution,
  67681. tileRanges: tileRanges
  67682. })
  67683. ]);
  67684. }
  67685. this.setState(ol.source.State.READY);
  67686. };
  67687. /**
  67688. * @inheritDoc
  67689. */
  67690. ol.source.TileUTFGrid.prototype.getTile = function(z, x, y, pixelRatio, projection) {
  67691. var tileCoordKey = this.getKeyZXY(z, x, y);
  67692. if (this.tileCache.containsKey(tileCoordKey)) {
  67693. return /** @type {!ol.Tile} */ (this.tileCache.get(tileCoordKey));
  67694. } else {
  67695. var tileCoord = [z, x, y];
  67696. var urlTileCoord =
  67697. this.getTileCoordForTileUrlFunction(tileCoord, projection);
  67698. var tileUrl = this.tileUrlFunction_(urlTileCoord, pixelRatio, projection);
  67699. var tile = new ol.source.TileUTFGrid.Tile_(
  67700. tileCoord,
  67701. tileUrl !== undefined ? ol.TileState.IDLE : ol.TileState.EMPTY,
  67702. tileUrl !== undefined ? tileUrl : '',
  67703. this.tileGrid.getTileCoordExtent(tileCoord),
  67704. this.preemptive_,
  67705. this.jsonp_);
  67706. this.tileCache.set(tileCoordKey, tile);
  67707. return tile;
  67708. }
  67709. };
  67710. /**
  67711. * @inheritDoc
  67712. */
  67713. ol.source.TileUTFGrid.prototype.useTile = function(z, x, y) {
  67714. var tileCoordKey = this.getKeyZXY(z, x, y);
  67715. if (this.tileCache.containsKey(tileCoordKey)) {
  67716. this.tileCache.get(tileCoordKey);
  67717. }
  67718. };
  67719. /**
  67720. * @constructor
  67721. * @extends {ol.Tile}
  67722. * @param {ol.TileCoord} tileCoord Tile coordinate.
  67723. * @param {ol.TileState} state State.
  67724. * @param {string} src Image source URI.
  67725. * @param {ol.Extent} extent Extent of the tile.
  67726. * @param {boolean} preemptive Load the tile when visible (before it's needed).
  67727. * @param {boolean} jsonp Load the tile as a script.
  67728. * @private
  67729. */
  67730. ol.source.TileUTFGrid.Tile_ = function(tileCoord, state, src, extent, preemptive, jsonp) {
  67731. ol.Tile.call(this, tileCoord, state);
  67732. /**
  67733. * @private
  67734. * @type {string}
  67735. */
  67736. this.src_ = src;
  67737. /**
  67738. * @private
  67739. * @type {ol.Extent}
  67740. */
  67741. this.extent_ = extent;
  67742. /**
  67743. * @private
  67744. * @type {boolean}
  67745. */
  67746. this.preemptive_ = preemptive;
  67747. /**
  67748. * @private
  67749. * @type {Array.<string>}
  67750. */
  67751. this.grid_ = null;
  67752. /**
  67753. * @private
  67754. * @type {Array.<string>}
  67755. */
  67756. this.keys_ = null;
  67757. /**
  67758. * @private
  67759. * @type {Object.<string, Object>|undefined}
  67760. */
  67761. this.data_ = null;
  67762. /**
  67763. * @private
  67764. * @type {boolean}
  67765. */
  67766. this.jsonp_ = jsonp;
  67767. };
  67768. ol.inherits(ol.source.TileUTFGrid.Tile_, ol.Tile);
  67769. /**
  67770. * Get the image element for this tile.
  67771. * @return {Image} Image.
  67772. */
  67773. ol.source.TileUTFGrid.Tile_.prototype.getImage = function() {
  67774. return null;
  67775. };
  67776. /**
  67777. * Synchronously returns data at given coordinate (if available).
  67778. * @param {ol.Coordinate} coordinate Coordinate.
  67779. * @return {*} The data.
  67780. */
  67781. ol.source.TileUTFGrid.Tile_.prototype.getData = function(coordinate) {
  67782. if (!this.grid_ || !this.keys_) {
  67783. return null;
  67784. }
  67785. var xRelative = (coordinate[0] - this.extent_[0]) /
  67786. (this.extent_[2] - this.extent_[0]);
  67787. var yRelative = (coordinate[1] - this.extent_[1]) /
  67788. (this.extent_[3] - this.extent_[1]);
  67789. var row = this.grid_[Math.floor((1 - yRelative) * this.grid_.length)];
  67790. if (typeof row !== 'string') {
  67791. return null;
  67792. }
  67793. var code = row.charCodeAt(Math.floor(xRelative * row.length));
  67794. if (code >= 93) {
  67795. code--;
  67796. }
  67797. if (code >= 35) {
  67798. code--;
  67799. }
  67800. code -= 32;
  67801. var data = null;
  67802. if (code in this.keys_) {
  67803. var id = this.keys_[code];
  67804. if (this.data_ && id in this.data_) {
  67805. data = this.data_[id];
  67806. } else {
  67807. data = id;
  67808. }
  67809. }
  67810. return data;
  67811. };
  67812. /**
  67813. * Calls the callback (synchronously by default) with the available data
  67814. * for given coordinate (or `null` if not yet loaded).
  67815. * @param {ol.Coordinate} coordinate Coordinate.
  67816. * @param {function(this: T, *)} callback Callback.
  67817. * @param {T=} opt_this The object to use as `this` in the callback.
  67818. * @param {boolean=} opt_request If `true` the callback is always async.
  67819. * The tile data is requested if not yet loaded.
  67820. * @template T
  67821. */
  67822. ol.source.TileUTFGrid.Tile_.prototype.forDataAtCoordinate = function(coordinate, callback, opt_this, opt_request) {
  67823. if (this.state == ol.TileState.IDLE && opt_request === true) {
  67824. ol.events.listenOnce(this, ol.events.EventType.CHANGE, function(e) {
  67825. callback.call(opt_this, this.getData(coordinate));
  67826. }, this);
  67827. this.loadInternal_();
  67828. } else {
  67829. if (opt_request === true) {
  67830. setTimeout(function() {
  67831. callback.call(opt_this, this.getData(coordinate));
  67832. }.bind(this), 0);
  67833. } else {
  67834. callback.call(opt_this, this.getData(coordinate));
  67835. }
  67836. }
  67837. };
  67838. /**
  67839. * @inheritDoc
  67840. */
  67841. ol.source.TileUTFGrid.Tile_.prototype.getKey = function() {
  67842. return this.src_;
  67843. };
  67844. /**
  67845. * @private
  67846. */
  67847. ol.source.TileUTFGrid.Tile_.prototype.handleError_ = function() {
  67848. this.state = ol.TileState.ERROR;
  67849. this.changed();
  67850. };
  67851. /**
  67852. * @param {!UTFGridJSON} json UTFGrid data.
  67853. * @private
  67854. */
  67855. ol.source.TileUTFGrid.Tile_.prototype.handleLoad_ = function(json) {
  67856. this.grid_ = json.grid;
  67857. this.keys_ = json.keys;
  67858. this.data_ = json.data;
  67859. this.state = ol.TileState.EMPTY;
  67860. this.changed();
  67861. };
  67862. /**
  67863. * @private
  67864. */
  67865. ol.source.TileUTFGrid.Tile_.prototype.loadInternal_ = function() {
  67866. if (this.state == ol.TileState.IDLE) {
  67867. this.state = ol.TileState.LOADING;
  67868. if (this.jsonp_) {
  67869. ol.net.jsonp(this.src_, this.handleLoad_.bind(this),
  67870. this.handleError_.bind(this));
  67871. } else {
  67872. var client = new XMLHttpRequest();
  67873. client.addEventListener('load', this.onXHRLoad_.bind(this));
  67874. client.addEventListener('error', this.onXHRError_.bind(this));
  67875. client.open('GET', this.src_);
  67876. client.send();
  67877. }
  67878. }
  67879. };
  67880. /**
  67881. * @private
  67882. * @param {Event} event The load event.
  67883. */
  67884. ol.source.TileUTFGrid.Tile_.prototype.onXHRLoad_ = function(event) {
  67885. var client = /** @type {XMLHttpRequest} */ (event.target);
  67886. // status will be 0 for file:// urls
  67887. if (!client.status || client.status >= 200 && client.status < 300) {
  67888. var response;
  67889. try {
  67890. response = /** @type {!UTFGridJSON} */(JSON.parse(client.responseText));
  67891. } catch (err) {
  67892. this.handleError_();
  67893. return;
  67894. }
  67895. this.handleLoad_(response);
  67896. } else {
  67897. this.handleError_();
  67898. }
  67899. };
  67900. /**
  67901. * @private
  67902. * @param {Event} event The error event.
  67903. */
  67904. ol.source.TileUTFGrid.Tile_.prototype.onXHRError_ = function(event) {
  67905. this.handleError_();
  67906. };
  67907. /**
  67908. * @override
  67909. */
  67910. ol.source.TileUTFGrid.Tile_.prototype.load = function() {
  67911. if (this.preemptive_) {
  67912. this.loadInternal_();
  67913. }
  67914. };
  67915. // FIXME add minZoom support
  67916. // FIXME add date line wrap (tile coord transform)
  67917. // FIXME cannot be shared between maps with different projections
  67918. goog.provide('ol.source.TileWMS');
  67919. goog.require('ol');
  67920. goog.require('ol.asserts');
  67921. goog.require('ol.extent');
  67922. goog.require('ol.obj');
  67923. goog.require('ol.math');
  67924. goog.require('ol.proj');
  67925. goog.require('ol.size');
  67926. goog.require('ol.source.TileImage');
  67927. goog.require('ol.source.WMSServerType');
  67928. goog.require('ol.tilecoord');
  67929. goog.require('ol.string');
  67930. goog.require('ol.uri');
  67931. /**
  67932. * @classdesc
  67933. * Layer source for tile data from WMS servers.
  67934. *
  67935. * @constructor
  67936. * @extends {ol.source.TileImage}
  67937. * @param {olx.source.TileWMSOptions=} opt_options Tile WMS options.
  67938. * @api
  67939. */
  67940. ol.source.TileWMS = function(opt_options) {
  67941. var options = opt_options || {};
  67942. var params = options.params || {};
  67943. var transparent = 'TRANSPARENT' in params ? params['TRANSPARENT'] : true;
  67944. ol.source.TileImage.call(this, {
  67945. attributions: options.attributions,
  67946. cacheSize: options.cacheSize,
  67947. crossOrigin: options.crossOrigin,
  67948. logo: options.logo,
  67949. opaque: !transparent,
  67950. projection: options.projection,
  67951. reprojectionErrorThreshold: options.reprojectionErrorThreshold,
  67952. tileClass: options.tileClass,
  67953. tileGrid: options.tileGrid,
  67954. tileLoadFunction: options.tileLoadFunction,
  67955. url: options.url,
  67956. urls: options.urls,
  67957. wrapX: options.wrapX !== undefined ? options.wrapX : true
  67958. });
  67959. /**
  67960. * @private
  67961. * @type {number}
  67962. */
  67963. this.gutter_ = options.gutter !== undefined ? options.gutter : 0;
  67964. /**
  67965. * @private
  67966. * @type {!Object}
  67967. */
  67968. this.params_ = params;
  67969. /**
  67970. * @private
  67971. * @type {boolean}
  67972. */
  67973. this.v13_ = true;
  67974. /**
  67975. * @private
  67976. * @type {ol.source.WMSServerType|undefined}
  67977. */
  67978. this.serverType_ = /** @type {ol.source.WMSServerType|undefined} */ (options.serverType);
  67979. /**
  67980. * @private
  67981. * @type {boolean}
  67982. */
  67983. this.hidpi_ = options.hidpi !== undefined ? options.hidpi : true;
  67984. /**
  67985. * @private
  67986. * @type {string}
  67987. */
  67988. this.coordKeyPrefix_ = '';
  67989. this.resetCoordKeyPrefix_();
  67990. /**
  67991. * @private
  67992. * @type {ol.Extent}
  67993. */
  67994. this.tmpExtent_ = ol.extent.createEmpty();
  67995. this.updateV13_();
  67996. this.setKey(this.getKeyForParams_());
  67997. };
  67998. ol.inherits(ol.source.TileWMS, ol.source.TileImage);
  67999. /**
  68000. * Return the GetFeatureInfo URL for the passed coordinate, resolution, and
  68001. * projection. Return `undefined` if the GetFeatureInfo URL cannot be
  68002. * constructed.
  68003. * @param {ol.Coordinate} coordinate Coordinate.
  68004. * @param {number} resolution Resolution.
  68005. * @param {ol.ProjectionLike} projection Projection.
  68006. * @param {!Object} params GetFeatureInfo params. `INFO_FORMAT` at least should
  68007. * be provided. If `QUERY_LAYERS` is not provided then the layers specified
  68008. * in the `LAYERS` parameter will be used. `VERSION` should not be
  68009. * specified here.
  68010. * @return {string|undefined} GetFeatureInfo URL.
  68011. * @api
  68012. */
  68013. ol.source.TileWMS.prototype.getGetFeatureInfoUrl = function(coordinate, resolution, projection, params) {
  68014. var projectionObj = ol.proj.get(projection);
  68015. var tileGrid = this.getTileGrid();
  68016. if (!tileGrid) {
  68017. tileGrid = this.getTileGridForProjection(projectionObj);
  68018. }
  68019. var tileCoord = tileGrid.getTileCoordForCoordAndResolution(
  68020. coordinate, resolution);
  68021. if (tileGrid.getResolutions().length <= tileCoord[0]) {
  68022. return undefined;
  68023. }
  68024. var tileResolution = tileGrid.getResolution(tileCoord[0]);
  68025. var tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent_);
  68026. var tileSize = ol.size.toSize(
  68027. tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
  68028. var gutter = this.gutter_;
  68029. if (gutter !== 0) {
  68030. tileSize = ol.size.buffer(tileSize, gutter, this.tmpSize);
  68031. tileExtent = ol.extent.buffer(tileExtent,
  68032. tileResolution * gutter, tileExtent);
  68033. }
  68034. var baseParams = {
  68035. 'SERVICE': 'WMS',
  68036. 'VERSION': ol.DEFAULT_WMS_VERSION,
  68037. 'REQUEST': 'GetFeatureInfo',
  68038. 'FORMAT': 'image/png',
  68039. 'TRANSPARENT': true,
  68040. 'QUERY_LAYERS': this.params_['LAYERS']
  68041. };
  68042. ol.obj.assign(baseParams, this.params_, params);
  68043. var x = Math.floor((coordinate[0] - tileExtent[0]) / tileResolution);
  68044. var y = Math.floor((tileExtent[3] - coordinate[1]) / tileResolution);
  68045. baseParams[this.v13_ ? 'I' : 'X'] = x;
  68046. baseParams[this.v13_ ? 'J' : 'Y'] = y;
  68047. return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
  68048. 1, projectionObj, baseParams);
  68049. };
  68050. /**
  68051. * @inheritDoc
  68052. */
  68053. ol.source.TileWMS.prototype.getGutterInternal = function() {
  68054. return this.gutter_;
  68055. };
  68056. /**
  68057. * @inheritDoc
  68058. */
  68059. ol.source.TileWMS.prototype.getKeyZXY = function(z, x, y) {
  68060. return this.coordKeyPrefix_ + ol.source.TileImage.prototype.getKeyZXY.call(this, z, x, y);
  68061. };
  68062. /**
  68063. * Get the user-provided params, i.e. those passed to the constructor through
  68064. * the "params" option, and possibly updated using the updateParams method.
  68065. * @return {Object} Params.
  68066. * @api
  68067. */
  68068. ol.source.TileWMS.prototype.getParams = function() {
  68069. return this.params_;
  68070. };
  68071. /**
  68072. * @param {ol.TileCoord} tileCoord Tile coordinate.
  68073. * @param {ol.Size} tileSize Tile size.
  68074. * @param {ol.Extent} tileExtent Tile extent.
  68075. * @param {number} pixelRatio Pixel ratio.
  68076. * @param {ol.proj.Projection} projection Projection.
  68077. * @param {Object} params Params.
  68078. * @return {string|undefined} Request URL.
  68079. * @private
  68080. */
  68081. ol.source.TileWMS.prototype.getRequestUrl_ = function(tileCoord, tileSize, tileExtent,
  68082. pixelRatio, projection, params) {
  68083. var urls = this.urls;
  68084. if (!urls) {
  68085. return undefined;
  68086. }
  68087. params['WIDTH'] = tileSize[0];
  68088. params['HEIGHT'] = tileSize[1];
  68089. params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode();
  68090. if (!('STYLES' in this.params_)) {
  68091. params['STYLES'] = '';
  68092. }
  68093. if (pixelRatio != 1) {
  68094. switch (this.serverType_) {
  68095. case ol.source.WMSServerType.GEOSERVER:
  68096. var dpi = (90 * pixelRatio + 0.5) | 0;
  68097. if ('FORMAT_OPTIONS' in params) {
  68098. params['FORMAT_OPTIONS'] += ';dpi:' + dpi;
  68099. } else {
  68100. params['FORMAT_OPTIONS'] = 'dpi:' + dpi;
  68101. }
  68102. break;
  68103. case ol.source.WMSServerType.MAPSERVER:
  68104. params['MAP_RESOLUTION'] = 90 * pixelRatio;
  68105. break;
  68106. case ol.source.WMSServerType.CARMENTA_SERVER:
  68107. case ol.source.WMSServerType.QGIS:
  68108. params['DPI'] = 90 * pixelRatio;
  68109. break;
  68110. default:
  68111. ol.asserts.assert(false, 52); // Unknown `serverType` configured
  68112. break;
  68113. }
  68114. }
  68115. var axisOrientation = projection.getAxisOrientation();
  68116. var bbox = tileExtent;
  68117. if (this.v13_ && axisOrientation.substr(0, 2) == 'ne') {
  68118. var tmp;
  68119. tmp = tileExtent[0];
  68120. bbox[0] = tileExtent[1];
  68121. bbox[1] = tmp;
  68122. tmp = tileExtent[2];
  68123. bbox[2] = tileExtent[3];
  68124. bbox[3] = tmp;
  68125. }
  68126. params['BBOX'] = bbox.join(',');
  68127. var url;
  68128. if (urls.length == 1) {
  68129. url = urls[0];
  68130. } else {
  68131. var index = ol.math.modulo(ol.tilecoord.hash(tileCoord), urls.length);
  68132. url = urls[index];
  68133. }
  68134. return ol.uri.appendParams(url, params);
  68135. };
  68136. /**
  68137. * @inheritDoc
  68138. */
  68139. ol.source.TileWMS.prototype.getTilePixelRatio = function(pixelRatio) {
  68140. return (!this.hidpi_ || this.serverType_ === undefined) ? 1 :
  68141. /** @type {number} */ (pixelRatio);
  68142. };
  68143. /**
  68144. * @private
  68145. */
  68146. ol.source.TileWMS.prototype.resetCoordKeyPrefix_ = function() {
  68147. var i = 0;
  68148. var res = [];
  68149. if (this.urls) {
  68150. var j, jj;
  68151. for (j = 0, jj = this.urls.length; j < jj; ++j) {
  68152. res[i++] = this.urls[j];
  68153. }
  68154. }
  68155. this.coordKeyPrefix_ = res.join('#');
  68156. };
  68157. /**
  68158. * @private
  68159. * @return {string} The key for the current params.
  68160. */
  68161. ol.source.TileWMS.prototype.getKeyForParams_ = function() {
  68162. var i = 0;
  68163. var res = [];
  68164. for (var key in this.params_) {
  68165. res[i++] = key + '-' + this.params_[key];
  68166. }
  68167. return res.join('/');
  68168. };
  68169. /**
  68170. * @inheritDoc
  68171. */
  68172. ol.source.TileWMS.prototype.fixedTileUrlFunction = function(tileCoord, pixelRatio, projection) {
  68173. var tileGrid = this.getTileGrid();
  68174. if (!tileGrid) {
  68175. tileGrid = this.getTileGridForProjection(projection);
  68176. }
  68177. if (tileGrid.getResolutions().length <= tileCoord[0]) {
  68178. return undefined;
  68179. }
  68180. if (pixelRatio != 1 && (!this.hidpi_ || this.serverType_ === undefined)) {
  68181. pixelRatio = 1;
  68182. }
  68183. var tileResolution = tileGrid.getResolution(tileCoord[0]);
  68184. var tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent_);
  68185. var tileSize = ol.size.toSize(
  68186. tileGrid.getTileSize(tileCoord[0]), this.tmpSize);
  68187. var gutter = this.gutter_;
  68188. if (gutter !== 0) {
  68189. tileSize = ol.size.buffer(tileSize, gutter, this.tmpSize);
  68190. tileExtent = ol.extent.buffer(tileExtent,
  68191. tileResolution * gutter, tileExtent);
  68192. }
  68193. if (pixelRatio != 1) {
  68194. tileSize = ol.size.scale(tileSize, pixelRatio, this.tmpSize);
  68195. }
  68196. var baseParams = {
  68197. 'SERVICE': 'WMS',
  68198. 'VERSION': ol.DEFAULT_WMS_VERSION,
  68199. 'REQUEST': 'GetMap',
  68200. 'FORMAT': 'image/png',
  68201. 'TRANSPARENT': true
  68202. };
  68203. ol.obj.assign(baseParams, this.params_);
  68204. return this.getRequestUrl_(tileCoord, tileSize, tileExtent,
  68205. pixelRatio, projection, baseParams);
  68206. };
  68207. /**
  68208. * @inheritDoc
  68209. */
  68210. ol.source.TileWMS.prototype.setUrls = function(urls) {
  68211. ol.source.TileImage.prototype.setUrls.call(this, urls);
  68212. this.resetCoordKeyPrefix_();
  68213. };
  68214. /**
  68215. * Update the user-provided params.
  68216. * @param {Object} params Params.
  68217. * @api
  68218. */
  68219. ol.source.TileWMS.prototype.updateParams = function(params) {
  68220. ol.obj.assign(this.params_, params);
  68221. this.resetCoordKeyPrefix_();
  68222. this.updateV13_();
  68223. this.setKey(this.getKeyForParams_());
  68224. };
  68225. /**
  68226. * @private
  68227. */
  68228. ol.source.TileWMS.prototype.updateV13_ = function() {
  68229. var version = this.params_['VERSION'] || ol.DEFAULT_WMS_VERSION;
  68230. this.v13_ = ol.string.compareVersions(version, '1.3') >= 0;
  68231. };
  68232. goog.provide('ol.VectorImageTile');
  68233. goog.require('ol');
  68234. goog.require('ol.Tile');
  68235. goog.require('ol.TileState');
  68236. goog.require('ol.array');
  68237. goog.require('ol.dom');
  68238. goog.require('ol.events');
  68239. goog.require('ol.extent');
  68240. goog.require('ol.events.EventType');
  68241. goog.require('ol.featureloader');
  68242. /**
  68243. * @constructor
  68244. * @extends {ol.Tile}
  68245. * @param {ol.TileCoord} tileCoord Tile coordinate.
  68246. * @param {ol.TileState} state State.
  68247. * @param {string} src Data source url.
  68248. * @param {ol.format.Feature} format Feature format.
  68249. * @param {ol.TileLoadFunctionType} tileLoadFunction Tile load function.
  68250. * @param {ol.TileCoord} urlTileCoord Wrapped tile coordinate for source urls.
  68251. * @param {ol.TileUrlFunctionType} tileUrlFunction Tile url function.
  68252. * @param {ol.tilegrid.TileGrid} sourceTileGrid Tile grid of the source.
  68253. * @param {ol.tilegrid.TileGrid} tileGrid Tile grid of the renderer.
  68254. * @param {Object.<string,ol.VectorTile>} sourceTiles Source tiles.
  68255. * @param {number} pixelRatio Pixel ratio.
  68256. * @param {ol.proj.Projection} projection Projection.
  68257. * @param {function(new: ol.VectorTile, ol.TileCoord, ol.TileState, string,
  68258. * ol.format.Feature, ol.TileLoadFunctionType)} tileClass Class to
  68259. * instantiate for source tiles.
  68260. * @param {function(this: ol.source.VectorTile, ol.events.Event)} handleTileChange
  68261. * Function to call when a source tile's state changes.
  68262. */
  68263. ol.VectorImageTile = function(tileCoord, state, src, format, tileLoadFunction,
  68264. urlTileCoord, tileUrlFunction, sourceTileGrid, tileGrid, sourceTiles,
  68265. pixelRatio, projection, tileClass, handleTileChange) {
  68266. ol.Tile.call(this, tileCoord, state);
  68267. /**
  68268. * @private
  68269. * @type {Object.<string, CanvasRenderingContext2D>}
  68270. */
  68271. this.context_ = {};
  68272. /**
  68273. * @private
  68274. * @type {ol.FeatureLoader}
  68275. */
  68276. this.loader_;
  68277. /**
  68278. * @private
  68279. * @type {Object.<string, ol.TileReplayState>}
  68280. */
  68281. this.replayState_ = {};
  68282. /**
  68283. * @private
  68284. * @type {Object.<string,ol.VectorTile>}
  68285. */
  68286. this.sourceTiles_ = sourceTiles;
  68287. /**
  68288. * Keys of source tiles used by this tile. Use with {@link #getTile}.
  68289. * @type {Array.<string>}
  68290. */
  68291. this.tileKeys = [];
  68292. /**
  68293. * @type {string}
  68294. */
  68295. this.src_ = src;
  68296. /**
  68297. * @type {ol.TileCoord}
  68298. */
  68299. this.wrappedTileCoord = urlTileCoord;
  68300. /**
  68301. * @type {Array.<ol.EventsKey>}
  68302. */
  68303. this.loadListenerKeys_ = [];
  68304. /**
  68305. * @type {Array.<ol.EventsKey>}
  68306. */
  68307. this.sourceTileListenerKeys_ = [];
  68308. if (urlTileCoord) {
  68309. var extent = tileGrid.getTileCoordExtent(urlTileCoord);
  68310. var resolution = tileGrid.getResolution(tileCoord[0]);
  68311. var sourceZ = sourceTileGrid.getZForResolution(resolution);
  68312. sourceTileGrid.forEachTileCoord(extent, sourceZ, function(sourceTileCoord) {
  68313. var sharedExtent = ol.extent.getIntersection(extent,
  68314. sourceTileGrid.getTileCoordExtent(sourceTileCoord));
  68315. if (ol.extent.getWidth(sharedExtent) / resolution >= 0.5 &&
  68316. ol.extent.getHeight(sharedExtent) / resolution >= 0.5) {
  68317. // only include source tile if overlap is at least 1 pixel
  68318. var sourceTileKey = sourceTileCoord.toString();
  68319. var sourceTile = sourceTiles[sourceTileKey];
  68320. if (!sourceTile) {
  68321. var tileUrl = tileUrlFunction(sourceTileCoord, pixelRatio, projection);
  68322. sourceTile = sourceTiles[sourceTileKey] = new tileClass(sourceTileCoord,
  68323. tileUrl == undefined ? ol.TileState.EMPTY : ol.TileState.IDLE,
  68324. tileUrl == undefined ? '' : tileUrl,
  68325. format, tileLoadFunction);
  68326. this.sourceTileListenerKeys_.push(
  68327. ol.events.listen(sourceTile, ol.events.EventType.CHANGE, handleTileChange));
  68328. }
  68329. sourceTile.consumers++;
  68330. this.tileKeys.push(sourceTileKey);
  68331. }
  68332. }.bind(this));
  68333. }
  68334. };
  68335. ol.inherits(ol.VectorImageTile, ol.Tile);
  68336. /**
  68337. * @inheritDoc
  68338. */
  68339. ol.VectorImageTile.prototype.disposeInternal = function() {
  68340. for (var i = 0, ii = this.tileKeys.length; i < ii; ++i) {
  68341. var sourceTileKey = this.tileKeys[i];
  68342. var sourceTile = this.getTile(sourceTileKey);
  68343. sourceTile.consumers--;
  68344. if (sourceTile.consumers == 0) {
  68345. delete this.sourceTiles_[sourceTileKey];
  68346. sourceTile.dispose();
  68347. }
  68348. }
  68349. this.tileKeys.length = 0;
  68350. this.sourceTiles_ = null;
  68351. if (this.state == ol.TileState.LOADING) {
  68352. this.loadListenerKeys_.forEach(ol.events.unlistenByKey);
  68353. this.loadListenerKeys_.length = 0;
  68354. }
  68355. if (this.interimTile) {
  68356. this.interimTile.dispose();
  68357. }
  68358. this.state = ol.TileState.ABORT;
  68359. this.changed();
  68360. this.sourceTileListenerKeys_.forEach(ol.events.unlistenByKey);
  68361. this.sourceTileListenerKeys_.length = 0;
  68362. ol.Tile.prototype.disposeInternal.call(this);
  68363. };
  68364. /**
  68365. * @param {ol.layer.Layer} layer Layer.
  68366. * @return {CanvasRenderingContext2D} The rendering context.
  68367. */
  68368. ol.VectorImageTile.prototype.getContext = function(layer) {
  68369. var key = ol.getUid(layer).toString();
  68370. if (!(key in this.context_)) {
  68371. this.context_[key] = ol.dom.createCanvasContext2D();
  68372. }
  68373. return this.context_[key];
  68374. };
  68375. /**
  68376. * Get the Canvas for this tile.
  68377. * @param {ol.layer.Layer} layer Layer.
  68378. * @return {HTMLCanvasElement} Canvas.
  68379. */
  68380. ol.VectorImageTile.prototype.getImage = function(layer) {
  68381. return this.getReplayState(layer).renderedTileRevision == -1 ?
  68382. null : this.getContext(layer).canvas;
  68383. };
  68384. /**
  68385. * @param {ol.layer.Layer} layer Layer.
  68386. * @return {ol.TileReplayState} The replay state.
  68387. */
  68388. ol.VectorImageTile.prototype.getReplayState = function(layer) {
  68389. var key = ol.getUid(layer).toString();
  68390. if (!(key in this.replayState_)) {
  68391. this.replayState_[key] = {
  68392. dirty: false,
  68393. renderedRenderOrder: null,
  68394. renderedRevision: -1,
  68395. renderedTileRevision: -1
  68396. };
  68397. }
  68398. return this.replayState_[key];
  68399. };
  68400. /**
  68401. * @inheritDoc
  68402. */
  68403. ol.VectorImageTile.prototype.getKey = function() {
  68404. return this.tileKeys.join('/') + '/' + this.src_;
  68405. };
  68406. /**
  68407. * @param {string} tileKey Key (tileCoord) of the source tile.
  68408. * @return {ol.VectorTile} Source tile.
  68409. */
  68410. ol.VectorImageTile.prototype.getTile = function(tileKey) {
  68411. return this.sourceTiles_[tileKey];
  68412. };
  68413. /**
  68414. * @inheritDoc
  68415. */
  68416. ol.VectorImageTile.prototype.load = function() {
  68417. var leftToLoad = 0;
  68418. if (this.state == ol.TileState.IDLE) {
  68419. this.setState(ol.TileState.LOADING);
  68420. }
  68421. if (this.state == ol.TileState.LOADING) {
  68422. this.tileKeys.forEach(function(sourceTileKey) {
  68423. var sourceTile = this.getTile(sourceTileKey);
  68424. if (sourceTile.state == ol.TileState.IDLE) {
  68425. sourceTile.setLoader(this.loader_);
  68426. sourceTile.load();
  68427. }
  68428. if (sourceTile.state == ol.TileState.LOADING) {
  68429. var key = ol.events.listen(sourceTile, ol.events.EventType.CHANGE, function(e) {
  68430. var state = sourceTile.getState();
  68431. if (state == ol.TileState.LOADED ||
  68432. state == ol.TileState.ERROR) {
  68433. --leftToLoad;
  68434. ol.events.unlistenByKey(key);
  68435. ol.array.remove(this.loadListenerKeys_, key);
  68436. if (leftToLoad == 0) {
  68437. this.finishLoading_();
  68438. }
  68439. }
  68440. }.bind(this));
  68441. this.loadListenerKeys_.push(key);
  68442. ++leftToLoad;
  68443. }
  68444. }.bind(this));
  68445. }
  68446. if (leftToLoad == 0) {
  68447. setTimeout(this.finishLoading_.bind(this), 0);
  68448. }
  68449. };
  68450. /**
  68451. * @private
  68452. */
  68453. ol.VectorImageTile.prototype.finishLoading_ = function() {
  68454. var errors = false;
  68455. var loaded = this.tileKeys.length;
  68456. var state;
  68457. for (var i = loaded - 1; i >= 0; --i) {
  68458. state = this.getTile(this.tileKeys[i]).getState();
  68459. if (state != ol.TileState.LOADED) {
  68460. if (state == ol.TileState.ERROR) {
  68461. errors = true;
  68462. }
  68463. --loaded;
  68464. }
  68465. }
  68466. this.setState(loaded > 0 ?
  68467. ol.TileState.LOADED :
  68468. (errors ? ol.TileState.ERROR : ol.TileState.EMPTY));
  68469. };
  68470. /**
  68471. * Sets the loader for a tile.
  68472. * @param {ol.VectorTile} tile Vector tile.
  68473. * @param {string} url URL.
  68474. */
  68475. ol.VectorImageTile.defaultLoadFunction = function(tile, url) {
  68476. var loader = ol.featureloader.loadFeaturesXhr(
  68477. url, tile.getFormat(), tile.onLoad.bind(tile), tile.onError.bind(tile));
  68478. tile.setLoader(loader);
  68479. };
  68480. goog.provide('ol.VectorTile');
  68481. goog.require('ol');
  68482. goog.require('ol.Tile');
  68483. goog.require('ol.TileState');
  68484. /**
  68485. * @constructor
  68486. * @extends {ol.Tile}
  68487. * @param {ol.TileCoord} tileCoord Tile coordinate.
  68488. * @param {ol.TileState} state State.
  68489. * @param {string} src Data source url.
  68490. * @param {ol.format.Feature} format Feature format.
  68491. * @param {ol.TileLoadFunctionType} tileLoadFunction Tile load function.
  68492. */
  68493. ol.VectorTile = function(tileCoord, state, src, format, tileLoadFunction) {
  68494. ol.Tile.call(this, tileCoord, state);
  68495. /**
  68496. * @type {number}
  68497. */
  68498. this.consumers = 0;
  68499. /**
  68500. * @private
  68501. * @type {ol.Extent}
  68502. */
  68503. this.extent_ = null;
  68504. /**
  68505. * @private
  68506. * @type {ol.format.Feature}
  68507. */
  68508. this.format_ = format;
  68509. /**
  68510. * @private
  68511. * @type {Array.<ol.Feature>}
  68512. */
  68513. this.features_ = null;
  68514. /**
  68515. * @private
  68516. * @type {ol.FeatureLoader}
  68517. */
  68518. this.loader_;
  68519. /**
  68520. * Data projection
  68521. * @private
  68522. * @type {ol.proj.Projection}
  68523. */
  68524. this.projection_;
  68525. /**
  68526. * @private
  68527. * @type {Object.<string, ol.render.ReplayGroup>}
  68528. */
  68529. this.replayGroups_ = {};
  68530. /**
  68531. * @private
  68532. * @type {ol.TileLoadFunctionType}
  68533. */
  68534. this.tileLoadFunction_ = tileLoadFunction;
  68535. /**
  68536. * @private
  68537. * @type {string}
  68538. */
  68539. this.url_ = src;
  68540. };
  68541. ol.inherits(ol.VectorTile, ol.Tile);
  68542. /**
  68543. * @inheritDoc
  68544. */
  68545. ol.VectorTile.prototype.disposeInternal = function() {
  68546. this.features_ = null;
  68547. this.replayGroups_ = {};
  68548. this.state = ol.TileState.ABORT;
  68549. this.changed();
  68550. ol.Tile.prototype.disposeInternal.call(this);
  68551. };
  68552. /**
  68553. * Gets the extent of the vector tile.
  68554. * @return {ol.Extent} The extent.
  68555. */
  68556. ol.VectorTile.prototype.getExtent = function() {
  68557. return this.extent_ || ol.VectorTile.DEFAULT_EXTENT;
  68558. };
  68559. /**
  68560. * Get the feature format assigned for reading this tile's features.
  68561. * @return {ol.format.Feature} Feature format.
  68562. * @api
  68563. */
  68564. ol.VectorTile.prototype.getFormat = function() {
  68565. return this.format_;
  68566. };
  68567. /**
  68568. * Get the features for this tile. Geometries will be in the projection returned
  68569. * by {@link ol.VectorTile#getProjection}.
  68570. * @return {Array.<ol.Feature|ol.render.Feature>} Features.
  68571. * @api
  68572. */
  68573. ol.VectorTile.prototype.getFeatures = function() {
  68574. return this.features_;
  68575. };
  68576. /**
  68577. * @inheritDoc
  68578. */
  68579. ol.VectorTile.prototype.getKey = function() {
  68580. return this.url_;
  68581. };
  68582. /**
  68583. * Get the feature projection of features returned by
  68584. * {@link ol.VectorTile#getFeatures}.
  68585. * @return {ol.proj.Projection} Feature projection.
  68586. * @api
  68587. */
  68588. ol.VectorTile.prototype.getProjection = function() {
  68589. return this.projection_;
  68590. };
  68591. /**
  68592. * @param {ol.layer.Layer} layer Layer.
  68593. * @param {string} key Key.
  68594. * @return {ol.render.ReplayGroup} Replay group.
  68595. */
  68596. ol.VectorTile.prototype.getReplayGroup = function(layer, key) {
  68597. return this.replayGroups_[ol.getUid(layer) + ',' + key];
  68598. };
  68599. /**
  68600. * @inheritDoc
  68601. */
  68602. ol.VectorTile.prototype.load = function() {
  68603. if (this.state == ol.TileState.IDLE) {
  68604. this.setState(ol.TileState.LOADING);
  68605. this.tileLoadFunction_(this, this.url_);
  68606. this.loader_(null, NaN, null);
  68607. }
  68608. };
  68609. /**
  68610. * Handler for successful tile load.
  68611. * @param {Array.<ol.Feature>} features The loaded features.
  68612. * @param {ol.proj.Projection} dataProjection Data projection.
  68613. * @param {ol.Extent} extent Extent.
  68614. */
  68615. ol.VectorTile.prototype.onLoad = function(features, dataProjection, extent) {
  68616. this.setProjection(dataProjection);
  68617. this.setFeatures(features);
  68618. this.setExtent(extent);
  68619. };
  68620. /**
  68621. * Handler for tile load errors.
  68622. */
  68623. ol.VectorTile.prototype.onError = function() {
  68624. this.setState(ol.TileState.ERROR);
  68625. };
  68626. /**
  68627. * Function for use in an {@link ol.source.VectorTile}'s `tileLoadFunction`.
  68628. * Sets the extent of the vector tile. This is only required for tiles in
  68629. * projections with `tile-pixels` as units. The extent should be set to
  68630. * `[0, 0, tilePixelSize, tilePixelSize]`, where `tilePixelSize` is calculated
  68631. * by multiplying the tile size with the tile pixel ratio. For sources using
  68632. * {@link ol.format.MVT} as feature format, the
  68633. * {@link ol.format.MVT#getLastExtent} method will return the correct extent.
  68634. * The default is `[0, 0, 4096, 4096]`.
  68635. * @param {ol.Extent} extent The extent.
  68636. * @api
  68637. */
  68638. ol.VectorTile.prototype.setExtent = function(extent) {
  68639. this.extent_ = extent;
  68640. };
  68641. /**
  68642. * Function for use in an {@link ol.source.VectorTile}'s `tileLoadFunction`.
  68643. * Sets the features for the tile.
  68644. * @param {Array.<ol.Feature>} features Features.
  68645. * @api
  68646. */
  68647. ol.VectorTile.prototype.setFeatures = function(features) {
  68648. this.features_ = features;
  68649. this.setState(ol.TileState.LOADED);
  68650. };
  68651. /**
  68652. * Function for use in an {@link ol.source.VectorTile}'s `tileLoadFunction`.
  68653. * Sets the projection of the features that were added with
  68654. * {@link ol.VectorTile#setFeatures}.
  68655. * @param {ol.proj.Projection} projection Feature projection.
  68656. * @api
  68657. */
  68658. ol.VectorTile.prototype.setProjection = function(projection) {
  68659. this.projection_ = projection;
  68660. };
  68661. /**
  68662. * @param {ol.layer.Layer} layer Layer.
  68663. * @param {string} key Key.
  68664. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  68665. */
  68666. ol.VectorTile.prototype.setReplayGroup = function(layer, key, replayGroup) {
  68667. this.replayGroups_[ol.getUid(layer) + ',' + key] = replayGroup;
  68668. };
  68669. /**
  68670. * Set the feature loader for reading this tile's features.
  68671. * @param {ol.FeatureLoader} loader Feature loader.
  68672. * @api
  68673. */
  68674. ol.VectorTile.prototype.setLoader = function(loader) {
  68675. this.loader_ = loader;
  68676. };
  68677. /**
  68678. * @const
  68679. * @type {ol.Extent}
  68680. */
  68681. ol.VectorTile.DEFAULT_EXTENT = [0, 0, 4096, 4096];
  68682. goog.provide('ol.source.VectorTile');
  68683. goog.require('ol');
  68684. goog.require('ol.TileState');
  68685. goog.require('ol.VectorImageTile');
  68686. goog.require('ol.VectorTile');
  68687. goog.require('ol.proj');
  68688. goog.require('ol.size');
  68689. goog.require('ol.tilegrid');
  68690. goog.require('ol.source.UrlTile');
  68691. /**
  68692. * @classdesc
  68693. * Class for layer sources providing vector data divided into a tile grid, to be
  68694. * used with {@link ol.layer.VectorTile}. Although this source receives tiles
  68695. * with vector features from the server, it is not meant for feature editing.
  68696. * Features are optimized for rendering, their geometries are clipped at or near
  68697. * tile boundaries and simplified for a view resolution. See
  68698. * {@link ol.source.Vector} for vector sources that are suitable for feature
  68699. * editing.
  68700. *
  68701. * @constructor
  68702. * @fires ol.source.Tile.Event
  68703. * @extends {ol.source.UrlTile}
  68704. * @param {olx.source.VectorTileOptions} options Vector tile options.
  68705. * @api
  68706. */
  68707. ol.source.VectorTile = function(options) {
  68708. var projection = options.projection || 'EPSG:3857';
  68709. var extent = options.extent || ol.tilegrid.extentFromProjection(projection);
  68710. var tileGrid = options.tileGrid || ol.tilegrid.createXYZ({
  68711. extent: extent,
  68712. maxZoom: options.maxZoom || 22,
  68713. minZoom: options.minZoom,
  68714. tileSize: options.tileSize || 512
  68715. });
  68716. ol.source.UrlTile.call(this, {
  68717. attributions: options.attributions,
  68718. cacheSize: options.cacheSize !== undefined ? options.cacheSize : 128,
  68719. extent: extent,
  68720. logo: options.logo,
  68721. opaque: false,
  68722. projection: projection,
  68723. state: options.state,
  68724. tileGrid: tileGrid,
  68725. tileLoadFunction: options.tileLoadFunction ?
  68726. options.tileLoadFunction : ol.VectorImageTile.defaultLoadFunction,
  68727. tileUrlFunction: options.tileUrlFunction,
  68728. url: options.url,
  68729. urls: options.urls,
  68730. wrapX: options.wrapX === undefined ? true : options.wrapX
  68731. });
  68732. /**
  68733. * @private
  68734. * @type {ol.format.Feature}
  68735. */
  68736. this.format_ = options.format ? options.format : null;
  68737. /**
  68738. * @private
  68739. * @type {Object.<string,ol.VectorTile>}
  68740. */
  68741. this.sourceTiles_ = {};
  68742. /**
  68743. * @private
  68744. * @type {boolean}
  68745. */
  68746. this.overlaps_ = options.overlaps == undefined ? true : options.overlaps;
  68747. /**
  68748. * @protected
  68749. * @type {function(new: ol.VectorTile, ol.TileCoord, ol.TileState, string,
  68750. * ol.format.Feature, ol.TileLoadFunctionType)}
  68751. */
  68752. this.tileClass = options.tileClass ? options.tileClass : ol.VectorTile;
  68753. /**
  68754. * @private
  68755. * @type {Object.<string,ol.tilegrid.TileGrid>}
  68756. */
  68757. this.tileGrids_ = {};
  68758. if (!this.tileGrid) {
  68759. this.tileGrid = this.getTileGridForProjection(ol.proj.get(options.projection || 'EPSG:3857'));
  68760. }
  68761. };
  68762. ol.inherits(ol.source.VectorTile, ol.source.UrlTile);
  68763. /**
  68764. * @return {boolean} The source can have overlapping geometries.
  68765. */
  68766. ol.source.VectorTile.prototype.getOverlaps = function() {
  68767. return this.overlaps_;
  68768. };
  68769. /**
  68770. * @inheritDoc
  68771. */
  68772. ol.source.VectorTile.prototype.getTile = function(z, x, y, pixelRatio, projection) {
  68773. var tileCoordKey = this.getKeyZXY(z, x, y);
  68774. if (this.tileCache.containsKey(tileCoordKey)) {
  68775. return /** @type {!ol.Tile} */ (this.tileCache.get(tileCoordKey));
  68776. } else {
  68777. var tileCoord = [z, x, y];
  68778. var urlTileCoord = this.getTileCoordForTileUrlFunction(
  68779. tileCoord, projection);
  68780. var tileUrl = urlTileCoord ?
  68781. this.tileUrlFunction(urlTileCoord, pixelRatio, projection) : undefined;
  68782. var tile = new ol.VectorImageTile(
  68783. tileCoord,
  68784. tileUrl !== undefined ? ol.TileState.IDLE : ol.TileState.EMPTY,
  68785. tileUrl !== undefined ? tileUrl : '',
  68786. this.format_, this.tileLoadFunction, urlTileCoord, this.tileUrlFunction,
  68787. this.tileGrid, this.getTileGridForProjection(projection),
  68788. this.sourceTiles_, pixelRatio, projection, this.tileClass,
  68789. this.handleTileChange.bind(this));
  68790. this.tileCache.set(tileCoordKey, tile);
  68791. return tile;
  68792. }
  68793. };
  68794. /**
  68795. * @inheritDoc
  68796. */
  68797. ol.source.VectorTile.prototype.getTileGridForProjection = function(projection) {
  68798. var code = projection.getCode();
  68799. var tileGrid = this.tileGrids_[code];
  68800. if (!tileGrid) {
  68801. // A tile grid that matches the tile size of the source tile grid is more
  68802. // likely to have 1:1 relationships between source tiles and rendered tiles.
  68803. var sourceTileGrid = this.tileGrid;
  68804. tileGrid = this.tileGrids_[code] = ol.tilegrid.createForProjection(projection, undefined,
  68805. sourceTileGrid ? sourceTileGrid.getTileSize(sourceTileGrid.getMinZoom()) : undefined);
  68806. }
  68807. return tileGrid;
  68808. };
  68809. /**
  68810. * @inheritDoc
  68811. */
  68812. ol.source.VectorTile.prototype.getTilePixelRatio = function(pixelRatio) {
  68813. return pixelRatio;
  68814. };
  68815. /**
  68816. * @inheritDoc
  68817. */
  68818. ol.source.VectorTile.prototype.getTilePixelSize = function(z, pixelRatio, projection) {
  68819. var tileSize = ol.size.toSize(this.getTileGridForProjection(projection).getTileSize(z));
  68820. return [Math.round(tileSize[0] * pixelRatio), Math.round(tileSize[1] * pixelRatio)];
  68821. };
  68822. goog.provide('ol.source.WMTSRequestEncoding');
  68823. /**
  68824. * Request encoding. One of 'KVP', 'REST'.
  68825. * @enum {string}
  68826. */
  68827. ol.source.WMTSRequestEncoding = {
  68828. KVP: 'KVP', // see spec §8
  68829. REST: 'REST' // see spec §10
  68830. };
  68831. goog.provide('ol.tilegrid.WMTS');
  68832. goog.require('ol');
  68833. goog.require('ol.array');
  68834. goog.require('ol.proj');
  68835. goog.require('ol.tilegrid.TileGrid');
  68836. /**
  68837. * @classdesc
  68838. * Set the grid pattern for sources accessing WMTS tiled-image servers.
  68839. *
  68840. * @constructor
  68841. * @extends {ol.tilegrid.TileGrid}
  68842. * @param {olx.tilegrid.WMTSOptions} options WMTS options.
  68843. * @struct
  68844. * @api
  68845. */
  68846. ol.tilegrid.WMTS = function(options) {
  68847. /**
  68848. * @private
  68849. * @type {!Array.<string>}
  68850. */
  68851. this.matrixIds_ = options.matrixIds;
  68852. // FIXME: should the matrixIds become optional?
  68853. ol.tilegrid.TileGrid.call(this, {
  68854. extent: options.extent,
  68855. origin: options.origin,
  68856. origins: options.origins,
  68857. resolutions: options.resolutions,
  68858. tileSize: options.tileSize,
  68859. tileSizes: options.tileSizes,
  68860. sizes: options.sizes
  68861. });
  68862. };
  68863. ol.inherits(ol.tilegrid.WMTS, ol.tilegrid.TileGrid);
  68864. /**
  68865. * @param {number} z Z.
  68866. * @return {string} MatrixId..
  68867. */
  68868. ol.tilegrid.WMTS.prototype.getMatrixId = function(z) {
  68869. return this.matrixIds_[z];
  68870. };
  68871. /**
  68872. * Get the list of matrix identifiers.
  68873. * @return {Array.<string>} MatrixIds.
  68874. * @api
  68875. */
  68876. ol.tilegrid.WMTS.prototype.getMatrixIds = function() {
  68877. return this.matrixIds_;
  68878. };
  68879. /**
  68880. * Create a tile grid from a WMTS capabilities matrix set and an
  68881. * optional TileMatrixSetLimits.
  68882. * @param {Object} matrixSet An object representing a matrixSet in the
  68883. * capabilities document.
  68884. * @param {ol.Extent=} opt_extent An optional extent to restrict the tile
  68885. * ranges the server provides.
  68886. * @param {Array.<Object>=} opt_matrixLimits An optional object representing
  68887. * the available matrices for tileGrid.
  68888. * @return {ol.tilegrid.WMTS} WMTS tileGrid instance.
  68889. * @api
  68890. */
  68891. ol.tilegrid.WMTS.createFromCapabilitiesMatrixSet = function(matrixSet, opt_extent,
  68892. opt_matrixLimits) {
  68893. /** @type {!Array.<number>} */
  68894. var resolutions = [];
  68895. /** @type {!Array.<string>} */
  68896. var matrixIds = [];
  68897. /** @type {!Array.<ol.Coordinate>} */
  68898. var origins = [];
  68899. /** @type {!Array.<ol.Size>} */
  68900. var tileSizes = [];
  68901. /** @type {!Array.<ol.Size>} */
  68902. var sizes = [];
  68903. var matrixLimits = opt_matrixLimits !== undefined ? opt_matrixLimits : [];
  68904. var supportedCRSPropName = 'SupportedCRS';
  68905. var matrixIdsPropName = 'TileMatrix';
  68906. var identifierPropName = 'Identifier';
  68907. var scaleDenominatorPropName = 'ScaleDenominator';
  68908. var topLeftCornerPropName = 'TopLeftCorner';
  68909. var tileWidthPropName = 'TileWidth';
  68910. var tileHeightPropName = 'TileHeight';
  68911. var projection;
  68912. projection = ol.proj.get(matrixSet[supportedCRSPropName].replace(
  68913. /urn:ogc:def:crs:(\w+):(.*:)?(\w+)$/, '$1:$3'));
  68914. var metersPerUnit = projection.getMetersPerUnit();
  68915. // swap origin x and y coordinates if axis orientation is lat/long
  68916. var switchOriginXY = projection.getAxisOrientation().substr(0, 2) == 'ne';
  68917. matrixSet[matrixIdsPropName].sort(function(a, b) {
  68918. return b[scaleDenominatorPropName] - a[scaleDenominatorPropName];
  68919. });
  68920. matrixSet[matrixIdsPropName].forEach(function(elt, index, array) {
  68921. var matrixAvailable;
  68922. // use of matrixLimits to filter TileMatrices from GetCapabilities
  68923. // TileMatrixSet from unavailable matrix levels.
  68924. if (matrixLimits.length > 0) {
  68925. matrixAvailable = ol.array.find(matrixLimits,
  68926. function(elt_ml, index_ml, array_ml) {
  68927. return elt[identifierPropName] == elt_ml[matrixIdsPropName];
  68928. });
  68929. } else {
  68930. matrixAvailable = true;
  68931. }
  68932. if (matrixAvailable) {
  68933. matrixIds.push(elt[identifierPropName]);
  68934. var resolution = elt[scaleDenominatorPropName] * 0.28E-3 / metersPerUnit;
  68935. var tileWidth = elt[tileWidthPropName];
  68936. var tileHeight = elt[tileHeightPropName];
  68937. if (switchOriginXY) {
  68938. origins.push([elt[topLeftCornerPropName][1],
  68939. elt[topLeftCornerPropName][0]]);
  68940. } else {
  68941. origins.push(elt[topLeftCornerPropName]);
  68942. }
  68943. resolutions.push(resolution);
  68944. tileSizes.push(tileWidth == tileHeight ?
  68945. tileWidth : [tileWidth, tileHeight]);
  68946. // top-left origin, so height is negative
  68947. sizes.push([elt['MatrixWidth'], -elt['MatrixHeight']]);
  68948. }
  68949. });
  68950. return new ol.tilegrid.WMTS({
  68951. extent: opt_extent,
  68952. origins: origins,
  68953. resolutions: resolutions,
  68954. matrixIds: matrixIds,
  68955. tileSizes: tileSizes,
  68956. sizes: sizes
  68957. });
  68958. };
  68959. goog.provide('ol.source.WMTS');
  68960. goog.require('ol');
  68961. goog.require('ol.TileUrlFunction');
  68962. goog.require('ol.array');
  68963. goog.require('ol.extent');
  68964. goog.require('ol.obj');
  68965. goog.require('ol.proj');
  68966. goog.require('ol.source.TileImage');
  68967. goog.require('ol.source.WMTSRequestEncoding');
  68968. goog.require('ol.tilegrid.WMTS');
  68969. goog.require('ol.uri');
  68970. /**
  68971. * @classdesc
  68972. * Layer source for tile data from WMTS servers.
  68973. *
  68974. * @constructor
  68975. * @extends {ol.source.TileImage}
  68976. * @param {olx.source.WMTSOptions} options WMTS options.
  68977. * @api
  68978. */
  68979. ol.source.WMTS = function(options) {
  68980. // TODO: add support for TileMatrixLimits
  68981. /**
  68982. * @private
  68983. * @type {string}
  68984. */
  68985. this.version_ = options.version !== undefined ? options.version : '1.0.0';
  68986. /**
  68987. * @private
  68988. * @type {string}
  68989. */
  68990. this.format_ = options.format !== undefined ? options.format : 'image/jpeg';
  68991. /**
  68992. * @private
  68993. * @type {!Object}
  68994. */
  68995. this.dimensions_ = options.dimensions !== undefined ? options.dimensions : {};
  68996. /**
  68997. * @private
  68998. * @type {string}
  68999. */
  69000. this.layer_ = options.layer;
  69001. /**
  69002. * @private
  69003. * @type {string}
  69004. */
  69005. this.matrixSet_ = options.matrixSet;
  69006. /**
  69007. * @private
  69008. * @type {string}
  69009. */
  69010. this.style_ = options.style;
  69011. var urls = options.urls;
  69012. if (urls === undefined && options.url !== undefined) {
  69013. urls = ol.TileUrlFunction.expandUrl(options.url);
  69014. }
  69015. // FIXME: should we guess this requestEncoding from options.url(s)
  69016. // structure? that would mean KVP only if a template is not provided.
  69017. /**
  69018. * @private
  69019. * @type {ol.source.WMTSRequestEncoding}
  69020. */
  69021. this.requestEncoding_ = options.requestEncoding !== undefined ?
  69022. /** @type {ol.source.WMTSRequestEncoding} */ (options.requestEncoding) :
  69023. ol.source.WMTSRequestEncoding.KVP;
  69024. var requestEncoding = this.requestEncoding_;
  69025. // FIXME: should we create a default tileGrid?
  69026. // we could issue a getCapabilities xhr to retrieve missing configuration
  69027. var tileGrid = options.tileGrid;
  69028. // context property names are lower case to allow for a case insensitive
  69029. // replacement as some services use different naming conventions
  69030. var context = {
  69031. 'layer': this.layer_,
  69032. 'style': this.style_,
  69033. 'tilematrixset': this.matrixSet_
  69034. };
  69035. if (requestEncoding == ol.source.WMTSRequestEncoding.KVP) {
  69036. ol.obj.assign(context, {
  69037. 'Service': 'WMTS',
  69038. 'Request': 'GetTile',
  69039. 'Version': this.version_,
  69040. 'Format': this.format_
  69041. });
  69042. }
  69043. var dimensions = this.dimensions_;
  69044. /**
  69045. * @param {string} template Template.
  69046. * @return {ol.TileUrlFunctionType} Tile URL function.
  69047. */
  69048. function createFromWMTSTemplate(template) {
  69049. // TODO: we may want to create our own appendParams function so that params
  69050. // order conforms to wmts spec guidance, and so that we can avoid to escape
  69051. // special template params
  69052. template = (requestEncoding == ol.source.WMTSRequestEncoding.KVP) ?
  69053. ol.uri.appendParams(template, context) :
  69054. template.replace(/\{(\w+?)\}/g, function(m, p) {
  69055. return (p.toLowerCase() in context) ? context[p.toLowerCase()] : m;
  69056. });
  69057. return (
  69058. /**
  69059. * @param {ol.TileCoord} tileCoord Tile coordinate.
  69060. * @param {number} pixelRatio Pixel ratio.
  69061. * @param {ol.proj.Projection} projection Projection.
  69062. * @return {string|undefined} Tile URL.
  69063. */
  69064. function(tileCoord, pixelRatio, projection) {
  69065. if (!tileCoord) {
  69066. return undefined;
  69067. } else {
  69068. var localContext = {
  69069. 'TileMatrix': tileGrid.getMatrixId(tileCoord[0]),
  69070. 'TileCol': tileCoord[1],
  69071. 'TileRow': -tileCoord[2] - 1
  69072. };
  69073. ol.obj.assign(localContext, dimensions);
  69074. var url = template;
  69075. if (requestEncoding == ol.source.WMTSRequestEncoding.KVP) {
  69076. url = ol.uri.appendParams(url, localContext);
  69077. } else {
  69078. url = url.replace(/\{(\w+?)\}/g, function(m, p) {
  69079. return localContext[p];
  69080. });
  69081. }
  69082. return url;
  69083. }
  69084. });
  69085. }
  69086. var tileUrlFunction = (urls && urls.length > 0) ?
  69087. ol.TileUrlFunction.createFromTileUrlFunctions(
  69088. urls.map(createFromWMTSTemplate)) :
  69089. ol.TileUrlFunction.nullTileUrlFunction;
  69090. ol.source.TileImage.call(this, {
  69091. attributions: options.attributions,
  69092. cacheSize: options.cacheSize,
  69093. crossOrigin: options.crossOrigin,
  69094. logo: options.logo,
  69095. projection: options.projection,
  69096. reprojectionErrorThreshold: options.reprojectionErrorThreshold,
  69097. tileClass: options.tileClass,
  69098. tileGrid: tileGrid,
  69099. tileLoadFunction: options.tileLoadFunction,
  69100. tilePixelRatio: options.tilePixelRatio,
  69101. tileUrlFunction: tileUrlFunction,
  69102. urls: urls,
  69103. wrapX: options.wrapX !== undefined ? options.wrapX : false
  69104. });
  69105. this.setKey(this.getKeyForDimensions_());
  69106. };
  69107. ol.inherits(ol.source.WMTS, ol.source.TileImage);
  69108. /**
  69109. * Get the dimensions, i.e. those passed to the constructor through the
  69110. * "dimensions" option, and possibly updated using the updateDimensions
  69111. * method.
  69112. * @return {!Object} Dimensions.
  69113. * @api
  69114. */
  69115. ol.source.WMTS.prototype.getDimensions = function() {
  69116. return this.dimensions_;
  69117. };
  69118. /**
  69119. * Return the image format of the WMTS source.
  69120. * @return {string} Format.
  69121. * @api
  69122. */
  69123. ol.source.WMTS.prototype.getFormat = function() {
  69124. return this.format_;
  69125. };
  69126. /**
  69127. * Return the layer of the WMTS source.
  69128. * @return {string} Layer.
  69129. * @api
  69130. */
  69131. ol.source.WMTS.prototype.getLayer = function() {
  69132. return this.layer_;
  69133. };
  69134. /**
  69135. * Return the matrix set of the WMTS source.
  69136. * @return {string} MatrixSet.
  69137. * @api
  69138. */
  69139. ol.source.WMTS.prototype.getMatrixSet = function() {
  69140. return this.matrixSet_;
  69141. };
  69142. /**
  69143. * Return the request encoding, either "KVP" or "REST".
  69144. * @return {ol.source.WMTSRequestEncoding} Request encoding.
  69145. * @api
  69146. */
  69147. ol.source.WMTS.prototype.getRequestEncoding = function() {
  69148. return this.requestEncoding_;
  69149. };
  69150. /**
  69151. * Return the style of the WMTS source.
  69152. * @return {string} Style.
  69153. * @api
  69154. */
  69155. ol.source.WMTS.prototype.getStyle = function() {
  69156. return this.style_;
  69157. };
  69158. /**
  69159. * Return the version of the WMTS source.
  69160. * @return {string} Version.
  69161. * @api
  69162. */
  69163. ol.source.WMTS.prototype.getVersion = function() {
  69164. return this.version_;
  69165. };
  69166. /**
  69167. * @private
  69168. * @return {string} The key for the current dimensions.
  69169. */
  69170. ol.source.WMTS.prototype.getKeyForDimensions_ = function() {
  69171. var i = 0;
  69172. var res = [];
  69173. for (var key in this.dimensions_) {
  69174. res[i++] = key + '-' + this.dimensions_[key];
  69175. }
  69176. return res.join('/');
  69177. };
  69178. /**
  69179. * Update the dimensions.
  69180. * @param {Object} dimensions Dimensions.
  69181. * @api
  69182. */
  69183. ol.source.WMTS.prototype.updateDimensions = function(dimensions) {
  69184. ol.obj.assign(this.dimensions_, dimensions);
  69185. this.setKey(this.getKeyForDimensions_());
  69186. };
  69187. /**
  69188. * Generate source options from a capabilities object.
  69189. * @param {Object} wmtsCap An object representing the capabilities document.
  69190. * @param {Object} config Configuration properties for the layer. Defaults for
  69191. * the layer will apply if not provided.
  69192. *
  69193. * Required config properties:
  69194. * - layer - {string} The layer identifier.
  69195. *
  69196. * Optional config properties:
  69197. * - matrixSet - {string} The matrix set identifier, required if there is
  69198. * more than one matrix set in the layer capabilities.
  69199. * - projection - {string} The desired CRS when no matrixSet is specified.
  69200. * eg: "EPSG:3857". If the desired projection is not available,
  69201. * an error is thrown.
  69202. * - requestEncoding - {string} url encoding format for the layer. Default is
  69203. * the first tile url format found in the GetCapabilities response.
  69204. * - style - {string} The name of the style
  69205. * - format - {string} Image format for the layer. Default is the first
  69206. * format returned in the GetCapabilities response.
  69207. * - crossOrigin - {string|null|undefined} Cross origin. Default is `undefined`.
  69208. * @return {?olx.source.WMTSOptions} WMTS source options object or `null` if the layer was not found.
  69209. * @api
  69210. */
  69211. ol.source.WMTS.optionsFromCapabilities = function(wmtsCap, config) {
  69212. var layers = wmtsCap['Contents']['Layer'];
  69213. var l = ol.array.find(layers, function(elt, index, array) {
  69214. return elt['Identifier'] == config['layer'];
  69215. });
  69216. if (l === null) {
  69217. return null;
  69218. }
  69219. var tileMatrixSets = wmtsCap['Contents']['TileMatrixSet'];
  69220. var idx, matrixSet, matrixLimits;
  69221. if (l['TileMatrixSetLink'].length > 1) {
  69222. if ('projection' in config) {
  69223. idx = ol.array.findIndex(l['TileMatrixSetLink'],
  69224. function(elt, index, array) {
  69225. var tileMatrixSet = ol.array.find(tileMatrixSets, function(el) {
  69226. return el['Identifier'] == elt['TileMatrixSet'];
  69227. });
  69228. var supportedCRS = tileMatrixSet['SupportedCRS'].replace(/urn:ogc:def:crs:(\w+):(.*:)?(\w+)$/, '$1:$3');
  69229. var proj1 = ol.proj.get(supportedCRS);
  69230. var proj2 = ol.proj.get(config['projection']);
  69231. if (proj1 && proj2) {
  69232. return ol.proj.equivalent(proj1, proj2);
  69233. } else {
  69234. return supportedCRS == config['projection'];
  69235. }
  69236. });
  69237. } else {
  69238. idx = ol.array.findIndex(l['TileMatrixSetLink'],
  69239. function(elt, index, array) {
  69240. return elt['TileMatrixSet'] == config['matrixSet'];
  69241. });
  69242. }
  69243. } else {
  69244. idx = 0;
  69245. }
  69246. if (idx < 0) {
  69247. idx = 0;
  69248. }
  69249. matrixSet = /** @type {string} */
  69250. (l['TileMatrixSetLink'][idx]['TileMatrixSet']);
  69251. matrixLimits = /** @type {Array.<Object>} */
  69252. (l['TileMatrixSetLink'][idx]['TileMatrixSetLimits']);
  69253. var format = /** @type {string} */ (l['Format'][0]);
  69254. if ('format' in config) {
  69255. format = config['format'];
  69256. }
  69257. idx = ol.array.findIndex(l['Style'], function(elt, index, array) {
  69258. if ('style' in config) {
  69259. return elt['Title'] == config['style'];
  69260. } else {
  69261. return elt['isDefault'];
  69262. }
  69263. });
  69264. if (idx < 0) {
  69265. idx = 0;
  69266. }
  69267. var style = /** @type {string} */ (l['Style'][idx]['Identifier']);
  69268. var dimensions = {};
  69269. if ('Dimension' in l) {
  69270. l['Dimension'].forEach(function(elt, index, array) {
  69271. var key = elt['Identifier'];
  69272. var value = elt['Default'];
  69273. if (value === undefined) {
  69274. value = elt['Value'][0];
  69275. }
  69276. dimensions[key] = value;
  69277. });
  69278. }
  69279. var matrixSets = wmtsCap['Contents']['TileMatrixSet'];
  69280. var matrixSetObj = ol.array.find(matrixSets, function(elt, index, array) {
  69281. return elt['Identifier'] == matrixSet;
  69282. });
  69283. var projection;
  69284. if ('projection' in config) {
  69285. projection = ol.proj.get(config['projection']);
  69286. } else {
  69287. projection = ol.proj.get(matrixSetObj['SupportedCRS'].replace(
  69288. /urn:ogc:def:crs:(\w+):(.*:)?(\w+)$/, '$1:$3'));
  69289. }
  69290. var wgs84BoundingBox = l['WGS84BoundingBox'];
  69291. var extent, wrapX;
  69292. if (wgs84BoundingBox !== undefined) {
  69293. var wgs84ProjectionExtent = ol.proj.get('EPSG:4326').getExtent();
  69294. wrapX = (wgs84BoundingBox[0] == wgs84ProjectionExtent[0] &&
  69295. wgs84BoundingBox[2] == wgs84ProjectionExtent[2]);
  69296. extent = ol.proj.transformExtent(
  69297. wgs84BoundingBox, 'EPSG:4326', projection);
  69298. var projectionExtent = projection.getExtent();
  69299. if (projectionExtent) {
  69300. // If possible, do a sanity check on the extent - it should never be
  69301. // bigger than the validity extent of the projection of a matrix set.
  69302. if (!ol.extent.containsExtent(projectionExtent, extent)) {
  69303. extent = undefined;
  69304. }
  69305. }
  69306. }
  69307. var tileGrid = ol.tilegrid.WMTS.createFromCapabilitiesMatrixSet(
  69308. matrixSetObj, extent, matrixLimits);
  69309. /** @type {!Array.<string>} */
  69310. var urls = [];
  69311. var requestEncoding = config['requestEncoding'];
  69312. requestEncoding = requestEncoding !== undefined ? requestEncoding : '';
  69313. if ('OperationsMetadata' in wmtsCap && 'GetTile' in wmtsCap['OperationsMetadata']) {
  69314. var gets = wmtsCap['OperationsMetadata']['GetTile']['DCP']['HTTP']['Get'];
  69315. for (var i = 0, ii = gets.length; i < ii; ++i) {
  69316. var constraint = ol.array.find(gets[i]['Constraint'], function(element) {
  69317. return element['name'] == 'GetEncoding';
  69318. });
  69319. var encodings = constraint['AllowedValues']['Value'];
  69320. if (requestEncoding === '') {
  69321. // requestEncoding not provided, use the first encoding from the list
  69322. requestEncoding = encodings[0];
  69323. }
  69324. if (requestEncoding === ol.source.WMTSRequestEncoding.KVP) {
  69325. if (ol.array.includes(encodings, ol.source.WMTSRequestEncoding.KVP)) {
  69326. urls.push(/** @type {string} */ (gets[i]['href']));
  69327. }
  69328. } else {
  69329. break;
  69330. }
  69331. }
  69332. }
  69333. if (urls.length === 0) {
  69334. requestEncoding = ol.source.WMTSRequestEncoding.REST;
  69335. l['ResourceURL'].forEach(function(element) {
  69336. if (element['resourceType'] === 'tile') {
  69337. format = element['format'];
  69338. urls.push(/** @type {string} */ (element['template']));
  69339. }
  69340. });
  69341. }
  69342. return {
  69343. urls: urls,
  69344. layer: config['layer'],
  69345. matrixSet: matrixSet,
  69346. format: format,
  69347. projection: projection,
  69348. requestEncoding: requestEncoding,
  69349. tileGrid: tileGrid,
  69350. style: style,
  69351. dimensions: dimensions,
  69352. wrapX: wrapX,
  69353. crossOrigin: config['crossOrigin']
  69354. };
  69355. };
  69356. goog.provide('ol.source.Zoomify');
  69357. goog.require('ol');
  69358. goog.require('ol.ImageTile');
  69359. goog.require('ol.TileState');
  69360. goog.require('ol.TileUrlFunction');
  69361. goog.require('ol.asserts');
  69362. goog.require('ol.dom');
  69363. goog.require('ol.extent');
  69364. goog.require('ol.source.TileImage');
  69365. goog.require('ol.tilegrid.TileGrid');
  69366. /**
  69367. * @classdesc
  69368. * Layer source for tile data in Zoomify format.
  69369. *
  69370. * @constructor
  69371. * @extends {ol.source.TileImage}
  69372. * @param {olx.source.ZoomifyOptions=} opt_options Options.
  69373. * @api
  69374. */
  69375. ol.source.Zoomify = function(opt_options) {
  69376. var options = opt_options || {};
  69377. var size = options.size;
  69378. var tierSizeCalculation = options.tierSizeCalculation !== undefined ?
  69379. options.tierSizeCalculation :
  69380. ol.source.Zoomify.TierSizeCalculation_.DEFAULT;
  69381. var imageWidth = size[0];
  69382. var imageHeight = size[1];
  69383. var tierSizeInTiles = [];
  69384. var tileSize = ol.DEFAULT_TILE_SIZE;
  69385. switch (tierSizeCalculation) {
  69386. case ol.source.Zoomify.TierSizeCalculation_.DEFAULT:
  69387. while (imageWidth > tileSize || imageHeight > tileSize) {
  69388. tierSizeInTiles.push([
  69389. Math.ceil(imageWidth / tileSize),
  69390. Math.ceil(imageHeight / tileSize)
  69391. ]);
  69392. tileSize += tileSize;
  69393. }
  69394. break;
  69395. case ol.source.Zoomify.TierSizeCalculation_.TRUNCATED:
  69396. var width = imageWidth;
  69397. var height = imageHeight;
  69398. while (width > tileSize || height > tileSize) {
  69399. tierSizeInTiles.push([
  69400. Math.ceil(width / tileSize),
  69401. Math.ceil(height / tileSize)
  69402. ]);
  69403. width >>= 1;
  69404. height >>= 1;
  69405. }
  69406. break;
  69407. default:
  69408. ol.asserts.assert(false, 53); // Unknown `tierSizeCalculation` configured
  69409. break;
  69410. }
  69411. tierSizeInTiles.push([1, 1]);
  69412. tierSizeInTiles.reverse();
  69413. var resolutions = [1];
  69414. var tileCountUpToTier = [0];
  69415. var i, ii;
  69416. for (i = 1, ii = tierSizeInTiles.length; i < ii; i++) {
  69417. resolutions.push(1 << i);
  69418. tileCountUpToTier.push(
  69419. tierSizeInTiles[i - 1][0] * tierSizeInTiles[i - 1][1] +
  69420. tileCountUpToTier[i - 1]
  69421. );
  69422. }
  69423. resolutions.reverse();
  69424. var extent = [0, -size[1], size[0], 0];
  69425. var tileGrid = new ol.tilegrid.TileGrid({
  69426. extent: extent,
  69427. origin: ol.extent.getTopLeft(extent),
  69428. resolutions: resolutions
  69429. });
  69430. var url = options.url;
  69431. if (url && url.indexOf('{TileGroup}') == -1) {
  69432. url += '{TileGroup}/{z}-{x}-{y}.jpg';
  69433. }
  69434. var urls = ol.TileUrlFunction.expandUrl(url);
  69435. /**
  69436. * @param {string} template Template.
  69437. * @return {ol.TileUrlFunctionType} Tile URL function.
  69438. */
  69439. function createFromTemplate(template) {
  69440. return (
  69441. /**
  69442. * @param {ol.TileCoord} tileCoord Tile Coordinate.
  69443. * @param {number} pixelRatio Pixel ratio.
  69444. * @param {ol.proj.Projection} projection Projection.
  69445. * @return {string|undefined} Tile URL.
  69446. */
  69447. function(tileCoord, pixelRatio, projection) {
  69448. if (!tileCoord) {
  69449. return undefined;
  69450. } else {
  69451. var tileCoordZ = tileCoord[0];
  69452. var tileCoordX = tileCoord[1];
  69453. var tileCoordY = -tileCoord[2] - 1;
  69454. var tileIndex =
  69455. tileCoordX +
  69456. tileCoordY * tierSizeInTiles[tileCoordZ][0] +
  69457. tileCountUpToTier[tileCoordZ];
  69458. var tileGroup = (tileIndex / ol.DEFAULT_TILE_SIZE) | 0;
  69459. var localContext = {
  69460. 'z': tileCoordZ,
  69461. 'x': tileCoordX,
  69462. 'y': tileCoordY,
  69463. 'TileGroup': 'TileGroup' + tileGroup
  69464. };
  69465. return template.replace(/\{(\w+?)\}/g, function(m, p) {
  69466. return localContext[p];
  69467. });
  69468. }
  69469. });
  69470. }
  69471. var tileUrlFunction = ol.TileUrlFunction.createFromTileUrlFunctions(urls.map(createFromTemplate));
  69472. ol.source.TileImage.call(this, {
  69473. attributions: options.attributions,
  69474. cacheSize: options.cacheSize,
  69475. crossOrigin: options.crossOrigin,
  69476. logo: options.logo,
  69477. projection: options.projection,
  69478. reprojectionErrorThreshold: options.reprojectionErrorThreshold,
  69479. tileClass: ol.source.Zoomify.Tile_,
  69480. tileGrid: tileGrid,
  69481. tileUrlFunction: tileUrlFunction
  69482. });
  69483. };
  69484. ol.inherits(ol.source.Zoomify, ol.source.TileImage);
  69485. /**
  69486. * @constructor
  69487. * @extends {ol.ImageTile}
  69488. * @param {ol.TileCoord} tileCoord Tile coordinate.
  69489. * @param {ol.TileState} state State.
  69490. * @param {string} src Image source URI.
  69491. * @param {?string} crossOrigin Cross origin.
  69492. * @param {ol.TileLoadFunctionType} tileLoadFunction Tile load function.
  69493. * @private
  69494. */
  69495. ol.source.Zoomify.Tile_ = function(
  69496. tileCoord, state, src, crossOrigin, tileLoadFunction) {
  69497. ol.ImageTile.call(this, tileCoord, state, src, crossOrigin, tileLoadFunction);
  69498. /**
  69499. * @private
  69500. * @type {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement}
  69501. */
  69502. this.zoomifyImage_ = null;
  69503. };
  69504. ol.inherits(ol.source.Zoomify.Tile_, ol.ImageTile);
  69505. /**
  69506. * @inheritDoc
  69507. */
  69508. ol.source.Zoomify.Tile_.prototype.getImage = function() {
  69509. if (this.zoomifyImage_) {
  69510. return this.zoomifyImage_;
  69511. }
  69512. var tileSize = ol.DEFAULT_TILE_SIZE;
  69513. var image = ol.ImageTile.prototype.getImage.call(this);
  69514. if (this.state == ol.TileState.LOADED) {
  69515. if (image.width == tileSize && image.height == tileSize) {
  69516. this.zoomifyImage_ = image;
  69517. return image;
  69518. } else {
  69519. var context = ol.dom.createCanvasContext2D(tileSize, tileSize);
  69520. context.drawImage(image, 0, 0);
  69521. this.zoomifyImage_ = context.canvas;
  69522. return context.canvas;
  69523. }
  69524. } else {
  69525. return image;
  69526. }
  69527. };
  69528. /**
  69529. * @enum {string}
  69530. * @private
  69531. */
  69532. ol.source.Zoomify.TierSizeCalculation_ = {
  69533. DEFAULT: 'default',
  69534. TRUNCATED: 'truncated'
  69535. };
  69536. // Copyright 2009 The Closure Library Authors.
  69537. // All Rights Reserved.
  69538. //
  69539. // Licensed under the Apache License, Version 2.0 (the "License");
  69540. // you may not use this file except in compliance with the License.
  69541. // You may obtain a copy of the License at
  69542. //
  69543. // http://www.apache.org/licenses/LICENSE-2.0
  69544. //
  69545. // Unless required by applicable law or agreed to in writing, software
  69546. // distributed under the License is distributed on an "AS-IS" BASIS,
  69547. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  69548. // See the License for the specific language governing permissions and
  69549. // limitations under the License.
  69550. //
  69551. // This file has been auto-generated by GenJsDeps, please do not edit.
  69552. goog.addDependency(
  69553. 'demos/editor/equationeditor.js', ['goog.demos.editor.EquationEditor'],
  69554. ['goog.ui.equation.EquationEditorDialog']);
  69555. goog.addDependency(
  69556. 'demos/editor/helloworld.js', ['goog.demos.editor.HelloWorld'],
  69557. ['goog.dom', 'goog.dom.TagName', 'goog.editor.Plugin']);
  69558. goog.addDependency(
  69559. 'demos/editor/helloworlddialog.js',
  69560. [
  69561. 'goog.demos.editor.HelloWorldDialog',
  69562. 'goog.demos.editor.HelloWorldDialog.OkEvent'
  69563. ],
  69564. [
  69565. 'goog.dom.TagName', 'goog.events.Event', 'goog.string',
  69566. 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.AbstractDialog.Builder',
  69567. 'goog.ui.editor.AbstractDialog.EventType'
  69568. ]);
  69569. goog.addDependency(
  69570. 'demos/editor/helloworlddialogplugin.js',
  69571. [
  69572. 'goog.demos.editor.HelloWorldDialogPlugin',
  69573. 'goog.demos.editor.HelloWorldDialogPlugin.Command'
  69574. ],
  69575. [
  69576. 'goog.demos.editor.HelloWorldDialog', 'goog.dom.TagName',
  69577. 'goog.editor.plugins.AbstractDialogPlugin', 'goog.editor.range',
  69578. 'goog.functions', 'goog.ui.editor.AbstractDialog.EventType'
  69579. ]);
  69580. /**
  69581. * @fileoverview Custom exports file.
  69582. * @suppress {checkVars,extraRequire}
  69583. */
  69584. goog.require('ol');
  69585. goog.require('ol.AssertionError');
  69586. goog.require('ol.Attribution');
  69587. goog.require('ol.Collection');
  69588. goog.require('ol.DeviceOrientation');
  69589. goog.require('ol.Feature');
  69590. goog.require('ol.Geolocation');
  69591. goog.require('ol.Graticule');
  69592. goog.require('ol.Image');
  69593. goog.require('ol.ImageTile');
  69594. goog.require('ol.Kinetic');
  69595. goog.require('ol.Map');
  69596. goog.require('ol.MapBrowserEvent');
  69597. goog.require('ol.MapEvent');
  69598. goog.require('ol.Object');
  69599. goog.require('ol.Observable');
  69600. goog.require('ol.Overlay');
  69601. goog.require('ol.Sphere');
  69602. goog.require('ol.Tile');
  69603. goog.require('ol.VectorTile');
  69604. goog.require('ol.View');
  69605. goog.require('ol.color');
  69606. goog.require('ol.colorlike');
  69607. goog.require('ol.control');
  69608. goog.require('ol.control.Attribution');
  69609. goog.require('ol.control.Control');
  69610. goog.require('ol.control.FullScreen');
  69611. goog.require('ol.control.MousePosition');
  69612. goog.require('ol.control.OverviewMap');
  69613. goog.require('ol.control.Rotate');
  69614. goog.require('ol.control.ScaleLine');
  69615. goog.require('ol.control.Zoom');
  69616. goog.require('ol.control.ZoomSlider');
  69617. goog.require('ol.control.ZoomToExtent');
  69618. goog.require('ol.coordinate');
  69619. goog.require('ol.easing');
  69620. goog.require('ol.events.Event');
  69621. goog.require('ol.events.condition');
  69622. goog.require('ol.extent');
  69623. goog.require('ol.featureloader');
  69624. goog.require('ol.format.EsriJSON');
  69625. goog.require('ol.format.Feature');
  69626. goog.require('ol.format.GML');
  69627. goog.require('ol.format.GML2');
  69628. goog.require('ol.format.GML3');
  69629. goog.require('ol.format.GMLBase');
  69630. goog.require('ol.format.GPX');
  69631. goog.require('ol.format.GeoJSON');
  69632. goog.require('ol.format.IGC');
  69633. goog.require('ol.format.KML');
  69634. goog.require('ol.format.MVT');
  69635. goog.require('ol.format.OSMXML');
  69636. goog.require('ol.format.Polyline');
  69637. goog.require('ol.format.TopoJSON');
  69638. goog.require('ol.format.WFS');
  69639. goog.require('ol.format.WKT');
  69640. goog.require('ol.format.WMSCapabilities');
  69641. goog.require('ol.format.WMSGetFeatureInfo');
  69642. goog.require('ol.format.WMTSCapabilities');
  69643. goog.require('ol.format.filter');
  69644. goog.require('ol.format.filter.And');
  69645. goog.require('ol.format.filter.Bbox');
  69646. goog.require('ol.format.filter.Comparison');
  69647. goog.require('ol.format.filter.ComparisonBinary');
  69648. goog.require('ol.format.filter.During');
  69649. goog.require('ol.format.filter.EqualTo');
  69650. goog.require('ol.format.filter.Filter');
  69651. goog.require('ol.format.filter.GreaterThan');
  69652. goog.require('ol.format.filter.GreaterThanOrEqualTo');
  69653. goog.require('ol.format.filter.Intersects');
  69654. goog.require('ol.format.filter.IsBetween');
  69655. goog.require('ol.format.filter.IsLike');
  69656. goog.require('ol.format.filter.IsNull');
  69657. goog.require('ol.format.filter.LessThan');
  69658. goog.require('ol.format.filter.LessThanOrEqualTo');
  69659. goog.require('ol.format.filter.Not');
  69660. goog.require('ol.format.filter.NotEqualTo');
  69661. goog.require('ol.format.filter.Or');
  69662. goog.require('ol.format.filter.Spatial');
  69663. goog.require('ol.format.filter.Within');
  69664. goog.require('ol.geom.Circle');
  69665. goog.require('ol.geom.Geometry');
  69666. goog.require('ol.geom.GeometryCollection');
  69667. goog.require('ol.geom.LineString');
  69668. goog.require('ol.geom.LinearRing');
  69669. goog.require('ol.geom.MultiLineString');
  69670. goog.require('ol.geom.MultiPoint');
  69671. goog.require('ol.geom.MultiPolygon');
  69672. goog.require('ol.geom.Point');
  69673. goog.require('ol.geom.Polygon');
  69674. goog.require('ol.geom.SimpleGeometry');
  69675. goog.require('ol.has');
  69676. goog.require('ol.interaction');
  69677. goog.require('ol.interaction.DoubleClickZoom');
  69678. goog.require('ol.interaction.DragAndDrop');
  69679. goog.require('ol.interaction.DragBox');
  69680. goog.require('ol.interaction.DragPan');
  69681. goog.require('ol.interaction.DragRotate');
  69682. goog.require('ol.interaction.DragRotateAndZoom');
  69683. goog.require('ol.interaction.DragZoom');
  69684. goog.require('ol.interaction.Draw');
  69685. goog.require('ol.interaction.Extent');
  69686. goog.require('ol.interaction.Interaction');
  69687. goog.require('ol.interaction.KeyboardPan');
  69688. goog.require('ol.interaction.KeyboardZoom');
  69689. goog.require('ol.interaction.Modify');
  69690. goog.require('ol.interaction.MouseWheelZoom');
  69691. goog.require('ol.interaction.PinchRotate');
  69692. goog.require('ol.interaction.PinchZoom');
  69693. goog.require('ol.interaction.Pointer');
  69694. goog.require('ol.interaction.Select');
  69695. goog.require('ol.interaction.Snap');
  69696. goog.require('ol.interaction.Translate');
  69697. goog.require('ol.layer.Base');
  69698. goog.require('ol.layer.Group');
  69699. goog.require('ol.layer.Heatmap');
  69700. goog.require('ol.layer.Image');
  69701. goog.require('ol.layer.Layer');
  69702. goog.require('ol.layer.Tile');
  69703. goog.require('ol.layer.Vector');
  69704. goog.require('ol.layer.VectorTile');
  69705. goog.require('ol.loadingstrategy');
  69706. goog.require('ol.proj');
  69707. goog.require('ol.proj.Projection');
  69708. goog.require('ol.proj.Units');
  69709. goog.require('ol.proj.common');
  69710. goog.require('ol.render');
  69711. goog.require('ol.render.Event');
  69712. goog.require('ol.render.Feature');
  69713. goog.require('ol.render.VectorContext');
  69714. goog.require('ol.render.canvas.Immediate');
  69715. goog.require('ol.render.webgl.Immediate');
  69716. goog.require('ol.size');
  69717. goog.require('ol.source.BingMaps');
  69718. goog.require('ol.source.CartoDB');
  69719. goog.require('ol.source.Cluster');
  69720. goog.require('ol.source.Image');
  69721. goog.require('ol.source.ImageArcGISRest');
  69722. goog.require('ol.source.ImageCanvas');
  69723. goog.require('ol.source.ImageMapGuide');
  69724. goog.require('ol.source.ImageStatic');
  69725. goog.require('ol.source.ImageVector');
  69726. goog.require('ol.source.ImageWMS');
  69727. goog.require('ol.source.OSM');
  69728. goog.require('ol.source.Raster');
  69729. goog.require('ol.source.Source');
  69730. goog.require('ol.source.Stamen');
  69731. goog.require('ol.source.Tile');
  69732. goog.require('ol.source.TileArcGISRest');
  69733. goog.require('ol.source.TileDebug');
  69734. goog.require('ol.source.TileImage');
  69735. goog.require('ol.source.TileJSON');
  69736. goog.require('ol.source.TileUTFGrid');
  69737. goog.require('ol.source.TileWMS');
  69738. goog.require('ol.source.UrlTile');
  69739. goog.require('ol.source.Vector');
  69740. goog.require('ol.source.VectorTile');
  69741. goog.require('ol.source.WMTS');
  69742. goog.require('ol.source.XYZ');
  69743. goog.require('ol.source.Zoomify');
  69744. goog.require('ol.style.AtlasManager');
  69745. goog.require('ol.style.Circle');
  69746. goog.require('ol.style.Fill');
  69747. goog.require('ol.style.Icon');
  69748. goog.require('ol.style.Image');
  69749. goog.require('ol.style.RegularShape');
  69750. goog.require('ol.style.Stroke');
  69751. goog.require('ol.style.Style');
  69752. goog.require('ol.style.Text');
  69753. goog.require('ol.tilegrid');
  69754. goog.require('ol.tilegrid.TileGrid');
  69755. goog.require('ol.tilegrid.WMTS');
  69756. goog.require('ol.webgl.Context');
  69757. goog.require('ol.xml');
  69758. goog.exportProperty(
  69759. ol.AssertionError.prototype,
  69760. 'code',
  69761. ol.AssertionError.prototype.code);
  69762. goog.exportSymbol(
  69763. 'ol.Attribution',
  69764. ol.Attribution,
  69765. OPENLAYERS);
  69766. goog.exportProperty(
  69767. ol.Attribution.prototype,
  69768. 'getHTML',
  69769. ol.Attribution.prototype.getHTML);
  69770. goog.exportSymbol(
  69771. 'ol.Collection',
  69772. ol.Collection,
  69773. OPENLAYERS);
  69774. goog.exportProperty(
  69775. ol.Collection.prototype,
  69776. 'clear',
  69777. ol.Collection.prototype.clear);
  69778. goog.exportProperty(
  69779. ol.Collection.prototype,
  69780. 'extend',
  69781. ol.Collection.prototype.extend);
  69782. goog.exportProperty(
  69783. ol.Collection.prototype,
  69784. 'forEach',
  69785. ol.Collection.prototype.forEach);
  69786. goog.exportProperty(
  69787. ol.Collection.prototype,
  69788. 'getArray',
  69789. ol.Collection.prototype.getArray);
  69790. goog.exportProperty(
  69791. ol.Collection.prototype,
  69792. 'item',
  69793. ol.Collection.prototype.item);
  69794. goog.exportProperty(
  69795. ol.Collection.prototype,
  69796. 'getLength',
  69797. ol.Collection.prototype.getLength);
  69798. goog.exportProperty(
  69799. ol.Collection.prototype,
  69800. 'insertAt',
  69801. ol.Collection.prototype.insertAt);
  69802. goog.exportProperty(
  69803. ol.Collection.prototype,
  69804. 'pop',
  69805. ol.Collection.prototype.pop);
  69806. goog.exportProperty(
  69807. ol.Collection.prototype,
  69808. 'push',
  69809. ol.Collection.prototype.push);
  69810. goog.exportProperty(
  69811. ol.Collection.prototype,
  69812. 'remove',
  69813. ol.Collection.prototype.remove);
  69814. goog.exportProperty(
  69815. ol.Collection.prototype,
  69816. 'removeAt',
  69817. ol.Collection.prototype.removeAt);
  69818. goog.exportProperty(
  69819. ol.Collection.prototype,
  69820. 'setAt',
  69821. ol.Collection.prototype.setAt);
  69822. goog.exportProperty(
  69823. ol.Collection.Event.prototype,
  69824. 'element',
  69825. ol.Collection.Event.prototype.element);
  69826. goog.exportSymbol(
  69827. 'ol.color.asArray',
  69828. ol.color.asArray,
  69829. OPENLAYERS);
  69830. goog.exportSymbol(
  69831. 'ol.color.asString',
  69832. ol.color.asString,
  69833. OPENLAYERS);
  69834. goog.exportSymbol(
  69835. 'ol.colorlike.asColorLike',
  69836. ol.colorlike.asColorLike,
  69837. OPENLAYERS);
  69838. goog.exportSymbol(
  69839. 'ol.control.defaults',
  69840. ol.control.defaults,
  69841. OPENLAYERS);
  69842. goog.exportSymbol(
  69843. 'ol.coordinate.add',
  69844. ol.coordinate.add,
  69845. OPENLAYERS);
  69846. goog.exportSymbol(
  69847. 'ol.coordinate.createStringXY',
  69848. ol.coordinate.createStringXY,
  69849. OPENLAYERS);
  69850. goog.exportSymbol(
  69851. 'ol.coordinate.format',
  69852. ol.coordinate.format,
  69853. OPENLAYERS);
  69854. goog.exportSymbol(
  69855. 'ol.coordinate.rotate',
  69856. ol.coordinate.rotate,
  69857. OPENLAYERS);
  69858. goog.exportSymbol(
  69859. 'ol.coordinate.toStringHDMS',
  69860. ol.coordinate.toStringHDMS,
  69861. OPENLAYERS);
  69862. goog.exportSymbol(
  69863. 'ol.coordinate.toStringXY',
  69864. ol.coordinate.toStringXY,
  69865. OPENLAYERS);
  69866. goog.exportSymbol(
  69867. 'ol.DeviceOrientation',
  69868. ol.DeviceOrientation,
  69869. OPENLAYERS);
  69870. goog.exportProperty(
  69871. ol.DeviceOrientation.prototype,
  69872. 'getAlpha',
  69873. ol.DeviceOrientation.prototype.getAlpha);
  69874. goog.exportProperty(
  69875. ol.DeviceOrientation.prototype,
  69876. 'getBeta',
  69877. ol.DeviceOrientation.prototype.getBeta);
  69878. goog.exportProperty(
  69879. ol.DeviceOrientation.prototype,
  69880. 'getGamma',
  69881. ol.DeviceOrientation.prototype.getGamma);
  69882. goog.exportProperty(
  69883. ol.DeviceOrientation.prototype,
  69884. 'getHeading',
  69885. ol.DeviceOrientation.prototype.getHeading);
  69886. goog.exportProperty(
  69887. ol.DeviceOrientation.prototype,
  69888. 'getTracking',
  69889. ol.DeviceOrientation.prototype.getTracking);
  69890. goog.exportProperty(
  69891. ol.DeviceOrientation.prototype,
  69892. 'setTracking',
  69893. ol.DeviceOrientation.prototype.setTracking);
  69894. goog.exportSymbol(
  69895. 'ol.easing.easeIn',
  69896. ol.easing.easeIn,
  69897. OPENLAYERS);
  69898. goog.exportSymbol(
  69899. 'ol.easing.easeOut',
  69900. ol.easing.easeOut,
  69901. OPENLAYERS);
  69902. goog.exportSymbol(
  69903. 'ol.easing.inAndOut',
  69904. ol.easing.inAndOut,
  69905. OPENLAYERS);
  69906. goog.exportSymbol(
  69907. 'ol.easing.linear',
  69908. ol.easing.linear,
  69909. OPENLAYERS);
  69910. goog.exportSymbol(
  69911. 'ol.easing.upAndDown',
  69912. ol.easing.upAndDown,
  69913. OPENLAYERS);
  69914. goog.exportSymbol(
  69915. 'ol.extent.boundingExtent',
  69916. ol.extent.boundingExtent,
  69917. OPENLAYERS);
  69918. goog.exportSymbol(
  69919. 'ol.extent.buffer',
  69920. ol.extent.buffer,
  69921. OPENLAYERS);
  69922. goog.exportSymbol(
  69923. 'ol.extent.containsCoordinate',
  69924. ol.extent.containsCoordinate,
  69925. OPENLAYERS);
  69926. goog.exportSymbol(
  69927. 'ol.extent.containsExtent',
  69928. ol.extent.containsExtent,
  69929. OPENLAYERS);
  69930. goog.exportSymbol(
  69931. 'ol.extent.containsXY',
  69932. ol.extent.containsXY,
  69933. OPENLAYERS);
  69934. goog.exportSymbol(
  69935. 'ol.extent.createEmpty',
  69936. ol.extent.createEmpty,
  69937. OPENLAYERS);
  69938. goog.exportSymbol(
  69939. 'ol.extent.equals',
  69940. ol.extent.equals,
  69941. OPENLAYERS);
  69942. goog.exportSymbol(
  69943. 'ol.extent.extend',
  69944. ol.extent.extend,
  69945. OPENLAYERS);
  69946. goog.exportSymbol(
  69947. 'ol.extent.getArea',
  69948. ol.extent.getArea,
  69949. OPENLAYERS);
  69950. goog.exportSymbol(
  69951. 'ol.extent.getBottomLeft',
  69952. ol.extent.getBottomLeft,
  69953. OPENLAYERS);
  69954. goog.exportSymbol(
  69955. 'ol.extent.getBottomRight',
  69956. ol.extent.getBottomRight,
  69957. OPENLAYERS);
  69958. goog.exportSymbol(
  69959. 'ol.extent.getCenter',
  69960. ol.extent.getCenter,
  69961. OPENLAYERS);
  69962. goog.exportSymbol(
  69963. 'ol.extent.getHeight',
  69964. ol.extent.getHeight,
  69965. OPENLAYERS);
  69966. goog.exportSymbol(
  69967. 'ol.extent.getIntersection',
  69968. ol.extent.getIntersection,
  69969. OPENLAYERS);
  69970. goog.exportSymbol(
  69971. 'ol.extent.getSize',
  69972. ol.extent.getSize,
  69973. OPENLAYERS);
  69974. goog.exportSymbol(
  69975. 'ol.extent.getTopLeft',
  69976. ol.extent.getTopLeft,
  69977. OPENLAYERS);
  69978. goog.exportSymbol(
  69979. 'ol.extent.getTopRight',
  69980. ol.extent.getTopRight,
  69981. OPENLAYERS);
  69982. goog.exportSymbol(
  69983. 'ol.extent.getWidth',
  69984. ol.extent.getWidth,
  69985. OPENLAYERS);
  69986. goog.exportSymbol(
  69987. 'ol.extent.intersects',
  69988. ol.extent.intersects,
  69989. OPENLAYERS);
  69990. goog.exportSymbol(
  69991. 'ol.extent.isEmpty',
  69992. ol.extent.isEmpty,
  69993. OPENLAYERS);
  69994. goog.exportSymbol(
  69995. 'ol.extent.applyTransform',
  69996. ol.extent.applyTransform,
  69997. OPENLAYERS);
  69998. goog.exportSymbol(
  69999. 'ol.Feature',
  70000. ol.Feature,
  70001. OPENLAYERS);
  70002. goog.exportProperty(
  70003. ol.Feature.prototype,
  70004. 'clone',
  70005. ol.Feature.prototype.clone);
  70006. goog.exportProperty(
  70007. ol.Feature.prototype,
  70008. 'getGeometry',
  70009. ol.Feature.prototype.getGeometry);
  70010. goog.exportProperty(
  70011. ol.Feature.prototype,
  70012. 'getId',
  70013. ol.Feature.prototype.getId);
  70014. goog.exportProperty(
  70015. ol.Feature.prototype,
  70016. 'getGeometryName',
  70017. ol.Feature.prototype.getGeometryName);
  70018. goog.exportProperty(
  70019. ol.Feature.prototype,
  70020. 'getStyle',
  70021. ol.Feature.prototype.getStyle);
  70022. goog.exportProperty(
  70023. ol.Feature.prototype,
  70024. 'getStyleFunction',
  70025. ol.Feature.prototype.getStyleFunction);
  70026. goog.exportProperty(
  70027. ol.Feature.prototype,
  70028. 'setGeometry',
  70029. ol.Feature.prototype.setGeometry);
  70030. goog.exportProperty(
  70031. ol.Feature.prototype,
  70032. 'setStyle',
  70033. ol.Feature.prototype.setStyle);
  70034. goog.exportProperty(
  70035. ol.Feature.prototype,
  70036. 'setId',
  70037. ol.Feature.prototype.setId);
  70038. goog.exportProperty(
  70039. ol.Feature.prototype,
  70040. 'setGeometryName',
  70041. ol.Feature.prototype.setGeometryName);
  70042. goog.exportSymbol(
  70043. 'ol.featureloader.xhr',
  70044. ol.featureloader.xhr,
  70045. OPENLAYERS);
  70046. goog.exportSymbol(
  70047. 'ol.Geolocation',
  70048. ol.Geolocation,
  70049. OPENLAYERS);
  70050. goog.exportProperty(
  70051. ol.Geolocation.prototype,
  70052. 'getAccuracy',
  70053. ol.Geolocation.prototype.getAccuracy);
  70054. goog.exportProperty(
  70055. ol.Geolocation.prototype,
  70056. 'getAccuracyGeometry',
  70057. ol.Geolocation.prototype.getAccuracyGeometry);
  70058. goog.exportProperty(
  70059. ol.Geolocation.prototype,
  70060. 'getAltitude',
  70061. ol.Geolocation.prototype.getAltitude);
  70062. goog.exportProperty(
  70063. ol.Geolocation.prototype,
  70064. 'getAltitudeAccuracy',
  70065. ol.Geolocation.prototype.getAltitudeAccuracy);
  70066. goog.exportProperty(
  70067. ol.Geolocation.prototype,
  70068. 'getHeading',
  70069. ol.Geolocation.prototype.getHeading);
  70070. goog.exportProperty(
  70071. ol.Geolocation.prototype,
  70072. 'getPosition',
  70073. ol.Geolocation.prototype.getPosition);
  70074. goog.exportProperty(
  70075. ol.Geolocation.prototype,
  70076. 'getProjection',
  70077. ol.Geolocation.prototype.getProjection);
  70078. goog.exportProperty(
  70079. ol.Geolocation.prototype,
  70080. 'getSpeed',
  70081. ol.Geolocation.prototype.getSpeed);
  70082. goog.exportProperty(
  70083. ol.Geolocation.prototype,
  70084. 'getTracking',
  70085. ol.Geolocation.prototype.getTracking);
  70086. goog.exportProperty(
  70087. ol.Geolocation.prototype,
  70088. 'getTrackingOptions',
  70089. ol.Geolocation.prototype.getTrackingOptions);
  70090. goog.exportProperty(
  70091. ol.Geolocation.prototype,
  70092. 'setProjection',
  70093. ol.Geolocation.prototype.setProjection);
  70094. goog.exportProperty(
  70095. ol.Geolocation.prototype,
  70096. 'setTracking',
  70097. ol.Geolocation.prototype.setTracking);
  70098. goog.exportProperty(
  70099. ol.Geolocation.prototype,
  70100. 'setTrackingOptions',
  70101. ol.Geolocation.prototype.setTrackingOptions);
  70102. goog.exportSymbol(
  70103. 'ol.Graticule',
  70104. ol.Graticule,
  70105. OPENLAYERS);
  70106. goog.exportProperty(
  70107. ol.Graticule.prototype,
  70108. 'getMap',
  70109. ol.Graticule.prototype.getMap);
  70110. goog.exportProperty(
  70111. ol.Graticule.prototype,
  70112. 'getMeridians',
  70113. ol.Graticule.prototype.getMeridians);
  70114. goog.exportProperty(
  70115. ol.Graticule.prototype,
  70116. 'getParallels',
  70117. ol.Graticule.prototype.getParallels);
  70118. goog.exportProperty(
  70119. ol.Graticule.prototype,
  70120. 'setMap',
  70121. ol.Graticule.prototype.setMap);
  70122. goog.exportSymbol(
  70123. 'ol.has.DEVICE_PIXEL_RATIO',
  70124. ol.has.DEVICE_PIXEL_RATIO,
  70125. OPENLAYERS);
  70126. goog.exportSymbol(
  70127. 'ol.has.CANVAS',
  70128. ol.has.CANVAS,
  70129. OPENLAYERS);
  70130. goog.exportSymbol(
  70131. 'ol.has.DEVICE_ORIENTATION',
  70132. ol.has.DEVICE_ORIENTATION,
  70133. OPENLAYERS);
  70134. goog.exportSymbol(
  70135. 'ol.has.GEOLOCATION',
  70136. ol.has.GEOLOCATION,
  70137. OPENLAYERS);
  70138. goog.exportSymbol(
  70139. 'ol.has.TOUCH',
  70140. ol.has.TOUCH,
  70141. OPENLAYERS);
  70142. goog.exportSymbol(
  70143. 'ol.has.WEBGL',
  70144. ol.has.WEBGL,
  70145. OPENLAYERS);
  70146. goog.exportProperty(
  70147. ol.Image.prototype,
  70148. 'getImage',
  70149. ol.Image.prototype.getImage);
  70150. goog.exportProperty(
  70151. ol.Image.prototype,
  70152. 'load',
  70153. ol.Image.prototype.load);
  70154. goog.exportProperty(
  70155. ol.ImageTile.prototype,
  70156. 'getImage',
  70157. ol.ImageTile.prototype.getImage);
  70158. goog.exportSymbol(
  70159. 'ol.inherits',
  70160. ol.inherits,
  70161. OPENLAYERS);
  70162. goog.exportSymbol(
  70163. 'ol.interaction.defaults',
  70164. ol.interaction.defaults,
  70165. OPENLAYERS);
  70166. goog.exportSymbol(
  70167. 'ol.Kinetic',
  70168. ol.Kinetic,
  70169. OPENLAYERS);
  70170. goog.exportSymbol(
  70171. 'ol.loadingstrategy.all',
  70172. ol.loadingstrategy.all,
  70173. OPENLAYERS);
  70174. goog.exportSymbol(
  70175. 'ol.loadingstrategy.bbox',
  70176. ol.loadingstrategy.bbox,
  70177. OPENLAYERS);
  70178. goog.exportSymbol(
  70179. 'ol.loadingstrategy.tile',
  70180. ol.loadingstrategy.tile,
  70181. OPENLAYERS);
  70182. goog.exportSymbol(
  70183. 'ol.Map',
  70184. ol.Map,
  70185. OPENLAYERS);
  70186. goog.exportProperty(
  70187. ol.Map.prototype,
  70188. 'addControl',
  70189. ol.Map.prototype.addControl);
  70190. goog.exportProperty(
  70191. ol.Map.prototype,
  70192. 'addInteraction',
  70193. ol.Map.prototype.addInteraction);
  70194. goog.exportProperty(
  70195. ol.Map.prototype,
  70196. 'addLayer',
  70197. ol.Map.prototype.addLayer);
  70198. goog.exportProperty(
  70199. ol.Map.prototype,
  70200. 'addOverlay',
  70201. ol.Map.prototype.addOverlay);
  70202. goog.exportProperty(
  70203. ol.Map.prototype,
  70204. 'forEachFeatureAtPixel',
  70205. ol.Map.prototype.forEachFeatureAtPixel);
  70206. goog.exportProperty(
  70207. ol.Map.prototype,
  70208. 'getFeaturesAtPixel',
  70209. ol.Map.prototype.getFeaturesAtPixel);
  70210. goog.exportProperty(
  70211. ol.Map.prototype,
  70212. 'forEachLayerAtPixel',
  70213. ol.Map.prototype.forEachLayerAtPixel);
  70214. goog.exportProperty(
  70215. ol.Map.prototype,
  70216. 'hasFeatureAtPixel',
  70217. ol.Map.prototype.hasFeatureAtPixel);
  70218. goog.exportProperty(
  70219. ol.Map.prototype,
  70220. 'getEventCoordinate',
  70221. ol.Map.prototype.getEventCoordinate);
  70222. goog.exportProperty(
  70223. ol.Map.prototype,
  70224. 'getEventPixel',
  70225. ol.Map.prototype.getEventPixel);
  70226. goog.exportProperty(
  70227. ol.Map.prototype,
  70228. 'getTarget',
  70229. ol.Map.prototype.getTarget);
  70230. goog.exportProperty(
  70231. ol.Map.prototype,
  70232. 'getTargetElement',
  70233. ol.Map.prototype.getTargetElement);
  70234. goog.exportProperty(
  70235. ol.Map.prototype,
  70236. 'getCoordinateFromPixel',
  70237. ol.Map.prototype.getCoordinateFromPixel);
  70238. goog.exportProperty(
  70239. ol.Map.prototype,
  70240. 'getControls',
  70241. ol.Map.prototype.getControls);
  70242. goog.exportProperty(
  70243. ol.Map.prototype,
  70244. 'getOverlays',
  70245. ol.Map.prototype.getOverlays);
  70246. goog.exportProperty(
  70247. ol.Map.prototype,
  70248. 'getOverlayById',
  70249. ol.Map.prototype.getOverlayById);
  70250. goog.exportProperty(
  70251. ol.Map.prototype,
  70252. 'getInteractions',
  70253. ol.Map.prototype.getInteractions);
  70254. goog.exportProperty(
  70255. ol.Map.prototype,
  70256. 'getLayerGroup',
  70257. ol.Map.prototype.getLayerGroup);
  70258. goog.exportProperty(
  70259. ol.Map.prototype,
  70260. 'getLayers',
  70261. ol.Map.prototype.getLayers);
  70262. goog.exportProperty(
  70263. ol.Map.prototype,
  70264. 'getPixelFromCoordinate',
  70265. ol.Map.prototype.getPixelFromCoordinate);
  70266. goog.exportProperty(
  70267. ol.Map.prototype,
  70268. 'getSize',
  70269. ol.Map.prototype.getSize);
  70270. goog.exportProperty(
  70271. ol.Map.prototype,
  70272. 'getView',
  70273. ol.Map.prototype.getView);
  70274. goog.exportProperty(
  70275. ol.Map.prototype,
  70276. 'getViewport',
  70277. ol.Map.prototype.getViewport);
  70278. goog.exportProperty(
  70279. ol.Map.prototype,
  70280. 'renderSync',
  70281. ol.Map.prototype.renderSync);
  70282. goog.exportProperty(
  70283. ol.Map.prototype,
  70284. 'render',
  70285. ol.Map.prototype.render);
  70286. goog.exportProperty(
  70287. ol.Map.prototype,
  70288. 'removeControl',
  70289. ol.Map.prototype.removeControl);
  70290. goog.exportProperty(
  70291. ol.Map.prototype,
  70292. 'removeInteraction',
  70293. ol.Map.prototype.removeInteraction);
  70294. goog.exportProperty(
  70295. ol.Map.prototype,
  70296. 'removeLayer',
  70297. ol.Map.prototype.removeLayer);
  70298. goog.exportProperty(
  70299. ol.Map.prototype,
  70300. 'removeOverlay',
  70301. ol.Map.prototype.removeOverlay);
  70302. goog.exportProperty(
  70303. ol.Map.prototype,
  70304. 'setLayerGroup',
  70305. ol.Map.prototype.setLayerGroup);
  70306. goog.exportProperty(
  70307. ol.Map.prototype,
  70308. 'setSize',
  70309. ol.Map.prototype.setSize);
  70310. goog.exportProperty(
  70311. ol.Map.prototype,
  70312. 'setTarget',
  70313. ol.Map.prototype.setTarget);
  70314. goog.exportProperty(
  70315. ol.Map.prototype,
  70316. 'setView',
  70317. ol.Map.prototype.setView);
  70318. goog.exportProperty(
  70319. ol.Map.prototype,
  70320. 'updateSize',
  70321. ol.Map.prototype.updateSize);
  70322. goog.exportProperty(
  70323. ol.MapBrowserEvent.prototype,
  70324. 'originalEvent',
  70325. ol.MapBrowserEvent.prototype.originalEvent);
  70326. goog.exportProperty(
  70327. ol.MapBrowserEvent.prototype,
  70328. 'pixel',
  70329. ol.MapBrowserEvent.prototype.pixel);
  70330. goog.exportProperty(
  70331. ol.MapBrowserEvent.prototype,
  70332. 'coordinate',
  70333. ol.MapBrowserEvent.prototype.coordinate);
  70334. goog.exportProperty(
  70335. ol.MapBrowserEvent.prototype,
  70336. 'dragging',
  70337. ol.MapBrowserEvent.prototype.dragging);
  70338. goog.exportProperty(
  70339. ol.MapEvent.prototype,
  70340. 'map',
  70341. ol.MapEvent.prototype.map);
  70342. goog.exportProperty(
  70343. ol.MapEvent.prototype,
  70344. 'frameState',
  70345. ol.MapEvent.prototype.frameState);
  70346. goog.exportSymbol(
  70347. 'ol.Object',
  70348. ol.Object,
  70349. OPENLAYERS);
  70350. goog.exportProperty(
  70351. ol.Object.prototype,
  70352. 'get',
  70353. ol.Object.prototype.get);
  70354. goog.exportProperty(
  70355. ol.Object.prototype,
  70356. 'getKeys',
  70357. ol.Object.prototype.getKeys);
  70358. goog.exportProperty(
  70359. ol.Object.prototype,
  70360. 'getProperties',
  70361. ol.Object.prototype.getProperties);
  70362. goog.exportProperty(
  70363. ol.Object.prototype,
  70364. 'set',
  70365. ol.Object.prototype.set);
  70366. goog.exportProperty(
  70367. ol.Object.prototype,
  70368. 'setProperties',
  70369. ol.Object.prototype.setProperties);
  70370. goog.exportProperty(
  70371. ol.Object.prototype,
  70372. 'unset',
  70373. ol.Object.prototype.unset);
  70374. goog.exportProperty(
  70375. ol.Object.Event.prototype,
  70376. 'key',
  70377. ol.Object.Event.prototype.key);
  70378. goog.exportProperty(
  70379. ol.Object.Event.prototype,
  70380. 'oldValue',
  70381. ol.Object.Event.prototype.oldValue);
  70382. goog.exportSymbol(
  70383. 'ol.Observable',
  70384. ol.Observable,
  70385. OPENLAYERS);
  70386. goog.exportSymbol(
  70387. 'ol.Observable.unByKey',
  70388. ol.Observable.unByKey,
  70389. OPENLAYERS);
  70390. goog.exportProperty(
  70391. ol.Observable.prototype,
  70392. 'changed',
  70393. ol.Observable.prototype.changed);
  70394. goog.exportProperty(
  70395. ol.Observable.prototype,
  70396. 'dispatchEvent',
  70397. ol.Observable.prototype.dispatchEvent);
  70398. goog.exportProperty(
  70399. ol.Observable.prototype,
  70400. 'getRevision',
  70401. ol.Observable.prototype.getRevision);
  70402. goog.exportProperty(
  70403. ol.Observable.prototype,
  70404. 'on',
  70405. ol.Observable.prototype.on);
  70406. goog.exportProperty(
  70407. ol.Observable.prototype,
  70408. 'once',
  70409. ol.Observable.prototype.once);
  70410. goog.exportProperty(
  70411. ol.Observable.prototype,
  70412. 'un',
  70413. ol.Observable.prototype.un);
  70414. goog.exportSymbol(
  70415. 'ol.Overlay',
  70416. ol.Overlay,
  70417. OPENLAYERS);
  70418. goog.exportProperty(
  70419. ol.Overlay.prototype,
  70420. 'getElement',
  70421. ol.Overlay.prototype.getElement);
  70422. goog.exportProperty(
  70423. ol.Overlay.prototype,
  70424. 'getId',
  70425. ol.Overlay.prototype.getId);
  70426. goog.exportProperty(
  70427. ol.Overlay.prototype,
  70428. 'getMap',
  70429. ol.Overlay.prototype.getMap);
  70430. goog.exportProperty(
  70431. ol.Overlay.prototype,
  70432. 'getOffset',
  70433. ol.Overlay.prototype.getOffset);
  70434. goog.exportProperty(
  70435. ol.Overlay.prototype,
  70436. 'getPosition',
  70437. ol.Overlay.prototype.getPosition);
  70438. goog.exportProperty(
  70439. ol.Overlay.prototype,
  70440. 'getPositioning',
  70441. ol.Overlay.prototype.getPositioning);
  70442. goog.exportProperty(
  70443. ol.Overlay.prototype,
  70444. 'setElement',
  70445. ol.Overlay.prototype.setElement);
  70446. goog.exportProperty(
  70447. ol.Overlay.prototype,
  70448. 'setMap',
  70449. ol.Overlay.prototype.setMap);
  70450. goog.exportProperty(
  70451. ol.Overlay.prototype,
  70452. 'setOffset',
  70453. ol.Overlay.prototype.setOffset);
  70454. goog.exportProperty(
  70455. ol.Overlay.prototype,
  70456. 'setPosition',
  70457. ol.Overlay.prototype.setPosition);
  70458. goog.exportProperty(
  70459. ol.Overlay.prototype,
  70460. 'setPositioning',
  70461. ol.Overlay.prototype.setPositioning);
  70462. goog.exportSymbol(
  70463. 'ol.proj.METERS_PER_UNIT',
  70464. ol.proj.METERS_PER_UNIT,
  70465. OPENLAYERS);
  70466. goog.exportSymbol(
  70467. 'ol.proj.setProj4',
  70468. ol.proj.setProj4,
  70469. OPENLAYERS);
  70470. goog.exportSymbol(
  70471. 'ol.proj.getPointResolution',
  70472. ol.proj.getPointResolution,
  70473. OPENLAYERS);
  70474. goog.exportSymbol(
  70475. 'ol.proj.addEquivalentProjections',
  70476. ol.proj.addEquivalentProjections,
  70477. OPENLAYERS);
  70478. goog.exportSymbol(
  70479. 'ol.proj.addProjection',
  70480. ol.proj.addProjection,
  70481. OPENLAYERS);
  70482. goog.exportSymbol(
  70483. 'ol.proj.addCoordinateTransforms',
  70484. ol.proj.addCoordinateTransforms,
  70485. OPENLAYERS);
  70486. goog.exportSymbol(
  70487. 'ol.proj.fromLonLat',
  70488. ol.proj.fromLonLat,
  70489. OPENLAYERS);
  70490. goog.exportSymbol(
  70491. 'ol.proj.toLonLat',
  70492. ol.proj.toLonLat,
  70493. OPENLAYERS);
  70494. goog.exportSymbol(
  70495. 'ol.proj.get',
  70496. ol.proj.get,
  70497. OPENLAYERS);
  70498. goog.exportSymbol(
  70499. 'ol.proj.equivalent',
  70500. ol.proj.equivalent,
  70501. OPENLAYERS);
  70502. goog.exportSymbol(
  70503. 'ol.proj.getTransform',
  70504. ol.proj.getTransform,
  70505. OPENLAYERS);
  70506. goog.exportSymbol(
  70507. 'ol.proj.transform',
  70508. ol.proj.transform,
  70509. OPENLAYERS);
  70510. goog.exportSymbol(
  70511. 'ol.proj.transformExtent',
  70512. ol.proj.transformExtent,
  70513. OPENLAYERS);
  70514. goog.exportSymbol(
  70515. 'ol.render.toContext',
  70516. ol.render.toContext,
  70517. OPENLAYERS);
  70518. goog.exportSymbol(
  70519. 'ol.size.toSize',
  70520. ol.size.toSize,
  70521. OPENLAYERS);
  70522. goog.exportSymbol(
  70523. 'ol.Sphere',
  70524. ol.Sphere,
  70525. OPENLAYERS);
  70526. goog.exportProperty(
  70527. ol.Sphere.prototype,
  70528. 'geodesicArea',
  70529. ol.Sphere.prototype.geodesicArea);
  70530. goog.exportProperty(
  70531. ol.Sphere.prototype,
  70532. 'haversineDistance',
  70533. ol.Sphere.prototype.haversineDistance);
  70534. goog.exportSymbol(
  70535. 'ol.Sphere.getLength',
  70536. ol.Sphere.getLength,
  70537. OPENLAYERS);
  70538. goog.exportSymbol(
  70539. 'ol.Sphere.getArea',
  70540. ol.Sphere.getArea,
  70541. OPENLAYERS);
  70542. goog.exportProperty(
  70543. ol.Tile.prototype,
  70544. 'getTileCoord',
  70545. ol.Tile.prototype.getTileCoord);
  70546. goog.exportProperty(
  70547. ol.Tile.prototype,
  70548. 'load',
  70549. ol.Tile.prototype.load);
  70550. goog.exportSymbol(
  70551. 'ol.tilegrid.createXYZ',
  70552. ol.tilegrid.createXYZ,
  70553. OPENLAYERS);
  70554. goog.exportProperty(
  70555. ol.VectorTile.prototype,
  70556. 'getFormat',
  70557. ol.VectorTile.prototype.getFormat);
  70558. goog.exportProperty(
  70559. ol.VectorTile.prototype,
  70560. 'getFeatures',
  70561. ol.VectorTile.prototype.getFeatures);
  70562. goog.exportProperty(
  70563. ol.VectorTile.prototype,
  70564. 'getProjection',
  70565. ol.VectorTile.prototype.getProjection);
  70566. goog.exportProperty(
  70567. ol.VectorTile.prototype,
  70568. 'setExtent',
  70569. ol.VectorTile.prototype.setExtent);
  70570. goog.exportProperty(
  70571. ol.VectorTile.prototype,
  70572. 'setFeatures',
  70573. ol.VectorTile.prototype.setFeatures);
  70574. goog.exportProperty(
  70575. ol.VectorTile.prototype,
  70576. 'setProjection',
  70577. ol.VectorTile.prototype.setProjection);
  70578. goog.exportProperty(
  70579. ol.VectorTile.prototype,
  70580. 'setLoader',
  70581. ol.VectorTile.prototype.setLoader);
  70582. goog.exportSymbol(
  70583. 'ol.View',
  70584. ol.View,
  70585. OPENLAYERS);
  70586. goog.exportProperty(
  70587. ol.View.prototype,
  70588. 'animate',
  70589. ol.View.prototype.animate);
  70590. goog.exportProperty(
  70591. ol.View.prototype,
  70592. 'getAnimating',
  70593. ol.View.prototype.getAnimating);
  70594. goog.exportProperty(
  70595. ol.View.prototype,
  70596. 'getInteracting',
  70597. ol.View.prototype.getInteracting);
  70598. goog.exportProperty(
  70599. ol.View.prototype,
  70600. 'cancelAnimations',
  70601. ol.View.prototype.cancelAnimations);
  70602. goog.exportProperty(
  70603. ol.View.prototype,
  70604. 'constrainCenter',
  70605. ol.View.prototype.constrainCenter);
  70606. goog.exportProperty(
  70607. ol.View.prototype,
  70608. 'constrainResolution',
  70609. ol.View.prototype.constrainResolution);
  70610. goog.exportProperty(
  70611. ol.View.prototype,
  70612. 'constrainRotation',
  70613. ol.View.prototype.constrainRotation);
  70614. goog.exportProperty(
  70615. ol.View.prototype,
  70616. 'getCenter',
  70617. ol.View.prototype.getCenter);
  70618. goog.exportProperty(
  70619. ol.View.prototype,
  70620. 'calculateExtent',
  70621. ol.View.prototype.calculateExtent);
  70622. goog.exportProperty(
  70623. ol.View.prototype,
  70624. 'getMaxResolution',
  70625. ol.View.prototype.getMaxResolution);
  70626. goog.exportProperty(
  70627. ol.View.prototype,
  70628. 'getMinResolution',
  70629. ol.View.prototype.getMinResolution);
  70630. goog.exportProperty(
  70631. ol.View.prototype,
  70632. 'getMaxZoom',
  70633. ol.View.prototype.getMaxZoom);
  70634. goog.exportProperty(
  70635. ol.View.prototype,
  70636. 'setMaxZoom',
  70637. ol.View.prototype.setMaxZoom);
  70638. goog.exportProperty(
  70639. ol.View.prototype,
  70640. 'getMinZoom',
  70641. ol.View.prototype.getMinZoom);
  70642. goog.exportProperty(
  70643. ol.View.prototype,
  70644. 'setMinZoom',
  70645. ol.View.prototype.setMinZoom);
  70646. goog.exportProperty(
  70647. ol.View.prototype,
  70648. 'getProjection',
  70649. ol.View.prototype.getProjection);
  70650. goog.exportProperty(
  70651. ol.View.prototype,
  70652. 'getResolution',
  70653. ol.View.prototype.getResolution);
  70654. goog.exportProperty(
  70655. ol.View.prototype,
  70656. 'getResolutions',
  70657. ol.View.prototype.getResolutions);
  70658. goog.exportProperty(
  70659. ol.View.prototype,
  70660. 'getResolutionForExtent',
  70661. ol.View.prototype.getResolutionForExtent);
  70662. goog.exportProperty(
  70663. ol.View.prototype,
  70664. 'getRotation',
  70665. ol.View.prototype.getRotation);
  70666. goog.exportProperty(
  70667. ol.View.prototype,
  70668. 'getZoom',
  70669. ol.View.prototype.getZoom);
  70670. goog.exportProperty(
  70671. ol.View.prototype,
  70672. 'getZoomForResolution',
  70673. ol.View.prototype.getZoomForResolution);
  70674. goog.exportProperty(
  70675. ol.View.prototype,
  70676. 'getResolutionForZoom',
  70677. ol.View.prototype.getResolutionForZoom);
  70678. goog.exportProperty(
  70679. ol.View.prototype,
  70680. 'fit',
  70681. ol.View.prototype.fit);
  70682. goog.exportProperty(
  70683. ol.View.prototype,
  70684. 'centerOn',
  70685. ol.View.prototype.centerOn);
  70686. goog.exportProperty(
  70687. ol.View.prototype,
  70688. 'rotate',
  70689. ol.View.prototype.rotate);
  70690. goog.exportProperty(
  70691. ol.View.prototype,
  70692. 'setCenter',
  70693. ol.View.prototype.setCenter);
  70694. goog.exportProperty(
  70695. ol.View.prototype,
  70696. 'setResolution',
  70697. ol.View.prototype.setResolution);
  70698. goog.exportProperty(
  70699. ol.View.prototype,
  70700. 'setRotation',
  70701. ol.View.prototype.setRotation);
  70702. goog.exportProperty(
  70703. ol.View.prototype,
  70704. 'setZoom',
  70705. ol.View.prototype.setZoom);
  70706. goog.exportSymbol(
  70707. 'ol.xml.getAllTextContent',
  70708. ol.xml.getAllTextContent,
  70709. OPENLAYERS);
  70710. goog.exportSymbol(
  70711. 'ol.xml.parse',
  70712. ol.xml.parse,
  70713. OPENLAYERS);
  70714. goog.exportProperty(
  70715. ol.webgl.Context.prototype,
  70716. 'getGL',
  70717. ol.webgl.Context.prototype.getGL);
  70718. goog.exportProperty(
  70719. ol.webgl.Context.prototype,
  70720. 'useProgram',
  70721. ol.webgl.Context.prototype.useProgram);
  70722. goog.exportSymbol(
  70723. 'ol.tilegrid.TileGrid',
  70724. ol.tilegrid.TileGrid,
  70725. OPENLAYERS);
  70726. goog.exportProperty(
  70727. ol.tilegrid.TileGrid.prototype,
  70728. 'forEachTileCoord',
  70729. ol.tilegrid.TileGrid.prototype.forEachTileCoord);
  70730. goog.exportProperty(
  70731. ol.tilegrid.TileGrid.prototype,
  70732. 'getMaxZoom',
  70733. ol.tilegrid.TileGrid.prototype.getMaxZoom);
  70734. goog.exportProperty(
  70735. ol.tilegrid.TileGrid.prototype,
  70736. 'getMinZoom',
  70737. ol.tilegrid.TileGrid.prototype.getMinZoom);
  70738. goog.exportProperty(
  70739. ol.tilegrid.TileGrid.prototype,
  70740. 'getOrigin',
  70741. ol.tilegrid.TileGrid.prototype.getOrigin);
  70742. goog.exportProperty(
  70743. ol.tilegrid.TileGrid.prototype,
  70744. 'getResolution',
  70745. ol.tilegrid.TileGrid.prototype.getResolution);
  70746. goog.exportProperty(
  70747. ol.tilegrid.TileGrid.prototype,
  70748. 'getResolutions',
  70749. ol.tilegrid.TileGrid.prototype.getResolutions);
  70750. goog.exportProperty(
  70751. ol.tilegrid.TileGrid.prototype,
  70752. 'getTileCoordExtent',
  70753. ol.tilegrid.TileGrid.prototype.getTileCoordExtent);
  70754. goog.exportProperty(
  70755. ol.tilegrid.TileGrid.prototype,
  70756. 'getTileCoordForCoordAndResolution',
  70757. ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndResolution);
  70758. goog.exportProperty(
  70759. ol.tilegrid.TileGrid.prototype,
  70760. 'getTileCoordForCoordAndZ',
  70761. ol.tilegrid.TileGrid.prototype.getTileCoordForCoordAndZ);
  70762. goog.exportProperty(
  70763. ol.tilegrid.TileGrid.prototype,
  70764. 'getTileSize',
  70765. ol.tilegrid.TileGrid.prototype.getTileSize);
  70766. goog.exportProperty(
  70767. ol.tilegrid.TileGrid.prototype,
  70768. 'getZForResolution',
  70769. ol.tilegrid.TileGrid.prototype.getZForResolution);
  70770. goog.exportSymbol(
  70771. 'ol.tilegrid.WMTS',
  70772. ol.tilegrid.WMTS,
  70773. OPENLAYERS);
  70774. goog.exportProperty(
  70775. ol.tilegrid.WMTS.prototype,
  70776. 'getMatrixIds',
  70777. ol.tilegrid.WMTS.prototype.getMatrixIds);
  70778. goog.exportSymbol(
  70779. 'ol.tilegrid.WMTS.createFromCapabilitiesMatrixSet',
  70780. ol.tilegrid.WMTS.createFromCapabilitiesMatrixSet,
  70781. OPENLAYERS);
  70782. goog.exportSymbol(
  70783. 'ol.style.AtlasManager',
  70784. ol.style.AtlasManager,
  70785. OPENLAYERS);
  70786. goog.exportSymbol(
  70787. 'ol.style.Circle',
  70788. ol.style.Circle,
  70789. OPENLAYERS);
  70790. goog.exportProperty(
  70791. ol.style.Circle.prototype,
  70792. 'setRadius',
  70793. ol.style.Circle.prototype.setRadius);
  70794. goog.exportSymbol(
  70795. 'ol.style.Fill',
  70796. ol.style.Fill,
  70797. OPENLAYERS);
  70798. goog.exportProperty(
  70799. ol.style.Fill.prototype,
  70800. 'clone',
  70801. ol.style.Fill.prototype.clone);
  70802. goog.exportProperty(
  70803. ol.style.Fill.prototype,
  70804. 'getColor',
  70805. ol.style.Fill.prototype.getColor);
  70806. goog.exportProperty(
  70807. ol.style.Fill.prototype,
  70808. 'setColor',
  70809. ol.style.Fill.prototype.setColor);
  70810. goog.exportSymbol(
  70811. 'ol.style.Icon',
  70812. ol.style.Icon,
  70813. OPENLAYERS);
  70814. goog.exportProperty(
  70815. ol.style.Icon.prototype,
  70816. 'clone',
  70817. ol.style.Icon.prototype.clone);
  70818. goog.exportProperty(
  70819. ol.style.Icon.prototype,
  70820. 'getAnchor',
  70821. ol.style.Icon.prototype.getAnchor);
  70822. goog.exportProperty(
  70823. ol.style.Icon.prototype,
  70824. 'getColor',
  70825. ol.style.Icon.prototype.getColor);
  70826. goog.exportProperty(
  70827. ol.style.Icon.prototype,
  70828. 'getImage',
  70829. ol.style.Icon.prototype.getImage);
  70830. goog.exportProperty(
  70831. ol.style.Icon.prototype,
  70832. 'getOrigin',
  70833. ol.style.Icon.prototype.getOrigin);
  70834. goog.exportProperty(
  70835. ol.style.Icon.prototype,
  70836. 'getSrc',
  70837. ol.style.Icon.prototype.getSrc);
  70838. goog.exportProperty(
  70839. ol.style.Icon.prototype,
  70840. 'getSize',
  70841. ol.style.Icon.prototype.getSize);
  70842. goog.exportProperty(
  70843. ol.style.Icon.prototype,
  70844. 'load',
  70845. ol.style.Icon.prototype.load);
  70846. goog.exportSymbol(
  70847. 'ol.style.Image',
  70848. ol.style.Image,
  70849. OPENLAYERS);
  70850. goog.exportProperty(
  70851. ol.style.Image.prototype,
  70852. 'getOpacity',
  70853. ol.style.Image.prototype.getOpacity);
  70854. goog.exportProperty(
  70855. ol.style.Image.prototype,
  70856. 'getRotateWithView',
  70857. ol.style.Image.prototype.getRotateWithView);
  70858. goog.exportProperty(
  70859. ol.style.Image.prototype,
  70860. 'getRotation',
  70861. ol.style.Image.prototype.getRotation);
  70862. goog.exportProperty(
  70863. ol.style.Image.prototype,
  70864. 'getScale',
  70865. ol.style.Image.prototype.getScale);
  70866. goog.exportProperty(
  70867. ol.style.Image.prototype,
  70868. 'getSnapToPixel',
  70869. ol.style.Image.prototype.getSnapToPixel);
  70870. goog.exportProperty(
  70871. ol.style.Image.prototype,
  70872. 'setOpacity',
  70873. ol.style.Image.prototype.setOpacity);
  70874. goog.exportProperty(
  70875. ol.style.Image.prototype,
  70876. 'setRotation',
  70877. ol.style.Image.prototype.setRotation);
  70878. goog.exportProperty(
  70879. ol.style.Image.prototype,
  70880. 'setScale',
  70881. ol.style.Image.prototype.setScale);
  70882. goog.exportSymbol(
  70883. 'ol.style.RegularShape',
  70884. ol.style.RegularShape,
  70885. OPENLAYERS);
  70886. goog.exportProperty(
  70887. ol.style.RegularShape.prototype,
  70888. 'clone',
  70889. ol.style.RegularShape.prototype.clone);
  70890. goog.exportProperty(
  70891. ol.style.RegularShape.prototype,
  70892. 'getAnchor',
  70893. ol.style.RegularShape.prototype.getAnchor);
  70894. goog.exportProperty(
  70895. ol.style.RegularShape.prototype,
  70896. 'getAngle',
  70897. ol.style.RegularShape.prototype.getAngle);
  70898. goog.exportProperty(
  70899. ol.style.RegularShape.prototype,
  70900. 'getFill',
  70901. ol.style.RegularShape.prototype.getFill);
  70902. goog.exportProperty(
  70903. ol.style.RegularShape.prototype,
  70904. 'getImage',
  70905. ol.style.RegularShape.prototype.getImage);
  70906. goog.exportProperty(
  70907. ol.style.RegularShape.prototype,
  70908. 'getOrigin',
  70909. ol.style.RegularShape.prototype.getOrigin);
  70910. goog.exportProperty(
  70911. ol.style.RegularShape.prototype,
  70912. 'getPoints',
  70913. ol.style.RegularShape.prototype.getPoints);
  70914. goog.exportProperty(
  70915. ol.style.RegularShape.prototype,
  70916. 'getRadius',
  70917. ol.style.RegularShape.prototype.getRadius);
  70918. goog.exportProperty(
  70919. ol.style.RegularShape.prototype,
  70920. 'getRadius2',
  70921. ol.style.RegularShape.prototype.getRadius2);
  70922. goog.exportProperty(
  70923. ol.style.RegularShape.prototype,
  70924. 'getSize',
  70925. ol.style.RegularShape.prototype.getSize);
  70926. goog.exportProperty(
  70927. ol.style.RegularShape.prototype,
  70928. 'getStroke',
  70929. ol.style.RegularShape.prototype.getStroke);
  70930. goog.exportSymbol(
  70931. 'ol.style.Stroke',
  70932. ol.style.Stroke,
  70933. OPENLAYERS);
  70934. goog.exportProperty(
  70935. ol.style.Stroke.prototype,
  70936. 'clone',
  70937. ol.style.Stroke.prototype.clone);
  70938. goog.exportProperty(
  70939. ol.style.Stroke.prototype,
  70940. 'getColor',
  70941. ol.style.Stroke.prototype.getColor);
  70942. goog.exportProperty(
  70943. ol.style.Stroke.prototype,
  70944. 'getLineCap',
  70945. ol.style.Stroke.prototype.getLineCap);
  70946. goog.exportProperty(
  70947. ol.style.Stroke.prototype,
  70948. 'getLineDash',
  70949. ol.style.Stroke.prototype.getLineDash);
  70950. goog.exportProperty(
  70951. ol.style.Stroke.prototype,
  70952. 'getLineDashOffset',
  70953. ol.style.Stroke.prototype.getLineDashOffset);
  70954. goog.exportProperty(
  70955. ol.style.Stroke.prototype,
  70956. 'getLineJoin',
  70957. ol.style.Stroke.prototype.getLineJoin);
  70958. goog.exportProperty(
  70959. ol.style.Stroke.prototype,
  70960. 'getMiterLimit',
  70961. ol.style.Stroke.prototype.getMiterLimit);
  70962. goog.exportProperty(
  70963. ol.style.Stroke.prototype,
  70964. 'getWidth',
  70965. ol.style.Stroke.prototype.getWidth);
  70966. goog.exportProperty(
  70967. ol.style.Stroke.prototype,
  70968. 'setColor',
  70969. ol.style.Stroke.prototype.setColor);
  70970. goog.exportProperty(
  70971. ol.style.Stroke.prototype,
  70972. 'setLineCap',
  70973. ol.style.Stroke.prototype.setLineCap);
  70974. goog.exportProperty(
  70975. ol.style.Stroke.prototype,
  70976. 'setLineDash',
  70977. ol.style.Stroke.prototype.setLineDash);
  70978. goog.exportProperty(
  70979. ol.style.Stroke.prototype,
  70980. 'setLineDashOffset',
  70981. ol.style.Stroke.prototype.setLineDashOffset);
  70982. goog.exportProperty(
  70983. ol.style.Stroke.prototype,
  70984. 'setLineJoin',
  70985. ol.style.Stroke.prototype.setLineJoin);
  70986. goog.exportProperty(
  70987. ol.style.Stroke.prototype,
  70988. 'setMiterLimit',
  70989. ol.style.Stroke.prototype.setMiterLimit);
  70990. goog.exportProperty(
  70991. ol.style.Stroke.prototype,
  70992. 'setWidth',
  70993. ol.style.Stroke.prototype.setWidth);
  70994. goog.exportSymbol(
  70995. 'ol.style.Style',
  70996. ol.style.Style,
  70997. OPENLAYERS);
  70998. goog.exportProperty(
  70999. ol.style.Style.prototype,
  71000. 'clone',
  71001. ol.style.Style.prototype.clone);
  71002. goog.exportProperty(
  71003. ol.style.Style.prototype,
  71004. 'getRenderer',
  71005. ol.style.Style.prototype.getRenderer);
  71006. goog.exportProperty(
  71007. ol.style.Style.prototype,
  71008. 'setRenderer',
  71009. ol.style.Style.prototype.setRenderer);
  71010. goog.exportProperty(
  71011. ol.style.Style.prototype,
  71012. 'getGeometry',
  71013. ol.style.Style.prototype.getGeometry);
  71014. goog.exportProperty(
  71015. ol.style.Style.prototype,
  71016. 'getGeometryFunction',
  71017. ol.style.Style.prototype.getGeometryFunction);
  71018. goog.exportProperty(
  71019. ol.style.Style.prototype,
  71020. 'getFill',
  71021. ol.style.Style.prototype.getFill);
  71022. goog.exportProperty(
  71023. ol.style.Style.prototype,
  71024. 'setFill',
  71025. ol.style.Style.prototype.setFill);
  71026. goog.exportProperty(
  71027. ol.style.Style.prototype,
  71028. 'getImage',
  71029. ol.style.Style.prototype.getImage);
  71030. goog.exportProperty(
  71031. ol.style.Style.prototype,
  71032. 'setImage',
  71033. ol.style.Style.prototype.setImage);
  71034. goog.exportProperty(
  71035. ol.style.Style.prototype,
  71036. 'getStroke',
  71037. ol.style.Style.prototype.getStroke);
  71038. goog.exportProperty(
  71039. ol.style.Style.prototype,
  71040. 'setStroke',
  71041. ol.style.Style.prototype.setStroke);
  71042. goog.exportProperty(
  71043. ol.style.Style.prototype,
  71044. 'getText',
  71045. ol.style.Style.prototype.getText);
  71046. goog.exportProperty(
  71047. ol.style.Style.prototype,
  71048. 'setText',
  71049. ol.style.Style.prototype.setText);
  71050. goog.exportProperty(
  71051. ol.style.Style.prototype,
  71052. 'getZIndex',
  71053. ol.style.Style.prototype.getZIndex);
  71054. goog.exportProperty(
  71055. ol.style.Style.prototype,
  71056. 'setGeometry',
  71057. ol.style.Style.prototype.setGeometry);
  71058. goog.exportProperty(
  71059. ol.style.Style.prototype,
  71060. 'setZIndex',
  71061. ol.style.Style.prototype.setZIndex);
  71062. goog.exportSymbol(
  71063. 'ol.style.Text',
  71064. ol.style.Text,
  71065. OPENLAYERS);
  71066. goog.exportProperty(
  71067. ol.style.Text.prototype,
  71068. 'clone',
  71069. ol.style.Text.prototype.clone);
  71070. goog.exportProperty(
  71071. ol.style.Text.prototype,
  71072. 'getFont',
  71073. ol.style.Text.prototype.getFont);
  71074. goog.exportProperty(
  71075. ol.style.Text.prototype,
  71076. 'getOffsetX',
  71077. ol.style.Text.prototype.getOffsetX);
  71078. goog.exportProperty(
  71079. ol.style.Text.prototype,
  71080. 'getOffsetY',
  71081. ol.style.Text.prototype.getOffsetY);
  71082. goog.exportProperty(
  71083. ol.style.Text.prototype,
  71084. 'getFill',
  71085. ol.style.Text.prototype.getFill);
  71086. goog.exportProperty(
  71087. ol.style.Text.prototype,
  71088. 'getRotateWithView',
  71089. ol.style.Text.prototype.getRotateWithView);
  71090. goog.exportProperty(
  71091. ol.style.Text.prototype,
  71092. 'getRotation',
  71093. ol.style.Text.prototype.getRotation);
  71094. goog.exportProperty(
  71095. ol.style.Text.prototype,
  71096. 'getScale',
  71097. ol.style.Text.prototype.getScale);
  71098. goog.exportProperty(
  71099. ol.style.Text.prototype,
  71100. 'getStroke',
  71101. ol.style.Text.prototype.getStroke);
  71102. goog.exportProperty(
  71103. ol.style.Text.prototype,
  71104. 'getText',
  71105. ol.style.Text.prototype.getText);
  71106. goog.exportProperty(
  71107. ol.style.Text.prototype,
  71108. 'getTextAlign',
  71109. ol.style.Text.prototype.getTextAlign);
  71110. goog.exportProperty(
  71111. ol.style.Text.prototype,
  71112. 'getTextBaseline',
  71113. ol.style.Text.prototype.getTextBaseline);
  71114. goog.exportProperty(
  71115. ol.style.Text.prototype,
  71116. 'setFont',
  71117. ol.style.Text.prototype.setFont);
  71118. goog.exportProperty(
  71119. ol.style.Text.prototype,
  71120. 'setOffsetX',
  71121. ol.style.Text.prototype.setOffsetX);
  71122. goog.exportProperty(
  71123. ol.style.Text.prototype,
  71124. 'setOffsetY',
  71125. ol.style.Text.prototype.setOffsetY);
  71126. goog.exportProperty(
  71127. ol.style.Text.prototype,
  71128. 'setFill',
  71129. ol.style.Text.prototype.setFill);
  71130. goog.exportProperty(
  71131. ol.style.Text.prototype,
  71132. 'setRotation',
  71133. ol.style.Text.prototype.setRotation);
  71134. goog.exportProperty(
  71135. ol.style.Text.prototype,
  71136. 'setScale',
  71137. ol.style.Text.prototype.setScale);
  71138. goog.exportProperty(
  71139. ol.style.Text.prototype,
  71140. 'setStroke',
  71141. ol.style.Text.prototype.setStroke);
  71142. goog.exportProperty(
  71143. ol.style.Text.prototype,
  71144. 'setText',
  71145. ol.style.Text.prototype.setText);
  71146. goog.exportProperty(
  71147. ol.style.Text.prototype,
  71148. 'setTextAlign',
  71149. ol.style.Text.prototype.setTextAlign);
  71150. goog.exportProperty(
  71151. ol.style.Text.prototype,
  71152. 'setTextBaseline',
  71153. ol.style.Text.prototype.setTextBaseline);
  71154. goog.exportSymbol(
  71155. 'ol.source.BingMaps',
  71156. ol.source.BingMaps,
  71157. OPENLAYERS);
  71158. goog.exportSymbol(
  71159. 'ol.source.BingMaps.TOS_ATTRIBUTION',
  71160. ol.source.BingMaps.TOS_ATTRIBUTION,
  71161. OPENLAYERS);
  71162. goog.exportProperty(
  71163. ol.source.BingMaps.prototype,
  71164. 'getApiKey',
  71165. ol.source.BingMaps.prototype.getApiKey);
  71166. goog.exportProperty(
  71167. ol.source.BingMaps.prototype,
  71168. 'getImagerySet',
  71169. ol.source.BingMaps.prototype.getImagerySet);
  71170. goog.exportSymbol(
  71171. 'ol.source.CartoDB',
  71172. ol.source.CartoDB,
  71173. OPENLAYERS);
  71174. goog.exportProperty(
  71175. ol.source.CartoDB.prototype,
  71176. 'getConfig',
  71177. ol.source.CartoDB.prototype.getConfig);
  71178. goog.exportProperty(
  71179. ol.source.CartoDB.prototype,
  71180. 'updateConfig',
  71181. ol.source.CartoDB.prototype.updateConfig);
  71182. goog.exportProperty(
  71183. ol.source.CartoDB.prototype,
  71184. 'setConfig',
  71185. ol.source.CartoDB.prototype.setConfig);
  71186. goog.exportSymbol(
  71187. 'ol.source.Cluster',
  71188. ol.source.Cluster,
  71189. OPENLAYERS);
  71190. goog.exportProperty(
  71191. ol.source.Cluster.prototype,
  71192. 'getDistance',
  71193. ol.source.Cluster.prototype.getDistance);
  71194. goog.exportProperty(
  71195. ol.source.Cluster.prototype,
  71196. 'getSource',
  71197. ol.source.Cluster.prototype.getSource);
  71198. goog.exportProperty(
  71199. ol.source.Cluster.prototype,
  71200. 'setDistance',
  71201. ol.source.Cluster.prototype.setDistance);
  71202. goog.exportSymbol(
  71203. 'ol.source.Image',
  71204. ol.source.Image,
  71205. OPENLAYERS);
  71206. goog.exportProperty(
  71207. ol.source.Image.Event.prototype,
  71208. 'image',
  71209. ol.source.Image.Event.prototype.image);
  71210. goog.exportSymbol(
  71211. 'ol.source.ImageArcGISRest',
  71212. ol.source.ImageArcGISRest,
  71213. OPENLAYERS);
  71214. goog.exportProperty(
  71215. ol.source.ImageArcGISRest.prototype,
  71216. 'getParams',
  71217. ol.source.ImageArcGISRest.prototype.getParams);
  71218. goog.exportProperty(
  71219. ol.source.ImageArcGISRest.prototype,
  71220. 'getImageLoadFunction',
  71221. ol.source.ImageArcGISRest.prototype.getImageLoadFunction);
  71222. goog.exportProperty(
  71223. ol.source.ImageArcGISRest.prototype,
  71224. 'getUrl',
  71225. ol.source.ImageArcGISRest.prototype.getUrl);
  71226. goog.exportProperty(
  71227. ol.source.ImageArcGISRest.prototype,
  71228. 'setImageLoadFunction',
  71229. ol.source.ImageArcGISRest.prototype.setImageLoadFunction);
  71230. goog.exportProperty(
  71231. ol.source.ImageArcGISRest.prototype,
  71232. 'setUrl',
  71233. ol.source.ImageArcGISRest.prototype.setUrl);
  71234. goog.exportProperty(
  71235. ol.source.ImageArcGISRest.prototype,
  71236. 'updateParams',
  71237. ol.source.ImageArcGISRest.prototype.updateParams);
  71238. goog.exportSymbol(
  71239. 'ol.source.ImageCanvas',
  71240. ol.source.ImageCanvas,
  71241. OPENLAYERS);
  71242. goog.exportSymbol(
  71243. 'ol.source.ImageMapGuide',
  71244. ol.source.ImageMapGuide,
  71245. OPENLAYERS);
  71246. goog.exportProperty(
  71247. ol.source.ImageMapGuide.prototype,
  71248. 'getParams',
  71249. ol.source.ImageMapGuide.prototype.getParams);
  71250. goog.exportProperty(
  71251. ol.source.ImageMapGuide.prototype,
  71252. 'getImageLoadFunction',
  71253. ol.source.ImageMapGuide.prototype.getImageLoadFunction);
  71254. goog.exportProperty(
  71255. ol.source.ImageMapGuide.prototype,
  71256. 'updateParams',
  71257. ol.source.ImageMapGuide.prototype.updateParams);
  71258. goog.exportProperty(
  71259. ol.source.ImageMapGuide.prototype,
  71260. 'setImageLoadFunction',
  71261. ol.source.ImageMapGuide.prototype.setImageLoadFunction);
  71262. goog.exportSymbol(
  71263. 'ol.source.ImageStatic',
  71264. ol.source.ImageStatic,
  71265. OPENLAYERS);
  71266. goog.exportSymbol(
  71267. 'ol.source.ImageVector',
  71268. ol.source.ImageVector,
  71269. OPENLAYERS);
  71270. goog.exportProperty(
  71271. ol.source.ImageVector.prototype,
  71272. 'getSource',
  71273. ol.source.ImageVector.prototype.getSource);
  71274. goog.exportProperty(
  71275. ol.source.ImageVector.prototype,
  71276. 'getStyle',
  71277. ol.source.ImageVector.prototype.getStyle);
  71278. goog.exportProperty(
  71279. ol.source.ImageVector.prototype,
  71280. 'getStyleFunction',
  71281. ol.source.ImageVector.prototype.getStyleFunction);
  71282. goog.exportProperty(
  71283. ol.source.ImageVector.prototype,
  71284. 'setStyle',
  71285. ol.source.ImageVector.prototype.setStyle);
  71286. goog.exportSymbol(
  71287. 'ol.source.ImageWMS',
  71288. ol.source.ImageWMS,
  71289. OPENLAYERS);
  71290. goog.exportProperty(
  71291. ol.source.ImageWMS.prototype,
  71292. 'getGetFeatureInfoUrl',
  71293. ol.source.ImageWMS.prototype.getGetFeatureInfoUrl);
  71294. goog.exportProperty(
  71295. ol.source.ImageWMS.prototype,
  71296. 'getParams',
  71297. ol.source.ImageWMS.prototype.getParams);
  71298. goog.exportProperty(
  71299. ol.source.ImageWMS.prototype,
  71300. 'getImageLoadFunction',
  71301. ol.source.ImageWMS.prototype.getImageLoadFunction);
  71302. goog.exportProperty(
  71303. ol.source.ImageWMS.prototype,
  71304. 'getUrl',
  71305. ol.source.ImageWMS.prototype.getUrl);
  71306. goog.exportProperty(
  71307. ol.source.ImageWMS.prototype,
  71308. 'setImageLoadFunction',
  71309. ol.source.ImageWMS.prototype.setImageLoadFunction);
  71310. goog.exportProperty(
  71311. ol.source.ImageWMS.prototype,
  71312. 'setUrl',
  71313. ol.source.ImageWMS.prototype.setUrl);
  71314. goog.exportProperty(
  71315. ol.source.ImageWMS.prototype,
  71316. 'updateParams',
  71317. ol.source.ImageWMS.prototype.updateParams);
  71318. goog.exportSymbol(
  71319. 'ol.source.OSM',
  71320. ol.source.OSM,
  71321. OPENLAYERS);
  71322. goog.exportSymbol(
  71323. 'ol.source.OSM.ATTRIBUTION',
  71324. ol.source.OSM.ATTRIBUTION,
  71325. OPENLAYERS);
  71326. goog.exportSymbol(
  71327. 'ol.source.Raster',
  71328. ol.source.Raster,
  71329. OPENLAYERS);
  71330. goog.exportProperty(
  71331. ol.source.Raster.prototype,
  71332. 'setOperation',
  71333. ol.source.Raster.prototype.setOperation);
  71334. goog.exportProperty(
  71335. ol.source.Raster.Event.prototype,
  71336. 'extent',
  71337. ol.source.Raster.Event.prototype.extent);
  71338. goog.exportProperty(
  71339. ol.source.Raster.Event.prototype,
  71340. 'resolution',
  71341. ol.source.Raster.Event.prototype.resolution);
  71342. goog.exportProperty(
  71343. ol.source.Raster.Event.prototype,
  71344. 'data',
  71345. ol.source.Raster.Event.prototype.data);
  71346. goog.exportSymbol(
  71347. 'ol.source.Source',
  71348. ol.source.Source,
  71349. OPENLAYERS);
  71350. goog.exportProperty(
  71351. ol.source.Source.prototype,
  71352. 'getAttributions',
  71353. ol.source.Source.prototype.getAttributions);
  71354. goog.exportProperty(
  71355. ol.source.Source.prototype,
  71356. 'getLogo',
  71357. ol.source.Source.prototype.getLogo);
  71358. goog.exportProperty(
  71359. ol.source.Source.prototype,
  71360. 'getProjection',
  71361. ol.source.Source.prototype.getProjection);
  71362. goog.exportProperty(
  71363. ol.source.Source.prototype,
  71364. 'getState',
  71365. ol.source.Source.prototype.getState);
  71366. goog.exportProperty(
  71367. ol.source.Source.prototype,
  71368. 'refresh',
  71369. ol.source.Source.prototype.refresh);
  71370. goog.exportProperty(
  71371. ol.source.Source.prototype,
  71372. 'setAttributions',
  71373. ol.source.Source.prototype.setAttributions);
  71374. goog.exportSymbol(
  71375. 'ol.source.Stamen',
  71376. ol.source.Stamen,
  71377. OPENLAYERS);
  71378. goog.exportSymbol(
  71379. 'ol.source.Tile',
  71380. ol.source.Tile,
  71381. OPENLAYERS);
  71382. goog.exportProperty(
  71383. ol.source.Tile.prototype,
  71384. 'getTileGrid',
  71385. ol.source.Tile.prototype.getTileGrid);
  71386. goog.exportProperty(
  71387. ol.source.Tile.Event.prototype,
  71388. 'tile',
  71389. ol.source.Tile.Event.prototype.tile);
  71390. goog.exportSymbol(
  71391. 'ol.source.TileArcGISRest',
  71392. ol.source.TileArcGISRest,
  71393. OPENLAYERS);
  71394. goog.exportProperty(
  71395. ol.source.TileArcGISRest.prototype,
  71396. 'getParams',
  71397. ol.source.TileArcGISRest.prototype.getParams);
  71398. goog.exportProperty(
  71399. ol.source.TileArcGISRest.prototype,
  71400. 'updateParams',
  71401. ol.source.TileArcGISRest.prototype.updateParams);
  71402. goog.exportSymbol(
  71403. 'ol.source.TileDebug',
  71404. ol.source.TileDebug,
  71405. OPENLAYERS);
  71406. goog.exportSymbol(
  71407. 'ol.source.TileImage',
  71408. ol.source.TileImage,
  71409. OPENLAYERS);
  71410. goog.exportProperty(
  71411. ol.source.TileImage.prototype,
  71412. 'setRenderReprojectionEdges',
  71413. ol.source.TileImage.prototype.setRenderReprojectionEdges);
  71414. goog.exportProperty(
  71415. ol.source.TileImage.prototype,
  71416. 'setTileGridForProjection',
  71417. ol.source.TileImage.prototype.setTileGridForProjection);
  71418. goog.exportSymbol(
  71419. 'ol.source.TileJSON',
  71420. ol.source.TileJSON,
  71421. OPENLAYERS);
  71422. goog.exportProperty(
  71423. ol.source.TileJSON.prototype,
  71424. 'getTileJSON',
  71425. ol.source.TileJSON.prototype.getTileJSON);
  71426. goog.exportSymbol(
  71427. 'ol.source.TileUTFGrid',
  71428. ol.source.TileUTFGrid,
  71429. OPENLAYERS);
  71430. goog.exportProperty(
  71431. ol.source.TileUTFGrid.prototype,
  71432. 'getTemplate',
  71433. ol.source.TileUTFGrid.prototype.getTemplate);
  71434. goog.exportProperty(
  71435. ol.source.TileUTFGrid.prototype,
  71436. 'forDataAtCoordinateAndResolution',
  71437. ol.source.TileUTFGrid.prototype.forDataAtCoordinateAndResolution);
  71438. goog.exportSymbol(
  71439. 'ol.source.TileWMS',
  71440. ol.source.TileWMS,
  71441. OPENLAYERS);
  71442. goog.exportProperty(
  71443. ol.source.TileWMS.prototype,
  71444. 'getGetFeatureInfoUrl',
  71445. ol.source.TileWMS.prototype.getGetFeatureInfoUrl);
  71446. goog.exportProperty(
  71447. ol.source.TileWMS.prototype,
  71448. 'getParams',
  71449. ol.source.TileWMS.prototype.getParams);
  71450. goog.exportProperty(
  71451. ol.source.TileWMS.prototype,
  71452. 'updateParams',
  71453. ol.source.TileWMS.prototype.updateParams);
  71454. goog.exportProperty(
  71455. ol.source.UrlTile.prototype,
  71456. 'getTileLoadFunction',
  71457. ol.source.UrlTile.prototype.getTileLoadFunction);
  71458. goog.exportProperty(
  71459. ol.source.UrlTile.prototype,
  71460. 'getTileUrlFunction',
  71461. ol.source.UrlTile.prototype.getTileUrlFunction);
  71462. goog.exportProperty(
  71463. ol.source.UrlTile.prototype,
  71464. 'getUrls',
  71465. ol.source.UrlTile.prototype.getUrls);
  71466. goog.exportProperty(
  71467. ol.source.UrlTile.prototype,
  71468. 'setTileLoadFunction',
  71469. ol.source.UrlTile.prototype.setTileLoadFunction);
  71470. goog.exportProperty(
  71471. ol.source.UrlTile.prototype,
  71472. 'setTileUrlFunction',
  71473. ol.source.UrlTile.prototype.setTileUrlFunction);
  71474. goog.exportProperty(
  71475. ol.source.UrlTile.prototype,
  71476. 'setUrl',
  71477. ol.source.UrlTile.prototype.setUrl);
  71478. goog.exportProperty(
  71479. ol.source.UrlTile.prototype,
  71480. 'setUrls',
  71481. ol.source.UrlTile.prototype.setUrls);
  71482. goog.exportSymbol(
  71483. 'ol.source.Vector',
  71484. ol.source.Vector,
  71485. OPENLAYERS);
  71486. goog.exportProperty(
  71487. ol.source.Vector.prototype,
  71488. 'addFeature',
  71489. ol.source.Vector.prototype.addFeature);
  71490. goog.exportProperty(
  71491. ol.source.Vector.prototype,
  71492. 'addFeatures',
  71493. ol.source.Vector.prototype.addFeatures);
  71494. goog.exportProperty(
  71495. ol.source.Vector.prototype,
  71496. 'clear',
  71497. ol.source.Vector.prototype.clear);
  71498. goog.exportProperty(
  71499. ol.source.Vector.prototype,
  71500. 'forEachFeature',
  71501. ol.source.Vector.prototype.forEachFeature);
  71502. goog.exportProperty(
  71503. ol.source.Vector.prototype,
  71504. 'forEachFeatureInExtent',
  71505. ol.source.Vector.prototype.forEachFeatureInExtent);
  71506. goog.exportProperty(
  71507. ol.source.Vector.prototype,
  71508. 'forEachFeatureIntersectingExtent',
  71509. ol.source.Vector.prototype.forEachFeatureIntersectingExtent);
  71510. goog.exportProperty(
  71511. ol.source.Vector.prototype,
  71512. 'getFeaturesCollection',
  71513. ol.source.Vector.prototype.getFeaturesCollection);
  71514. goog.exportProperty(
  71515. ol.source.Vector.prototype,
  71516. 'getFeatures',
  71517. ol.source.Vector.prototype.getFeatures);
  71518. goog.exportProperty(
  71519. ol.source.Vector.prototype,
  71520. 'getFeaturesAtCoordinate',
  71521. ol.source.Vector.prototype.getFeaturesAtCoordinate);
  71522. goog.exportProperty(
  71523. ol.source.Vector.prototype,
  71524. 'getFeaturesInExtent',
  71525. ol.source.Vector.prototype.getFeaturesInExtent);
  71526. goog.exportProperty(
  71527. ol.source.Vector.prototype,
  71528. 'getClosestFeatureToCoordinate',
  71529. ol.source.Vector.prototype.getClosestFeatureToCoordinate);
  71530. goog.exportProperty(
  71531. ol.source.Vector.prototype,
  71532. 'getExtent',
  71533. ol.source.Vector.prototype.getExtent);
  71534. goog.exportProperty(
  71535. ol.source.Vector.prototype,
  71536. 'getFeatureById',
  71537. ol.source.Vector.prototype.getFeatureById);
  71538. goog.exportProperty(
  71539. ol.source.Vector.prototype,
  71540. 'getFormat',
  71541. ol.source.Vector.prototype.getFormat);
  71542. goog.exportProperty(
  71543. ol.source.Vector.prototype,
  71544. 'getUrl',
  71545. ol.source.Vector.prototype.getUrl);
  71546. goog.exportProperty(
  71547. ol.source.Vector.prototype,
  71548. 'removeFeature',
  71549. ol.source.Vector.prototype.removeFeature);
  71550. goog.exportProperty(
  71551. ol.source.Vector.Event.prototype,
  71552. 'feature',
  71553. ol.source.Vector.Event.prototype.feature);
  71554. goog.exportSymbol(
  71555. 'ol.source.VectorTile',
  71556. ol.source.VectorTile,
  71557. OPENLAYERS);
  71558. goog.exportSymbol(
  71559. 'ol.source.WMTS',
  71560. ol.source.WMTS,
  71561. OPENLAYERS);
  71562. goog.exportProperty(
  71563. ol.source.WMTS.prototype,
  71564. 'getDimensions',
  71565. ol.source.WMTS.prototype.getDimensions);
  71566. goog.exportProperty(
  71567. ol.source.WMTS.prototype,
  71568. 'getFormat',
  71569. ol.source.WMTS.prototype.getFormat);
  71570. goog.exportProperty(
  71571. ol.source.WMTS.prototype,
  71572. 'getLayer',
  71573. ol.source.WMTS.prototype.getLayer);
  71574. goog.exportProperty(
  71575. ol.source.WMTS.prototype,
  71576. 'getMatrixSet',
  71577. ol.source.WMTS.prototype.getMatrixSet);
  71578. goog.exportProperty(
  71579. ol.source.WMTS.prototype,
  71580. 'getRequestEncoding',
  71581. ol.source.WMTS.prototype.getRequestEncoding);
  71582. goog.exportProperty(
  71583. ol.source.WMTS.prototype,
  71584. 'getStyle',
  71585. ol.source.WMTS.prototype.getStyle);
  71586. goog.exportProperty(
  71587. ol.source.WMTS.prototype,
  71588. 'getVersion',
  71589. ol.source.WMTS.prototype.getVersion);
  71590. goog.exportProperty(
  71591. ol.source.WMTS.prototype,
  71592. 'updateDimensions',
  71593. ol.source.WMTS.prototype.updateDimensions);
  71594. goog.exportSymbol(
  71595. 'ol.source.WMTS.optionsFromCapabilities',
  71596. ol.source.WMTS.optionsFromCapabilities,
  71597. OPENLAYERS);
  71598. goog.exportSymbol(
  71599. 'ol.source.XYZ',
  71600. ol.source.XYZ,
  71601. OPENLAYERS);
  71602. goog.exportSymbol(
  71603. 'ol.source.Zoomify',
  71604. ol.source.Zoomify,
  71605. OPENLAYERS);
  71606. goog.exportProperty(
  71607. ol.render.Event.prototype,
  71608. 'vectorContext',
  71609. ol.render.Event.prototype.vectorContext);
  71610. goog.exportProperty(
  71611. ol.render.Event.prototype,
  71612. 'frameState',
  71613. ol.render.Event.prototype.frameState);
  71614. goog.exportProperty(
  71615. ol.render.Event.prototype,
  71616. 'context',
  71617. ol.render.Event.prototype.context);
  71618. goog.exportProperty(
  71619. ol.render.Event.prototype,
  71620. 'glContext',
  71621. ol.render.Event.prototype.glContext);
  71622. goog.exportProperty(
  71623. ol.render.Feature.prototype,
  71624. 'get',
  71625. ol.render.Feature.prototype.get);
  71626. goog.exportProperty(
  71627. ol.render.Feature.prototype,
  71628. 'getExtent',
  71629. ol.render.Feature.prototype.getExtent);
  71630. goog.exportProperty(
  71631. ol.render.Feature.prototype,
  71632. 'getId',
  71633. ol.render.Feature.prototype.getId);
  71634. goog.exportProperty(
  71635. ol.render.Feature.prototype,
  71636. 'getGeometry',
  71637. ol.render.Feature.prototype.getGeometry);
  71638. goog.exportProperty(
  71639. ol.render.Feature.prototype,
  71640. 'getProperties',
  71641. ol.render.Feature.prototype.getProperties);
  71642. goog.exportProperty(
  71643. ol.render.Feature.prototype,
  71644. 'getType',
  71645. ol.render.Feature.prototype.getType);
  71646. goog.exportSymbol(
  71647. 'ol.render.VectorContext',
  71648. ol.render.VectorContext,
  71649. OPENLAYERS);
  71650. goog.exportProperty(
  71651. ol.render.webgl.Immediate.prototype,
  71652. 'setStyle',
  71653. ol.render.webgl.Immediate.prototype.setStyle);
  71654. goog.exportProperty(
  71655. ol.render.webgl.Immediate.prototype,
  71656. 'drawGeometry',
  71657. ol.render.webgl.Immediate.prototype.drawGeometry);
  71658. goog.exportProperty(
  71659. ol.render.webgl.Immediate.prototype,
  71660. 'drawFeature',
  71661. ol.render.webgl.Immediate.prototype.drawFeature);
  71662. goog.exportProperty(
  71663. ol.render.canvas.Immediate.prototype,
  71664. 'drawCircle',
  71665. ol.render.canvas.Immediate.prototype.drawCircle);
  71666. goog.exportProperty(
  71667. ol.render.canvas.Immediate.prototype,
  71668. 'setStyle',
  71669. ol.render.canvas.Immediate.prototype.setStyle);
  71670. goog.exportProperty(
  71671. ol.render.canvas.Immediate.prototype,
  71672. 'drawGeometry',
  71673. ol.render.canvas.Immediate.prototype.drawGeometry);
  71674. goog.exportProperty(
  71675. ol.render.canvas.Immediate.prototype,
  71676. 'drawFeature',
  71677. ol.render.canvas.Immediate.prototype.drawFeature);
  71678. goog.exportSymbol(
  71679. 'ol.proj.common.add',
  71680. ol.proj.common.add,
  71681. OPENLAYERS);
  71682. goog.exportSymbol(
  71683. 'ol.proj.Projection',
  71684. ol.proj.Projection,
  71685. OPENLAYERS);
  71686. goog.exportProperty(
  71687. ol.proj.Projection.prototype,
  71688. 'getCode',
  71689. ol.proj.Projection.prototype.getCode);
  71690. goog.exportProperty(
  71691. ol.proj.Projection.prototype,
  71692. 'getExtent',
  71693. ol.proj.Projection.prototype.getExtent);
  71694. goog.exportProperty(
  71695. ol.proj.Projection.prototype,
  71696. 'getUnits',
  71697. ol.proj.Projection.prototype.getUnits);
  71698. goog.exportProperty(
  71699. ol.proj.Projection.prototype,
  71700. 'getMetersPerUnit',
  71701. ol.proj.Projection.prototype.getMetersPerUnit);
  71702. goog.exportProperty(
  71703. ol.proj.Projection.prototype,
  71704. 'getWorldExtent',
  71705. ol.proj.Projection.prototype.getWorldExtent);
  71706. goog.exportProperty(
  71707. ol.proj.Projection.prototype,
  71708. 'isGlobal',
  71709. ol.proj.Projection.prototype.isGlobal);
  71710. goog.exportProperty(
  71711. ol.proj.Projection.prototype,
  71712. 'setGlobal',
  71713. ol.proj.Projection.prototype.setGlobal);
  71714. goog.exportProperty(
  71715. ol.proj.Projection.prototype,
  71716. 'setExtent',
  71717. ol.proj.Projection.prototype.setExtent);
  71718. goog.exportProperty(
  71719. ol.proj.Projection.prototype,
  71720. 'setWorldExtent',
  71721. ol.proj.Projection.prototype.setWorldExtent);
  71722. goog.exportProperty(
  71723. ol.proj.Projection.prototype,
  71724. 'setGetPointResolution',
  71725. ol.proj.Projection.prototype.setGetPointResolution);
  71726. goog.exportSymbol(
  71727. 'ol.proj.Units.METERS_PER_UNIT',
  71728. ol.proj.Units.METERS_PER_UNIT,
  71729. OPENLAYERS);
  71730. goog.exportSymbol(
  71731. 'ol.layer.Base',
  71732. ol.layer.Base,
  71733. OPENLAYERS);
  71734. goog.exportProperty(
  71735. ol.layer.Base.prototype,
  71736. 'getExtent',
  71737. ol.layer.Base.prototype.getExtent);
  71738. goog.exportProperty(
  71739. ol.layer.Base.prototype,
  71740. 'getMaxResolution',
  71741. ol.layer.Base.prototype.getMaxResolution);
  71742. goog.exportProperty(
  71743. ol.layer.Base.prototype,
  71744. 'getMinResolution',
  71745. ol.layer.Base.prototype.getMinResolution);
  71746. goog.exportProperty(
  71747. ol.layer.Base.prototype,
  71748. 'getOpacity',
  71749. ol.layer.Base.prototype.getOpacity);
  71750. goog.exportProperty(
  71751. ol.layer.Base.prototype,
  71752. 'getVisible',
  71753. ol.layer.Base.prototype.getVisible);
  71754. goog.exportProperty(
  71755. ol.layer.Base.prototype,
  71756. 'getZIndex',
  71757. ol.layer.Base.prototype.getZIndex);
  71758. goog.exportProperty(
  71759. ol.layer.Base.prototype,
  71760. 'setExtent',
  71761. ol.layer.Base.prototype.setExtent);
  71762. goog.exportProperty(
  71763. ol.layer.Base.prototype,
  71764. 'setMaxResolution',
  71765. ol.layer.Base.prototype.setMaxResolution);
  71766. goog.exportProperty(
  71767. ol.layer.Base.prototype,
  71768. 'setMinResolution',
  71769. ol.layer.Base.prototype.setMinResolution);
  71770. goog.exportProperty(
  71771. ol.layer.Base.prototype,
  71772. 'setOpacity',
  71773. ol.layer.Base.prototype.setOpacity);
  71774. goog.exportProperty(
  71775. ol.layer.Base.prototype,
  71776. 'setVisible',
  71777. ol.layer.Base.prototype.setVisible);
  71778. goog.exportProperty(
  71779. ol.layer.Base.prototype,
  71780. 'setZIndex',
  71781. ol.layer.Base.prototype.setZIndex);
  71782. goog.exportSymbol(
  71783. 'ol.layer.Group',
  71784. ol.layer.Group,
  71785. OPENLAYERS);
  71786. goog.exportProperty(
  71787. ol.layer.Group.prototype,
  71788. 'getLayers',
  71789. ol.layer.Group.prototype.getLayers);
  71790. goog.exportProperty(
  71791. ol.layer.Group.prototype,
  71792. 'setLayers',
  71793. ol.layer.Group.prototype.setLayers);
  71794. goog.exportSymbol(
  71795. 'ol.layer.Heatmap',
  71796. ol.layer.Heatmap,
  71797. OPENLAYERS);
  71798. goog.exportProperty(
  71799. ol.layer.Heatmap.prototype,
  71800. 'getBlur',
  71801. ol.layer.Heatmap.prototype.getBlur);
  71802. goog.exportProperty(
  71803. ol.layer.Heatmap.prototype,
  71804. 'getGradient',
  71805. ol.layer.Heatmap.prototype.getGradient);
  71806. goog.exportProperty(
  71807. ol.layer.Heatmap.prototype,
  71808. 'getRadius',
  71809. ol.layer.Heatmap.prototype.getRadius);
  71810. goog.exportProperty(
  71811. ol.layer.Heatmap.prototype,
  71812. 'setBlur',
  71813. ol.layer.Heatmap.prototype.setBlur);
  71814. goog.exportProperty(
  71815. ol.layer.Heatmap.prototype,
  71816. 'setGradient',
  71817. ol.layer.Heatmap.prototype.setGradient);
  71818. goog.exportProperty(
  71819. ol.layer.Heatmap.prototype,
  71820. 'setRadius',
  71821. ol.layer.Heatmap.prototype.setRadius);
  71822. goog.exportSymbol(
  71823. 'ol.layer.Image',
  71824. ol.layer.Image,
  71825. OPENLAYERS);
  71826. goog.exportProperty(
  71827. ol.layer.Image.prototype,
  71828. 'getSource',
  71829. ol.layer.Image.prototype.getSource);
  71830. goog.exportSymbol(
  71831. 'ol.layer.Layer',
  71832. ol.layer.Layer,
  71833. OPENLAYERS);
  71834. goog.exportProperty(
  71835. ol.layer.Layer.prototype,
  71836. 'getSource',
  71837. ol.layer.Layer.prototype.getSource);
  71838. goog.exportProperty(
  71839. ol.layer.Layer.prototype,
  71840. 'setMap',
  71841. ol.layer.Layer.prototype.setMap);
  71842. goog.exportProperty(
  71843. ol.layer.Layer.prototype,
  71844. 'setSource',
  71845. ol.layer.Layer.prototype.setSource);
  71846. goog.exportSymbol(
  71847. 'ol.layer.Tile',
  71848. ol.layer.Tile,
  71849. OPENLAYERS);
  71850. goog.exportProperty(
  71851. ol.layer.Tile.prototype,
  71852. 'getPreload',
  71853. ol.layer.Tile.prototype.getPreload);
  71854. goog.exportProperty(
  71855. ol.layer.Tile.prototype,
  71856. 'getSource',
  71857. ol.layer.Tile.prototype.getSource);
  71858. goog.exportProperty(
  71859. ol.layer.Tile.prototype,
  71860. 'setPreload',
  71861. ol.layer.Tile.prototype.setPreload);
  71862. goog.exportProperty(
  71863. ol.layer.Tile.prototype,
  71864. 'getUseInterimTilesOnError',
  71865. ol.layer.Tile.prototype.getUseInterimTilesOnError);
  71866. goog.exportProperty(
  71867. ol.layer.Tile.prototype,
  71868. 'setUseInterimTilesOnError',
  71869. ol.layer.Tile.prototype.setUseInterimTilesOnError);
  71870. goog.exportSymbol(
  71871. 'ol.layer.Vector',
  71872. ol.layer.Vector,
  71873. OPENLAYERS);
  71874. goog.exportProperty(
  71875. ol.layer.Vector.prototype,
  71876. 'getSource',
  71877. ol.layer.Vector.prototype.getSource);
  71878. goog.exportProperty(
  71879. ol.layer.Vector.prototype,
  71880. 'getStyle',
  71881. ol.layer.Vector.prototype.getStyle);
  71882. goog.exportProperty(
  71883. ol.layer.Vector.prototype,
  71884. 'getStyleFunction',
  71885. ol.layer.Vector.prototype.getStyleFunction);
  71886. goog.exportProperty(
  71887. ol.layer.Vector.prototype,
  71888. 'setStyle',
  71889. ol.layer.Vector.prototype.setStyle);
  71890. goog.exportSymbol(
  71891. 'ol.layer.VectorTile',
  71892. ol.layer.VectorTile,
  71893. OPENLAYERS);
  71894. goog.exportProperty(
  71895. ol.layer.VectorTile.prototype,
  71896. 'getPreload',
  71897. ol.layer.VectorTile.prototype.getPreload);
  71898. goog.exportProperty(
  71899. ol.layer.VectorTile.prototype,
  71900. 'getUseInterimTilesOnError',
  71901. ol.layer.VectorTile.prototype.getUseInterimTilesOnError);
  71902. goog.exportProperty(
  71903. ol.layer.VectorTile.prototype,
  71904. 'setPreload',
  71905. ol.layer.VectorTile.prototype.setPreload);
  71906. goog.exportProperty(
  71907. ol.layer.VectorTile.prototype,
  71908. 'setUseInterimTilesOnError',
  71909. ol.layer.VectorTile.prototype.setUseInterimTilesOnError);
  71910. goog.exportProperty(
  71911. ol.layer.VectorTile.prototype,
  71912. 'getSource',
  71913. ol.layer.VectorTile.prototype.getSource);
  71914. goog.exportSymbol(
  71915. 'ol.interaction.DoubleClickZoom',
  71916. ol.interaction.DoubleClickZoom,
  71917. OPENLAYERS);
  71918. goog.exportSymbol(
  71919. 'ol.interaction.DoubleClickZoom.handleEvent',
  71920. ol.interaction.DoubleClickZoom.handleEvent,
  71921. OPENLAYERS);
  71922. goog.exportSymbol(
  71923. 'ol.interaction.DragAndDrop',
  71924. ol.interaction.DragAndDrop,
  71925. OPENLAYERS);
  71926. goog.exportSymbol(
  71927. 'ol.interaction.DragAndDrop.handleEvent',
  71928. ol.interaction.DragAndDrop.handleEvent,
  71929. OPENLAYERS);
  71930. goog.exportProperty(
  71931. ol.interaction.DragAndDrop.Event.prototype,
  71932. 'features',
  71933. ol.interaction.DragAndDrop.Event.prototype.features);
  71934. goog.exportProperty(
  71935. ol.interaction.DragAndDrop.Event.prototype,
  71936. 'file',
  71937. ol.interaction.DragAndDrop.Event.prototype.file);
  71938. goog.exportProperty(
  71939. ol.interaction.DragAndDrop.Event.prototype,
  71940. 'projection',
  71941. ol.interaction.DragAndDrop.Event.prototype.projection);
  71942. goog.exportSymbol(
  71943. 'ol.interaction.DragBox',
  71944. ol.interaction.DragBox,
  71945. OPENLAYERS);
  71946. goog.exportProperty(
  71947. ol.interaction.DragBox.prototype,
  71948. 'getGeometry',
  71949. ol.interaction.DragBox.prototype.getGeometry);
  71950. goog.exportProperty(
  71951. ol.interaction.DragBox.Event.prototype,
  71952. 'coordinate',
  71953. ol.interaction.DragBox.Event.prototype.coordinate);
  71954. goog.exportProperty(
  71955. ol.interaction.DragBox.Event.prototype,
  71956. 'mapBrowserEvent',
  71957. ol.interaction.DragBox.Event.prototype.mapBrowserEvent);
  71958. goog.exportSymbol(
  71959. 'ol.interaction.DragPan',
  71960. ol.interaction.DragPan,
  71961. OPENLAYERS);
  71962. goog.exportSymbol(
  71963. 'ol.interaction.DragRotate',
  71964. ol.interaction.DragRotate,
  71965. OPENLAYERS);
  71966. goog.exportSymbol(
  71967. 'ol.interaction.DragRotateAndZoom',
  71968. ol.interaction.DragRotateAndZoom,
  71969. OPENLAYERS);
  71970. goog.exportSymbol(
  71971. 'ol.interaction.DragZoom',
  71972. ol.interaction.DragZoom,
  71973. OPENLAYERS);
  71974. goog.exportSymbol(
  71975. 'ol.interaction.Draw',
  71976. ol.interaction.Draw,
  71977. OPENLAYERS);
  71978. goog.exportSymbol(
  71979. 'ol.interaction.Draw.handleEvent',
  71980. ol.interaction.Draw.handleEvent,
  71981. OPENLAYERS);
  71982. goog.exportProperty(
  71983. ol.interaction.Draw.prototype,
  71984. 'removeLastPoint',
  71985. ol.interaction.Draw.prototype.removeLastPoint);
  71986. goog.exportProperty(
  71987. ol.interaction.Draw.prototype,
  71988. 'finishDrawing',
  71989. ol.interaction.Draw.prototype.finishDrawing);
  71990. goog.exportProperty(
  71991. ol.interaction.Draw.prototype,
  71992. 'extend',
  71993. ol.interaction.Draw.prototype.extend);
  71994. goog.exportSymbol(
  71995. 'ol.interaction.Draw.createRegularPolygon',
  71996. ol.interaction.Draw.createRegularPolygon,
  71997. OPENLAYERS);
  71998. goog.exportSymbol(
  71999. 'ol.interaction.Draw.createBox',
  72000. ol.interaction.Draw.createBox,
  72001. OPENLAYERS);
  72002. goog.exportProperty(
  72003. ol.interaction.Draw.Event.prototype,
  72004. 'feature',
  72005. ol.interaction.Draw.Event.prototype.feature);
  72006. goog.exportSymbol(
  72007. 'ol.interaction.Extent',
  72008. ol.interaction.Extent,
  72009. OPENLAYERS);
  72010. goog.exportProperty(
  72011. ol.interaction.Extent.prototype,
  72012. 'getExtent',
  72013. ol.interaction.Extent.prototype.getExtent);
  72014. goog.exportProperty(
  72015. ol.interaction.Extent.prototype,
  72016. 'setExtent',
  72017. ol.interaction.Extent.prototype.setExtent);
  72018. goog.exportProperty(
  72019. ol.interaction.Extent.Event.prototype,
  72020. 'extent',
  72021. ol.interaction.Extent.Event.prototype.extent);
  72022. goog.exportSymbol(
  72023. 'ol.interaction.Interaction',
  72024. ol.interaction.Interaction,
  72025. OPENLAYERS);
  72026. goog.exportProperty(
  72027. ol.interaction.Interaction.prototype,
  72028. 'getActive',
  72029. ol.interaction.Interaction.prototype.getActive);
  72030. goog.exportProperty(
  72031. ol.interaction.Interaction.prototype,
  72032. 'getMap',
  72033. ol.interaction.Interaction.prototype.getMap);
  72034. goog.exportProperty(
  72035. ol.interaction.Interaction.prototype,
  72036. 'setActive',
  72037. ol.interaction.Interaction.prototype.setActive);
  72038. goog.exportSymbol(
  72039. 'ol.interaction.KeyboardPan',
  72040. ol.interaction.KeyboardPan,
  72041. OPENLAYERS);
  72042. goog.exportSymbol(
  72043. 'ol.interaction.KeyboardPan.handleEvent',
  72044. ol.interaction.KeyboardPan.handleEvent,
  72045. OPENLAYERS);
  72046. goog.exportSymbol(
  72047. 'ol.interaction.KeyboardZoom',
  72048. ol.interaction.KeyboardZoom,
  72049. OPENLAYERS);
  72050. goog.exportSymbol(
  72051. 'ol.interaction.KeyboardZoom.handleEvent',
  72052. ol.interaction.KeyboardZoom.handleEvent,
  72053. OPENLAYERS);
  72054. goog.exportSymbol(
  72055. 'ol.interaction.Modify',
  72056. ol.interaction.Modify,
  72057. OPENLAYERS);
  72058. goog.exportSymbol(
  72059. 'ol.interaction.Modify.handleEvent',
  72060. ol.interaction.Modify.handleEvent,
  72061. OPENLAYERS);
  72062. goog.exportProperty(
  72063. ol.interaction.Modify.prototype,
  72064. 'removePoint',
  72065. ol.interaction.Modify.prototype.removePoint);
  72066. goog.exportProperty(
  72067. ol.interaction.Modify.Event.prototype,
  72068. 'features',
  72069. ol.interaction.Modify.Event.prototype.features);
  72070. goog.exportProperty(
  72071. ol.interaction.Modify.Event.prototype,
  72072. 'mapBrowserEvent',
  72073. ol.interaction.Modify.Event.prototype.mapBrowserEvent);
  72074. goog.exportSymbol(
  72075. 'ol.interaction.MouseWheelZoom',
  72076. ol.interaction.MouseWheelZoom,
  72077. OPENLAYERS);
  72078. goog.exportSymbol(
  72079. 'ol.interaction.MouseWheelZoom.handleEvent',
  72080. ol.interaction.MouseWheelZoom.handleEvent,
  72081. OPENLAYERS);
  72082. goog.exportProperty(
  72083. ol.interaction.MouseWheelZoom.prototype,
  72084. 'setMouseAnchor',
  72085. ol.interaction.MouseWheelZoom.prototype.setMouseAnchor);
  72086. goog.exportSymbol(
  72087. 'ol.interaction.PinchRotate',
  72088. ol.interaction.PinchRotate,
  72089. OPENLAYERS);
  72090. goog.exportSymbol(
  72091. 'ol.interaction.PinchZoom',
  72092. ol.interaction.PinchZoom,
  72093. OPENLAYERS);
  72094. goog.exportSymbol(
  72095. 'ol.interaction.Pointer',
  72096. ol.interaction.Pointer,
  72097. OPENLAYERS);
  72098. goog.exportSymbol(
  72099. 'ol.interaction.Pointer.handleEvent',
  72100. ol.interaction.Pointer.handleEvent,
  72101. OPENLAYERS);
  72102. goog.exportSymbol(
  72103. 'ol.interaction.Select',
  72104. ol.interaction.Select,
  72105. OPENLAYERS);
  72106. goog.exportProperty(
  72107. ol.interaction.Select.prototype,
  72108. 'getFeatures',
  72109. ol.interaction.Select.prototype.getFeatures);
  72110. goog.exportProperty(
  72111. ol.interaction.Select.prototype,
  72112. 'getHitTolerance',
  72113. ol.interaction.Select.prototype.getHitTolerance);
  72114. goog.exportProperty(
  72115. ol.interaction.Select.prototype,
  72116. 'getLayer',
  72117. ol.interaction.Select.prototype.getLayer);
  72118. goog.exportSymbol(
  72119. 'ol.interaction.Select.handleEvent',
  72120. ol.interaction.Select.handleEvent,
  72121. OPENLAYERS);
  72122. goog.exportProperty(
  72123. ol.interaction.Select.prototype,
  72124. 'setHitTolerance',
  72125. ol.interaction.Select.prototype.setHitTolerance);
  72126. goog.exportProperty(
  72127. ol.interaction.Select.prototype,
  72128. 'setMap',
  72129. ol.interaction.Select.prototype.setMap);
  72130. goog.exportProperty(
  72131. ol.interaction.Select.Event.prototype,
  72132. 'selected',
  72133. ol.interaction.Select.Event.prototype.selected);
  72134. goog.exportProperty(
  72135. ol.interaction.Select.Event.prototype,
  72136. 'deselected',
  72137. ol.interaction.Select.Event.prototype.deselected);
  72138. goog.exportProperty(
  72139. ol.interaction.Select.Event.prototype,
  72140. 'mapBrowserEvent',
  72141. ol.interaction.Select.Event.prototype.mapBrowserEvent);
  72142. goog.exportSymbol(
  72143. 'ol.interaction.Snap',
  72144. ol.interaction.Snap,
  72145. OPENLAYERS);
  72146. goog.exportProperty(
  72147. ol.interaction.Snap.prototype,
  72148. 'addFeature',
  72149. ol.interaction.Snap.prototype.addFeature);
  72150. goog.exportProperty(
  72151. ol.interaction.Snap.prototype,
  72152. 'removeFeature',
  72153. ol.interaction.Snap.prototype.removeFeature);
  72154. goog.exportSymbol(
  72155. 'ol.interaction.Translate',
  72156. ol.interaction.Translate,
  72157. OPENLAYERS);
  72158. goog.exportProperty(
  72159. ol.interaction.Translate.prototype,
  72160. 'getHitTolerance',
  72161. ol.interaction.Translate.prototype.getHitTolerance);
  72162. goog.exportProperty(
  72163. ol.interaction.Translate.prototype,
  72164. 'setHitTolerance',
  72165. ol.interaction.Translate.prototype.setHitTolerance);
  72166. goog.exportProperty(
  72167. ol.interaction.Translate.Event.prototype,
  72168. 'features',
  72169. ol.interaction.Translate.Event.prototype.features);
  72170. goog.exportProperty(
  72171. ol.interaction.Translate.Event.prototype,
  72172. 'coordinate',
  72173. ol.interaction.Translate.Event.prototype.coordinate);
  72174. goog.exportSymbol(
  72175. 'ol.geom.Circle',
  72176. ol.geom.Circle,
  72177. OPENLAYERS);
  72178. goog.exportProperty(
  72179. ol.geom.Circle.prototype,
  72180. 'clone',
  72181. ol.geom.Circle.prototype.clone);
  72182. goog.exportProperty(
  72183. ol.geom.Circle.prototype,
  72184. 'getCenter',
  72185. ol.geom.Circle.prototype.getCenter);
  72186. goog.exportProperty(
  72187. ol.geom.Circle.prototype,
  72188. 'getRadius',
  72189. ol.geom.Circle.prototype.getRadius);
  72190. goog.exportProperty(
  72191. ol.geom.Circle.prototype,
  72192. 'getType',
  72193. ol.geom.Circle.prototype.getType);
  72194. goog.exportProperty(
  72195. ol.geom.Circle.prototype,
  72196. 'intersectsExtent',
  72197. ol.geom.Circle.prototype.intersectsExtent);
  72198. goog.exportProperty(
  72199. ol.geom.Circle.prototype,
  72200. 'setCenter',
  72201. ol.geom.Circle.prototype.setCenter);
  72202. goog.exportProperty(
  72203. ol.geom.Circle.prototype,
  72204. 'setCenterAndRadius',
  72205. ol.geom.Circle.prototype.setCenterAndRadius);
  72206. goog.exportProperty(
  72207. ol.geom.Circle.prototype,
  72208. 'setRadius',
  72209. ol.geom.Circle.prototype.setRadius);
  72210. goog.exportProperty(
  72211. ol.geom.Circle.prototype,
  72212. 'transform',
  72213. ol.geom.Circle.prototype.transform);
  72214. goog.exportSymbol(
  72215. 'ol.geom.Geometry',
  72216. ol.geom.Geometry,
  72217. OPENLAYERS);
  72218. goog.exportProperty(
  72219. ol.geom.Geometry.prototype,
  72220. 'getClosestPoint',
  72221. ol.geom.Geometry.prototype.getClosestPoint);
  72222. goog.exportProperty(
  72223. ol.geom.Geometry.prototype,
  72224. 'intersectsCoordinate',
  72225. ol.geom.Geometry.prototype.intersectsCoordinate);
  72226. goog.exportProperty(
  72227. ol.geom.Geometry.prototype,
  72228. 'getExtent',
  72229. ol.geom.Geometry.prototype.getExtent);
  72230. goog.exportProperty(
  72231. ol.geom.Geometry.prototype,
  72232. 'rotate',
  72233. ol.geom.Geometry.prototype.rotate);
  72234. goog.exportProperty(
  72235. ol.geom.Geometry.prototype,
  72236. 'scale',
  72237. ol.geom.Geometry.prototype.scale);
  72238. goog.exportProperty(
  72239. ol.geom.Geometry.prototype,
  72240. 'simplify',
  72241. ol.geom.Geometry.prototype.simplify);
  72242. goog.exportProperty(
  72243. ol.geom.Geometry.prototype,
  72244. 'transform',
  72245. ol.geom.Geometry.prototype.transform);
  72246. goog.exportSymbol(
  72247. 'ol.geom.GeometryCollection',
  72248. ol.geom.GeometryCollection,
  72249. OPENLAYERS);
  72250. goog.exportProperty(
  72251. ol.geom.GeometryCollection.prototype,
  72252. 'clone',
  72253. ol.geom.GeometryCollection.prototype.clone);
  72254. goog.exportProperty(
  72255. ol.geom.GeometryCollection.prototype,
  72256. 'getGeometries',
  72257. ol.geom.GeometryCollection.prototype.getGeometries);
  72258. goog.exportProperty(
  72259. ol.geom.GeometryCollection.prototype,
  72260. 'getType',
  72261. ol.geom.GeometryCollection.prototype.getType);
  72262. goog.exportProperty(
  72263. ol.geom.GeometryCollection.prototype,
  72264. 'intersectsExtent',
  72265. ol.geom.GeometryCollection.prototype.intersectsExtent);
  72266. goog.exportProperty(
  72267. ol.geom.GeometryCollection.prototype,
  72268. 'setGeometries',
  72269. ol.geom.GeometryCollection.prototype.setGeometries);
  72270. goog.exportProperty(
  72271. ol.geom.GeometryCollection.prototype,
  72272. 'applyTransform',
  72273. ol.geom.GeometryCollection.prototype.applyTransform);
  72274. goog.exportProperty(
  72275. ol.geom.GeometryCollection.prototype,
  72276. 'translate',
  72277. ol.geom.GeometryCollection.prototype.translate);
  72278. goog.exportSymbol(
  72279. 'ol.geom.LinearRing',
  72280. ol.geom.LinearRing,
  72281. OPENLAYERS);
  72282. goog.exportProperty(
  72283. ol.geom.LinearRing.prototype,
  72284. 'clone',
  72285. ol.geom.LinearRing.prototype.clone);
  72286. goog.exportProperty(
  72287. ol.geom.LinearRing.prototype,
  72288. 'getArea',
  72289. ol.geom.LinearRing.prototype.getArea);
  72290. goog.exportProperty(
  72291. ol.geom.LinearRing.prototype,
  72292. 'getCoordinates',
  72293. ol.geom.LinearRing.prototype.getCoordinates);
  72294. goog.exportProperty(
  72295. ol.geom.LinearRing.prototype,
  72296. 'getType',
  72297. ol.geom.LinearRing.prototype.getType);
  72298. goog.exportProperty(
  72299. ol.geom.LinearRing.prototype,
  72300. 'setCoordinates',
  72301. ol.geom.LinearRing.prototype.setCoordinates);
  72302. goog.exportSymbol(
  72303. 'ol.geom.LineString',
  72304. ol.geom.LineString,
  72305. OPENLAYERS);
  72306. goog.exportProperty(
  72307. ol.geom.LineString.prototype,
  72308. 'appendCoordinate',
  72309. ol.geom.LineString.prototype.appendCoordinate);
  72310. goog.exportProperty(
  72311. ol.geom.LineString.prototype,
  72312. 'clone',
  72313. ol.geom.LineString.prototype.clone);
  72314. goog.exportProperty(
  72315. ol.geom.LineString.prototype,
  72316. 'forEachSegment',
  72317. ol.geom.LineString.prototype.forEachSegment);
  72318. goog.exportProperty(
  72319. ol.geom.LineString.prototype,
  72320. 'getCoordinateAtM',
  72321. ol.geom.LineString.prototype.getCoordinateAtM);
  72322. goog.exportProperty(
  72323. ol.geom.LineString.prototype,
  72324. 'getCoordinates',
  72325. ol.geom.LineString.prototype.getCoordinates);
  72326. goog.exportProperty(
  72327. ol.geom.LineString.prototype,
  72328. 'getCoordinateAt',
  72329. ol.geom.LineString.prototype.getCoordinateAt);
  72330. goog.exportProperty(
  72331. ol.geom.LineString.prototype,
  72332. 'getLength',
  72333. ol.geom.LineString.prototype.getLength);
  72334. goog.exportProperty(
  72335. ol.geom.LineString.prototype,
  72336. 'getType',
  72337. ol.geom.LineString.prototype.getType);
  72338. goog.exportProperty(
  72339. ol.geom.LineString.prototype,
  72340. 'intersectsExtent',
  72341. ol.geom.LineString.prototype.intersectsExtent);
  72342. goog.exportProperty(
  72343. ol.geom.LineString.prototype,
  72344. 'setCoordinates',
  72345. ol.geom.LineString.prototype.setCoordinates);
  72346. goog.exportSymbol(
  72347. 'ol.geom.MultiLineString',
  72348. ol.geom.MultiLineString,
  72349. OPENLAYERS);
  72350. goog.exportProperty(
  72351. ol.geom.MultiLineString.prototype,
  72352. 'appendLineString',
  72353. ol.geom.MultiLineString.prototype.appendLineString);
  72354. goog.exportProperty(
  72355. ol.geom.MultiLineString.prototype,
  72356. 'clone',
  72357. ol.geom.MultiLineString.prototype.clone);
  72358. goog.exportProperty(
  72359. ol.geom.MultiLineString.prototype,
  72360. 'getCoordinateAtM',
  72361. ol.geom.MultiLineString.prototype.getCoordinateAtM);
  72362. goog.exportProperty(
  72363. ol.geom.MultiLineString.prototype,
  72364. 'getCoordinates',
  72365. ol.geom.MultiLineString.prototype.getCoordinates);
  72366. goog.exportProperty(
  72367. ol.geom.MultiLineString.prototype,
  72368. 'getLineString',
  72369. ol.geom.MultiLineString.prototype.getLineString);
  72370. goog.exportProperty(
  72371. ol.geom.MultiLineString.prototype,
  72372. 'getLineStrings',
  72373. ol.geom.MultiLineString.prototype.getLineStrings);
  72374. goog.exportProperty(
  72375. ol.geom.MultiLineString.prototype,
  72376. 'getType',
  72377. ol.geom.MultiLineString.prototype.getType);
  72378. goog.exportProperty(
  72379. ol.geom.MultiLineString.prototype,
  72380. 'intersectsExtent',
  72381. ol.geom.MultiLineString.prototype.intersectsExtent);
  72382. goog.exportProperty(
  72383. ol.geom.MultiLineString.prototype,
  72384. 'setCoordinates',
  72385. ol.geom.MultiLineString.prototype.setCoordinates);
  72386. goog.exportSymbol(
  72387. 'ol.geom.MultiPoint',
  72388. ol.geom.MultiPoint,
  72389. OPENLAYERS);
  72390. goog.exportProperty(
  72391. ol.geom.MultiPoint.prototype,
  72392. 'appendPoint',
  72393. ol.geom.MultiPoint.prototype.appendPoint);
  72394. goog.exportProperty(
  72395. ol.geom.MultiPoint.prototype,
  72396. 'clone',
  72397. ol.geom.MultiPoint.prototype.clone);
  72398. goog.exportProperty(
  72399. ol.geom.MultiPoint.prototype,
  72400. 'getCoordinates',
  72401. ol.geom.MultiPoint.prototype.getCoordinates);
  72402. goog.exportProperty(
  72403. ol.geom.MultiPoint.prototype,
  72404. 'getPoint',
  72405. ol.geom.MultiPoint.prototype.getPoint);
  72406. goog.exportProperty(
  72407. ol.geom.MultiPoint.prototype,
  72408. 'getPoints',
  72409. ol.geom.MultiPoint.prototype.getPoints);
  72410. goog.exportProperty(
  72411. ol.geom.MultiPoint.prototype,
  72412. 'getType',
  72413. ol.geom.MultiPoint.prototype.getType);
  72414. goog.exportProperty(
  72415. ol.geom.MultiPoint.prototype,
  72416. 'intersectsExtent',
  72417. ol.geom.MultiPoint.prototype.intersectsExtent);
  72418. goog.exportProperty(
  72419. ol.geom.MultiPoint.prototype,
  72420. 'setCoordinates',
  72421. ol.geom.MultiPoint.prototype.setCoordinates);
  72422. goog.exportSymbol(
  72423. 'ol.geom.MultiPolygon',
  72424. ol.geom.MultiPolygon,
  72425. OPENLAYERS);
  72426. goog.exportProperty(
  72427. ol.geom.MultiPolygon.prototype,
  72428. 'appendPolygon',
  72429. ol.geom.MultiPolygon.prototype.appendPolygon);
  72430. goog.exportProperty(
  72431. ol.geom.MultiPolygon.prototype,
  72432. 'clone',
  72433. ol.geom.MultiPolygon.prototype.clone);
  72434. goog.exportProperty(
  72435. ol.geom.MultiPolygon.prototype,
  72436. 'getArea',
  72437. ol.geom.MultiPolygon.prototype.getArea);
  72438. goog.exportProperty(
  72439. ol.geom.MultiPolygon.prototype,
  72440. 'getCoordinates',
  72441. ol.geom.MultiPolygon.prototype.getCoordinates);
  72442. goog.exportProperty(
  72443. ol.geom.MultiPolygon.prototype,
  72444. 'getInteriorPoints',
  72445. ol.geom.MultiPolygon.prototype.getInteriorPoints);
  72446. goog.exportProperty(
  72447. ol.geom.MultiPolygon.prototype,
  72448. 'getPolygon',
  72449. ol.geom.MultiPolygon.prototype.getPolygon);
  72450. goog.exportProperty(
  72451. ol.geom.MultiPolygon.prototype,
  72452. 'getPolygons',
  72453. ol.geom.MultiPolygon.prototype.getPolygons);
  72454. goog.exportProperty(
  72455. ol.geom.MultiPolygon.prototype,
  72456. 'getType',
  72457. ol.geom.MultiPolygon.prototype.getType);
  72458. goog.exportProperty(
  72459. ol.geom.MultiPolygon.prototype,
  72460. 'intersectsExtent',
  72461. ol.geom.MultiPolygon.prototype.intersectsExtent);
  72462. goog.exportProperty(
  72463. ol.geom.MultiPolygon.prototype,
  72464. 'setCoordinates',
  72465. ol.geom.MultiPolygon.prototype.setCoordinates);
  72466. goog.exportSymbol(
  72467. 'ol.geom.Point',
  72468. ol.geom.Point,
  72469. OPENLAYERS);
  72470. goog.exportProperty(
  72471. ol.geom.Point.prototype,
  72472. 'clone',
  72473. ol.geom.Point.prototype.clone);
  72474. goog.exportProperty(
  72475. ol.geom.Point.prototype,
  72476. 'getCoordinates',
  72477. ol.geom.Point.prototype.getCoordinates);
  72478. goog.exportProperty(
  72479. ol.geom.Point.prototype,
  72480. 'getType',
  72481. ol.geom.Point.prototype.getType);
  72482. goog.exportProperty(
  72483. ol.geom.Point.prototype,
  72484. 'intersectsExtent',
  72485. ol.geom.Point.prototype.intersectsExtent);
  72486. goog.exportProperty(
  72487. ol.geom.Point.prototype,
  72488. 'setCoordinates',
  72489. ol.geom.Point.prototype.setCoordinates);
  72490. goog.exportSymbol(
  72491. 'ol.geom.Polygon',
  72492. ol.geom.Polygon,
  72493. OPENLAYERS);
  72494. goog.exportProperty(
  72495. ol.geom.Polygon.prototype,
  72496. 'appendLinearRing',
  72497. ol.geom.Polygon.prototype.appendLinearRing);
  72498. goog.exportProperty(
  72499. ol.geom.Polygon.prototype,
  72500. 'clone',
  72501. ol.geom.Polygon.prototype.clone);
  72502. goog.exportProperty(
  72503. ol.geom.Polygon.prototype,
  72504. 'getArea',
  72505. ol.geom.Polygon.prototype.getArea);
  72506. goog.exportProperty(
  72507. ol.geom.Polygon.prototype,
  72508. 'getCoordinates',
  72509. ol.geom.Polygon.prototype.getCoordinates);
  72510. goog.exportProperty(
  72511. ol.geom.Polygon.prototype,
  72512. 'getInteriorPoint',
  72513. ol.geom.Polygon.prototype.getInteriorPoint);
  72514. goog.exportProperty(
  72515. ol.geom.Polygon.prototype,
  72516. 'getLinearRingCount',
  72517. ol.geom.Polygon.prototype.getLinearRingCount);
  72518. goog.exportProperty(
  72519. ol.geom.Polygon.prototype,
  72520. 'getLinearRing',
  72521. ol.geom.Polygon.prototype.getLinearRing);
  72522. goog.exportProperty(
  72523. ol.geom.Polygon.prototype,
  72524. 'getLinearRings',
  72525. ol.geom.Polygon.prototype.getLinearRings);
  72526. goog.exportProperty(
  72527. ol.geom.Polygon.prototype,
  72528. 'getType',
  72529. ol.geom.Polygon.prototype.getType);
  72530. goog.exportProperty(
  72531. ol.geom.Polygon.prototype,
  72532. 'intersectsExtent',
  72533. ol.geom.Polygon.prototype.intersectsExtent);
  72534. goog.exportProperty(
  72535. ol.geom.Polygon.prototype,
  72536. 'setCoordinates',
  72537. ol.geom.Polygon.prototype.setCoordinates);
  72538. goog.exportSymbol(
  72539. 'ol.geom.Polygon.circular',
  72540. ol.geom.Polygon.circular,
  72541. OPENLAYERS);
  72542. goog.exportSymbol(
  72543. 'ol.geom.Polygon.fromExtent',
  72544. ol.geom.Polygon.fromExtent,
  72545. OPENLAYERS);
  72546. goog.exportSymbol(
  72547. 'ol.geom.Polygon.fromCircle',
  72548. ol.geom.Polygon.fromCircle,
  72549. OPENLAYERS);
  72550. goog.exportSymbol(
  72551. 'ol.geom.SimpleGeometry',
  72552. ol.geom.SimpleGeometry,
  72553. OPENLAYERS);
  72554. goog.exportProperty(
  72555. ol.geom.SimpleGeometry.prototype,
  72556. 'getFirstCoordinate',
  72557. ol.geom.SimpleGeometry.prototype.getFirstCoordinate);
  72558. goog.exportProperty(
  72559. ol.geom.SimpleGeometry.prototype,
  72560. 'getLastCoordinate',
  72561. ol.geom.SimpleGeometry.prototype.getLastCoordinate);
  72562. goog.exportProperty(
  72563. ol.geom.SimpleGeometry.prototype,
  72564. 'getLayout',
  72565. ol.geom.SimpleGeometry.prototype.getLayout);
  72566. goog.exportProperty(
  72567. ol.geom.SimpleGeometry.prototype,
  72568. 'applyTransform',
  72569. ol.geom.SimpleGeometry.prototype.applyTransform);
  72570. goog.exportProperty(
  72571. ol.geom.SimpleGeometry.prototype,
  72572. 'translate',
  72573. ol.geom.SimpleGeometry.prototype.translate);
  72574. goog.exportSymbol(
  72575. 'ol.format.EsriJSON',
  72576. ol.format.EsriJSON,
  72577. OPENLAYERS);
  72578. goog.exportProperty(
  72579. ol.format.EsriJSON.prototype,
  72580. 'readFeature',
  72581. ol.format.EsriJSON.prototype.readFeature);
  72582. goog.exportProperty(
  72583. ol.format.EsriJSON.prototype,
  72584. 'readFeatures',
  72585. ol.format.EsriJSON.prototype.readFeatures);
  72586. goog.exportProperty(
  72587. ol.format.EsriJSON.prototype,
  72588. 'readGeometry',
  72589. ol.format.EsriJSON.prototype.readGeometry);
  72590. goog.exportProperty(
  72591. ol.format.EsriJSON.prototype,
  72592. 'readProjection',
  72593. ol.format.EsriJSON.prototype.readProjection);
  72594. goog.exportProperty(
  72595. ol.format.EsriJSON.prototype,
  72596. 'writeGeometry',
  72597. ol.format.EsriJSON.prototype.writeGeometry);
  72598. goog.exportProperty(
  72599. ol.format.EsriJSON.prototype,
  72600. 'writeGeometryObject',
  72601. ol.format.EsriJSON.prototype.writeGeometryObject);
  72602. goog.exportProperty(
  72603. ol.format.EsriJSON.prototype,
  72604. 'writeFeature',
  72605. ol.format.EsriJSON.prototype.writeFeature);
  72606. goog.exportProperty(
  72607. ol.format.EsriJSON.prototype,
  72608. 'writeFeatureObject',
  72609. ol.format.EsriJSON.prototype.writeFeatureObject);
  72610. goog.exportProperty(
  72611. ol.format.EsriJSON.prototype,
  72612. 'writeFeatures',
  72613. ol.format.EsriJSON.prototype.writeFeatures);
  72614. goog.exportProperty(
  72615. ol.format.EsriJSON.prototype,
  72616. 'writeFeaturesObject',
  72617. ol.format.EsriJSON.prototype.writeFeaturesObject);
  72618. goog.exportSymbol(
  72619. 'ol.format.Feature',
  72620. ol.format.Feature,
  72621. OPENLAYERS);
  72622. goog.exportSymbol(
  72623. 'ol.format.filter.and',
  72624. ol.format.filter.and,
  72625. OPENLAYERS);
  72626. goog.exportSymbol(
  72627. 'ol.format.filter.or',
  72628. ol.format.filter.or,
  72629. OPENLAYERS);
  72630. goog.exportSymbol(
  72631. 'ol.format.filter.not',
  72632. ol.format.filter.not,
  72633. OPENLAYERS);
  72634. goog.exportSymbol(
  72635. 'ol.format.filter.bbox',
  72636. ol.format.filter.bbox,
  72637. OPENLAYERS);
  72638. goog.exportSymbol(
  72639. 'ol.format.filter.intersects',
  72640. ol.format.filter.intersects,
  72641. OPENLAYERS);
  72642. goog.exportSymbol(
  72643. 'ol.format.filter.within',
  72644. ol.format.filter.within,
  72645. OPENLAYERS);
  72646. goog.exportSymbol(
  72647. 'ol.format.filter.equalTo',
  72648. ol.format.filter.equalTo,
  72649. OPENLAYERS);
  72650. goog.exportSymbol(
  72651. 'ol.format.filter.notEqualTo',
  72652. ol.format.filter.notEqualTo,
  72653. OPENLAYERS);
  72654. goog.exportSymbol(
  72655. 'ol.format.filter.lessThan',
  72656. ol.format.filter.lessThan,
  72657. OPENLAYERS);
  72658. goog.exportSymbol(
  72659. 'ol.format.filter.lessThanOrEqualTo',
  72660. ol.format.filter.lessThanOrEqualTo,
  72661. OPENLAYERS);
  72662. goog.exportSymbol(
  72663. 'ol.format.filter.greaterThan',
  72664. ol.format.filter.greaterThan,
  72665. OPENLAYERS);
  72666. goog.exportSymbol(
  72667. 'ol.format.filter.greaterThanOrEqualTo',
  72668. ol.format.filter.greaterThanOrEqualTo,
  72669. OPENLAYERS);
  72670. goog.exportSymbol(
  72671. 'ol.format.filter.isNull',
  72672. ol.format.filter.isNull,
  72673. OPENLAYERS);
  72674. goog.exportSymbol(
  72675. 'ol.format.filter.between',
  72676. ol.format.filter.between,
  72677. OPENLAYERS);
  72678. goog.exportSymbol(
  72679. 'ol.format.filter.like',
  72680. ol.format.filter.like,
  72681. OPENLAYERS);
  72682. goog.exportSymbol(
  72683. 'ol.format.filter.during',
  72684. ol.format.filter.during,
  72685. OPENLAYERS);
  72686. goog.exportSymbol(
  72687. 'ol.format.GeoJSON',
  72688. ol.format.GeoJSON,
  72689. OPENLAYERS);
  72690. goog.exportProperty(
  72691. ol.format.GeoJSON.prototype,
  72692. 'readFeature',
  72693. ol.format.GeoJSON.prototype.readFeature);
  72694. goog.exportProperty(
  72695. ol.format.GeoJSON.prototype,
  72696. 'readFeatures',
  72697. ol.format.GeoJSON.prototype.readFeatures);
  72698. goog.exportProperty(
  72699. ol.format.GeoJSON.prototype,
  72700. 'readGeometry',
  72701. ol.format.GeoJSON.prototype.readGeometry);
  72702. goog.exportProperty(
  72703. ol.format.GeoJSON.prototype,
  72704. 'readProjection',
  72705. ol.format.GeoJSON.prototype.readProjection);
  72706. goog.exportProperty(
  72707. ol.format.GeoJSON.prototype,
  72708. 'writeFeature',
  72709. ol.format.GeoJSON.prototype.writeFeature);
  72710. goog.exportProperty(
  72711. ol.format.GeoJSON.prototype,
  72712. 'writeFeatureObject',
  72713. ol.format.GeoJSON.prototype.writeFeatureObject);
  72714. goog.exportProperty(
  72715. ol.format.GeoJSON.prototype,
  72716. 'writeFeatures',
  72717. ol.format.GeoJSON.prototype.writeFeatures);
  72718. goog.exportProperty(
  72719. ol.format.GeoJSON.prototype,
  72720. 'writeFeaturesObject',
  72721. ol.format.GeoJSON.prototype.writeFeaturesObject);
  72722. goog.exportProperty(
  72723. ol.format.GeoJSON.prototype,
  72724. 'writeGeometry',
  72725. ol.format.GeoJSON.prototype.writeGeometry);
  72726. goog.exportProperty(
  72727. ol.format.GeoJSON.prototype,
  72728. 'writeGeometryObject',
  72729. ol.format.GeoJSON.prototype.writeGeometryObject);
  72730. goog.exportSymbol(
  72731. 'ol.format.GML',
  72732. ol.format.GML,
  72733. OPENLAYERS);
  72734. goog.exportProperty(
  72735. ol.format.GML.prototype,
  72736. 'writeFeatures',
  72737. ol.format.GML.prototype.writeFeatures);
  72738. goog.exportProperty(
  72739. ol.format.GML.prototype,
  72740. 'writeFeaturesNode',
  72741. ol.format.GML.prototype.writeFeaturesNode);
  72742. goog.exportSymbol(
  72743. 'ol.format.GML2',
  72744. ol.format.GML2,
  72745. OPENLAYERS);
  72746. goog.exportSymbol(
  72747. 'ol.format.GML3',
  72748. ol.format.GML3,
  72749. OPENLAYERS);
  72750. goog.exportProperty(
  72751. ol.format.GML3.prototype,
  72752. 'writeGeometryNode',
  72753. ol.format.GML3.prototype.writeGeometryNode);
  72754. goog.exportProperty(
  72755. ol.format.GML3.prototype,
  72756. 'writeFeatures',
  72757. ol.format.GML3.prototype.writeFeatures);
  72758. goog.exportProperty(
  72759. ol.format.GML3.prototype,
  72760. 'writeFeaturesNode',
  72761. ol.format.GML3.prototype.writeFeaturesNode);
  72762. goog.exportProperty(
  72763. ol.format.GMLBase.prototype,
  72764. 'readFeatures',
  72765. ol.format.GMLBase.prototype.readFeatures);
  72766. goog.exportSymbol(
  72767. 'ol.format.GPX',
  72768. ol.format.GPX,
  72769. OPENLAYERS);
  72770. goog.exportProperty(
  72771. ol.format.GPX.prototype,
  72772. 'readFeature',
  72773. ol.format.GPX.prototype.readFeature);
  72774. goog.exportProperty(
  72775. ol.format.GPX.prototype,
  72776. 'readFeatures',
  72777. ol.format.GPX.prototype.readFeatures);
  72778. goog.exportProperty(
  72779. ol.format.GPX.prototype,
  72780. 'readProjection',
  72781. ol.format.GPX.prototype.readProjection);
  72782. goog.exportProperty(
  72783. ol.format.GPX.prototype,
  72784. 'writeFeatures',
  72785. ol.format.GPX.prototype.writeFeatures);
  72786. goog.exportProperty(
  72787. ol.format.GPX.prototype,
  72788. 'writeFeaturesNode',
  72789. ol.format.GPX.prototype.writeFeaturesNode);
  72790. goog.exportSymbol(
  72791. 'ol.format.IGC',
  72792. ol.format.IGC,
  72793. OPENLAYERS);
  72794. goog.exportProperty(
  72795. ol.format.IGC.prototype,
  72796. 'readFeature',
  72797. ol.format.IGC.prototype.readFeature);
  72798. goog.exportProperty(
  72799. ol.format.IGC.prototype,
  72800. 'readFeatures',
  72801. ol.format.IGC.prototype.readFeatures);
  72802. goog.exportProperty(
  72803. ol.format.IGC.prototype,
  72804. 'readProjection',
  72805. ol.format.IGC.prototype.readProjection);
  72806. goog.exportSymbol(
  72807. 'ol.format.KML',
  72808. ol.format.KML,
  72809. OPENLAYERS);
  72810. goog.exportProperty(
  72811. ol.format.KML.prototype,
  72812. 'readFeature',
  72813. ol.format.KML.prototype.readFeature);
  72814. goog.exportProperty(
  72815. ol.format.KML.prototype,
  72816. 'readFeatures',
  72817. ol.format.KML.prototype.readFeatures);
  72818. goog.exportProperty(
  72819. ol.format.KML.prototype,
  72820. 'readName',
  72821. ol.format.KML.prototype.readName);
  72822. goog.exportProperty(
  72823. ol.format.KML.prototype,
  72824. 'readNetworkLinks',
  72825. ol.format.KML.prototype.readNetworkLinks);
  72826. goog.exportProperty(
  72827. ol.format.KML.prototype,
  72828. 'readRegion',
  72829. ol.format.KML.prototype.readRegion);
  72830. goog.exportProperty(
  72831. ol.format.KML.prototype,
  72832. 'readRegionFromNode',
  72833. ol.format.KML.prototype.readRegionFromNode);
  72834. goog.exportProperty(
  72835. ol.format.KML.prototype,
  72836. 'readProjection',
  72837. ol.format.KML.prototype.readProjection);
  72838. goog.exportProperty(
  72839. ol.format.KML.prototype,
  72840. 'writeFeatures',
  72841. ol.format.KML.prototype.writeFeatures);
  72842. goog.exportProperty(
  72843. ol.format.KML.prototype,
  72844. 'writeFeaturesNode',
  72845. ol.format.KML.prototype.writeFeaturesNode);
  72846. goog.exportSymbol(
  72847. 'ol.format.MVT',
  72848. ol.format.MVT,
  72849. OPENLAYERS);
  72850. goog.exportProperty(
  72851. ol.format.MVT.prototype,
  72852. 'getLastExtent',
  72853. ol.format.MVT.prototype.getLastExtent);
  72854. goog.exportProperty(
  72855. ol.format.MVT.prototype,
  72856. 'readFeatures',
  72857. ol.format.MVT.prototype.readFeatures);
  72858. goog.exportProperty(
  72859. ol.format.MVT.prototype,
  72860. 'readProjection',
  72861. ol.format.MVT.prototype.readProjection);
  72862. goog.exportProperty(
  72863. ol.format.MVT.prototype,
  72864. 'setLayers',
  72865. ol.format.MVT.prototype.setLayers);
  72866. goog.exportSymbol(
  72867. 'ol.format.OSMXML',
  72868. ol.format.OSMXML,
  72869. OPENLAYERS);
  72870. goog.exportProperty(
  72871. ol.format.OSMXML.prototype,
  72872. 'readFeatures',
  72873. ol.format.OSMXML.prototype.readFeatures);
  72874. goog.exportProperty(
  72875. ol.format.OSMXML.prototype,
  72876. 'readProjection',
  72877. ol.format.OSMXML.prototype.readProjection);
  72878. goog.exportSymbol(
  72879. 'ol.format.Polyline',
  72880. ol.format.Polyline,
  72881. OPENLAYERS);
  72882. goog.exportSymbol(
  72883. 'ol.format.Polyline.encodeDeltas',
  72884. ol.format.Polyline.encodeDeltas,
  72885. OPENLAYERS);
  72886. goog.exportSymbol(
  72887. 'ol.format.Polyline.decodeDeltas',
  72888. ol.format.Polyline.decodeDeltas,
  72889. OPENLAYERS);
  72890. goog.exportSymbol(
  72891. 'ol.format.Polyline.encodeFloats',
  72892. ol.format.Polyline.encodeFloats,
  72893. OPENLAYERS);
  72894. goog.exportSymbol(
  72895. 'ol.format.Polyline.decodeFloats',
  72896. ol.format.Polyline.decodeFloats,
  72897. OPENLAYERS);
  72898. goog.exportProperty(
  72899. ol.format.Polyline.prototype,
  72900. 'readFeature',
  72901. ol.format.Polyline.prototype.readFeature);
  72902. goog.exportProperty(
  72903. ol.format.Polyline.prototype,
  72904. 'readFeatures',
  72905. ol.format.Polyline.prototype.readFeatures);
  72906. goog.exportProperty(
  72907. ol.format.Polyline.prototype,
  72908. 'readGeometry',
  72909. ol.format.Polyline.prototype.readGeometry);
  72910. goog.exportProperty(
  72911. ol.format.Polyline.prototype,
  72912. 'readProjection',
  72913. ol.format.Polyline.prototype.readProjection);
  72914. goog.exportProperty(
  72915. ol.format.Polyline.prototype,
  72916. 'writeGeometry',
  72917. ol.format.Polyline.prototype.writeGeometry);
  72918. goog.exportSymbol(
  72919. 'ol.format.TopoJSON',
  72920. ol.format.TopoJSON,
  72921. OPENLAYERS);
  72922. goog.exportProperty(
  72923. ol.format.TopoJSON.prototype,
  72924. 'readFeatures',
  72925. ol.format.TopoJSON.prototype.readFeatures);
  72926. goog.exportProperty(
  72927. ol.format.TopoJSON.prototype,
  72928. 'readProjection',
  72929. ol.format.TopoJSON.prototype.readProjection);
  72930. goog.exportSymbol(
  72931. 'ol.format.WFS',
  72932. ol.format.WFS,
  72933. OPENLAYERS);
  72934. goog.exportProperty(
  72935. ol.format.WFS.prototype,
  72936. 'readFeatures',
  72937. ol.format.WFS.prototype.readFeatures);
  72938. goog.exportProperty(
  72939. ol.format.WFS.prototype,
  72940. 'readTransactionResponse',
  72941. ol.format.WFS.prototype.readTransactionResponse);
  72942. goog.exportProperty(
  72943. ol.format.WFS.prototype,
  72944. 'readFeatureCollectionMetadata',
  72945. ol.format.WFS.prototype.readFeatureCollectionMetadata);
  72946. goog.exportSymbol(
  72947. 'ol.format.WFS.writeFilter',
  72948. ol.format.WFS.writeFilter,
  72949. OPENLAYERS);
  72950. goog.exportProperty(
  72951. ol.format.WFS.prototype,
  72952. 'writeGetFeature',
  72953. ol.format.WFS.prototype.writeGetFeature);
  72954. goog.exportProperty(
  72955. ol.format.WFS.prototype,
  72956. 'writeTransaction',
  72957. ol.format.WFS.prototype.writeTransaction);
  72958. goog.exportProperty(
  72959. ol.format.WFS.prototype,
  72960. 'readProjection',
  72961. ol.format.WFS.prototype.readProjection);
  72962. goog.exportSymbol(
  72963. 'ol.format.WKT',
  72964. ol.format.WKT,
  72965. OPENLAYERS);
  72966. goog.exportProperty(
  72967. ol.format.WKT.prototype,
  72968. 'readFeature',
  72969. ol.format.WKT.prototype.readFeature);
  72970. goog.exportProperty(
  72971. ol.format.WKT.prototype,
  72972. 'readFeatures',
  72973. ol.format.WKT.prototype.readFeatures);
  72974. goog.exportProperty(
  72975. ol.format.WKT.prototype,
  72976. 'readGeometry',
  72977. ol.format.WKT.prototype.readGeometry);
  72978. goog.exportProperty(
  72979. ol.format.WKT.prototype,
  72980. 'writeFeature',
  72981. ol.format.WKT.prototype.writeFeature);
  72982. goog.exportProperty(
  72983. ol.format.WKT.prototype,
  72984. 'writeFeatures',
  72985. ol.format.WKT.prototype.writeFeatures);
  72986. goog.exportProperty(
  72987. ol.format.WKT.prototype,
  72988. 'writeGeometry',
  72989. ol.format.WKT.prototype.writeGeometry);
  72990. goog.exportSymbol(
  72991. 'ol.format.WMSCapabilities',
  72992. ol.format.WMSCapabilities,
  72993. OPENLAYERS);
  72994. goog.exportProperty(
  72995. ol.format.WMSCapabilities.prototype,
  72996. 'read',
  72997. ol.format.WMSCapabilities.prototype.read);
  72998. goog.exportSymbol(
  72999. 'ol.format.WMSGetFeatureInfo',
  73000. ol.format.WMSGetFeatureInfo,
  73001. OPENLAYERS);
  73002. goog.exportProperty(
  73003. ol.format.WMSGetFeatureInfo.prototype,
  73004. 'readFeatures',
  73005. ol.format.WMSGetFeatureInfo.prototype.readFeatures);
  73006. goog.exportSymbol(
  73007. 'ol.format.WMTSCapabilities',
  73008. ol.format.WMTSCapabilities,
  73009. OPENLAYERS);
  73010. goog.exportProperty(
  73011. ol.format.WMTSCapabilities.prototype,
  73012. 'read',
  73013. ol.format.WMTSCapabilities.prototype.read);
  73014. goog.exportSymbol(
  73015. 'ol.format.filter.And',
  73016. ol.format.filter.And,
  73017. OPENLAYERS);
  73018. goog.exportSymbol(
  73019. 'ol.format.filter.Bbox',
  73020. ol.format.filter.Bbox,
  73021. OPENLAYERS);
  73022. goog.exportSymbol(
  73023. 'ol.format.filter.Comparison',
  73024. ol.format.filter.Comparison,
  73025. OPENLAYERS);
  73026. goog.exportSymbol(
  73027. 'ol.format.filter.ComparisonBinary',
  73028. ol.format.filter.ComparisonBinary,
  73029. OPENLAYERS);
  73030. goog.exportSymbol(
  73031. 'ol.format.filter.During',
  73032. ol.format.filter.During,
  73033. OPENLAYERS);
  73034. goog.exportSymbol(
  73035. 'ol.format.filter.EqualTo',
  73036. ol.format.filter.EqualTo,
  73037. OPENLAYERS);
  73038. goog.exportSymbol(
  73039. 'ol.format.filter.Filter',
  73040. ol.format.filter.Filter,
  73041. OPENLAYERS);
  73042. goog.exportSymbol(
  73043. 'ol.format.filter.GreaterThan',
  73044. ol.format.filter.GreaterThan,
  73045. OPENLAYERS);
  73046. goog.exportSymbol(
  73047. 'ol.format.filter.GreaterThanOrEqualTo',
  73048. ol.format.filter.GreaterThanOrEqualTo,
  73049. OPENLAYERS);
  73050. goog.exportSymbol(
  73051. 'ol.format.filter.Intersects',
  73052. ol.format.filter.Intersects,
  73053. OPENLAYERS);
  73054. goog.exportSymbol(
  73055. 'ol.format.filter.IsBetween',
  73056. ol.format.filter.IsBetween,
  73057. OPENLAYERS);
  73058. goog.exportSymbol(
  73059. 'ol.format.filter.IsLike',
  73060. ol.format.filter.IsLike,
  73061. OPENLAYERS);
  73062. goog.exportSymbol(
  73063. 'ol.format.filter.IsNull',
  73064. ol.format.filter.IsNull,
  73065. OPENLAYERS);
  73066. goog.exportSymbol(
  73067. 'ol.format.filter.LessThan',
  73068. ol.format.filter.LessThan,
  73069. OPENLAYERS);
  73070. goog.exportSymbol(
  73071. 'ol.format.filter.LessThanOrEqualTo',
  73072. ol.format.filter.LessThanOrEqualTo,
  73073. OPENLAYERS);
  73074. goog.exportSymbol(
  73075. 'ol.format.filter.Not',
  73076. ol.format.filter.Not,
  73077. OPENLAYERS);
  73078. goog.exportSymbol(
  73079. 'ol.format.filter.NotEqualTo',
  73080. ol.format.filter.NotEqualTo,
  73081. OPENLAYERS);
  73082. goog.exportSymbol(
  73083. 'ol.format.filter.Or',
  73084. ol.format.filter.Or,
  73085. OPENLAYERS);
  73086. goog.exportSymbol(
  73087. 'ol.format.filter.Spatial',
  73088. ol.format.filter.Spatial,
  73089. OPENLAYERS);
  73090. goog.exportSymbol(
  73091. 'ol.format.filter.Within',
  73092. ol.format.filter.Within,
  73093. OPENLAYERS);
  73094. goog.exportSymbol(
  73095. 'ol.events.condition.altKeyOnly',
  73096. ol.events.condition.altKeyOnly,
  73097. OPENLAYERS);
  73098. goog.exportSymbol(
  73099. 'ol.events.condition.altShiftKeysOnly',
  73100. ol.events.condition.altShiftKeysOnly,
  73101. OPENLAYERS);
  73102. goog.exportSymbol(
  73103. 'ol.events.condition.always',
  73104. ol.events.condition.always,
  73105. OPENLAYERS);
  73106. goog.exportSymbol(
  73107. 'ol.events.condition.click',
  73108. ol.events.condition.click,
  73109. OPENLAYERS);
  73110. goog.exportSymbol(
  73111. 'ol.events.condition.never',
  73112. ol.events.condition.never,
  73113. OPENLAYERS);
  73114. goog.exportSymbol(
  73115. 'ol.events.condition.pointerMove',
  73116. ol.events.condition.pointerMove,
  73117. OPENLAYERS);
  73118. goog.exportSymbol(
  73119. 'ol.events.condition.singleClick',
  73120. ol.events.condition.singleClick,
  73121. OPENLAYERS);
  73122. goog.exportSymbol(
  73123. 'ol.events.condition.doubleClick',
  73124. ol.events.condition.doubleClick,
  73125. OPENLAYERS);
  73126. goog.exportSymbol(
  73127. 'ol.events.condition.noModifierKeys',
  73128. ol.events.condition.noModifierKeys,
  73129. OPENLAYERS);
  73130. goog.exportSymbol(
  73131. 'ol.events.condition.platformModifierKeyOnly',
  73132. ol.events.condition.platformModifierKeyOnly,
  73133. OPENLAYERS);
  73134. goog.exportSymbol(
  73135. 'ol.events.condition.shiftKeyOnly',
  73136. ol.events.condition.shiftKeyOnly,
  73137. OPENLAYERS);
  73138. goog.exportSymbol(
  73139. 'ol.events.condition.targetNotEditable',
  73140. ol.events.condition.targetNotEditable,
  73141. OPENLAYERS);
  73142. goog.exportSymbol(
  73143. 'ol.events.condition.mouseOnly',
  73144. ol.events.condition.mouseOnly,
  73145. OPENLAYERS);
  73146. goog.exportSymbol(
  73147. 'ol.events.condition.primaryAction',
  73148. ol.events.condition.primaryAction,
  73149. OPENLAYERS);
  73150. goog.exportProperty(
  73151. ol.events.Event.prototype,
  73152. 'type',
  73153. ol.events.Event.prototype.type);
  73154. goog.exportProperty(
  73155. ol.events.Event.prototype,
  73156. 'target',
  73157. ol.events.Event.prototype.target);
  73158. goog.exportProperty(
  73159. ol.events.Event.prototype,
  73160. 'preventDefault',
  73161. ol.events.Event.prototype.preventDefault);
  73162. goog.exportProperty(
  73163. ol.events.Event.prototype,
  73164. 'stopPropagation',
  73165. ol.events.Event.prototype.stopPropagation);
  73166. goog.exportSymbol(
  73167. 'ol.control.Attribution',
  73168. ol.control.Attribution,
  73169. OPENLAYERS);
  73170. goog.exportSymbol(
  73171. 'ol.control.Attribution.render',
  73172. ol.control.Attribution.render,
  73173. OPENLAYERS);
  73174. goog.exportProperty(
  73175. ol.control.Attribution.prototype,
  73176. 'getCollapsible',
  73177. ol.control.Attribution.prototype.getCollapsible);
  73178. goog.exportProperty(
  73179. ol.control.Attribution.prototype,
  73180. 'setCollapsible',
  73181. ol.control.Attribution.prototype.setCollapsible);
  73182. goog.exportProperty(
  73183. ol.control.Attribution.prototype,
  73184. 'setCollapsed',
  73185. ol.control.Attribution.prototype.setCollapsed);
  73186. goog.exportProperty(
  73187. ol.control.Attribution.prototype,
  73188. 'getCollapsed',
  73189. ol.control.Attribution.prototype.getCollapsed);
  73190. goog.exportSymbol(
  73191. 'ol.control.Control',
  73192. ol.control.Control,
  73193. OPENLAYERS);
  73194. goog.exportProperty(
  73195. ol.control.Control.prototype,
  73196. 'getMap',
  73197. ol.control.Control.prototype.getMap);
  73198. goog.exportProperty(
  73199. ol.control.Control.prototype,
  73200. 'setMap',
  73201. ol.control.Control.prototype.setMap);
  73202. goog.exportProperty(
  73203. ol.control.Control.prototype,
  73204. 'setTarget',
  73205. ol.control.Control.prototype.setTarget);
  73206. goog.exportSymbol(
  73207. 'ol.control.FullScreen',
  73208. ol.control.FullScreen,
  73209. OPENLAYERS);
  73210. goog.exportSymbol(
  73211. 'ol.control.MousePosition',
  73212. ol.control.MousePosition,
  73213. OPENLAYERS);
  73214. goog.exportSymbol(
  73215. 'ol.control.MousePosition.render',
  73216. ol.control.MousePosition.render,
  73217. OPENLAYERS);
  73218. goog.exportProperty(
  73219. ol.control.MousePosition.prototype,
  73220. 'getCoordinateFormat',
  73221. ol.control.MousePosition.prototype.getCoordinateFormat);
  73222. goog.exportProperty(
  73223. ol.control.MousePosition.prototype,
  73224. 'getProjection',
  73225. ol.control.MousePosition.prototype.getProjection);
  73226. goog.exportProperty(
  73227. ol.control.MousePosition.prototype,
  73228. 'setCoordinateFormat',
  73229. ol.control.MousePosition.prototype.setCoordinateFormat);
  73230. goog.exportProperty(
  73231. ol.control.MousePosition.prototype,
  73232. 'setProjection',
  73233. ol.control.MousePosition.prototype.setProjection);
  73234. goog.exportSymbol(
  73235. 'ol.control.OverviewMap',
  73236. ol.control.OverviewMap,
  73237. OPENLAYERS);
  73238. goog.exportSymbol(
  73239. 'ol.control.OverviewMap.render',
  73240. ol.control.OverviewMap.render,
  73241. OPENLAYERS);
  73242. goog.exportProperty(
  73243. ol.control.OverviewMap.prototype,
  73244. 'getCollapsible',
  73245. ol.control.OverviewMap.prototype.getCollapsible);
  73246. goog.exportProperty(
  73247. ol.control.OverviewMap.prototype,
  73248. 'setCollapsible',
  73249. ol.control.OverviewMap.prototype.setCollapsible);
  73250. goog.exportProperty(
  73251. ol.control.OverviewMap.prototype,
  73252. 'setCollapsed',
  73253. ol.control.OverviewMap.prototype.setCollapsed);
  73254. goog.exportProperty(
  73255. ol.control.OverviewMap.prototype,
  73256. 'getCollapsed',
  73257. ol.control.OverviewMap.prototype.getCollapsed);
  73258. goog.exportProperty(
  73259. ol.control.OverviewMap.prototype,
  73260. 'getOverviewMap',
  73261. ol.control.OverviewMap.prototype.getOverviewMap);
  73262. goog.exportSymbol(
  73263. 'ol.control.Rotate',
  73264. ol.control.Rotate,
  73265. OPENLAYERS);
  73266. goog.exportSymbol(
  73267. 'ol.control.Rotate.render',
  73268. ol.control.Rotate.render,
  73269. OPENLAYERS);
  73270. goog.exportSymbol(
  73271. 'ol.control.ScaleLine',
  73272. ol.control.ScaleLine,
  73273. OPENLAYERS);
  73274. goog.exportProperty(
  73275. ol.control.ScaleLine.prototype,
  73276. 'getUnits',
  73277. ol.control.ScaleLine.prototype.getUnits);
  73278. goog.exportSymbol(
  73279. 'ol.control.ScaleLine.render',
  73280. ol.control.ScaleLine.render,
  73281. OPENLAYERS);
  73282. goog.exportProperty(
  73283. ol.control.ScaleLine.prototype,
  73284. 'setUnits',
  73285. ol.control.ScaleLine.prototype.setUnits);
  73286. goog.exportSymbol(
  73287. 'ol.control.Zoom',
  73288. ol.control.Zoom,
  73289. OPENLAYERS);
  73290. goog.exportSymbol(
  73291. 'ol.control.ZoomSlider',
  73292. ol.control.ZoomSlider,
  73293. OPENLAYERS);
  73294. goog.exportSymbol(
  73295. 'ol.control.ZoomSlider.render',
  73296. ol.control.ZoomSlider.render,
  73297. OPENLAYERS);
  73298. goog.exportSymbol(
  73299. 'ol.control.ZoomToExtent',
  73300. ol.control.ZoomToExtent,
  73301. OPENLAYERS);
  73302. goog.exportProperty(
  73303. ol.Object.prototype,
  73304. 'changed',
  73305. ol.Object.prototype.changed);
  73306. goog.exportProperty(
  73307. ol.Object.prototype,
  73308. 'dispatchEvent',
  73309. ol.Object.prototype.dispatchEvent);
  73310. goog.exportProperty(
  73311. ol.Object.prototype,
  73312. 'getRevision',
  73313. ol.Object.prototype.getRevision);
  73314. goog.exportProperty(
  73315. ol.Object.prototype,
  73316. 'on',
  73317. ol.Object.prototype.on);
  73318. goog.exportProperty(
  73319. ol.Object.prototype,
  73320. 'once',
  73321. ol.Object.prototype.once);
  73322. goog.exportProperty(
  73323. ol.Object.prototype,
  73324. 'un',
  73325. ol.Object.prototype.un);
  73326. goog.exportProperty(
  73327. ol.Collection.prototype,
  73328. 'get',
  73329. ol.Collection.prototype.get);
  73330. goog.exportProperty(
  73331. ol.Collection.prototype,
  73332. 'getKeys',
  73333. ol.Collection.prototype.getKeys);
  73334. goog.exportProperty(
  73335. ol.Collection.prototype,
  73336. 'getProperties',
  73337. ol.Collection.prototype.getProperties);
  73338. goog.exportProperty(
  73339. ol.Collection.prototype,
  73340. 'set',
  73341. ol.Collection.prototype.set);
  73342. goog.exportProperty(
  73343. ol.Collection.prototype,
  73344. 'setProperties',
  73345. ol.Collection.prototype.setProperties);
  73346. goog.exportProperty(
  73347. ol.Collection.prototype,
  73348. 'unset',
  73349. ol.Collection.prototype.unset);
  73350. goog.exportProperty(
  73351. ol.Collection.prototype,
  73352. 'changed',
  73353. ol.Collection.prototype.changed);
  73354. goog.exportProperty(
  73355. ol.Collection.prototype,
  73356. 'dispatchEvent',
  73357. ol.Collection.prototype.dispatchEvent);
  73358. goog.exportProperty(
  73359. ol.Collection.prototype,
  73360. 'getRevision',
  73361. ol.Collection.prototype.getRevision);
  73362. goog.exportProperty(
  73363. ol.Collection.prototype,
  73364. 'on',
  73365. ol.Collection.prototype.on);
  73366. goog.exportProperty(
  73367. ol.Collection.prototype,
  73368. 'once',
  73369. ol.Collection.prototype.once);
  73370. goog.exportProperty(
  73371. ol.Collection.prototype,
  73372. 'un',
  73373. ol.Collection.prototype.un);
  73374. goog.exportProperty(
  73375. ol.Collection.Event.prototype,
  73376. 'type',
  73377. ol.Collection.Event.prototype.type);
  73378. goog.exportProperty(
  73379. ol.Collection.Event.prototype,
  73380. 'target',
  73381. ol.Collection.Event.prototype.target);
  73382. goog.exportProperty(
  73383. ol.Collection.Event.prototype,
  73384. 'preventDefault',
  73385. ol.Collection.Event.prototype.preventDefault);
  73386. goog.exportProperty(
  73387. ol.Collection.Event.prototype,
  73388. 'stopPropagation',
  73389. ol.Collection.Event.prototype.stopPropagation);
  73390. goog.exportProperty(
  73391. ol.DeviceOrientation.prototype,
  73392. 'get',
  73393. ol.DeviceOrientation.prototype.get);
  73394. goog.exportProperty(
  73395. ol.DeviceOrientation.prototype,
  73396. 'getKeys',
  73397. ol.DeviceOrientation.prototype.getKeys);
  73398. goog.exportProperty(
  73399. ol.DeviceOrientation.prototype,
  73400. 'getProperties',
  73401. ol.DeviceOrientation.prototype.getProperties);
  73402. goog.exportProperty(
  73403. ol.DeviceOrientation.prototype,
  73404. 'set',
  73405. ol.DeviceOrientation.prototype.set);
  73406. goog.exportProperty(
  73407. ol.DeviceOrientation.prototype,
  73408. 'setProperties',
  73409. ol.DeviceOrientation.prototype.setProperties);
  73410. goog.exportProperty(
  73411. ol.DeviceOrientation.prototype,
  73412. 'unset',
  73413. ol.DeviceOrientation.prototype.unset);
  73414. goog.exportProperty(
  73415. ol.DeviceOrientation.prototype,
  73416. 'changed',
  73417. ol.DeviceOrientation.prototype.changed);
  73418. goog.exportProperty(
  73419. ol.DeviceOrientation.prototype,
  73420. 'dispatchEvent',
  73421. ol.DeviceOrientation.prototype.dispatchEvent);
  73422. goog.exportProperty(
  73423. ol.DeviceOrientation.prototype,
  73424. 'getRevision',
  73425. ol.DeviceOrientation.prototype.getRevision);
  73426. goog.exportProperty(
  73427. ol.DeviceOrientation.prototype,
  73428. 'on',
  73429. ol.DeviceOrientation.prototype.on);
  73430. goog.exportProperty(
  73431. ol.DeviceOrientation.prototype,
  73432. 'once',
  73433. ol.DeviceOrientation.prototype.once);
  73434. goog.exportProperty(
  73435. ol.DeviceOrientation.prototype,
  73436. 'un',
  73437. ol.DeviceOrientation.prototype.un);
  73438. goog.exportProperty(
  73439. ol.Feature.prototype,
  73440. 'get',
  73441. ol.Feature.prototype.get);
  73442. goog.exportProperty(
  73443. ol.Feature.prototype,
  73444. 'getKeys',
  73445. ol.Feature.prototype.getKeys);
  73446. goog.exportProperty(
  73447. ol.Feature.prototype,
  73448. 'getProperties',
  73449. ol.Feature.prototype.getProperties);
  73450. goog.exportProperty(
  73451. ol.Feature.prototype,
  73452. 'set',
  73453. ol.Feature.prototype.set);
  73454. goog.exportProperty(
  73455. ol.Feature.prototype,
  73456. 'setProperties',
  73457. ol.Feature.prototype.setProperties);
  73458. goog.exportProperty(
  73459. ol.Feature.prototype,
  73460. 'unset',
  73461. ol.Feature.prototype.unset);
  73462. goog.exportProperty(
  73463. ol.Feature.prototype,
  73464. 'changed',
  73465. ol.Feature.prototype.changed);
  73466. goog.exportProperty(
  73467. ol.Feature.prototype,
  73468. 'dispatchEvent',
  73469. ol.Feature.prototype.dispatchEvent);
  73470. goog.exportProperty(
  73471. ol.Feature.prototype,
  73472. 'getRevision',
  73473. ol.Feature.prototype.getRevision);
  73474. goog.exportProperty(
  73475. ol.Feature.prototype,
  73476. 'on',
  73477. ol.Feature.prototype.on);
  73478. goog.exportProperty(
  73479. ol.Feature.prototype,
  73480. 'once',
  73481. ol.Feature.prototype.once);
  73482. goog.exportProperty(
  73483. ol.Feature.prototype,
  73484. 'un',
  73485. ol.Feature.prototype.un);
  73486. goog.exportProperty(
  73487. ol.Geolocation.prototype,
  73488. 'get',
  73489. ol.Geolocation.prototype.get);
  73490. goog.exportProperty(
  73491. ol.Geolocation.prototype,
  73492. 'getKeys',
  73493. ol.Geolocation.prototype.getKeys);
  73494. goog.exportProperty(
  73495. ol.Geolocation.prototype,
  73496. 'getProperties',
  73497. ol.Geolocation.prototype.getProperties);
  73498. goog.exportProperty(
  73499. ol.Geolocation.prototype,
  73500. 'set',
  73501. ol.Geolocation.prototype.set);
  73502. goog.exportProperty(
  73503. ol.Geolocation.prototype,
  73504. 'setProperties',
  73505. ol.Geolocation.prototype.setProperties);
  73506. goog.exportProperty(
  73507. ol.Geolocation.prototype,
  73508. 'unset',
  73509. ol.Geolocation.prototype.unset);
  73510. goog.exportProperty(
  73511. ol.Geolocation.prototype,
  73512. 'changed',
  73513. ol.Geolocation.prototype.changed);
  73514. goog.exportProperty(
  73515. ol.Geolocation.prototype,
  73516. 'dispatchEvent',
  73517. ol.Geolocation.prototype.dispatchEvent);
  73518. goog.exportProperty(
  73519. ol.Geolocation.prototype,
  73520. 'getRevision',
  73521. ol.Geolocation.prototype.getRevision);
  73522. goog.exportProperty(
  73523. ol.Geolocation.prototype,
  73524. 'on',
  73525. ol.Geolocation.prototype.on);
  73526. goog.exportProperty(
  73527. ol.Geolocation.prototype,
  73528. 'once',
  73529. ol.Geolocation.prototype.once);
  73530. goog.exportProperty(
  73531. ol.Geolocation.prototype,
  73532. 'un',
  73533. ol.Geolocation.prototype.un);
  73534. goog.exportProperty(
  73535. ol.ImageTile.prototype,
  73536. 'getTileCoord',
  73537. ol.ImageTile.prototype.getTileCoord);
  73538. goog.exportProperty(
  73539. ol.ImageTile.prototype,
  73540. 'load',
  73541. ol.ImageTile.prototype.load);
  73542. goog.exportProperty(
  73543. ol.Map.prototype,
  73544. 'get',
  73545. ol.Map.prototype.get);
  73546. goog.exportProperty(
  73547. ol.Map.prototype,
  73548. 'getKeys',
  73549. ol.Map.prototype.getKeys);
  73550. goog.exportProperty(
  73551. ol.Map.prototype,
  73552. 'getProperties',
  73553. ol.Map.prototype.getProperties);
  73554. goog.exportProperty(
  73555. ol.Map.prototype,
  73556. 'set',
  73557. ol.Map.prototype.set);
  73558. goog.exportProperty(
  73559. ol.Map.prototype,
  73560. 'setProperties',
  73561. ol.Map.prototype.setProperties);
  73562. goog.exportProperty(
  73563. ol.Map.prototype,
  73564. 'unset',
  73565. ol.Map.prototype.unset);
  73566. goog.exportProperty(
  73567. ol.Map.prototype,
  73568. 'changed',
  73569. ol.Map.prototype.changed);
  73570. goog.exportProperty(
  73571. ol.Map.prototype,
  73572. 'dispatchEvent',
  73573. ol.Map.prototype.dispatchEvent);
  73574. goog.exportProperty(
  73575. ol.Map.prototype,
  73576. 'getRevision',
  73577. ol.Map.prototype.getRevision);
  73578. goog.exportProperty(
  73579. ol.Map.prototype,
  73580. 'on',
  73581. ol.Map.prototype.on);
  73582. goog.exportProperty(
  73583. ol.Map.prototype,
  73584. 'once',
  73585. ol.Map.prototype.once);
  73586. goog.exportProperty(
  73587. ol.Map.prototype,
  73588. 'un',
  73589. ol.Map.prototype.un);
  73590. goog.exportProperty(
  73591. ol.MapEvent.prototype,
  73592. 'type',
  73593. ol.MapEvent.prototype.type);
  73594. goog.exportProperty(
  73595. ol.MapEvent.prototype,
  73596. 'target',
  73597. ol.MapEvent.prototype.target);
  73598. goog.exportProperty(
  73599. ol.MapEvent.prototype,
  73600. 'preventDefault',
  73601. ol.MapEvent.prototype.preventDefault);
  73602. goog.exportProperty(
  73603. ol.MapEvent.prototype,
  73604. 'stopPropagation',
  73605. ol.MapEvent.prototype.stopPropagation);
  73606. goog.exportProperty(
  73607. ol.MapBrowserEvent.prototype,
  73608. 'map',
  73609. ol.MapBrowserEvent.prototype.map);
  73610. goog.exportProperty(
  73611. ol.MapBrowserEvent.prototype,
  73612. 'frameState',
  73613. ol.MapBrowserEvent.prototype.frameState);
  73614. goog.exportProperty(
  73615. ol.MapBrowserEvent.prototype,
  73616. 'type',
  73617. ol.MapBrowserEvent.prototype.type);
  73618. goog.exportProperty(
  73619. ol.MapBrowserEvent.prototype,
  73620. 'target',
  73621. ol.MapBrowserEvent.prototype.target);
  73622. goog.exportProperty(
  73623. ol.MapBrowserEvent.prototype,
  73624. 'preventDefault',
  73625. ol.MapBrowserEvent.prototype.preventDefault);
  73626. goog.exportProperty(
  73627. ol.MapBrowserEvent.prototype,
  73628. 'stopPropagation',
  73629. ol.MapBrowserEvent.prototype.stopPropagation);
  73630. goog.exportProperty(
  73631. ol.MapBrowserPointerEvent.prototype,
  73632. 'originalEvent',
  73633. ol.MapBrowserPointerEvent.prototype.originalEvent);
  73634. goog.exportProperty(
  73635. ol.MapBrowserPointerEvent.prototype,
  73636. 'pixel',
  73637. ol.MapBrowserPointerEvent.prototype.pixel);
  73638. goog.exportProperty(
  73639. ol.MapBrowserPointerEvent.prototype,
  73640. 'coordinate',
  73641. ol.MapBrowserPointerEvent.prototype.coordinate);
  73642. goog.exportProperty(
  73643. ol.MapBrowserPointerEvent.prototype,
  73644. 'dragging',
  73645. ol.MapBrowserPointerEvent.prototype.dragging);
  73646. goog.exportProperty(
  73647. ol.MapBrowserPointerEvent.prototype,
  73648. 'preventDefault',
  73649. ol.MapBrowserPointerEvent.prototype.preventDefault);
  73650. goog.exportProperty(
  73651. ol.MapBrowserPointerEvent.prototype,
  73652. 'stopPropagation',
  73653. ol.MapBrowserPointerEvent.prototype.stopPropagation);
  73654. goog.exportProperty(
  73655. ol.MapBrowserPointerEvent.prototype,
  73656. 'map',
  73657. ol.MapBrowserPointerEvent.prototype.map);
  73658. goog.exportProperty(
  73659. ol.MapBrowserPointerEvent.prototype,
  73660. 'frameState',
  73661. ol.MapBrowserPointerEvent.prototype.frameState);
  73662. goog.exportProperty(
  73663. ol.MapBrowserPointerEvent.prototype,
  73664. 'type',
  73665. ol.MapBrowserPointerEvent.prototype.type);
  73666. goog.exportProperty(
  73667. ol.MapBrowserPointerEvent.prototype,
  73668. 'target',
  73669. ol.MapBrowserPointerEvent.prototype.target);
  73670. goog.exportProperty(
  73671. ol.Object.Event.prototype,
  73672. 'type',
  73673. ol.Object.Event.prototype.type);
  73674. goog.exportProperty(
  73675. ol.Object.Event.prototype,
  73676. 'target',
  73677. ol.Object.Event.prototype.target);
  73678. goog.exportProperty(
  73679. ol.Object.Event.prototype,
  73680. 'preventDefault',
  73681. ol.Object.Event.prototype.preventDefault);
  73682. goog.exportProperty(
  73683. ol.Object.Event.prototype,
  73684. 'stopPropagation',
  73685. ol.Object.Event.prototype.stopPropagation);
  73686. goog.exportProperty(
  73687. ol.Overlay.prototype,
  73688. 'get',
  73689. ol.Overlay.prototype.get);
  73690. goog.exportProperty(
  73691. ol.Overlay.prototype,
  73692. 'getKeys',
  73693. ol.Overlay.prototype.getKeys);
  73694. goog.exportProperty(
  73695. ol.Overlay.prototype,
  73696. 'getProperties',
  73697. ol.Overlay.prototype.getProperties);
  73698. goog.exportProperty(
  73699. ol.Overlay.prototype,
  73700. 'set',
  73701. ol.Overlay.prototype.set);
  73702. goog.exportProperty(
  73703. ol.Overlay.prototype,
  73704. 'setProperties',
  73705. ol.Overlay.prototype.setProperties);
  73706. goog.exportProperty(
  73707. ol.Overlay.prototype,
  73708. 'unset',
  73709. ol.Overlay.prototype.unset);
  73710. goog.exportProperty(
  73711. ol.Overlay.prototype,
  73712. 'changed',
  73713. ol.Overlay.prototype.changed);
  73714. goog.exportProperty(
  73715. ol.Overlay.prototype,
  73716. 'dispatchEvent',
  73717. ol.Overlay.prototype.dispatchEvent);
  73718. goog.exportProperty(
  73719. ol.Overlay.prototype,
  73720. 'getRevision',
  73721. ol.Overlay.prototype.getRevision);
  73722. goog.exportProperty(
  73723. ol.Overlay.prototype,
  73724. 'on',
  73725. ol.Overlay.prototype.on);
  73726. goog.exportProperty(
  73727. ol.Overlay.prototype,
  73728. 'once',
  73729. ol.Overlay.prototype.once);
  73730. goog.exportProperty(
  73731. ol.Overlay.prototype,
  73732. 'un',
  73733. ol.Overlay.prototype.un);
  73734. goog.exportProperty(
  73735. ol.VectorImageTile.prototype,
  73736. 'getTileCoord',
  73737. ol.VectorImageTile.prototype.getTileCoord);
  73738. goog.exportProperty(
  73739. ol.VectorImageTile.prototype,
  73740. 'load',
  73741. ol.VectorImageTile.prototype.load);
  73742. goog.exportProperty(
  73743. ol.VectorTile.prototype,
  73744. 'getTileCoord',
  73745. ol.VectorTile.prototype.getTileCoord);
  73746. goog.exportProperty(
  73747. ol.VectorTile.prototype,
  73748. 'load',
  73749. ol.VectorTile.prototype.load);
  73750. goog.exportProperty(
  73751. ol.View.prototype,
  73752. 'get',
  73753. ol.View.prototype.get);
  73754. goog.exportProperty(
  73755. ol.View.prototype,
  73756. 'getKeys',
  73757. ol.View.prototype.getKeys);
  73758. goog.exportProperty(
  73759. ol.View.prototype,
  73760. 'getProperties',
  73761. ol.View.prototype.getProperties);
  73762. goog.exportProperty(
  73763. ol.View.prototype,
  73764. 'set',
  73765. ol.View.prototype.set);
  73766. goog.exportProperty(
  73767. ol.View.prototype,
  73768. 'setProperties',
  73769. ol.View.prototype.setProperties);
  73770. goog.exportProperty(
  73771. ol.View.prototype,
  73772. 'unset',
  73773. ol.View.prototype.unset);
  73774. goog.exportProperty(
  73775. ol.View.prototype,
  73776. 'changed',
  73777. ol.View.prototype.changed);
  73778. goog.exportProperty(
  73779. ol.View.prototype,
  73780. 'dispatchEvent',
  73781. ol.View.prototype.dispatchEvent);
  73782. goog.exportProperty(
  73783. ol.View.prototype,
  73784. 'getRevision',
  73785. ol.View.prototype.getRevision);
  73786. goog.exportProperty(
  73787. ol.View.prototype,
  73788. 'on',
  73789. ol.View.prototype.on);
  73790. goog.exportProperty(
  73791. ol.View.prototype,
  73792. 'once',
  73793. ol.View.prototype.once);
  73794. goog.exportProperty(
  73795. ol.View.prototype,
  73796. 'un',
  73797. ol.View.prototype.un);
  73798. goog.exportProperty(
  73799. ol.tilegrid.WMTS.prototype,
  73800. 'forEachTileCoord',
  73801. ol.tilegrid.WMTS.prototype.forEachTileCoord);
  73802. goog.exportProperty(
  73803. ol.tilegrid.WMTS.prototype,
  73804. 'getMaxZoom',
  73805. ol.tilegrid.WMTS.prototype.getMaxZoom);
  73806. goog.exportProperty(
  73807. ol.tilegrid.WMTS.prototype,
  73808. 'getMinZoom',
  73809. ol.tilegrid.WMTS.prototype.getMinZoom);
  73810. goog.exportProperty(
  73811. ol.tilegrid.WMTS.prototype,
  73812. 'getOrigin',
  73813. ol.tilegrid.WMTS.prototype.getOrigin);
  73814. goog.exportProperty(
  73815. ol.tilegrid.WMTS.prototype,
  73816. 'getResolution',
  73817. ol.tilegrid.WMTS.prototype.getResolution);
  73818. goog.exportProperty(
  73819. ol.tilegrid.WMTS.prototype,
  73820. 'getResolutions',
  73821. ol.tilegrid.WMTS.prototype.getResolutions);
  73822. goog.exportProperty(
  73823. ol.tilegrid.WMTS.prototype,
  73824. 'getTileCoordExtent',
  73825. ol.tilegrid.WMTS.prototype.getTileCoordExtent);
  73826. goog.exportProperty(
  73827. ol.tilegrid.WMTS.prototype,
  73828. 'getTileCoordForCoordAndResolution',
  73829. ol.tilegrid.WMTS.prototype.getTileCoordForCoordAndResolution);
  73830. goog.exportProperty(
  73831. ol.tilegrid.WMTS.prototype,
  73832. 'getTileCoordForCoordAndZ',
  73833. ol.tilegrid.WMTS.prototype.getTileCoordForCoordAndZ);
  73834. goog.exportProperty(
  73835. ol.tilegrid.WMTS.prototype,
  73836. 'getTileSize',
  73837. ol.tilegrid.WMTS.prototype.getTileSize);
  73838. goog.exportProperty(
  73839. ol.tilegrid.WMTS.prototype,
  73840. 'getZForResolution',
  73841. ol.tilegrid.WMTS.prototype.getZForResolution);
  73842. goog.exportProperty(
  73843. ol.style.RegularShape.prototype,
  73844. 'getOpacity',
  73845. ol.style.RegularShape.prototype.getOpacity);
  73846. goog.exportProperty(
  73847. ol.style.RegularShape.prototype,
  73848. 'getRotateWithView',
  73849. ol.style.RegularShape.prototype.getRotateWithView);
  73850. goog.exportProperty(
  73851. ol.style.RegularShape.prototype,
  73852. 'getRotation',
  73853. ol.style.RegularShape.prototype.getRotation);
  73854. goog.exportProperty(
  73855. ol.style.RegularShape.prototype,
  73856. 'getScale',
  73857. ol.style.RegularShape.prototype.getScale);
  73858. goog.exportProperty(
  73859. ol.style.RegularShape.prototype,
  73860. 'getSnapToPixel',
  73861. ol.style.RegularShape.prototype.getSnapToPixel);
  73862. goog.exportProperty(
  73863. ol.style.RegularShape.prototype,
  73864. 'setOpacity',
  73865. ol.style.RegularShape.prototype.setOpacity);
  73866. goog.exportProperty(
  73867. ol.style.RegularShape.prototype,
  73868. 'setRotation',
  73869. ol.style.RegularShape.prototype.setRotation);
  73870. goog.exportProperty(
  73871. ol.style.RegularShape.prototype,
  73872. 'setScale',
  73873. ol.style.RegularShape.prototype.setScale);
  73874. goog.exportProperty(
  73875. ol.style.Circle.prototype,
  73876. 'clone',
  73877. ol.style.Circle.prototype.clone);
  73878. goog.exportProperty(
  73879. ol.style.Circle.prototype,
  73880. 'getAngle',
  73881. ol.style.Circle.prototype.getAngle);
  73882. goog.exportProperty(
  73883. ol.style.Circle.prototype,
  73884. 'getFill',
  73885. ol.style.Circle.prototype.getFill);
  73886. goog.exportProperty(
  73887. ol.style.Circle.prototype,
  73888. 'getPoints',
  73889. ol.style.Circle.prototype.getPoints);
  73890. goog.exportProperty(
  73891. ol.style.Circle.prototype,
  73892. 'getRadius',
  73893. ol.style.Circle.prototype.getRadius);
  73894. goog.exportProperty(
  73895. ol.style.Circle.prototype,
  73896. 'getRadius2',
  73897. ol.style.Circle.prototype.getRadius2);
  73898. goog.exportProperty(
  73899. ol.style.Circle.prototype,
  73900. 'getStroke',
  73901. ol.style.Circle.prototype.getStroke);
  73902. goog.exportProperty(
  73903. ol.style.Circle.prototype,
  73904. 'getOpacity',
  73905. ol.style.Circle.prototype.getOpacity);
  73906. goog.exportProperty(
  73907. ol.style.Circle.prototype,
  73908. 'getRotateWithView',
  73909. ol.style.Circle.prototype.getRotateWithView);
  73910. goog.exportProperty(
  73911. ol.style.Circle.prototype,
  73912. 'getRotation',
  73913. ol.style.Circle.prototype.getRotation);
  73914. goog.exportProperty(
  73915. ol.style.Circle.prototype,
  73916. 'getScale',
  73917. ol.style.Circle.prototype.getScale);
  73918. goog.exportProperty(
  73919. ol.style.Circle.prototype,
  73920. 'getSnapToPixel',
  73921. ol.style.Circle.prototype.getSnapToPixel);
  73922. goog.exportProperty(
  73923. ol.style.Circle.prototype,
  73924. 'setOpacity',
  73925. ol.style.Circle.prototype.setOpacity);
  73926. goog.exportProperty(
  73927. ol.style.Circle.prototype,
  73928. 'setRotation',
  73929. ol.style.Circle.prototype.setRotation);
  73930. goog.exportProperty(
  73931. ol.style.Circle.prototype,
  73932. 'setScale',
  73933. ol.style.Circle.prototype.setScale);
  73934. goog.exportProperty(
  73935. ol.style.Icon.prototype,
  73936. 'getOpacity',
  73937. ol.style.Icon.prototype.getOpacity);
  73938. goog.exportProperty(
  73939. ol.style.Icon.prototype,
  73940. 'getRotateWithView',
  73941. ol.style.Icon.prototype.getRotateWithView);
  73942. goog.exportProperty(
  73943. ol.style.Icon.prototype,
  73944. 'getRotation',
  73945. ol.style.Icon.prototype.getRotation);
  73946. goog.exportProperty(
  73947. ol.style.Icon.prototype,
  73948. 'getScale',
  73949. ol.style.Icon.prototype.getScale);
  73950. goog.exportProperty(
  73951. ol.style.Icon.prototype,
  73952. 'getSnapToPixel',
  73953. ol.style.Icon.prototype.getSnapToPixel);
  73954. goog.exportProperty(
  73955. ol.style.Icon.prototype,
  73956. 'setOpacity',
  73957. ol.style.Icon.prototype.setOpacity);
  73958. goog.exportProperty(
  73959. ol.style.Icon.prototype,
  73960. 'setRotation',
  73961. ol.style.Icon.prototype.setRotation);
  73962. goog.exportProperty(
  73963. ol.style.Icon.prototype,
  73964. 'setScale',
  73965. ol.style.Icon.prototype.setScale);
  73966. goog.exportProperty(
  73967. ol.source.Source.prototype,
  73968. 'get',
  73969. ol.source.Source.prototype.get);
  73970. goog.exportProperty(
  73971. ol.source.Source.prototype,
  73972. 'getKeys',
  73973. ol.source.Source.prototype.getKeys);
  73974. goog.exportProperty(
  73975. ol.source.Source.prototype,
  73976. 'getProperties',
  73977. ol.source.Source.prototype.getProperties);
  73978. goog.exportProperty(
  73979. ol.source.Source.prototype,
  73980. 'set',
  73981. ol.source.Source.prototype.set);
  73982. goog.exportProperty(
  73983. ol.source.Source.prototype,
  73984. 'setProperties',
  73985. ol.source.Source.prototype.setProperties);
  73986. goog.exportProperty(
  73987. ol.source.Source.prototype,
  73988. 'unset',
  73989. ol.source.Source.prototype.unset);
  73990. goog.exportProperty(
  73991. ol.source.Source.prototype,
  73992. 'changed',
  73993. ol.source.Source.prototype.changed);
  73994. goog.exportProperty(
  73995. ol.source.Source.prototype,
  73996. 'dispatchEvent',
  73997. ol.source.Source.prototype.dispatchEvent);
  73998. goog.exportProperty(
  73999. ol.source.Source.prototype,
  74000. 'getRevision',
  74001. ol.source.Source.prototype.getRevision);
  74002. goog.exportProperty(
  74003. ol.source.Source.prototype,
  74004. 'on',
  74005. ol.source.Source.prototype.on);
  74006. goog.exportProperty(
  74007. ol.source.Source.prototype,
  74008. 'once',
  74009. ol.source.Source.prototype.once);
  74010. goog.exportProperty(
  74011. ol.source.Source.prototype,
  74012. 'un',
  74013. ol.source.Source.prototype.un);
  74014. goog.exportProperty(
  74015. ol.source.Tile.prototype,
  74016. 'getAttributions',
  74017. ol.source.Tile.prototype.getAttributions);
  74018. goog.exportProperty(
  74019. ol.source.Tile.prototype,
  74020. 'getLogo',
  74021. ol.source.Tile.prototype.getLogo);
  74022. goog.exportProperty(
  74023. ol.source.Tile.prototype,
  74024. 'getProjection',
  74025. ol.source.Tile.prototype.getProjection);
  74026. goog.exportProperty(
  74027. ol.source.Tile.prototype,
  74028. 'getState',
  74029. ol.source.Tile.prototype.getState);
  74030. goog.exportProperty(
  74031. ol.source.Tile.prototype,
  74032. 'refresh',
  74033. ol.source.Tile.prototype.refresh);
  74034. goog.exportProperty(
  74035. ol.source.Tile.prototype,
  74036. 'setAttributions',
  74037. ol.source.Tile.prototype.setAttributions);
  74038. goog.exportProperty(
  74039. ol.source.Tile.prototype,
  74040. 'get',
  74041. ol.source.Tile.prototype.get);
  74042. goog.exportProperty(
  74043. ol.source.Tile.prototype,
  74044. 'getKeys',
  74045. ol.source.Tile.prototype.getKeys);
  74046. goog.exportProperty(
  74047. ol.source.Tile.prototype,
  74048. 'getProperties',
  74049. ol.source.Tile.prototype.getProperties);
  74050. goog.exportProperty(
  74051. ol.source.Tile.prototype,
  74052. 'set',
  74053. ol.source.Tile.prototype.set);
  74054. goog.exportProperty(
  74055. ol.source.Tile.prototype,
  74056. 'setProperties',
  74057. ol.source.Tile.prototype.setProperties);
  74058. goog.exportProperty(
  74059. ol.source.Tile.prototype,
  74060. 'unset',
  74061. ol.source.Tile.prototype.unset);
  74062. goog.exportProperty(
  74063. ol.source.Tile.prototype,
  74064. 'changed',
  74065. ol.source.Tile.prototype.changed);
  74066. goog.exportProperty(
  74067. ol.source.Tile.prototype,
  74068. 'dispatchEvent',
  74069. ol.source.Tile.prototype.dispatchEvent);
  74070. goog.exportProperty(
  74071. ol.source.Tile.prototype,
  74072. 'getRevision',
  74073. ol.source.Tile.prototype.getRevision);
  74074. goog.exportProperty(
  74075. ol.source.Tile.prototype,
  74076. 'on',
  74077. ol.source.Tile.prototype.on);
  74078. goog.exportProperty(
  74079. ol.source.Tile.prototype,
  74080. 'once',
  74081. ol.source.Tile.prototype.once);
  74082. goog.exportProperty(
  74083. ol.source.Tile.prototype,
  74084. 'un',
  74085. ol.source.Tile.prototype.un);
  74086. goog.exportProperty(
  74087. ol.source.UrlTile.prototype,
  74088. 'getTileGrid',
  74089. ol.source.UrlTile.prototype.getTileGrid);
  74090. goog.exportProperty(
  74091. ol.source.UrlTile.prototype,
  74092. 'refresh',
  74093. ol.source.UrlTile.prototype.refresh);
  74094. goog.exportProperty(
  74095. ol.source.UrlTile.prototype,
  74096. 'getAttributions',
  74097. ol.source.UrlTile.prototype.getAttributions);
  74098. goog.exportProperty(
  74099. ol.source.UrlTile.prototype,
  74100. 'getLogo',
  74101. ol.source.UrlTile.prototype.getLogo);
  74102. goog.exportProperty(
  74103. ol.source.UrlTile.prototype,
  74104. 'getProjection',
  74105. ol.source.UrlTile.prototype.getProjection);
  74106. goog.exportProperty(
  74107. ol.source.UrlTile.prototype,
  74108. 'getState',
  74109. ol.source.UrlTile.prototype.getState);
  74110. goog.exportProperty(
  74111. ol.source.UrlTile.prototype,
  74112. 'setAttributions',
  74113. ol.source.UrlTile.prototype.setAttributions);
  74114. goog.exportProperty(
  74115. ol.source.UrlTile.prototype,
  74116. 'get',
  74117. ol.source.UrlTile.prototype.get);
  74118. goog.exportProperty(
  74119. ol.source.UrlTile.prototype,
  74120. 'getKeys',
  74121. ol.source.UrlTile.prototype.getKeys);
  74122. goog.exportProperty(
  74123. ol.source.UrlTile.prototype,
  74124. 'getProperties',
  74125. ol.source.UrlTile.prototype.getProperties);
  74126. goog.exportProperty(
  74127. ol.source.UrlTile.prototype,
  74128. 'set',
  74129. ol.source.UrlTile.prototype.set);
  74130. goog.exportProperty(
  74131. ol.source.UrlTile.prototype,
  74132. 'setProperties',
  74133. ol.source.UrlTile.prototype.setProperties);
  74134. goog.exportProperty(
  74135. ol.source.UrlTile.prototype,
  74136. 'unset',
  74137. ol.source.UrlTile.prototype.unset);
  74138. goog.exportProperty(
  74139. ol.source.UrlTile.prototype,
  74140. 'changed',
  74141. ol.source.UrlTile.prototype.changed);
  74142. goog.exportProperty(
  74143. ol.source.UrlTile.prototype,
  74144. 'dispatchEvent',
  74145. ol.source.UrlTile.prototype.dispatchEvent);
  74146. goog.exportProperty(
  74147. ol.source.UrlTile.prototype,
  74148. 'getRevision',
  74149. ol.source.UrlTile.prototype.getRevision);
  74150. goog.exportProperty(
  74151. ol.source.UrlTile.prototype,
  74152. 'on',
  74153. ol.source.UrlTile.prototype.on);
  74154. goog.exportProperty(
  74155. ol.source.UrlTile.prototype,
  74156. 'once',
  74157. ol.source.UrlTile.prototype.once);
  74158. goog.exportProperty(
  74159. ol.source.UrlTile.prototype,
  74160. 'un',
  74161. ol.source.UrlTile.prototype.un);
  74162. goog.exportProperty(
  74163. ol.source.TileImage.prototype,
  74164. 'getTileLoadFunction',
  74165. ol.source.TileImage.prototype.getTileLoadFunction);
  74166. goog.exportProperty(
  74167. ol.source.TileImage.prototype,
  74168. 'getTileUrlFunction',
  74169. ol.source.TileImage.prototype.getTileUrlFunction);
  74170. goog.exportProperty(
  74171. ol.source.TileImage.prototype,
  74172. 'getUrls',
  74173. ol.source.TileImage.prototype.getUrls);
  74174. goog.exportProperty(
  74175. ol.source.TileImage.prototype,
  74176. 'setTileLoadFunction',
  74177. ol.source.TileImage.prototype.setTileLoadFunction);
  74178. goog.exportProperty(
  74179. ol.source.TileImage.prototype,
  74180. 'setTileUrlFunction',
  74181. ol.source.TileImage.prototype.setTileUrlFunction);
  74182. goog.exportProperty(
  74183. ol.source.TileImage.prototype,
  74184. 'setUrl',
  74185. ol.source.TileImage.prototype.setUrl);
  74186. goog.exportProperty(
  74187. ol.source.TileImage.prototype,
  74188. 'setUrls',
  74189. ol.source.TileImage.prototype.setUrls);
  74190. goog.exportProperty(
  74191. ol.source.TileImage.prototype,
  74192. 'getTileGrid',
  74193. ol.source.TileImage.prototype.getTileGrid);
  74194. goog.exportProperty(
  74195. ol.source.TileImage.prototype,
  74196. 'refresh',
  74197. ol.source.TileImage.prototype.refresh);
  74198. goog.exportProperty(
  74199. ol.source.TileImage.prototype,
  74200. 'getAttributions',
  74201. ol.source.TileImage.prototype.getAttributions);
  74202. goog.exportProperty(
  74203. ol.source.TileImage.prototype,
  74204. 'getLogo',
  74205. ol.source.TileImage.prototype.getLogo);
  74206. goog.exportProperty(
  74207. ol.source.TileImage.prototype,
  74208. 'getProjection',
  74209. ol.source.TileImage.prototype.getProjection);
  74210. goog.exportProperty(
  74211. ol.source.TileImage.prototype,
  74212. 'getState',
  74213. ol.source.TileImage.prototype.getState);
  74214. goog.exportProperty(
  74215. ol.source.TileImage.prototype,
  74216. 'setAttributions',
  74217. ol.source.TileImage.prototype.setAttributions);
  74218. goog.exportProperty(
  74219. ol.source.TileImage.prototype,
  74220. 'get',
  74221. ol.source.TileImage.prototype.get);
  74222. goog.exportProperty(
  74223. ol.source.TileImage.prototype,
  74224. 'getKeys',
  74225. ol.source.TileImage.prototype.getKeys);
  74226. goog.exportProperty(
  74227. ol.source.TileImage.prototype,
  74228. 'getProperties',
  74229. ol.source.TileImage.prototype.getProperties);
  74230. goog.exportProperty(
  74231. ol.source.TileImage.prototype,
  74232. 'set',
  74233. ol.source.TileImage.prototype.set);
  74234. goog.exportProperty(
  74235. ol.source.TileImage.prototype,
  74236. 'setProperties',
  74237. ol.source.TileImage.prototype.setProperties);
  74238. goog.exportProperty(
  74239. ol.source.TileImage.prototype,
  74240. 'unset',
  74241. ol.source.TileImage.prototype.unset);
  74242. goog.exportProperty(
  74243. ol.source.TileImage.prototype,
  74244. 'changed',
  74245. ol.source.TileImage.prototype.changed);
  74246. goog.exportProperty(
  74247. ol.source.TileImage.prototype,
  74248. 'dispatchEvent',
  74249. ol.source.TileImage.prototype.dispatchEvent);
  74250. goog.exportProperty(
  74251. ol.source.TileImage.prototype,
  74252. 'getRevision',
  74253. ol.source.TileImage.prototype.getRevision);
  74254. goog.exportProperty(
  74255. ol.source.TileImage.prototype,
  74256. 'on',
  74257. ol.source.TileImage.prototype.on);
  74258. goog.exportProperty(
  74259. ol.source.TileImage.prototype,
  74260. 'once',
  74261. ol.source.TileImage.prototype.once);
  74262. goog.exportProperty(
  74263. ol.source.TileImage.prototype,
  74264. 'un',
  74265. ol.source.TileImage.prototype.un);
  74266. goog.exportProperty(
  74267. ol.source.BingMaps.prototype,
  74268. 'setRenderReprojectionEdges',
  74269. ol.source.BingMaps.prototype.setRenderReprojectionEdges);
  74270. goog.exportProperty(
  74271. ol.source.BingMaps.prototype,
  74272. 'setTileGridForProjection',
  74273. ol.source.BingMaps.prototype.setTileGridForProjection);
  74274. goog.exportProperty(
  74275. ol.source.BingMaps.prototype,
  74276. 'getTileLoadFunction',
  74277. ol.source.BingMaps.prototype.getTileLoadFunction);
  74278. goog.exportProperty(
  74279. ol.source.BingMaps.prototype,
  74280. 'getTileUrlFunction',
  74281. ol.source.BingMaps.prototype.getTileUrlFunction);
  74282. goog.exportProperty(
  74283. ol.source.BingMaps.prototype,
  74284. 'getUrls',
  74285. ol.source.BingMaps.prototype.getUrls);
  74286. goog.exportProperty(
  74287. ol.source.BingMaps.prototype,
  74288. 'setTileLoadFunction',
  74289. ol.source.BingMaps.prototype.setTileLoadFunction);
  74290. goog.exportProperty(
  74291. ol.source.BingMaps.prototype,
  74292. 'setTileUrlFunction',
  74293. ol.source.BingMaps.prototype.setTileUrlFunction);
  74294. goog.exportProperty(
  74295. ol.source.BingMaps.prototype,
  74296. 'setUrl',
  74297. ol.source.BingMaps.prototype.setUrl);
  74298. goog.exportProperty(
  74299. ol.source.BingMaps.prototype,
  74300. 'setUrls',
  74301. ol.source.BingMaps.prototype.setUrls);
  74302. goog.exportProperty(
  74303. ol.source.BingMaps.prototype,
  74304. 'getTileGrid',
  74305. ol.source.BingMaps.prototype.getTileGrid);
  74306. goog.exportProperty(
  74307. ol.source.BingMaps.prototype,
  74308. 'refresh',
  74309. ol.source.BingMaps.prototype.refresh);
  74310. goog.exportProperty(
  74311. ol.source.BingMaps.prototype,
  74312. 'getAttributions',
  74313. ol.source.BingMaps.prototype.getAttributions);
  74314. goog.exportProperty(
  74315. ol.source.BingMaps.prototype,
  74316. 'getLogo',
  74317. ol.source.BingMaps.prototype.getLogo);
  74318. goog.exportProperty(
  74319. ol.source.BingMaps.prototype,
  74320. 'getProjection',
  74321. ol.source.BingMaps.prototype.getProjection);
  74322. goog.exportProperty(
  74323. ol.source.BingMaps.prototype,
  74324. 'getState',
  74325. ol.source.BingMaps.prototype.getState);
  74326. goog.exportProperty(
  74327. ol.source.BingMaps.prototype,
  74328. 'setAttributions',
  74329. ol.source.BingMaps.prototype.setAttributions);
  74330. goog.exportProperty(
  74331. ol.source.BingMaps.prototype,
  74332. 'get',
  74333. ol.source.BingMaps.prototype.get);
  74334. goog.exportProperty(
  74335. ol.source.BingMaps.prototype,
  74336. 'getKeys',
  74337. ol.source.BingMaps.prototype.getKeys);
  74338. goog.exportProperty(
  74339. ol.source.BingMaps.prototype,
  74340. 'getProperties',
  74341. ol.source.BingMaps.prototype.getProperties);
  74342. goog.exportProperty(
  74343. ol.source.BingMaps.prototype,
  74344. 'set',
  74345. ol.source.BingMaps.prototype.set);
  74346. goog.exportProperty(
  74347. ol.source.BingMaps.prototype,
  74348. 'setProperties',
  74349. ol.source.BingMaps.prototype.setProperties);
  74350. goog.exportProperty(
  74351. ol.source.BingMaps.prototype,
  74352. 'unset',
  74353. ol.source.BingMaps.prototype.unset);
  74354. goog.exportProperty(
  74355. ol.source.BingMaps.prototype,
  74356. 'changed',
  74357. ol.source.BingMaps.prototype.changed);
  74358. goog.exportProperty(
  74359. ol.source.BingMaps.prototype,
  74360. 'dispatchEvent',
  74361. ol.source.BingMaps.prototype.dispatchEvent);
  74362. goog.exportProperty(
  74363. ol.source.BingMaps.prototype,
  74364. 'getRevision',
  74365. ol.source.BingMaps.prototype.getRevision);
  74366. goog.exportProperty(
  74367. ol.source.BingMaps.prototype,
  74368. 'on',
  74369. ol.source.BingMaps.prototype.on);
  74370. goog.exportProperty(
  74371. ol.source.BingMaps.prototype,
  74372. 'once',
  74373. ol.source.BingMaps.prototype.once);
  74374. goog.exportProperty(
  74375. ol.source.BingMaps.prototype,
  74376. 'un',
  74377. ol.source.BingMaps.prototype.un);
  74378. goog.exportProperty(
  74379. ol.source.XYZ.prototype,
  74380. 'setRenderReprojectionEdges',
  74381. ol.source.XYZ.prototype.setRenderReprojectionEdges);
  74382. goog.exportProperty(
  74383. ol.source.XYZ.prototype,
  74384. 'setTileGridForProjection',
  74385. ol.source.XYZ.prototype.setTileGridForProjection);
  74386. goog.exportProperty(
  74387. ol.source.XYZ.prototype,
  74388. 'getTileLoadFunction',
  74389. ol.source.XYZ.prototype.getTileLoadFunction);
  74390. goog.exportProperty(
  74391. ol.source.XYZ.prototype,
  74392. 'getTileUrlFunction',
  74393. ol.source.XYZ.prototype.getTileUrlFunction);
  74394. goog.exportProperty(
  74395. ol.source.XYZ.prototype,
  74396. 'getUrls',
  74397. ol.source.XYZ.prototype.getUrls);
  74398. goog.exportProperty(
  74399. ol.source.XYZ.prototype,
  74400. 'setTileLoadFunction',
  74401. ol.source.XYZ.prototype.setTileLoadFunction);
  74402. goog.exportProperty(
  74403. ol.source.XYZ.prototype,
  74404. 'setTileUrlFunction',
  74405. ol.source.XYZ.prototype.setTileUrlFunction);
  74406. goog.exportProperty(
  74407. ol.source.XYZ.prototype,
  74408. 'setUrl',
  74409. ol.source.XYZ.prototype.setUrl);
  74410. goog.exportProperty(
  74411. ol.source.XYZ.prototype,
  74412. 'setUrls',
  74413. ol.source.XYZ.prototype.setUrls);
  74414. goog.exportProperty(
  74415. ol.source.XYZ.prototype,
  74416. 'getTileGrid',
  74417. ol.source.XYZ.prototype.getTileGrid);
  74418. goog.exportProperty(
  74419. ol.source.XYZ.prototype,
  74420. 'refresh',
  74421. ol.source.XYZ.prototype.refresh);
  74422. goog.exportProperty(
  74423. ol.source.XYZ.prototype,
  74424. 'getAttributions',
  74425. ol.source.XYZ.prototype.getAttributions);
  74426. goog.exportProperty(
  74427. ol.source.XYZ.prototype,
  74428. 'getLogo',
  74429. ol.source.XYZ.prototype.getLogo);
  74430. goog.exportProperty(
  74431. ol.source.XYZ.prototype,
  74432. 'getProjection',
  74433. ol.source.XYZ.prototype.getProjection);
  74434. goog.exportProperty(
  74435. ol.source.XYZ.prototype,
  74436. 'getState',
  74437. ol.source.XYZ.prototype.getState);
  74438. goog.exportProperty(
  74439. ol.source.XYZ.prototype,
  74440. 'setAttributions',
  74441. ol.source.XYZ.prototype.setAttributions);
  74442. goog.exportProperty(
  74443. ol.source.XYZ.prototype,
  74444. 'get',
  74445. ol.source.XYZ.prototype.get);
  74446. goog.exportProperty(
  74447. ol.source.XYZ.prototype,
  74448. 'getKeys',
  74449. ol.source.XYZ.prototype.getKeys);
  74450. goog.exportProperty(
  74451. ol.source.XYZ.prototype,
  74452. 'getProperties',
  74453. ol.source.XYZ.prototype.getProperties);
  74454. goog.exportProperty(
  74455. ol.source.XYZ.prototype,
  74456. 'set',
  74457. ol.source.XYZ.prototype.set);
  74458. goog.exportProperty(
  74459. ol.source.XYZ.prototype,
  74460. 'setProperties',
  74461. ol.source.XYZ.prototype.setProperties);
  74462. goog.exportProperty(
  74463. ol.source.XYZ.prototype,
  74464. 'unset',
  74465. ol.source.XYZ.prototype.unset);
  74466. goog.exportProperty(
  74467. ol.source.XYZ.prototype,
  74468. 'changed',
  74469. ol.source.XYZ.prototype.changed);
  74470. goog.exportProperty(
  74471. ol.source.XYZ.prototype,
  74472. 'dispatchEvent',
  74473. ol.source.XYZ.prototype.dispatchEvent);
  74474. goog.exportProperty(
  74475. ol.source.XYZ.prototype,
  74476. 'getRevision',
  74477. ol.source.XYZ.prototype.getRevision);
  74478. goog.exportProperty(
  74479. ol.source.XYZ.prototype,
  74480. 'on',
  74481. ol.source.XYZ.prototype.on);
  74482. goog.exportProperty(
  74483. ol.source.XYZ.prototype,
  74484. 'once',
  74485. ol.source.XYZ.prototype.once);
  74486. goog.exportProperty(
  74487. ol.source.XYZ.prototype,
  74488. 'un',
  74489. ol.source.XYZ.prototype.un);
  74490. goog.exportProperty(
  74491. ol.source.CartoDB.prototype,
  74492. 'setRenderReprojectionEdges',
  74493. ol.source.CartoDB.prototype.setRenderReprojectionEdges);
  74494. goog.exportProperty(
  74495. ol.source.CartoDB.prototype,
  74496. 'setTileGridForProjection',
  74497. ol.source.CartoDB.prototype.setTileGridForProjection);
  74498. goog.exportProperty(
  74499. ol.source.CartoDB.prototype,
  74500. 'getTileLoadFunction',
  74501. ol.source.CartoDB.prototype.getTileLoadFunction);
  74502. goog.exportProperty(
  74503. ol.source.CartoDB.prototype,
  74504. 'getTileUrlFunction',
  74505. ol.source.CartoDB.prototype.getTileUrlFunction);
  74506. goog.exportProperty(
  74507. ol.source.CartoDB.prototype,
  74508. 'getUrls',
  74509. ol.source.CartoDB.prototype.getUrls);
  74510. goog.exportProperty(
  74511. ol.source.CartoDB.prototype,
  74512. 'setTileLoadFunction',
  74513. ol.source.CartoDB.prototype.setTileLoadFunction);
  74514. goog.exportProperty(
  74515. ol.source.CartoDB.prototype,
  74516. 'setTileUrlFunction',
  74517. ol.source.CartoDB.prototype.setTileUrlFunction);
  74518. goog.exportProperty(
  74519. ol.source.CartoDB.prototype,
  74520. 'setUrl',
  74521. ol.source.CartoDB.prototype.setUrl);
  74522. goog.exportProperty(
  74523. ol.source.CartoDB.prototype,
  74524. 'setUrls',
  74525. ol.source.CartoDB.prototype.setUrls);
  74526. goog.exportProperty(
  74527. ol.source.CartoDB.prototype,
  74528. 'getTileGrid',
  74529. ol.source.CartoDB.prototype.getTileGrid);
  74530. goog.exportProperty(
  74531. ol.source.CartoDB.prototype,
  74532. 'refresh',
  74533. ol.source.CartoDB.prototype.refresh);
  74534. goog.exportProperty(
  74535. ol.source.CartoDB.prototype,
  74536. 'getAttributions',
  74537. ol.source.CartoDB.prototype.getAttributions);
  74538. goog.exportProperty(
  74539. ol.source.CartoDB.prototype,
  74540. 'getLogo',
  74541. ol.source.CartoDB.prototype.getLogo);
  74542. goog.exportProperty(
  74543. ol.source.CartoDB.prototype,
  74544. 'getProjection',
  74545. ol.source.CartoDB.prototype.getProjection);
  74546. goog.exportProperty(
  74547. ol.source.CartoDB.prototype,
  74548. 'getState',
  74549. ol.source.CartoDB.prototype.getState);
  74550. goog.exportProperty(
  74551. ol.source.CartoDB.prototype,
  74552. 'setAttributions',
  74553. ol.source.CartoDB.prototype.setAttributions);
  74554. goog.exportProperty(
  74555. ol.source.CartoDB.prototype,
  74556. 'get',
  74557. ol.source.CartoDB.prototype.get);
  74558. goog.exportProperty(
  74559. ol.source.CartoDB.prototype,
  74560. 'getKeys',
  74561. ol.source.CartoDB.prototype.getKeys);
  74562. goog.exportProperty(
  74563. ol.source.CartoDB.prototype,
  74564. 'getProperties',
  74565. ol.source.CartoDB.prototype.getProperties);
  74566. goog.exportProperty(
  74567. ol.source.CartoDB.prototype,
  74568. 'set',
  74569. ol.source.CartoDB.prototype.set);
  74570. goog.exportProperty(
  74571. ol.source.CartoDB.prototype,
  74572. 'setProperties',
  74573. ol.source.CartoDB.prototype.setProperties);
  74574. goog.exportProperty(
  74575. ol.source.CartoDB.prototype,
  74576. 'unset',
  74577. ol.source.CartoDB.prototype.unset);
  74578. goog.exportProperty(
  74579. ol.source.CartoDB.prototype,
  74580. 'changed',
  74581. ol.source.CartoDB.prototype.changed);
  74582. goog.exportProperty(
  74583. ol.source.CartoDB.prototype,
  74584. 'dispatchEvent',
  74585. ol.source.CartoDB.prototype.dispatchEvent);
  74586. goog.exportProperty(
  74587. ol.source.CartoDB.prototype,
  74588. 'getRevision',
  74589. ol.source.CartoDB.prototype.getRevision);
  74590. goog.exportProperty(
  74591. ol.source.CartoDB.prototype,
  74592. 'on',
  74593. ol.source.CartoDB.prototype.on);
  74594. goog.exportProperty(
  74595. ol.source.CartoDB.prototype,
  74596. 'once',
  74597. ol.source.CartoDB.prototype.once);
  74598. goog.exportProperty(
  74599. ol.source.CartoDB.prototype,
  74600. 'un',
  74601. ol.source.CartoDB.prototype.un);
  74602. goog.exportProperty(
  74603. ol.source.Vector.prototype,
  74604. 'getAttributions',
  74605. ol.source.Vector.prototype.getAttributions);
  74606. goog.exportProperty(
  74607. ol.source.Vector.prototype,
  74608. 'getLogo',
  74609. ol.source.Vector.prototype.getLogo);
  74610. goog.exportProperty(
  74611. ol.source.Vector.prototype,
  74612. 'getProjection',
  74613. ol.source.Vector.prototype.getProjection);
  74614. goog.exportProperty(
  74615. ol.source.Vector.prototype,
  74616. 'getState',
  74617. ol.source.Vector.prototype.getState);
  74618. goog.exportProperty(
  74619. ol.source.Vector.prototype,
  74620. 'refresh',
  74621. ol.source.Vector.prototype.refresh);
  74622. goog.exportProperty(
  74623. ol.source.Vector.prototype,
  74624. 'setAttributions',
  74625. ol.source.Vector.prototype.setAttributions);
  74626. goog.exportProperty(
  74627. ol.source.Vector.prototype,
  74628. 'get',
  74629. ol.source.Vector.prototype.get);
  74630. goog.exportProperty(
  74631. ol.source.Vector.prototype,
  74632. 'getKeys',
  74633. ol.source.Vector.prototype.getKeys);
  74634. goog.exportProperty(
  74635. ol.source.Vector.prototype,
  74636. 'getProperties',
  74637. ol.source.Vector.prototype.getProperties);
  74638. goog.exportProperty(
  74639. ol.source.Vector.prototype,
  74640. 'set',
  74641. ol.source.Vector.prototype.set);
  74642. goog.exportProperty(
  74643. ol.source.Vector.prototype,
  74644. 'setProperties',
  74645. ol.source.Vector.prototype.setProperties);
  74646. goog.exportProperty(
  74647. ol.source.Vector.prototype,
  74648. 'unset',
  74649. ol.source.Vector.prototype.unset);
  74650. goog.exportProperty(
  74651. ol.source.Vector.prototype,
  74652. 'changed',
  74653. ol.source.Vector.prototype.changed);
  74654. goog.exportProperty(
  74655. ol.source.Vector.prototype,
  74656. 'dispatchEvent',
  74657. ol.source.Vector.prototype.dispatchEvent);
  74658. goog.exportProperty(
  74659. ol.source.Vector.prototype,
  74660. 'getRevision',
  74661. ol.source.Vector.prototype.getRevision);
  74662. goog.exportProperty(
  74663. ol.source.Vector.prototype,
  74664. 'on',
  74665. ol.source.Vector.prototype.on);
  74666. goog.exportProperty(
  74667. ol.source.Vector.prototype,
  74668. 'once',
  74669. ol.source.Vector.prototype.once);
  74670. goog.exportProperty(
  74671. ol.source.Vector.prototype,
  74672. 'un',
  74673. ol.source.Vector.prototype.un);
  74674. goog.exportProperty(
  74675. ol.source.Cluster.prototype,
  74676. 'addFeature',
  74677. ol.source.Cluster.prototype.addFeature);
  74678. goog.exportProperty(
  74679. ol.source.Cluster.prototype,
  74680. 'addFeatures',
  74681. ol.source.Cluster.prototype.addFeatures);
  74682. goog.exportProperty(
  74683. ol.source.Cluster.prototype,
  74684. 'clear',
  74685. ol.source.Cluster.prototype.clear);
  74686. goog.exportProperty(
  74687. ol.source.Cluster.prototype,
  74688. 'forEachFeature',
  74689. ol.source.Cluster.prototype.forEachFeature);
  74690. goog.exportProperty(
  74691. ol.source.Cluster.prototype,
  74692. 'forEachFeatureInExtent',
  74693. ol.source.Cluster.prototype.forEachFeatureInExtent);
  74694. goog.exportProperty(
  74695. ol.source.Cluster.prototype,
  74696. 'forEachFeatureIntersectingExtent',
  74697. ol.source.Cluster.prototype.forEachFeatureIntersectingExtent);
  74698. goog.exportProperty(
  74699. ol.source.Cluster.prototype,
  74700. 'getFeaturesCollection',
  74701. ol.source.Cluster.prototype.getFeaturesCollection);
  74702. goog.exportProperty(
  74703. ol.source.Cluster.prototype,
  74704. 'getFeatures',
  74705. ol.source.Cluster.prototype.getFeatures);
  74706. goog.exportProperty(
  74707. ol.source.Cluster.prototype,
  74708. 'getFeaturesAtCoordinate',
  74709. ol.source.Cluster.prototype.getFeaturesAtCoordinate);
  74710. goog.exportProperty(
  74711. ol.source.Cluster.prototype,
  74712. 'getFeaturesInExtent',
  74713. ol.source.Cluster.prototype.getFeaturesInExtent);
  74714. goog.exportProperty(
  74715. ol.source.Cluster.prototype,
  74716. 'getClosestFeatureToCoordinate',
  74717. ol.source.Cluster.prototype.getClosestFeatureToCoordinate);
  74718. goog.exportProperty(
  74719. ol.source.Cluster.prototype,
  74720. 'getExtent',
  74721. ol.source.Cluster.prototype.getExtent);
  74722. goog.exportProperty(
  74723. ol.source.Cluster.prototype,
  74724. 'getFeatureById',
  74725. ol.source.Cluster.prototype.getFeatureById);
  74726. goog.exportProperty(
  74727. ol.source.Cluster.prototype,
  74728. 'getFormat',
  74729. ol.source.Cluster.prototype.getFormat);
  74730. goog.exportProperty(
  74731. ol.source.Cluster.prototype,
  74732. 'getUrl',
  74733. ol.source.Cluster.prototype.getUrl);
  74734. goog.exportProperty(
  74735. ol.source.Cluster.prototype,
  74736. 'removeFeature',
  74737. ol.source.Cluster.prototype.removeFeature);
  74738. goog.exportProperty(
  74739. ol.source.Cluster.prototype,
  74740. 'getAttributions',
  74741. ol.source.Cluster.prototype.getAttributions);
  74742. goog.exportProperty(
  74743. ol.source.Cluster.prototype,
  74744. 'getLogo',
  74745. ol.source.Cluster.prototype.getLogo);
  74746. goog.exportProperty(
  74747. ol.source.Cluster.prototype,
  74748. 'getProjection',
  74749. ol.source.Cluster.prototype.getProjection);
  74750. goog.exportProperty(
  74751. ol.source.Cluster.prototype,
  74752. 'getState',
  74753. ol.source.Cluster.prototype.getState);
  74754. goog.exportProperty(
  74755. ol.source.Cluster.prototype,
  74756. 'refresh',
  74757. ol.source.Cluster.prototype.refresh);
  74758. goog.exportProperty(
  74759. ol.source.Cluster.prototype,
  74760. 'setAttributions',
  74761. ol.source.Cluster.prototype.setAttributions);
  74762. goog.exportProperty(
  74763. ol.source.Cluster.prototype,
  74764. 'get',
  74765. ol.source.Cluster.prototype.get);
  74766. goog.exportProperty(
  74767. ol.source.Cluster.prototype,
  74768. 'getKeys',
  74769. ol.source.Cluster.prototype.getKeys);
  74770. goog.exportProperty(
  74771. ol.source.Cluster.prototype,
  74772. 'getProperties',
  74773. ol.source.Cluster.prototype.getProperties);
  74774. goog.exportProperty(
  74775. ol.source.Cluster.prototype,
  74776. 'set',
  74777. ol.source.Cluster.prototype.set);
  74778. goog.exportProperty(
  74779. ol.source.Cluster.prototype,
  74780. 'setProperties',
  74781. ol.source.Cluster.prototype.setProperties);
  74782. goog.exportProperty(
  74783. ol.source.Cluster.prototype,
  74784. 'unset',
  74785. ol.source.Cluster.prototype.unset);
  74786. goog.exportProperty(
  74787. ol.source.Cluster.prototype,
  74788. 'changed',
  74789. ol.source.Cluster.prototype.changed);
  74790. goog.exportProperty(
  74791. ol.source.Cluster.prototype,
  74792. 'dispatchEvent',
  74793. ol.source.Cluster.prototype.dispatchEvent);
  74794. goog.exportProperty(
  74795. ol.source.Cluster.prototype,
  74796. 'getRevision',
  74797. ol.source.Cluster.prototype.getRevision);
  74798. goog.exportProperty(
  74799. ol.source.Cluster.prototype,
  74800. 'on',
  74801. ol.source.Cluster.prototype.on);
  74802. goog.exportProperty(
  74803. ol.source.Cluster.prototype,
  74804. 'once',
  74805. ol.source.Cluster.prototype.once);
  74806. goog.exportProperty(
  74807. ol.source.Cluster.prototype,
  74808. 'un',
  74809. ol.source.Cluster.prototype.un);
  74810. goog.exportProperty(
  74811. ol.source.Image.prototype,
  74812. 'getAttributions',
  74813. ol.source.Image.prototype.getAttributions);
  74814. goog.exportProperty(
  74815. ol.source.Image.prototype,
  74816. 'getLogo',
  74817. ol.source.Image.prototype.getLogo);
  74818. goog.exportProperty(
  74819. ol.source.Image.prototype,
  74820. 'getProjection',
  74821. ol.source.Image.prototype.getProjection);
  74822. goog.exportProperty(
  74823. ol.source.Image.prototype,
  74824. 'getState',
  74825. ol.source.Image.prototype.getState);
  74826. goog.exportProperty(
  74827. ol.source.Image.prototype,
  74828. 'refresh',
  74829. ol.source.Image.prototype.refresh);
  74830. goog.exportProperty(
  74831. ol.source.Image.prototype,
  74832. 'setAttributions',
  74833. ol.source.Image.prototype.setAttributions);
  74834. goog.exportProperty(
  74835. ol.source.Image.prototype,
  74836. 'get',
  74837. ol.source.Image.prototype.get);
  74838. goog.exportProperty(
  74839. ol.source.Image.prototype,
  74840. 'getKeys',
  74841. ol.source.Image.prototype.getKeys);
  74842. goog.exportProperty(
  74843. ol.source.Image.prototype,
  74844. 'getProperties',
  74845. ol.source.Image.prototype.getProperties);
  74846. goog.exportProperty(
  74847. ol.source.Image.prototype,
  74848. 'set',
  74849. ol.source.Image.prototype.set);
  74850. goog.exportProperty(
  74851. ol.source.Image.prototype,
  74852. 'setProperties',
  74853. ol.source.Image.prototype.setProperties);
  74854. goog.exportProperty(
  74855. ol.source.Image.prototype,
  74856. 'unset',
  74857. ol.source.Image.prototype.unset);
  74858. goog.exportProperty(
  74859. ol.source.Image.prototype,
  74860. 'changed',
  74861. ol.source.Image.prototype.changed);
  74862. goog.exportProperty(
  74863. ol.source.Image.prototype,
  74864. 'dispatchEvent',
  74865. ol.source.Image.prototype.dispatchEvent);
  74866. goog.exportProperty(
  74867. ol.source.Image.prototype,
  74868. 'getRevision',
  74869. ol.source.Image.prototype.getRevision);
  74870. goog.exportProperty(
  74871. ol.source.Image.prototype,
  74872. 'on',
  74873. ol.source.Image.prototype.on);
  74874. goog.exportProperty(
  74875. ol.source.Image.prototype,
  74876. 'once',
  74877. ol.source.Image.prototype.once);
  74878. goog.exportProperty(
  74879. ol.source.Image.prototype,
  74880. 'un',
  74881. ol.source.Image.prototype.un);
  74882. goog.exportProperty(
  74883. ol.source.Image.Event.prototype,
  74884. 'type',
  74885. ol.source.Image.Event.prototype.type);
  74886. goog.exportProperty(
  74887. ol.source.Image.Event.prototype,
  74888. 'target',
  74889. ol.source.Image.Event.prototype.target);
  74890. goog.exportProperty(
  74891. ol.source.Image.Event.prototype,
  74892. 'preventDefault',
  74893. ol.source.Image.Event.prototype.preventDefault);
  74894. goog.exportProperty(
  74895. ol.source.Image.Event.prototype,
  74896. 'stopPropagation',
  74897. ol.source.Image.Event.prototype.stopPropagation);
  74898. goog.exportProperty(
  74899. ol.source.ImageArcGISRest.prototype,
  74900. 'getAttributions',
  74901. ol.source.ImageArcGISRest.prototype.getAttributions);
  74902. goog.exportProperty(
  74903. ol.source.ImageArcGISRest.prototype,
  74904. 'getLogo',
  74905. ol.source.ImageArcGISRest.prototype.getLogo);
  74906. goog.exportProperty(
  74907. ol.source.ImageArcGISRest.prototype,
  74908. 'getProjection',
  74909. ol.source.ImageArcGISRest.prototype.getProjection);
  74910. goog.exportProperty(
  74911. ol.source.ImageArcGISRest.prototype,
  74912. 'getState',
  74913. ol.source.ImageArcGISRest.prototype.getState);
  74914. goog.exportProperty(
  74915. ol.source.ImageArcGISRest.prototype,
  74916. 'refresh',
  74917. ol.source.ImageArcGISRest.prototype.refresh);
  74918. goog.exportProperty(
  74919. ol.source.ImageArcGISRest.prototype,
  74920. 'setAttributions',
  74921. ol.source.ImageArcGISRest.prototype.setAttributions);
  74922. goog.exportProperty(
  74923. ol.source.ImageArcGISRest.prototype,
  74924. 'get',
  74925. ol.source.ImageArcGISRest.prototype.get);
  74926. goog.exportProperty(
  74927. ol.source.ImageArcGISRest.prototype,
  74928. 'getKeys',
  74929. ol.source.ImageArcGISRest.prototype.getKeys);
  74930. goog.exportProperty(
  74931. ol.source.ImageArcGISRest.prototype,
  74932. 'getProperties',
  74933. ol.source.ImageArcGISRest.prototype.getProperties);
  74934. goog.exportProperty(
  74935. ol.source.ImageArcGISRest.prototype,
  74936. 'set',
  74937. ol.source.ImageArcGISRest.prototype.set);
  74938. goog.exportProperty(
  74939. ol.source.ImageArcGISRest.prototype,
  74940. 'setProperties',
  74941. ol.source.ImageArcGISRest.prototype.setProperties);
  74942. goog.exportProperty(
  74943. ol.source.ImageArcGISRest.prototype,
  74944. 'unset',
  74945. ol.source.ImageArcGISRest.prototype.unset);
  74946. goog.exportProperty(
  74947. ol.source.ImageArcGISRest.prototype,
  74948. 'changed',
  74949. ol.source.ImageArcGISRest.prototype.changed);
  74950. goog.exportProperty(
  74951. ol.source.ImageArcGISRest.prototype,
  74952. 'dispatchEvent',
  74953. ol.source.ImageArcGISRest.prototype.dispatchEvent);
  74954. goog.exportProperty(
  74955. ol.source.ImageArcGISRest.prototype,
  74956. 'getRevision',
  74957. ol.source.ImageArcGISRest.prototype.getRevision);
  74958. goog.exportProperty(
  74959. ol.source.ImageArcGISRest.prototype,
  74960. 'on',
  74961. ol.source.ImageArcGISRest.prototype.on);
  74962. goog.exportProperty(
  74963. ol.source.ImageArcGISRest.prototype,
  74964. 'once',
  74965. ol.source.ImageArcGISRest.prototype.once);
  74966. goog.exportProperty(
  74967. ol.source.ImageArcGISRest.prototype,
  74968. 'un',
  74969. ol.source.ImageArcGISRest.prototype.un);
  74970. goog.exportProperty(
  74971. ol.source.ImageCanvas.prototype,
  74972. 'getAttributions',
  74973. ol.source.ImageCanvas.prototype.getAttributions);
  74974. goog.exportProperty(
  74975. ol.source.ImageCanvas.prototype,
  74976. 'getLogo',
  74977. ol.source.ImageCanvas.prototype.getLogo);
  74978. goog.exportProperty(
  74979. ol.source.ImageCanvas.prototype,
  74980. 'getProjection',
  74981. ol.source.ImageCanvas.prototype.getProjection);
  74982. goog.exportProperty(
  74983. ol.source.ImageCanvas.prototype,
  74984. 'getState',
  74985. ol.source.ImageCanvas.prototype.getState);
  74986. goog.exportProperty(
  74987. ol.source.ImageCanvas.prototype,
  74988. 'refresh',
  74989. ol.source.ImageCanvas.prototype.refresh);
  74990. goog.exportProperty(
  74991. ol.source.ImageCanvas.prototype,
  74992. 'setAttributions',
  74993. ol.source.ImageCanvas.prototype.setAttributions);
  74994. goog.exportProperty(
  74995. ol.source.ImageCanvas.prototype,
  74996. 'get',
  74997. ol.source.ImageCanvas.prototype.get);
  74998. goog.exportProperty(
  74999. ol.source.ImageCanvas.prototype,
  75000. 'getKeys',
  75001. ol.source.ImageCanvas.prototype.getKeys);
  75002. goog.exportProperty(
  75003. ol.source.ImageCanvas.prototype,
  75004. 'getProperties',
  75005. ol.source.ImageCanvas.prototype.getProperties);
  75006. goog.exportProperty(
  75007. ol.source.ImageCanvas.prototype,
  75008. 'set',
  75009. ol.source.ImageCanvas.prototype.set);
  75010. goog.exportProperty(
  75011. ol.source.ImageCanvas.prototype,
  75012. 'setProperties',
  75013. ol.source.ImageCanvas.prototype.setProperties);
  75014. goog.exportProperty(
  75015. ol.source.ImageCanvas.prototype,
  75016. 'unset',
  75017. ol.source.ImageCanvas.prototype.unset);
  75018. goog.exportProperty(
  75019. ol.source.ImageCanvas.prototype,
  75020. 'changed',
  75021. ol.source.ImageCanvas.prototype.changed);
  75022. goog.exportProperty(
  75023. ol.source.ImageCanvas.prototype,
  75024. 'dispatchEvent',
  75025. ol.source.ImageCanvas.prototype.dispatchEvent);
  75026. goog.exportProperty(
  75027. ol.source.ImageCanvas.prototype,
  75028. 'getRevision',
  75029. ol.source.ImageCanvas.prototype.getRevision);
  75030. goog.exportProperty(
  75031. ol.source.ImageCanvas.prototype,
  75032. 'on',
  75033. ol.source.ImageCanvas.prototype.on);
  75034. goog.exportProperty(
  75035. ol.source.ImageCanvas.prototype,
  75036. 'once',
  75037. ol.source.ImageCanvas.prototype.once);
  75038. goog.exportProperty(
  75039. ol.source.ImageCanvas.prototype,
  75040. 'un',
  75041. ol.source.ImageCanvas.prototype.un);
  75042. goog.exportProperty(
  75043. ol.source.ImageMapGuide.prototype,
  75044. 'getAttributions',
  75045. ol.source.ImageMapGuide.prototype.getAttributions);
  75046. goog.exportProperty(
  75047. ol.source.ImageMapGuide.prototype,
  75048. 'getLogo',
  75049. ol.source.ImageMapGuide.prototype.getLogo);
  75050. goog.exportProperty(
  75051. ol.source.ImageMapGuide.prototype,
  75052. 'getProjection',
  75053. ol.source.ImageMapGuide.prototype.getProjection);
  75054. goog.exportProperty(
  75055. ol.source.ImageMapGuide.prototype,
  75056. 'getState',
  75057. ol.source.ImageMapGuide.prototype.getState);
  75058. goog.exportProperty(
  75059. ol.source.ImageMapGuide.prototype,
  75060. 'refresh',
  75061. ol.source.ImageMapGuide.prototype.refresh);
  75062. goog.exportProperty(
  75063. ol.source.ImageMapGuide.prototype,
  75064. 'setAttributions',
  75065. ol.source.ImageMapGuide.prototype.setAttributions);
  75066. goog.exportProperty(
  75067. ol.source.ImageMapGuide.prototype,
  75068. 'get',
  75069. ol.source.ImageMapGuide.prototype.get);
  75070. goog.exportProperty(
  75071. ol.source.ImageMapGuide.prototype,
  75072. 'getKeys',
  75073. ol.source.ImageMapGuide.prototype.getKeys);
  75074. goog.exportProperty(
  75075. ol.source.ImageMapGuide.prototype,
  75076. 'getProperties',
  75077. ol.source.ImageMapGuide.prototype.getProperties);
  75078. goog.exportProperty(
  75079. ol.source.ImageMapGuide.prototype,
  75080. 'set',
  75081. ol.source.ImageMapGuide.prototype.set);
  75082. goog.exportProperty(
  75083. ol.source.ImageMapGuide.prototype,
  75084. 'setProperties',
  75085. ol.source.ImageMapGuide.prototype.setProperties);
  75086. goog.exportProperty(
  75087. ol.source.ImageMapGuide.prototype,
  75088. 'unset',
  75089. ol.source.ImageMapGuide.prototype.unset);
  75090. goog.exportProperty(
  75091. ol.source.ImageMapGuide.prototype,
  75092. 'changed',
  75093. ol.source.ImageMapGuide.prototype.changed);
  75094. goog.exportProperty(
  75095. ol.source.ImageMapGuide.prototype,
  75096. 'dispatchEvent',
  75097. ol.source.ImageMapGuide.prototype.dispatchEvent);
  75098. goog.exportProperty(
  75099. ol.source.ImageMapGuide.prototype,
  75100. 'getRevision',
  75101. ol.source.ImageMapGuide.prototype.getRevision);
  75102. goog.exportProperty(
  75103. ol.source.ImageMapGuide.prototype,
  75104. 'on',
  75105. ol.source.ImageMapGuide.prototype.on);
  75106. goog.exportProperty(
  75107. ol.source.ImageMapGuide.prototype,
  75108. 'once',
  75109. ol.source.ImageMapGuide.prototype.once);
  75110. goog.exportProperty(
  75111. ol.source.ImageMapGuide.prototype,
  75112. 'un',
  75113. ol.source.ImageMapGuide.prototype.un);
  75114. goog.exportProperty(
  75115. ol.source.ImageStatic.prototype,
  75116. 'getAttributions',
  75117. ol.source.ImageStatic.prototype.getAttributions);
  75118. goog.exportProperty(
  75119. ol.source.ImageStatic.prototype,
  75120. 'getLogo',
  75121. ol.source.ImageStatic.prototype.getLogo);
  75122. goog.exportProperty(
  75123. ol.source.ImageStatic.prototype,
  75124. 'getProjection',
  75125. ol.source.ImageStatic.prototype.getProjection);
  75126. goog.exportProperty(
  75127. ol.source.ImageStatic.prototype,
  75128. 'getState',
  75129. ol.source.ImageStatic.prototype.getState);
  75130. goog.exportProperty(
  75131. ol.source.ImageStatic.prototype,
  75132. 'refresh',
  75133. ol.source.ImageStatic.prototype.refresh);
  75134. goog.exportProperty(
  75135. ol.source.ImageStatic.prototype,
  75136. 'setAttributions',
  75137. ol.source.ImageStatic.prototype.setAttributions);
  75138. goog.exportProperty(
  75139. ol.source.ImageStatic.prototype,
  75140. 'get',
  75141. ol.source.ImageStatic.prototype.get);
  75142. goog.exportProperty(
  75143. ol.source.ImageStatic.prototype,
  75144. 'getKeys',
  75145. ol.source.ImageStatic.prototype.getKeys);
  75146. goog.exportProperty(
  75147. ol.source.ImageStatic.prototype,
  75148. 'getProperties',
  75149. ol.source.ImageStatic.prototype.getProperties);
  75150. goog.exportProperty(
  75151. ol.source.ImageStatic.prototype,
  75152. 'set',
  75153. ol.source.ImageStatic.prototype.set);
  75154. goog.exportProperty(
  75155. ol.source.ImageStatic.prototype,
  75156. 'setProperties',
  75157. ol.source.ImageStatic.prototype.setProperties);
  75158. goog.exportProperty(
  75159. ol.source.ImageStatic.prototype,
  75160. 'unset',
  75161. ol.source.ImageStatic.prototype.unset);
  75162. goog.exportProperty(
  75163. ol.source.ImageStatic.prototype,
  75164. 'changed',
  75165. ol.source.ImageStatic.prototype.changed);
  75166. goog.exportProperty(
  75167. ol.source.ImageStatic.prototype,
  75168. 'dispatchEvent',
  75169. ol.source.ImageStatic.prototype.dispatchEvent);
  75170. goog.exportProperty(
  75171. ol.source.ImageStatic.prototype,
  75172. 'getRevision',
  75173. ol.source.ImageStatic.prototype.getRevision);
  75174. goog.exportProperty(
  75175. ol.source.ImageStatic.prototype,
  75176. 'on',
  75177. ol.source.ImageStatic.prototype.on);
  75178. goog.exportProperty(
  75179. ol.source.ImageStatic.prototype,
  75180. 'once',
  75181. ol.source.ImageStatic.prototype.once);
  75182. goog.exportProperty(
  75183. ol.source.ImageStatic.prototype,
  75184. 'un',
  75185. ol.source.ImageStatic.prototype.un);
  75186. goog.exportProperty(
  75187. ol.source.ImageVector.prototype,
  75188. 'getAttributions',
  75189. ol.source.ImageVector.prototype.getAttributions);
  75190. goog.exportProperty(
  75191. ol.source.ImageVector.prototype,
  75192. 'getLogo',
  75193. ol.source.ImageVector.prototype.getLogo);
  75194. goog.exportProperty(
  75195. ol.source.ImageVector.prototype,
  75196. 'getProjection',
  75197. ol.source.ImageVector.prototype.getProjection);
  75198. goog.exportProperty(
  75199. ol.source.ImageVector.prototype,
  75200. 'getState',
  75201. ol.source.ImageVector.prototype.getState);
  75202. goog.exportProperty(
  75203. ol.source.ImageVector.prototype,
  75204. 'refresh',
  75205. ol.source.ImageVector.prototype.refresh);
  75206. goog.exportProperty(
  75207. ol.source.ImageVector.prototype,
  75208. 'setAttributions',
  75209. ol.source.ImageVector.prototype.setAttributions);
  75210. goog.exportProperty(
  75211. ol.source.ImageVector.prototype,
  75212. 'get',
  75213. ol.source.ImageVector.prototype.get);
  75214. goog.exportProperty(
  75215. ol.source.ImageVector.prototype,
  75216. 'getKeys',
  75217. ol.source.ImageVector.prototype.getKeys);
  75218. goog.exportProperty(
  75219. ol.source.ImageVector.prototype,
  75220. 'getProperties',
  75221. ol.source.ImageVector.prototype.getProperties);
  75222. goog.exportProperty(
  75223. ol.source.ImageVector.prototype,
  75224. 'set',
  75225. ol.source.ImageVector.prototype.set);
  75226. goog.exportProperty(
  75227. ol.source.ImageVector.prototype,
  75228. 'setProperties',
  75229. ol.source.ImageVector.prototype.setProperties);
  75230. goog.exportProperty(
  75231. ol.source.ImageVector.prototype,
  75232. 'unset',
  75233. ol.source.ImageVector.prototype.unset);
  75234. goog.exportProperty(
  75235. ol.source.ImageVector.prototype,
  75236. 'changed',
  75237. ol.source.ImageVector.prototype.changed);
  75238. goog.exportProperty(
  75239. ol.source.ImageVector.prototype,
  75240. 'dispatchEvent',
  75241. ol.source.ImageVector.prototype.dispatchEvent);
  75242. goog.exportProperty(
  75243. ol.source.ImageVector.prototype,
  75244. 'getRevision',
  75245. ol.source.ImageVector.prototype.getRevision);
  75246. goog.exportProperty(
  75247. ol.source.ImageVector.prototype,
  75248. 'on',
  75249. ol.source.ImageVector.prototype.on);
  75250. goog.exportProperty(
  75251. ol.source.ImageVector.prototype,
  75252. 'once',
  75253. ol.source.ImageVector.prototype.once);
  75254. goog.exportProperty(
  75255. ol.source.ImageVector.prototype,
  75256. 'un',
  75257. ol.source.ImageVector.prototype.un);
  75258. goog.exportProperty(
  75259. ol.source.ImageWMS.prototype,
  75260. 'getAttributions',
  75261. ol.source.ImageWMS.prototype.getAttributions);
  75262. goog.exportProperty(
  75263. ol.source.ImageWMS.prototype,
  75264. 'getLogo',
  75265. ol.source.ImageWMS.prototype.getLogo);
  75266. goog.exportProperty(
  75267. ol.source.ImageWMS.prototype,
  75268. 'getProjection',
  75269. ol.source.ImageWMS.prototype.getProjection);
  75270. goog.exportProperty(
  75271. ol.source.ImageWMS.prototype,
  75272. 'getState',
  75273. ol.source.ImageWMS.prototype.getState);
  75274. goog.exportProperty(
  75275. ol.source.ImageWMS.prototype,
  75276. 'refresh',
  75277. ol.source.ImageWMS.prototype.refresh);
  75278. goog.exportProperty(
  75279. ol.source.ImageWMS.prototype,
  75280. 'setAttributions',
  75281. ol.source.ImageWMS.prototype.setAttributions);
  75282. goog.exportProperty(
  75283. ol.source.ImageWMS.prototype,
  75284. 'get',
  75285. ol.source.ImageWMS.prototype.get);
  75286. goog.exportProperty(
  75287. ol.source.ImageWMS.prototype,
  75288. 'getKeys',
  75289. ol.source.ImageWMS.prototype.getKeys);
  75290. goog.exportProperty(
  75291. ol.source.ImageWMS.prototype,
  75292. 'getProperties',
  75293. ol.source.ImageWMS.prototype.getProperties);
  75294. goog.exportProperty(
  75295. ol.source.ImageWMS.prototype,
  75296. 'set',
  75297. ol.source.ImageWMS.prototype.set);
  75298. goog.exportProperty(
  75299. ol.source.ImageWMS.prototype,
  75300. 'setProperties',
  75301. ol.source.ImageWMS.prototype.setProperties);
  75302. goog.exportProperty(
  75303. ol.source.ImageWMS.prototype,
  75304. 'unset',
  75305. ol.source.ImageWMS.prototype.unset);
  75306. goog.exportProperty(
  75307. ol.source.ImageWMS.prototype,
  75308. 'changed',
  75309. ol.source.ImageWMS.prototype.changed);
  75310. goog.exportProperty(
  75311. ol.source.ImageWMS.prototype,
  75312. 'dispatchEvent',
  75313. ol.source.ImageWMS.prototype.dispatchEvent);
  75314. goog.exportProperty(
  75315. ol.source.ImageWMS.prototype,
  75316. 'getRevision',
  75317. ol.source.ImageWMS.prototype.getRevision);
  75318. goog.exportProperty(
  75319. ol.source.ImageWMS.prototype,
  75320. 'on',
  75321. ol.source.ImageWMS.prototype.on);
  75322. goog.exportProperty(
  75323. ol.source.ImageWMS.prototype,
  75324. 'once',
  75325. ol.source.ImageWMS.prototype.once);
  75326. goog.exportProperty(
  75327. ol.source.ImageWMS.prototype,
  75328. 'un',
  75329. ol.source.ImageWMS.prototype.un);
  75330. goog.exportProperty(
  75331. ol.source.OSM.prototype,
  75332. 'setRenderReprojectionEdges',
  75333. ol.source.OSM.prototype.setRenderReprojectionEdges);
  75334. goog.exportProperty(
  75335. ol.source.OSM.prototype,
  75336. 'setTileGridForProjection',
  75337. ol.source.OSM.prototype.setTileGridForProjection);
  75338. goog.exportProperty(
  75339. ol.source.OSM.prototype,
  75340. 'getTileLoadFunction',
  75341. ol.source.OSM.prototype.getTileLoadFunction);
  75342. goog.exportProperty(
  75343. ol.source.OSM.prototype,
  75344. 'getTileUrlFunction',
  75345. ol.source.OSM.prototype.getTileUrlFunction);
  75346. goog.exportProperty(
  75347. ol.source.OSM.prototype,
  75348. 'getUrls',
  75349. ol.source.OSM.prototype.getUrls);
  75350. goog.exportProperty(
  75351. ol.source.OSM.prototype,
  75352. 'setTileLoadFunction',
  75353. ol.source.OSM.prototype.setTileLoadFunction);
  75354. goog.exportProperty(
  75355. ol.source.OSM.prototype,
  75356. 'setTileUrlFunction',
  75357. ol.source.OSM.prototype.setTileUrlFunction);
  75358. goog.exportProperty(
  75359. ol.source.OSM.prototype,
  75360. 'setUrl',
  75361. ol.source.OSM.prototype.setUrl);
  75362. goog.exportProperty(
  75363. ol.source.OSM.prototype,
  75364. 'setUrls',
  75365. ol.source.OSM.prototype.setUrls);
  75366. goog.exportProperty(
  75367. ol.source.OSM.prototype,
  75368. 'getTileGrid',
  75369. ol.source.OSM.prototype.getTileGrid);
  75370. goog.exportProperty(
  75371. ol.source.OSM.prototype,
  75372. 'refresh',
  75373. ol.source.OSM.prototype.refresh);
  75374. goog.exportProperty(
  75375. ol.source.OSM.prototype,
  75376. 'getAttributions',
  75377. ol.source.OSM.prototype.getAttributions);
  75378. goog.exportProperty(
  75379. ol.source.OSM.prototype,
  75380. 'getLogo',
  75381. ol.source.OSM.prototype.getLogo);
  75382. goog.exportProperty(
  75383. ol.source.OSM.prototype,
  75384. 'getProjection',
  75385. ol.source.OSM.prototype.getProjection);
  75386. goog.exportProperty(
  75387. ol.source.OSM.prototype,
  75388. 'getState',
  75389. ol.source.OSM.prototype.getState);
  75390. goog.exportProperty(
  75391. ol.source.OSM.prototype,
  75392. 'setAttributions',
  75393. ol.source.OSM.prototype.setAttributions);
  75394. goog.exportProperty(
  75395. ol.source.OSM.prototype,
  75396. 'get',
  75397. ol.source.OSM.prototype.get);
  75398. goog.exportProperty(
  75399. ol.source.OSM.prototype,
  75400. 'getKeys',
  75401. ol.source.OSM.prototype.getKeys);
  75402. goog.exportProperty(
  75403. ol.source.OSM.prototype,
  75404. 'getProperties',
  75405. ol.source.OSM.prototype.getProperties);
  75406. goog.exportProperty(
  75407. ol.source.OSM.prototype,
  75408. 'set',
  75409. ol.source.OSM.prototype.set);
  75410. goog.exportProperty(
  75411. ol.source.OSM.prototype,
  75412. 'setProperties',
  75413. ol.source.OSM.prototype.setProperties);
  75414. goog.exportProperty(
  75415. ol.source.OSM.prototype,
  75416. 'unset',
  75417. ol.source.OSM.prototype.unset);
  75418. goog.exportProperty(
  75419. ol.source.OSM.prototype,
  75420. 'changed',
  75421. ol.source.OSM.prototype.changed);
  75422. goog.exportProperty(
  75423. ol.source.OSM.prototype,
  75424. 'dispatchEvent',
  75425. ol.source.OSM.prototype.dispatchEvent);
  75426. goog.exportProperty(
  75427. ol.source.OSM.prototype,
  75428. 'getRevision',
  75429. ol.source.OSM.prototype.getRevision);
  75430. goog.exportProperty(
  75431. ol.source.OSM.prototype,
  75432. 'on',
  75433. ol.source.OSM.prototype.on);
  75434. goog.exportProperty(
  75435. ol.source.OSM.prototype,
  75436. 'once',
  75437. ol.source.OSM.prototype.once);
  75438. goog.exportProperty(
  75439. ol.source.OSM.prototype,
  75440. 'un',
  75441. ol.source.OSM.prototype.un);
  75442. goog.exportProperty(
  75443. ol.source.Raster.prototype,
  75444. 'getAttributions',
  75445. ol.source.Raster.prototype.getAttributions);
  75446. goog.exportProperty(
  75447. ol.source.Raster.prototype,
  75448. 'getLogo',
  75449. ol.source.Raster.prototype.getLogo);
  75450. goog.exportProperty(
  75451. ol.source.Raster.prototype,
  75452. 'getProjection',
  75453. ol.source.Raster.prototype.getProjection);
  75454. goog.exportProperty(
  75455. ol.source.Raster.prototype,
  75456. 'getState',
  75457. ol.source.Raster.prototype.getState);
  75458. goog.exportProperty(
  75459. ol.source.Raster.prototype,
  75460. 'refresh',
  75461. ol.source.Raster.prototype.refresh);
  75462. goog.exportProperty(
  75463. ol.source.Raster.prototype,
  75464. 'setAttributions',
  75465. ol.source.Raster.prototype.setAttributions);
  75466. goog.exportProperty(
  75467. ol.source.Raster.prototype,
  75468. 'get',
  75469. ol.source.Raster.prototype.get);
  75470. goog.exportProperty(
  75471. ol.source.Raster.prototype,
  75472. 'getKeys',
  75473. ol.source.Raster.prototype.getKeys);
  75474. goog.exportProperty(
  75475. ol.source.Raster.prototype,
  75476. 'getProperties',
  75477. ol.source.Raster.prototype.getProperties);
  75478. goog.exportProperty(
  75479. ol.source.Raster.prototype,
  75480. 'set',
  75481. ol.source.Raster.prototype.set);
  75482. goog.exportProperty(
  75483. ol.source.Raster.prototype,
  75484. 'setProperties',
  75485. ol.source.Raster.prototype.setProperties);
  75486. goog.exportProperty(
  75487. ol.source.Raster.prototype,
  75488. 'unset',
  75489. ol.source.Raster.prototype.unset);
  75490. goog.exportProperty(
  75491. ol.source.Raster.prototype,
  75492. 'changed',
  75493. ol.source.Raster.prototype.changed);
  75494. goog.exportProperty(
  75495. ol.source.Raster.prototype,
  75496. 'dispatchEvent',
  75497. ol.source.Raster.prototype.dispatchEvent);
  75498. goog.exportProperty(
  75499. ol.source.Raster.prototype,
  75500. 'getRevision',
  75501. ol.source.Raster.prototype.getRevision);
  75502. goog.exportProperty(
  75503. ol.source.Raster.prototype,
  75504. 'on',
  75505. ol.source.Raster.prototype.on);
  75506. goog.exportProperty(
  75507. ol.source.Raster.prototype,
  75508. 'once',
  75509. ol.source.Raster.prototype.once);
  75510. goog.exportProperty(
  75511. ol.source.Raster.prototype,
  75512. 'un',
  75513. ol.source.Raster.prototype.un);
  75514. goog.exportProperty(
  75515. ol.source.Raster.Event.prototype,
  75516. 'type',
  75517. ol.source.Raster.Event.prototype.type);
  75518. goog.exportProperty(
  75519. ol.source.Raster.Event.prototype,
  75520. 'target',
  75521. ol.source.Raster.Event.prototype.target);
  75522. goog.exportProperty(
  75523. ol.source.Raster.Event.prototype,
  75524. 'preventDefault',
  75525. ol.source.Raster.Event.prototype.preventDefault);
  75526. goog.exportProperty(
  75527. ol.source.Raster.Event.prototype,
  75528. 'stopPropagation',
  75529. ol.source.Raster.Event.prototype.stopPropagation);
  75530. goog.exportProperty(
  75531. ol.source.Stamen.prototype,
  75532. 'setRenderReprojectionEdges',
  75533. ol.source.Stamen.prototype.setRenderReprojectionEdges);
  75534. goog.exportProperty(
  75535. ol.source.Stamen.prototype,
  75536. 'setTileGridForProjection',
  75537. ol.source.Stamen.prototype.setTileGridForProjection);
  75538. goog.exportProperty(
  75539. ol.source.Stamen.prototype,
  75540. 'getTileLoadFunction',
  75541. ol.source.Stamen.prototype.getTileLoadFunction);
  75542. goog.exportProperty(
  75543. ol.source.Stamen.prototype,
  75544. 'getTileUrlFunction',
  75545. ol.source.Stamen.prototype.getTileUrlFunction);
  75546. goog.exportProperty(
  75547. ol.source.Stamen.prototype,
  75548. 'getUrls',
  75549. ol.source.Stamen.prototype.getUrls);
  75550. goog.exportProperty(
  75551. ol.source.Stamen.prototype,
  75552. 'setTileLoadFunction',
  75553. ol.source.Stamen.prototype.setTileLoadFunction);
  75554. goog.exportProperty(
  75555. ol.source.Stamen.prototype,
  75556. 'setTileUrlFunction',
  75557. ol.source.Stamen.prototype.setTileUrlFunction);
  75558. goog.exportProperty(
  75559. ol.source.Stamen.prototype,
  75560. 'setUrl',
  75561. ol.source.Stamen.prototype.setUrl);
  75562. goog.exportProperty(
  75563. ol.source.Stamen.prototype,
  75564. 'setUrls',
  75565. ol.source.Stamen.prototype.setUrls);
  75566. goog.exportProperty(
  75567. ol.source.Stamen.prototype,
  75568. 'getTileGrid',
  75569. ol.source.Stamen.prototype.getTileGrid);
  75570. goog.exportProperty(
  75571. ol.source.Stamen.prototype,
  75572. 'refresh',
  75573. ol.source.Stamen.prototype.refresh);
  75574. goog.exportProperty(
  75575. ol.source.Stamen.prototype,
  75576. 'getAttributions',
  75577. ol.source.Stamen.prototype.getAttributions);
  75578. goog.exportProperty(
  75579. ol.source.Stamen.prototype,
  75580. 'getLogo',
  75581. ol.source.Stamen.prototype.getLogo);
  75582. goog.exportProperty(
  75583. ol.source.Stamen.prototype,
  75584. 'getProjection',
  75585. ol.source.Stamen.prototype.getProjection);
  75586. goog.exportProperty(
  75587. ol.source.Stamen.prototype,
  75588. 'getState',
  75589. ol.source.Stamen.prototype.getState);
  75590. goog.exportProperty(
  75591. ol.source.Stamen.prototype,
  75592. 'setAttributions',
  75593. ol.source.Stamen.prototype.setAttributions);
  75594. goog.exportProperty(
  75595. ol.source.Stamen.prototype,
  75596. 'get',
  75597. ol.source.Stamen.prototype.get);
  75598. goog.exportProperty(
  75599. ol.source.Stamen.prototype,
  75600. 'getKeys',
  75601. ol.source.Stamen.prototype.getKeys);
  75602. goog.exportProperty(
  75603. ol.source.Stamen.prototype,
  75604. 'getProperties',
  75605. ol.source.Stamen.prototype.getProperties);
  75606. goog.exportProperty(
  75607. ol.source.Stamen.prototype,
  75608. 'set',
  75609. ol.source.Stamen.prototype.set);
  75610. goog.exportProperty(
  75611. ol.source.Stamen.prototype,
  75612. 'setProperties',
  75613. ol.source.Stamen.prototype.setProperties);
  75614. goog.exportProperty(
  75615. ol.source.Stamen.prototype,
  75616. 'unset',
  75617. ol.source.Stamen.prototype.unset);
  75618. goog.exportProperty(
  75619. ol.source.Stamen.prototype,
  75620. 'changed',
  75621. ol.source.Stamen.prototype.changed);
  75622. goog.exportProperty(
  75623. ol.source.Stamen.prototype,
  75624. 'dispatchEvent',
  75625. ol.source.Stamen.prototype.dispatchEvent);
  75626. goog.exportProperty(
  75627. ol.source.Stamen.prototype,
  75628. 'getRevision',
  75629. ol.source.Stamen.prototype.getRevision);
  75630. goog.exportProperty(
  75631. ol.source.Stamen.prototype,
  75632. 'on',
  75633. ol.source.Stamen.prototype.on);
  75634. goog.exportProperty(
  75635. ol.source.Stamen.prototype,
  75636. 'once',
  75637. ol.source.Stamen.prototype.once);
  75638. goog.exportProperty(
  75639. ol.source.Stamen.prototype,
  75640. 'un',
  75641. ol.source.Stamen.prototype.un);
  75642. goog.exportProperty(
  75643. ol.source.Tile.Event.prototype,
  75644. 'type',
  75645. ol.source.Tile.Event.prototype.type);
  75646. goog.exportProperty(
  75647. ol.source.Tile.Event.prototype,
  75648. 'target',
  75649. ol.source.Tile.Event.prototype.target);
  75650. goog.exportProperty(
  75651. ol.source.Tile.Event.prototype,
  75652. 'preventDefault',
  75653. ol.source.Tile.Event.prototype.preventDefault);
  75654. goog.exportProperty(
  75655. ol.source.Tile.Event.prototype,
  75656. 'stopPropagation',
  75657. ol.source.Tile.Event.prototype.stopPropagation);
  75658. goog.exportProperty(
  75659. ol.source.TileArcGISRest.prototype,
  75660. 'setRenderReprojectionEdges',
  75661. ol.source.TileArcGISRest.prototype.setRenderReprojectionEdges);
  75662. goog.exportProperty(
  75663. ol.source.TileArcGISRest.prototype,
  75664. 'setTileGridForProjection',
  75665. ol.source.TileArcGISRest.prototype.setTileGridForProjection);
  75666. goog.exportProperty(
  75667. ol.source.TileArcGISRest.prototype,
  75668. 'getTileLoadFunction',
  75669. ol.source.TileArcGISRest.prototype.getTileLoadFunction);
  75670. goog.exportProperty(
  75671. ol.source.TileArcGISRest.prototype,
  75672. 'getTileUrlFunction',
  75673. ol.source.TileArcGISRest.prototype.getTileUrlFunction);
  75674. goog.exportProperty(
  75675. ol.source.TileArcGISRest.prototype,
  75676. 'getUrls',
  75677. ol.source.TileArcGISRest.prototype.getUrls);
  75678. goog.exportProperty(
  75679. ol.source.TileArcGISRest.prototype,
  75680. 'setTileLoadFunction',
  75681. ol.source.TileArcGISRest.prototype.setTileLoadFunction);
  75682. goog.exportProperty(
  75683. ol.source.TileArcGISRest.prototype,
  75684. 'setTileUrlFunction',
  75685. ol.source.TileArcGISRest.prototype.setTileUrlFunction);
  75686. goog.exportProperty(
  75687. ol.source.TileArcGISRest.prototype,
  75688. 'setUrl',
  75689. ol.source.TileArcGISRest.prototype.setUrl);
  75690. goog.exportProperty(
  75691. ol.source.TileArcGISRest.prototype,
  75692. 'setUrls',
  75693. ol.source.TileArcGISRest.prototype.setUrls);
  75694. goog.exportProperty(
  75695. ol.source.TileArcGISRest.prototype,
  75696. 'getTileGrid',
  75697. ol.source.TileArcGISRest.prototype.getTileGrid);
  75698. goog.exportProperty(
  75699. ol.source.TileArcGISRest.prototype,
  75700. 'refresh',
  75701. ol.source.TileArcGISRest.prototype.refresh);
  75702. goog.exportProperty(
  75703. ol.source.TileArcGISRest.prototype,
  75704. 'getAttributions',
  75705. ol.source.TileArcGISRest.prototype.getAttributions);
  75706. goog.exportProperty(
  75707. ol.source.TileArcGISRest.prototype,
  75708. 'getLogo',
  75709. ol.source.TileArcGISRest.prototype.getLogo);
  75710. goog.exportProperty(
  75711. ol.source.TileArcGISRest.prototype,
  75712. 'getProjection',
  75713. ol.source.TileArcGISRest.prototype.getProjection);
  75714. goog.exportProperty(
  75715. ol.source.TileArcGISRest.prototype,
  75716. 'getState',
  75717. ol.source.TileArcGISRest.prototype.getState);
  75718. goog.exportProperty(
  75719. ol.source.TileArcGISRest.prototype,
  75720. 'setAttributions',
  75721. ol.source.TileArcGISRest.prototype.setAttributions);
  75722. goog.exportProperty(
  75723. ol.source.TileArcGISRest.prototype,
  75724. 'get',
  75725. ol.source.TileArcGISRest.prototype.get);
  75726. goog.exportProperty(
  75727. ol.source.TileArcGISRest.prototype,
  75728. 'getKeys',
  75729. ol.source.TileArcGISRest.prototype.getKeys);
  75730. goog.exportProperty(
  75731. ol.source.TileArcGISRest.prototype,
  75732. 'getProperties',
  75733. ol.source.TileArcGISRest.prototype.getProperties);
  75734. goog.exportProperty(
  75735. ol.source.TileArcGISRest.prototype,
  75736. 'set',
  75737. ol.source.TileArcGISRest.prototype.set);
  75738. goog.exportProperty(
  75739. ol.source.TileArcGISRest.prototype,
  75740. 'setProperties',
  75741. ol.source.TileArcGISRest.prototype.setProperties);
  75742. goog.exportProperty(
  75743. ol.source.TileArcGISRest.prototype,
  75744. 'unset',
  75745. ol.source.TileArcGISRest.prototype.unset);
  75746. goog.exportProperty(
  75747. ol.source.TileArcGISRest.prototype,
  75748. 'changed',
  75749. ol.source.TileArcGISRest.prototype.changed);
  75750. goog.exportProperty(
  75751. ol.source.TileArcGISRest.prototype,
  75752. 'dispatchEvent',
  75753. ol.source.TileArcGISRest.prototype.dispatchEvent);
  75754. goog.exportProperty(
  75755. ol.source.TileArcGISRest.prototype,
  75756. 'getRevision',
  75757. ol.source.TileArcGISRest.prototype.getRevision);
  75758. goog.exportProperty(
  75759. ol.source.TileArcGISRest.prototype,
  75760. 'on',
  75761. ol.source.TileArcGISRest.prototype.on);
  75762. goog.exportProperty(
  75763. ol.source.TileArcGISRest.prototype,
  75764. 'once',
  75765. ol.source.TileArcGISRest.prototype.once);
  75766. goog.exportProperty(
  75767. ol.source.TileArcGISRest.prototype,
  75768. 'un',
  75769. ol.source.TileArcGISRest.prototype.un);
  75770. goog.exportProperty(
  75771. ol.source.TileDebug.prototype,
  75772. 'getTileGrid',
  75773. ol.source.TileDebug.prototype.getTileGrid);
  75774. goog.exportProperty(
  75775. ol.source.TileDebug.prototype,
  75776. 'refresh',
  75777. ol.source.TileDebug.prototype.refresh);
  75778. goog.exportProperty(
  75779. ol.source.TileDebug.prototype,
  75780. 'getAttributions',
  75781. ol.source.TileDebug.prototype.getAttributions);
  75782. goog.exportProperty(
  75783. ol.source.TileDebug.prototype,
  75784. 'getLogo',
  75785. ol.source.TileDebug.prototype.getLogo);
  75786. goog.exportProperty(
  75787. ol.source.TileDebug.prototype,
  75788. 'getProjection',
  75789. ol.source.TileDebug.prototype.getProjection);
  75790. goog.exportProperty(
  75791. ol.source.TileDebug.prototype,
  75792. 'getState',
  75793. ol.source.TileDebug.prototype.getState);
  75794. goog.exportProperty(
  75795. ol.source.TileDebug.prototype,
  75796. 'setAttributions',
  75797. ol.source.TileDebug.prototype.setAttributions);
  75798. goog.exportProperty(
  75799. ol.source.TileDebug.prototype,
  75800. 'get',
  75801. ol.source.TileDebug.prototype.get);
  75802. goog.exportProperty(
  75803. ol.source.TileDebug.prototype,
  75804. 'getKeys',
  75805. ol.source.TileDebug.prototype.getKeys);
  75806. goog.exportProperty(
  75807. ol.source.TileDebug.prototype,
  75808. 'getProperties',
  75809. ol.source.TileDebug.prototype.getProperties);
  75810. goog.exportProperty(
  75811. ol.source.TileDebug.prototype,
  75812. 'set',
  75813. ol.source.TileDebug.prototype.set);
  75814. goog.exportProperty(
  75815. ol.source.TileDebug.prototype,
  75816. 'setProperties',
  75817. ol.source.TileDebug.prototype.setProperties);
  75818. goog.exportProperty(
  75819. ol.source.TileDebug.prototype,
  75820. 'unset',
  75821. ol.source.TileDebug.prototype.unset);
  75822. goog.exportProperty(
  75823. ol.source.TileDebug.prototype,
  75824. 'changed',
  75825. ol.source.TileDebug.prototype.changed);
  75826. goog.exportProperty(
  75827. ol.source.TileDebug.prototype,
  75828. 'dispatchEvent',
  75829. ol.source.TileDebug.prototype.dispatchEvent);
  75830. goog.exportProperty(
  75831. ol.source.TileDebug.prototype,
  75832. 'getRevision',
  75833. ol.source.TileDebug.prototype.getRevision);
  75834. goog.exportProperty(
  75835. ol.source.TileDebug.prototype,
  75836. 'on',
  75837. ol.source.TileDebug.prototype.on);
  75838. goog.exportProperty(
  75839. ol.source.TileDebug.prototype,
  75840. 'once',
  75841. ol.source.TileDebug.prototype.once);
  75842. goog.exportProperty(
  75843. ol.source.TileDebug.prototype,
  75844. 'un',
  75845. ol.source.TileDebug.prototype.un);
  75846. goog.exportProperty(
  75847. ol.source.TileJSON.prototype,
  75848. 'setRenderReprojectionEdges',
  75849. ol.source.TileJSON.prototype.setRenderReprojectionEdges);
  75850. goog.exportProperty(
  75851. ol.source.TileJSON.prototype,
  75852. 'setTileGridForProjection',
  75853. ol.source.TileJSON.prototype.setTileGridForProjection);
  75854. goog.exportProperty(
  75855. ol.source.TileJSON.prototype,
  75856. 'getTileLoadFunction',
  75857. ol.source.TileJSON.prototype.getTileLoadFunction);
  75858. goog.exportProperty(
  75859. ol.source.TileJSON.prototype,
  75860. 'getTileUrlFunction',
  75861. ol.source.TileJSON.prototype.getTileUrlFunction);
  75862. goog.exportProperty(
  75863. ol.source.TileJSON.prototype,
  75864. 'getUrls',
  75865. ol.source.TileJSON.prototype.getUrls);
  75866. goog.exportProperty(
  75867. ol.source.TileJSON.prototype,
  75868. 'setTileLoadFunction',
  75869. ol.source.TileJSON.prototype.setTileLoadFunction);
  75870. goog.exportProperty(
  75871. ol.source.TileJSON.prototype,
  75872. 'setTileUrlFunction',
  75873. ol.source.TileJSON.prototype.setTileUrlFunction);
  75874. goog.exportProperty(
  75875. ol.source.TileJSON.prototype,
  75876. 'setUrl',
  75877. ol.source.TileJSON.prototype.setUrl);
  75878. goog.exportProperty(
  75879. ol.source.TileJSON.prototype,
  75880. 'setUrls',
  75881. ol.source.TileJSON.prototype.setUrls);
  75882. goog.exportProperty(
  75883. ol.source.TileJSON.prototype,
  75884. 'getTileGrid',
  75885. ol.source.TileJSON.prototype.getTileGrid);
  75886. goog.exportProperty(
  75887. ol.source.TileJSON.prototype,
  75888. 'refresh',
  75889. ol.source.TileJSON.prototype.refresh);
  75890. goog.exportProperty(
  75891. ol.source.TileJSON.prototype,
  75892. 'getAttributions',
  75893. ol.source.TileJSON.prototype.getAttributions);
  75894. goog.exportProperty(
  75895. ol.source.TileJSON.prototype,
  75896. 'getLogo',
  75897. ol.source.TileJSON.prototype.getLogo);
  75898. goog.exportProperty(
  75899. ol.source.TileJSON.prototype,
  75900. 'getProjection',
  75901. ol.source.TileJSON.prototype.getProjection);
  75902. goog.exportProperty(
  75903. ol.source.TileJSON.prototype,
  75904. 'getState',
  75905. ol.source.TileJSON.prototype.getState);
  75906. goog.exportProperty(
  75907. ol.source.TileJSON.prototype,
  75908. 'setAttributions',
  75909. ol.source.TileJSON.prototype.setAttributions);
  75910. goog.exportProperty(
  75911. ol.source.TileJSON.prototype,
  75912. 'get',
  75913. ol.source.TileJSON.prototype.get);
  75914. goog.exportProperty(
  75915. ol.source.TileJSON.prototype,
  75916. 'getKeys',
  75917. ol.source.TileJSON.prototype.getKeys);
  75918. goog.exportProperty(
  75919. ol.source.TileJSON.prototype,
  75920. 'getProperties',
  75921. ol.source.TileJSON.prototype.getProperties);
  75922. goog.exportProperty(
  75923. ol.source.TileJSON.prototype,
  75924. 'set',
  75925. ol.source.TileJSON.prototype.set);
  75926. goog.exportProperty(
  75927. ol.source.TileJSON.prototype,
  75928. 'setProperties',
  75929. ol.source.TileJSON.prototype.setProperties);
  75930. goog.exportProperty(
  75931. ol.source.TileJSON.prototype,
  75932. 'unset',
  75933. ol.source.TileJSON.prototype.unset);
  75934. goog.exportProperty(
  75935. ol.source.TileJSON.prototype,
  75936. 'changed',
  75937. ol.source.TileJSON.prototype.changed);
  75938. goog.exportProperty(
  75939. ol.source.TileJSON.prototype,
  75940. 'dispatchEvent',
  75941. ol.source.TileJSON.prototype.dispatchEvent);
  75942. goog.exportProperty(
  75943. ol.source.TileJSON.prototype,
  75944. 'getRevision',
  75945. ol.source.TileJSON.prototype.getRevision);
  75946. goog.exportProperty(
  75947. ol.source.TileJSON.prototype,
  75948. 'on',
  75949. ol.source.TileJSON.prototype.on);
  75950. goog.exportProperty(
  75951. ol.source.TileJSON.prototype,
  75952. 'once',
  75953. ol.source.TileJSON.prototype.once);
  75954. goog.exportProperty(
  75955. ol.source.TileJSON.prototype,
  75956. 'un',
  75957. ol.source.TileJSON.prototype.un);
  75958. goog.exportProperty(
  75959. ol.source.TileUTFGrid.prototype,
  75960. 'getTileGrid',
  75961. ol.source.TileUTFGrid.prototype.getTileGrid);
  75962. goog.exportProperty(
  75963. ol.source.TileUTFGrid.prototype,
  75964. 'refresh',
  75965. ol.source.TileUTFGrid.prototype.refresh);
  75966. goog.exportProperty(
  75967. ol.source.TileUTFGrid.prototype,
  75968. 'getAttributions',
  75969. ol.source.TileUTFGrid.prototype.getAttributions);
  75970. goog.exportProperty(
  75971. ol.source.TileUTFGrid.prototype,
  75972. 'getLogo',
  75973. ol.source.TileUTFGrid.prototype.getLogo);
  75974. goog.exportProperty(
  75975. ol.source.TileUTFGrid.prototype,
  75976. 'getProjection',
  75977. ol.source.TileUTFGrid.prototype.getProjection);
  75978. goog.exportProperty(
  75979. ol.source.TileUTFGrid.prototype,
  75980. 'getState',
  75981. ol.source.TileUTFGrid.prototype.getState);
  75982. goog.exportProperty(
  75983. ol.source.TileUTFGrid.prototype,
  75984. 'setAttributions',
  75985. ol.source.TileUTFGrid.prototype.setAttributions);
  75986. goog.exportProperty(
  75987. ol.source.TileUTFGrid.prototype,
  75988. 'get',
  75989. ol.source.TileUTFGrid.prototype.get);
  75990. goog.exportProperty(
  75991. ol.source.TileUTFGrid.prototype,
  75992. 'getKeys',
  75993. ol.source.TileUTFGrid.prototype.getKeys);
  75994. goog.exportProperty(
  75995. ol.source.TileUTFGrid.prototype,
  75996. 'getProperties',
  75997. ol.source.TileUTFGrid.prototype.getProperties);
  75998. goog.exportProperty(
  75999. ol.source.TileUTFGrid.prototype,
  76000. 'set',
  76001. ol.source.TileUTFGrid.prototype.set);
  76002. goog.exportProperty(
  76003. ol.source.TileUTFGrid.prototype,
  76004. 'setProperties',
  76005. ol.source.TileUTFGrid.prototype.setProperties);
  76006. goog.exportProperty(
  76007. ol.source.TileUTFGrid.prototype,
  76008. 'unset',
  76009. ol.source.TileUTFGrid.prototype.unset);
  76010. goog.exportProperty(
  76011. ol.source.TileUTFGrid.prototype,
  76012. 'changed',
  76013. ol.source.TileUTFGrid.prototype.changed);
  76014. goog.exportProperty(
  76015. ol.source.TileUTFGrid.prototype,
  76016. 'dispatchEvent',
  76017. ol.source.TileUTFGrid.prototype.dispatchEvent);
  76018. goog.exportProperty(
  76019. ol.source.TileUTFGrid.prototype,
  76020. 'getRevision',
  76021. ol.source.TileUTFGrid.prototype.getRevision);
  76022. goog.exportProperty(
  76023. ol.source.TileUTFGrid.prototype,
  76024. 'on',
  76025. ol.source.TileUTFGrid.prototype.on);
  76026. goog.exportProperty(
  76027. ol.source.TileUTFGrid.prototype,
  76028. 'once',
  76029. ol.source.TileUTFGrid.prototype.once);
  76030. goog.exportProperty(
  76031. ol.source.TileUTFGrid.prototype,
  76032. 'un',
  76033. ol.source.TileUTFGrid.prototype.un);
  76034. goog.exportProperty(
  76035. ol.source.TileWMS.prototype,
  76036. 'setRenderReprojectionEdges',
  76037. ol.source.TileWMS.prototype.setRenderReprojectionEdges);
  76038. goog.exportProperty(
  76039. ol.source.TileWMS.prototype,
  76040. 'setTileGridForProjection',
  76041. ol.source.TileWMS.prototype.setTileGridForProjection);
  76042. goog.exportProperty(
  76043. ol.source.TileWMS.prototype,
  76044. 'getTileLoadFunction',
  76045. ol.source.TileWMS.prototype.getTileLoadFunction);
  76046. goog.exportProperty(
  76047. ol.source.TileWMS.prototype,
  76048. 'getTileUrlFunction',
  76049. ol.source.TileWMS.prototype.getTileUrlFunction);
  76050. goog.exportProperty(
  76051. ol.source.TileWMS.prototype,
  76052. 'getUrls',
  76053. ol.source.TileWMS.prototype.getUrls);
  76054. goog.exportProperty(
  76055. ol.source.TileWMS.prototype,
  76056. 'setTileLoadFunction',
  76057. ol.source.TileWMS.prototype.setTileLoadFunction);
  76058. goog.exportProperty(
  76059. ol.source.TileWMS.prototype,
  76060. 'setTileUrlFunction',
  76061. ol.source.TileWMS.prototype.setTileUrlFunction);
  76062. goog.exportProperty(
  76063. ol.source.TileWMS.prototype,
  76064. 'setUrl',
  76065. ol.source.TileWMS.prototype.setUrl);
  76066. goog.exportProperty(
  76067. ol.source.TileWMS.prototype,
  76068. 'setUrls',
  76069. ol.source.TileWMS.prototype.setUrls);
  76070. goog.exportProperty(
  76071. ol.source.TileWMS.prototype,
  76072. 'getTileGrid',
  76073. ol.source.TileWMS.prototype.getTileGrid);
  76074. goog.exportProperty(
  76075. ol.source.TileWMS.prototype,
  76076. 'refresh',
  76077. ol.source.TileWMS.prototype.refresh);
  76078. goog.exportProperty(
  76079. ol.source.TileWMS.prototype,
  76080. 'getAttributions',
  76081. ol.source.TileWMS.prototype.getAttributions);
  76082. goog.exportProperty(
  76083. ol.source.TileWMS.prototype,
  76084. 'getLogo',
  76085. ol.source.TileWMS.prototype.getLogo);
  76086. goog.exportProperty(
  76087. ol.source.TileWMS.prototype,
  76088. 'getProjection',
  76089. ol.source.TileWMS.prototype.getProjection);
  76090. goog.exportProperty(
  76091. ol.source.TileWMS.prototype,
  76092. 'getState',
  76093. ol.source.TileWMS.prototype.getState);
  76094. goog.exportProperty(
  76095. ol.source.TileWMS.prototype,
  76096. 'setAttributions',
  76097. ol.source.TileWMS.prototype.setAttributions);
  76098. goog.exportProperty(
  76099. ol.source.TileWMS.prototype,
  76100. 'get',
  76101. ol.source.TileWMS.prototype.get);
  76102. goog.exportProperty(
  76103. ol.source.TileWMS.prototype,
  76104. 'getKeys',
  76105. ol.source.TileWMS.prototype.getKeys);
  76106. goog.exportProperty(
  76107. ol.source.TileWMS.prototype,
  76108. 'getProperties',
  76109. ol.source.TileWMS.prototype.getProperties);
  76110. goog.exportProperty(
  76111. ol.source.TileWMS.prototype,
  76112. 'set',
  76113. ol.source.TileWMS.prototype.set);
  76114. goog.exportProperty(
  76115. ol.source.TileWMS.prototype,
  76116. 'setProperties',
  76117. ol.source.TileWMS.prototype.setProperties);
  76118. goog.exportProperty(
  76119. ol.source.TileWMS.prototype,
  76120. 'unset',
  76121. ol.source.TileWMS.prototype.unset);
  76122. goog.exportProperty(
  76123. ol.source.TileWMS.prototype,
  76124. 'changed',
  76125. ol.source.TileWMS.prototype.changed);
  76126. goog.exportProperty(
  76127. ol.source.TileWMS.prototype,
  76128. 'dispatchEvent',
  76129. ol.source.TileWMS.prototype.dispatchEvent);
  76130. goog.exportProperty(
  76131. ol.source.TileWMS.prototype,
  76132. 'getRevision',
  76133. ol.source.TileWMS.prototype.getRevision);
  76134. goog.exportProperty(
  76135. ol.source.TileWMS.prototype,
  76136. 'on',
  76137. ol.source.TileWMS.prototype.on);
  76138. goog.exportProperty(
  76139. ol.source.TileWMS.prototype,
  76140. 'once',
  76141. ol.source.TileWMS.prototype.once);
  76142. goog.exportProperty(
  76143. ol.source.TileWMS.prototype,
  76144. 'un',
  76145. ol.source.TileWMS.prototype.un);
  76146. goog.exportProperty(
  76147. ol.source.Vector.Event.prototype,
  76148. 'type',
  76149. ol.source.Vector.Event.prototype.type);
  76150. goog.exportProperty(
  76151. ol.source.Vector.Event.prototype,
  76152. 'target',
  76153. ol.source.Vector.Event.prototype.target);
  76154. goog.exportProperty(
  76155. ol.source.Vector.Event.prototype,
  76156. 'preventDefault',
  76157. ol.source.Vector.Event.prototype.preventDefault);
  76158. goog.exportProperty(
  76159. ol.source.Vector.Event.prototype,
  76160. 'stopPropagation',
  76161. ol.source.Vector.Event.prototype.stopPropagation);
  76162. goog.exportProperty(
  76163. ol.source.VectorTile.prototype,
  76164. 'getTileLoadFunction',
  76165. ol.source.VectorTile.prototype.getTileLoadFunction);
  76166. goog.exportProperty(
  76167. ol.source.VectorTile.prototype,
  76168. 'getTileUrlFunction',
  76169. ol.source.VectorTile.prototype.getTileUrlFunction);
  76170. goog.exportProperty(
  76171. ol.source.VectorTile.prototype,
  76172. 'getUrls',
  76173. ol.source.VectorTile.prototype.getUrls);
  76174. goog.exportProperty(
  76175. ol.source.VectorTile.prototype,
  76176. 'setTileLoadFunction',
  76177. ol.source.VectorTile.prototype.setTileLoadFunction);
  76178. goog.exportProperty(
  76179. ol.source.VectorTile.prototype,
  76180. 'setTileUrlFunction',
  76181. ol.source.VectorTile.prototype.setTileUrlFunction);
  76182. goog.exportProperty(
  76183. ol.source.VectorTile.prototype,
  76184. 'setUrl',
  76185. ol.source.VectorTile.prototype.setUrl);
  76186. goog.exportProperty(
  76187. ol.source.VectorTile.prototype,
  76188. 'setUrls',
  76189. ol.source.VectorTile.prototype.setUrls);
  76190. goog.exportProperty(
  76191. ol.source.VectorTile.prototype,
  76192. 'getTileGrid',
  76193. ol.source.VectorTile.prototype.getTileGrid);
  76194. goog.exportProperty(
  76195. ol.source.VectorTile.prototype,
  76196. 'refresh',
  76197. ol.source.VectorTile.prototype.refresh);
  76198. goog.exportProperty(
  76199. ol.source.VectorTile.prototype,
  76200. 'getAttributions',
  76201. ol.source.VectorTile.prototype.getAttributions);
  76202. goog.exportProperty(
  76203. ol.source.VectorTile.prototype,
  76204. 'getLogo',
  76205. ol.source.VectorTile.prototype.getLogo);
  76206. goog.exportProperty(
  76207. ol.source.VectorTile.prototype,
  76208. 'getProjection',
  76209. ol.source.VectorTile.prototype.getProjection);
  76210. goog.exportProperty(
  76211. ol.source.VectorTile.prototype,
  76212. 'getState',
  76213. ol.source.VectorTile.prototype.getState);
  76214. goog.exportProperty(
  76215. ol.source.VectorTile.prototype,
  76216. 'setAttributions',
  76217. ol.source.VectorTile.prototype.setAttributions);
  76218. goog.exportProperty(
  76219. ol.source.VectorTile.prototype,
  76220. 'get',
  76221. ol.source.VectorTile.prototype.get);
  76222. goog.exportProperty(
  76223. ol.source.VectorTile.prototype,
  76224. 'getKeys',
  76225. ol.source.VectorTile.prototype.getKeys);
  76226. goog.exportProperty(
  76227. ol.source.VectorTile.prototype,
  76228. 'getProperties',
  76229. ol.source.VectorTile.prototype.getProperties);
  76230. goog.exportProperty(
  76231. ol.source.VectorTile.prototype,
  76232. 'set',
  76233. ol.source.VectorTile.prototype.set);
  76234. goog.exportProperty(
  76235. ol.source.VectorTile.prototype,
  76236. 'setProperties',
  76237. ol.source.VectorTile.prototype.setProperties);
  76238. goog.exportProperty(
  76239. ol.source.VectorTile.prototype,
  76240. 'unset',
  76241. ol.source.VectorTile.prototype.unset);
  76242. goog.exportProperty(
  76243. ol.source.VectorTile.prototype,
  76244. 'changed',
  76245. ol.source.VectorTile.prototype.changed);
  76246. goog.exportProperty(
  76247. ol.source.VectorTile.prototype,
  76248. 'dispatchEvent',
  76249. ol.source.VectorTile.prototype.dispatchEvent);
  76250. goog.exportProperty(
  76251. ol.source.VectorTile.prototype,
  76252. 'getRevision',
  76253. ol.source.VectorTile.prototype.getRevision);
  76254. goog.exportProperty(
  76255. ol.source.VectorTile.prototype,
  76256. 'on',
  76257. ol.source.VectorTile.prototype.on);
  76258. goog.exportProperty(
  76259. ol.source.VectorTile.prototype,
  76260. 'once',
  76261. ol.source.VectorTile.prototype.once);
  76262. goog.exportProperty(
  76263. ol.source.VectorTile.prototype,
  76264. 'un',
  76265. ol.source.VectorTile.prototype.un);
  76266. goog.exportProperty(
  76267. ol.source.WMTS.prototype,
  76268. 'setRenderReprojectionEdges',
  76269. ol.source.WMTS.prototype.setRenderReprojectionEdges);
  76270. goog.exportProperty(
  76271. ol.source.WMTS.prototype,
  76272. 'setTileGridForProjection',
  76273. ol.source.WMTS.prototype.setTileGridForProjection);
  76274. goog.exportProperty(
  76275. ol.source.WMTS.prototype,
  76276. 'getTileLoadFunction',
  76277. ol.source.WMTS.prototype.getTileLoadFunction);
  76278. goog.exportProperty(
  76279. ol.source.WMTS.prototype,
  76280. 'getTileUrlFunction',
  76281. ol.source.WMTS.prototype.getTileUrlFunction);
  76282. goog.exportProperty(
  76283. ol.source.WMTS.prototype,
  76284. 'getUrls',
  76285. ol.source.WMTS.prototype.getUrls);
  76286. goog.exportProperty(
  76287. ol.source.WMTS.prototype,
  76288. 'setTileLoadFunction',
  76289. ol.source.WMTS.prototype.setTileLoadFunction);
  76290. goog.exportProperty(
  76291. ol.source.WMTS.prototype,
  76292. 'setTileUrlFunction',
  76293. ol.source.WMTS.prototype.setTileUrlFunction);
  76294. goog.exportProperty(
  76295. ol.source.WMTS.prototype,
  76296. 'setUrl',
  76297. ol.source.WMTS.prototype.setUrl);
  76298. goog.exportProperty(
  76299. ol.source.WMTS.prototype,
  76300. 'setUrls',
  76301. ol.source.WMTS.prototype.setUrls);
  76302. goog.exportProperty(
  76303. ol.source.WMTS.prototype,
  76304. 'getTileGrid',
  76305. ol.source.WMTS.prototype.getTileGrid);
  76306. goog.exportProperty(
  76307. ol.source.WMTS.prototype,
  76308. 'refresh',
  76309. ol.source.WMTS.prototype.refresh);
  76310. goog.exportProperty(
  76311. ol.source.WMTS.prototype,
  76312. 'getAttributions',
  76313. ol.source.WMTS.prototype.getAttributions);
  76314. goog.exportProperty(
  76315. ol.source.WMTS.prototype,
  76316. 'getLogo',
  76317. ol.source.WMTS.prototype.getLogo);
  76318. goog.exportProperty(
  76319. ol.source.WMTS.prototype,
  76320. 'getProjection',
  76321. ol.source.WMTS.prototype.getProjection);
  76322. goog.exportProperty(
  76323. ol.source.WMTS.prototype,
  76324. 'getState',
  76325. ol.source.WMTS.prototype.getState);
  76326. goog.exportProperty(
  76327. ol.source.WMTS.prototype,
  76328. 'setAttributions',
  76329. ol.source.WMTS.prototype.setAttributions);
  76330. goog.exportProperty(
  76331. ol.source.WMTS.prototype,
  76332. 'get',
  76333. ol.source.WMTS.prototype.get);
  76334. goog.exportProperty(
  76335. ol.source.WMTS.prototype,
  76336. 'getKeys',
  76337. ol.source.WMTS.prototype.getKeys);
  76338. goog.exportProperty(
  76339. ol.source.WMTS.prototype,
  76340. 'getProperties',
  76341. ol.source.WMTS.prototype.getProperties);
  76342. goog.exportProperty(
  76343. ol.source.WMTS.prototype,
  76344. 'set',
  76345. ol.source.WMTS.prototype.set);
  76346. goog.exportProperty(
  76347. ol.source.WMTS.prototype,
  76348. 'setProperties',
  76349. ol.source.WMTS.prototype.setProperties);
  76350. goog.exportProperty(
  76351. ol.source.WMTS.prototype,
  76352. 'unset',
  76353. ol.source.WMTS.prototype.unset);
  76354. goog.exportProperty(
  76355. ol.source.WMTS.prototype,
  76356. 'changed',
  76357. ol.source.WMTS.prototype.changed);
  76358. goog.exportProperty(
  76359. ol.source.WMTS.prototype,
  76360. 'dispatchEvent',
  76361. ol.source.WMTS.prototype.dispatchEvent);
  76362. goog.exportProperty(
  76363. ol.source.WMTS.prototype,
  76364. 'getRevision',
  76365. ol.source.WMTS.prototype.getRevision);
  76366. goog.exportProperty(
  76367. ol.source.WMTS.prototype,
  76368. 'on',
  76369. ol.source.WMTS.prototype.on);
  76370. goog.exportProperty(
  76371. ol.source.WMTS.prototype,
  76372. 'once',
  76373. ol.source.WMTS.prototype.once);
  76374. goog.exportProperty(
  76375. ol.source.WMTS.prototype,
  76376. 'un',
  76377. ol.source.WMTS.prototype.un);
  76378. goog.exportProperty(
  76379. ol.source.Zoomify.prototype,
  76380. 'setRenderReprojectionEdges',
  76381. ol.source.Zoomify.prototype.setRenderReprojectionEdges);
  76382. goog.exportProperty(
  76383. ol.source.Zoomify.prototype,
  76384. 'setTileGridForProjection',
  76385. ol.source.Zoomify.prototype.setTileGridForProjection);
  76386. goog.exportProperty(
  76387. ol.source.Zoomify.prototype,
  76388. 'getTileLoadFunction',
  76389. ol.source.Zoomify.prototype.getTileLoadFunction);
  76390. goog.exportProperty(
  76391. ol.source.Zoomify.prototype,
  76392. 'getTileUrlFunction',
  76393. ol.source.Zoomify.prototype.getTileUrlFunction);
  76394. goog.exportProperty(
  76395. ol.source.Zoomify.prototype,
  76396. 'getUrls',
  76397. ol.source.Zoomify.prototype.getUrls);
  76398. goog.exportProperty(
  76399. ol.source.Zoomify.prototype,
  76400. 'setTileLoadFunction',
  76401. ol.source.Zoomify.prototype.setTileLoadFunction);
  76402. goog.exportProperty(
  76403. ol.source.Zoomify.prototype,
  76404. 'setTileUrlFunction',
  76405. ol.source.Zoomify.prototype.setTileUrlFunction);
  76406. goog.exportProperty(
  76407. ol.source.Zoomify.prototype,
  76408. 'setUrl',
  76409. ol.source.Zoomify.prototype.setUrl);
  76410. goog.exportProperty(
  76411. ol.source.Zoomify.prototype,
  76412. 'setUrls',
  76413. ol.source.Zoomify.prototype.setUrls);
  76414. goog.exportProperty(
  76415. ol.source.Zoomify.prototype,
  76416. 'getTileGrid',
  76417. ol.source.Zoomify.prototype.getTileGrid);
  76418. goog.exportProperty(
  76419. ol.source.Zoomify.prototype,
  76420. 'refresh',
  76421. ol.source.Zoomify.prototype.refresh);
  76422. goog.exportProperty(
  76423. ol.source.Zoomify.prototype,
  76424. 'getAttributions',
  76425. ol.source.Zoomify.prototype.getAttributions);
  76426. goog.exportProperty(
  76427. ol.source.Zoomify.prototype,
  76428. 'getLogo',
  76429. ol.source.Zoomify.prototype.getLogo);
  76430. goog.exportProperty(
  76431. ol.source.Zoomify.prototype,
  76432. 'getProjection',
  76433. ol.source.Zoomify.prototype.getProjection);
  76434. goog.exportProperty(
  76435. ol.source.Zoomify.prototype,
  76436. 'getState',
  76437. ol.source.Zoomify.prototype.getState);
  76438. goog.exportProperty(
  76439. ol.source.Zoomify.prototype,
  76440. 'setAttributions',
  76441. ol.source.Zoomify.prototype.setAttributions);
  76442. goog.exportProperty(
  76443. ol.source.Zoomify.prototype,
  76444. 'get',
  76445. ol.source.Zoomify.prototype.get);
  76446. goog.exportProperty(
  76447. ol.source.Zoomify.prototype,
  76448. 'getKeys',
  76449. ol.source.Zoomify.prototype.getKeys);
  76450. goog.exportProperty(
  76451. ol.source.Zoomify.prototype,
  76452. 'getProperties',
  76453. ol.source.Zoomify.prototype.getProperties);
  76454. goog.exportProperty(
  76455. ol.source.Zoomify.prototype,
  76456. 'set',
  76457. ol.source.Zoomify.prototype.set);
  76458. goog.exportProperty(
  76459. ol.source.Zoomify.prototype,
  76460. 'setProperties',
  76461. ol.source.Zoomify.prototype.setProperties);
  76462. goog.exportProperty(
  76463. ol.source.Zoomify.prototype,
  76464. 'unset',
  76465. ol.source.Zoomify.prototype.unset);
  76466. goog.exportProperty(
  76467. ol.source.Zoomify.prototype,
  76468. 'changed',
  76469. ol.source.Zoomify.prototype.changed);
  76470. goog.exportProperty(
  76471. ol.source.Zoomify.prototype,
  76472. 'dispatchEvent',
  76473. ol.source.Zoomify.prototype.dispatchEvent);
  76474. goog.exportProperty(
  76475. ol.source.Zoomify.prototype,
  76476. 'getRevision',
  76477. ol.source.Zoomify.prototype.getRevision);
  76478. goog.exportProperty(
  76479. ol.source.Zoomify.prototype,
  76480. 'on',
  76481. ol.source.Zoomify.prototype.on);
  76482. goog.exportProperty(
  76483. ol.source.Zoomify.prototype,
  76484. 'once',
  76485. ol.source.Zoomify.prototype.once);
  76486. goog.exportProperty(
  76487. ol.source.Zoomify.prototype,
  76488. 'un',
  76489. ol.source.Zoomify.prototype.un);
  76490. goog.exportProperty(
  76491. ol.reproj.Tile.prototype,
  76492. 'getTileCoord',
  76493. ol.reproj.Tile.prototype.getTileCoord);
  76494. goog.exportProperty(
  76495. ol.reproj.Tile.prototype,
  76496. 'load',
  76497. ol.reproj.Tile.prototype.load);
  76498. goog.exportProperty(
  76499. ol.renderer.Layer.prototype,
  76500. 'changed',
  76501. ol.renderer.Layer.prototype.changed);
  76502. goog.exportProperty(
  76503. ol.renderer.Layer.prototype,
  76504. 'dispatchEvent',
  76505. ol.renderer.Layer.prototype.dispatchEvent);
  76506. goog.exportProperty(
  76507. ol.renderer.Layer.prototype,
  76508. 'getRevision',
  76509. ol.renderer.Layer.prototype.getRevision);
  76510. goog.exportProperty(
  76511. ol.renderer.Layer.prototype,
  76512. 'on',
  76513. ol.renderer.Layer.prototype.on);
  76514. goog.exportProperty(
  76515. ol.renderer.Layer.prototype,
  76516. 'once',
  76517. ol.renderer.Layer.prototype.once);
  76518. goog.exportProperty(
  76519. ol.renderer.Layer.prototype,
  76520. 'un',
  76521. ol.renderer.Layer.prototype.un);
  76522. goog.exportProperty(
  76523. ol.renderer.webgl.Layer.prototype,
  76524. 'changed',
  76525. ol.renderer.webgl.Layer.prototype.changed);
  76526. goog.exportProperty(
  76527. ol.renderer.webgl.Layer.prototype,
  76528. 'dispatchEvent',
  76529. ol.renderer.webgl.Layer.prototype.dispatchEvent);
  76530. goog.exportProperty(
  76531. ol.renderer.webgl.Layer.prototype,
  76532. 'getRevision',
  76533. ol.renderer.webgl.Layer.prototype.getRevision);
  76534. goog.exportProperty(
  76535. ol.renderer.webgl.Layer.prototype,
  76536. 'on',
  76537. ol.renderer.webgl.Layer.prototype.on);
  76538. goog.exportProperty(
  76539. ol.renderer.webgl.Layer.prototype,
  76540. 'once',
  76541. ol.renderer.webgl.Layer.prototype.once);
  76542. goog.exportProperty(
  76543. ol.renderer.webgl.Layer.prototype,
  76544. 'un',
  76545. ol.renderer.webgl.Layer.prototype.un);
  76546. goog.exportProperty(
  76547. ol.renderer.webgl.ImageLayer.prototype,
  76548. 'changed',
  76549. ol.renderer.webgl.ImageLayer.prototype.changed);
  76550. goog.exportProperty(
  76551. ol.renderer.webgl.ImageLayer.prototype,
  76552. 'dispatchEvent',
  76553. ol.renderer.webgl.ImageLayer.prototype.dispatchEvent);
  76554. goog.exportProperty(
  76555. ol.renderer.webgl.ImageLayer.prototype,
  76556. 'getRevision',
  76557. ol.renderer.webgl.ImageLayer.prototype.getRevision);
  76558. goog.exportProperty(
  76559. ol.renderer.webgl.ImageLayer.prototype,
  76560. 'on',
  76561. ol.renderer.webgl.ImageLayer.prototype.on);
  76562. goog.exportProperty(
  76563. ol.renderer.webgl.ImageLayer.prototype,
  76564. 'once',
  76565. ol.renderer.webgl.ImageLayer.prototype.once);
  76566. goog.exportProperty(
  76567. ol.renderer.webgl.ImageLayer.prototype,
  76568. 'un',
  76569. ol.renderer.webgl.ImageLayer.prototype.un);
  76570. goog.exportProperty(
  76571. ol.renderer.webgl.TileLayer.prototype,
  76572. 'changed',
  76573. ol.renderer.webgl.TileLayer.prototype.changed);
  76574. goog.exportProperty(
  76575. ol.renderer.webgl.TileLayer.prototype,
  76576. 'dispatchEvent',
  76577. ol.renderer.webgl.TileLayer.prototype.dispatchEvent);
  76578. goog.exportProperty(
  76579. ol.renderer.webgl.TileLayer.prototype,
  76580. 'getRevision',
  76581. ol.renderer.webgl.TileLayer.prototype.getRevision);
  76582. goog.exportProperty(
  76583. ol.renderer.webgl.TileLayer.prototype,
  76584. 'on',
  76585. ol.renderer.webgl.TileLayer.prototype.on);
  76586. goog.exportProperty(
  76587. ol.renderer.webgl.TileLayer.prototype,
  76588. 'once',
  76589. ol.renderer.webgl.TileLayer.prototype.once);
  76590. goog.exportProperty(
  76591. ol.renderer.webgl.TileLayer.prototype,
  76592. 'un',
  76593. ol.renderer.webgl.TileLayer.prototype.un);
  76594. goog.exportProperty(
  76595. ol.renderer.webgl.VectorLayer.prototype,
  76596. 'changed',
  76597. ol.renderer.webgl.VectorLayer.prototype.changed);
  76598. goog.exportProperty(
  76599. ol.renderer.webgl.VectorLayer.prototype,
  76600. 'dispatchEvent',
  76601. ol.renderer.webgl.VectorLayer.prototype.dispatchEvent);
  76602. goog.exportProperty(
  76603. ol.renderer.webgl.VectorLayer.prototype,
  76604. 'getRevision',
  76605. ol.renderer.webgl.VectorLayer.prototype.getRevision);
  76606. goog.exportProperty(
  76607. ol.renderer.webgl.VectorLayer.prototype,
  76608. 'on',
  76609. ol.renderer.webgl.VectorLayer.prototype.on);
  76610. goog.exportProperty(
  76611. ol.renderer.webgl.VectorLayer.prototype,
  76612. 'once',
  76613. ol.renderer.webgl.VectorLayer.prototype.once);
  76614. goog.exportProperty(
  76615. ol.renderer.webgl.VectorLayer.prototype,
  76616. 'un',
  76617. ol.renderer.webgl.VectorLayer.prototype.un);
  76618. goog.exportProperty(
  76619. ol.renderer.canvas.Layer.prototype,
  76620. 'changed',
  76621. ol.renderer.canvas.Layer.prototype.changed);
  76622. goog.exportProperty(
  76623. ol.renderer.canvas.Layer.prototype,
  76624. 'dispatchEvent',
  76625. ol.renderer.canvas.Layer.prototype.dispatchEvent);
  76626. goog.exportProperty(
  76627. ol.renderer.canvas.Layer.prototype,
  76628. 'getRevision',
  76629. ol.renderer.canvas.Layer.prototype.getRevision);
  76630. goog.exportProperty(
  76631. ol.renderer.canvas.Layer.prototype,
  76632. 'on',
  76633. ol.renderer.canvas.Layer.prototype.on);
  76634. goog.exportProperty(
  76635. ol.renderer.canvas.Layer.prototype,
  76636. 'once',
  76637. ol.renderer.canvas.Layer.prototype.once);
  76638. goog.exportProperty(
  76639. ol.renderer.canvas.Layer.prototype,
  76640. 'un',
  76641. ol.renderer.canvas.Layer.prototype.un);
  76642. goog.exportProperty(
  76643. ol.renderer.canvas.IntermediateCanvas.prototype,
  76644. 'changed',
  76645. ol.renderer.canvas.IntermediateCanvas.prototype.changed);
  76646. goog.exportProperty(
  76647. ol.renderer.canvas.IntermediateCanvas.prototype,
  76648. 'dispatchEvent',
  76649. ol.renderer.canvas.IntermediateCanvas.prototype.dispatchEvent);
  76650. goog.exportProperty(
  76651. ol.renderer.canvas.IntermediateCanvas.prototype,
  76652. 'getRevision',
  76653. ol.renderer.canvas.IntermediateCanvas.prototype.getRevision);
  76654. goog.exportProperty(
  76655. ol.renderer.canvas.IntermediateCanvas.prototype,
  76656. 'on',
  76657. ol.renderer.canvas.IntermediateCanvas.prototype.on);
  76658. goog.exportProperty(
  76659. ol.renderer.canvas.IntermediateCanvas.prototype,
  76660. 'once',
  76661. ol.renderer.canvas.IntermediateCanvas.prototype.once);
  76662. goog.exportProperty(
  76663. ol.renderer.canvas.IntermediateCanvas.prototype,
  76664. 'un',
  76665. ol.renderer.canvas.IntermediateCanvas.prototype.un);
  76666. goog.exportProperty(
  76667. ol.renderer.canvas.ImageLayer.prototype,
  76668. 'changed',
  76669. ol.renderer.canvas.ImageLayer.prototype.changed);
  76670. goog.exportProperty(
  76671. ol.renderer.canvas.ImageLayer.prototype,
  76672. 'dispatchEvent',
  76673. ol.renderer.canvas.ImageLayer.prototype.dispatchEvent);
  76674. goog.exportProperty(
  76675. ol.renderer.canvas.ImageLayer.prototype,
  76676. 'getRevision',
  76677. ol.renderer.canvas.ImageLayer.prototype.getRevision);
  76678. goog.exportProperty(
  76679. ol.renderer.canvas.ImageLayer.prototype,
  76680. 'on',
  76681. ol.renderer.canvas.ImageLayer.prototype.on);
  76682. goog.exportProperty(
  76683. ol.renderer.canvas.ImageLayer.prototype,
  76684. 'once',
  76685. ol.renderer.canvas.ImageLayer.prototype.once);
  76686. goog.exportProperty(
  76687. ol.renderer.canvas.ImageLayer.prototype,
  76688. 'un',
  76689. ol.renderer.canvas.ImageLayer.prototype.un);
  76690. goog.exportProperty(
  76691. ol.renderer.canvas.TileLayer.prototype,
  76692. 'changed',
  76693. ol.renderer.canvas.TileLayer.prototype.changed);
  76694. goog.exportProperty(
  76695. ol.renderer.canvas.TileLayer.prototype,
  76696. 'dispatchEvent',
  76697. ol.renderer.canvas.TileLayer.prototype.dispatchEvent);
  76698. goog.exportProperty(
  76699. ol.renderer.canvas.TileLayer.prototype,
  76700. 'getRevision',
  76701. ol.renderer.canvas.TileLayer.prototype.getRevision);
  76702. goog.exportProperty(
  76703. ol.renderer.canvas.TileLayer.prototype,
  76704. 'on',
  76705. ol.renderer.canvas.TileLayer.prototype.on);
  76706. goog.exportProperty(
  76707. ol.renderer.canvas.TileLayer.prototype,
  76708. 'once',
  76709. ol.renderer.canvas.TileLayer.prototype.once);
  76710. goog.exportProperty(
  76711. ol.renderer.canvas.TileLayer.prototype,
  76712. 'un',
  76713. ol.renderer.canvas.TileLayer.prototype.un);
  76714. goog.exportProperty(
  76715. ol.renderer.canvas.VectorLayer.prototype,
  76716. 'changed',
  76717. ol.renderer.canvas.VectorLayer.prototype.changed);
  76718. goog.exportProperty(
  76719. ol.renderer.canvas.VectorLayer.prototype,
  76720. 'dispatchEvent',
  76721. ol.renderer.canvas.VectorLayer.prototype.dispatchEvent);
  76722. goog.exportProperty(
  76723. ol.renderer.canvas.VectorLayer.prototype,
  76724. 'getRevision',
  76725. ol.renderer.canvas.VectorLayer.prototype.getRevision);
  76726. goog.exportProperty(
  76727. ol.renderer.canvas.VectorLayer.prototype,
  76728. 'on',
  76729. ol.renderer.canvas.VectorLayer.prototype.on);
  76730. goog.exportProperty(
  76731. ol.renderer.canvas.VectorLayer.prototype,
  76732. 'once',
  76733. ol.renderer.canvas.VectorLayer.prototype.once);
  76734. goog.exportProperty(
  76735. ol.renderer.canvas.VectorLayer.prototype,
  76736. 'un',
  76737. ol.renderer.canvas.VectorLayer.prototype.un);
  76738. goog.exportProperty(
  76739. ol.renderer.canvas.VectorTileLayer.prototype,
  76740. 'changed',
  76741. ol.renderer.canvas.VectorTileLayer.prototype.changed);
  76742. goog.exportProperty(
  76743. ol.renderer.canvas.VectorTileLayer.prototype,
  76744. 'dispatchEvent',
  76745. ol.renderer.canvas.VectorTileLayer.prototype.dispatchEvent);
  76746. goog.exportProperty(
  76747. ol.renderer.canvas.VectorTileLayer.prototype,
  76748. 'getRevision',
  76749. ol.renderer.canvas.VectorTileLayer.prototype.getRevision);
  76750. goog.exportProperty(
  76751. ol.renderer.canvas.VectorTileLayer.prototype,
  76752. 'on',
  76753. ol.renderer.canvas.VectorTileLayer.prototype.on);
  76754. goog.exportProperty(
  76755. ol.renderer.canvas.VectorTileLayer.prototype,
  76756. 'once',
  76757. ol.renderer.canvas.VectorTileLayer.prototype.once);
  76758. goog.exportProperty(
  76759. ol.renderer.canvas.VectorTileLayer.prototype,
  76760. 'un',
  76761. ol.renderer.canvas.VectorTileLayer.prototype.un);
  76762. goog.exportProperty(
  76763. ol.render.Event.prototype,
  76764. 'type',
  76765. ol.render.Event.prototype.type);
  76766. goog.exportProperty(
  76767. ol.render.Event.prototype,
  76768. 'target',
  76769. ol.render.Event.prototype.target);
  76770. goog.exportProperty(
  76771. ol.render.Event.prototype,
  76772. 'preventDefault',
  76773. ol.render.Event.prototype.preventDefault);
  76774. goog.exportProperty(
  76775. ol.render.Event.prototype,
  76776. 'stopPropagation',
  76777. ol.render.Event.prototype.stopPropagation);
  76778. goog.exportProperty(
  76779. ol.pointer.PointerEvent.prototype,
  76780. 'type',
  76781. ol.pointer.PointerEvent.prototype.type);
  76782. goog.exportProperty(
  76783. ol.pointer.PointerEvent.prototype,
  76784. 'target',
  76785. ol.pointer.PointerEvent.prototype.target);
  76786. goog.exportProperty(
  76787. ol.pointer.PointerEvent.prototype,
  76788. 'preventDefault',
  76789. ol.pointer.PointerEvent.prototype.preventDefault);
  76790. goog.exportProperty(
  76791. ol.pointer.PointerEvent.prototype,
  76792. 'stopPropagation',
  76793. ol.pointer.PointerEvent.prototype.stopPropagation);
  76794. goog.exportProperty(
  76795. ol.layer.Base.prototype,
  76796. 'get',
  76797. ol.layer.Base.prototype.get);
  76798. goog.exportProperty(
  76799. ol.layer.Base.prototype,
  76800. 'getKeys',
  76801. ol.layer.Base.prototype.getKeys);
  76802. goog.exportProperty(
  76803. ol.layer.Base.prototype,
  76804. 'getProperties',
  76805. ol.layer.Base.prototype.getProperties);
  76806. goog.exportProperty(
  76807. ol.layer.Base.prototype,
  76808. 'set',
  76809. ol.layer.Base.prototype.set);
  76810. goog.exportProperty(
  76811. ol.layer.Base.prototype,
  76812. 'setProperties',
  76813. ol.layer.Base.prototype.setProperties);
  76814. goog.exportProperty(
  76815. ol.layer.Base.prototype,
  76816. 'unset',
  76817. ol.layer.Base.prototype.unset);
  76818. goog.exportProperty(
  76819. ol.layer.Base.prototype,
  76820. 'changed',
  76821. ol.layer.Base.prototype.changed);
  76822. goog.exportProperty(
  76823. ol.layer.Base.prototype,
  76824. 'dispatchEvent',
  76825. ol.layer.Base.prototype.dispatchEvent);
  76826. goog.exportProperty(
  76827. ol.layer.Base.prototype,
  76828. 'getRevision',
  76829. ol.layer.Base.prototype.getRevision);
  76830. goog.exportProperty(
  76831. ol.layer.Base.prototype,
  76832. 'on',
  76833. ol.layer.Base.prototype.on);
  76834. goog.exportProperty(
  76835. ol.layer.Base.prototype,
  76836. 'once',
  76837. ol.layer.Base.prototype.once);
  76838. goog.exportProperty(
  76839. ol.layer.Base.prototype,
  76840. 'un',
  76841. ol.layer.Base.prototype.un);
  76842. goog.exportProperty(
  76843. ol.layer.Group.prototype,
  76844. 'getExtent',
  76845. ol.layer.Group.prototype.getExtent);
  76846. goog.exportProperty(
  76847. ol.layer.Group.prototype,
  76848. 'getMaxResolution',
  76849. ol.layer.Group.prototype.getMaxResolution);
  76850. goog.exportProperty(
  76851. ol.layer.Group.prototype,
  76852. 'getMinResolution',
  76853. ol.layer.Group.prototype.getMinResolution);
  76854. goog.exportProperty(
  76855. ol.layer.Group.prototype,
  76856. 'getOpacity',
  76857. ol.layer.Group.prototype.getOpacity);
  76858. goog.exportProperty(
  76859. ol.layer.Group.prototype,
  76860. 'getVisible',
  76861. ol.layer.Group.prototype.getVisible);
  76862. goog.exportProperty(
  76863. ol.layer.Group.prototype,
  76864. 'getZIndex',
  76865. ol.layer.Group.prototype.getZIndex);
  76866. goog.exportProperty(
  76867. ol.layer.Group.prototype,
  76868. 'setExtent',
  76869. ol.layer.Group.prototype.setExtent);
  76870. goog.exportProperty(
  76871. ol.layer.Group.prototype,
  76872. 'setMaxResolution',
  76873. ol.layer.Group.prototype.setMaxResolution);
  76874. goog.exportProperty(
  76875. ol.layer.Group.prototype,
  76876. 'setMinResolution',
  76877. ol.layer.Group.prototype.setMinResolution);
  76878. goog.exportProperty(
  76879. ol.layer.Group.prototype,
  76880. 'setOpacity',
  76881. ol.layer.Group.prototype.setOpacity);
  76882. goog.exportProperty(
  76883. ol.layer.Group.prototype,
  76884. 'setVisible',
  76885. ol.layer.Group.prototype.setVisible);
  76886. goog.exportProperty(
  76887. ol.layer.Group.prototype,
  76888. 'setZIndex',
  76889. ol.layer.Group.prototype.setZIndex);
  76890. goog.exportProperty(
  76891. ol.layer.Group.prototype,
  76892. 'get',
  76893. ol.layer.Group.prototype.get);
  76894. goog.exportProperty(
  76895. ol.layer.Group.prototype,
  76896. 'getKeys',
  76897. ol.layer.Group.prototype.getKeys);
  76898. goog.exportProperty(
  76899. ol.layer.Group.prototype,
  76900. 'getProperties',
  76901. ol.layer.Group.prototype.getProperties);
  76902. goog.exportProperty(
  76903. ol.layer.Group.prototype,
  76904. 'set',
  76905. ol.layer.Group.prototype.set);
  76906. goog.exportProperty(
  76907. ol.layer.Group.prototype,
  76908. 'setProperties',
  76909. ol.layer.Group.prototype.setProperties);
  76910. goog.exportProperty(
  76911. ol.layer.Group.prototype,
  76912. 'unset',
  76913. ol.layer.Group.prototype.unset);
  76914. goog.exportProperty(
  76915. ol.layer.Group.prototype,
  76916. 'changed',
  76917. ol.layer.Group.prototype.changed);
  76918. goog.exportProperty(
  76919. ol.layer.Group.prototype,
  76920. 'dispatchEvent',
  76921. ol.layer.Group.prototype.dispatchEvent);
  76922. goog.exportProperty(
  76923. ol.layer.Group.prototype,
  76924. 'getRevision',
  76925. ol.layer.Group.prototype.getRevision);
  76926. goog.exportProperty(
  76927. ol.layer.Group.prototype,
  76928. 'on',
  76929. ol.layer.Group.prototype.on);
  76930. goog.exportProperty(
  76931. ol.layer.Group.prototype,
  76932. 'once',
  76933. ol.layer.Group.prototype.once);
  76934. goog.exportProperty(
  76935. ol.layer.Group.prototype,
  76936. 'un',
  76937. ol.layer.Group.prototype.un);
  76938. goog.exportProperty(
  76939. ol.layer.Layer.prototype,
  76940. 'getExtent',
  76941. ol.layer.Layer.prototype.getExtent);
  76942. goog.exportProperty(
  76943. ol.layer.Layer.prototype,
  76944. 'getMaxResolution',
  76945. ol.layer.Layer.prototype.getMaxResolution);
  76946. goog.exportProperty(
  76947. ol.layer.Layer.prototype,
  76948. 'getMinResolution',
  76949. ol.layer.Layer.prototype.getMinResolution);
  76950. goog.exportProperty(
  76951. ol.layer.Layer.prototype,
  76952. 'getOpacity',
  76953. ol.layer.Layer.prototype.getOpacity);
  76954. goog.exportProperty(
  76955. ol.layer.Layer.prototype,
  76956. 'getVisible',
  76957. ol.layer.Layer.prototype.getVisible);
  76958. goog.exportProperty(
  76959. ol.layer.Layer.prototype,
  76960. 'getZIndex',
  76961. ol.layer.Layer.prototype.getZIndex);
  76962. goog.exportProperty(
  76963. ol.layer.Layer.prototype,
  76964. 'setExtent',
  76965. ol.layer.Layer.prototype.setExtent);
  76966. goog.exportProperty(
  76967. ol.layer.Layer.prototype,
  76968. 'setMaxResolution',
  76969. ol.layer.Layer.prototype.setMaxResolution);
  76970. goog.exportProperty(
  76971. ol.layer.Layer.prototype,
  76972. 'setMinResolution',
  76973. ol.layer.Layer.prototype.setMinResolution);
  76974. goog.exportProperty(
  76975. ol.layer.Layer.prototype,
  76976. 'setOpacity',
  76977. ol.layer.Layer.prototype.setOpacity);
  76978. goog.exportProperty(
  76979. ol.layer.Layer.prototype,
  76980. 'setVisible',
  76981. ol.layer.Layer.prototype.setVisible);
  76982. goog.exportProperty(
  76983. ol.layer.Layer.prototype,
  76984. 'setZIndex',
  76985. ol.layer.Layer.prototype.setZIndex);
  76986. goog.exportProperty(
  76987. ol.layer.Layer.prototype,
  76988. 'get',
  76989. ol.layer.Layer.prototype.get);
  76990. goog.exportProperty(
  76991. ol.layer.Layer.prototype,
  76992. 'getKeys',
  76993. ol.layer.Layer.prototype.getKeys);
  76994. goog.exportProperty(
  76995. ol.layer.Layer.prototype,
  76996. 'getProperties',
  76997. ol.layer.Layer.prototype.getProperties);
  76998. goog.exportProperty(
  76999. ol.layer.Layer.prototype,
  77000. 'set',
  77001. ol.layer.Layer.prototype.set);
  77002. goog.exportProperty(
  77003. ol.layer.Layer.prototype,
  77004. 'setProperties',
  77005. ol.layer.Layer.prototype.setProperties);
  77006. goog.exportProperty(
  77007. ol.layer.Layer.prototype,
  77008. 'unset',
  77009. ol.layer.Layer.prototype.unset);
  77010. goog.exportProperty(
  77011. ol.layer.Layer.prototype,
  77012. 'changed',
  77013. ol.layer.Layer.prototype.changed);
  77014. goog.exportProperty(
  77015. ol.layer.Layer.prototype,
  77016. 'dispatchEvent',
  77017. ol.layer.Layer.prototype.dispatchEvent);
  77018. goog.exportProperty(
  77019. ol.layer.Layer.prototype,
  77020. 'getRevision',
  77021. ol.layer.Layer.prototype.getRevision);
  77022. goog.exportProperty(
  77023. ol.layer.Layer.prototype,
  77024. 'on',
  77025. ol.layer.Layer.prototype.on);
  77026. goog.exportProperty(
  77027. ol.layer.Layer.prototype,
  77028. 'once',
  77029. ol.layer.Layer.prototype.once);
  77030. goog.exportProperty(
  77031. ol.layer.Layer.prototype,
  77032. 'un',
  77033. ol.layer.Layer.prototype.un);
  77034. goog.exportProperty(
  77035. ol.layer.Vector.prototype,
  77036. 'setMap',
  77037. ol.layer.Vector.prototype.setMap);
  77038. goog.exportProperty(
  77039. ol.layer.Vector.prototype,
  77040. 'setSource',
  77041. ol.layer.Vector.prototype.setSource);
  77042. goog.exportProperty(
  77043. ol.layer.Vector.prototype,
  77044. 'getExtent',
  77045. ol.layer.Vector.prototype.getExtent);
  77046. goog.exportProperty(
  77047. ol.layer.Vector.prototype,
  77048. 'getMaxResolution',
  77049. ol.layer.Vector.prototype.getMaxResolution);
  77050. goog.exportProperty(
  77051. ol.layer.Vector.prototype,
  77052. 'getMinResolution',
  77053. ol.layer.Vector.prototype.getMinResolution);
  77054. goog.exportProperty(
  77055. ol.layer.Vector.prototype,
  77056. 'getOpacity',
  77057. ol.layer.Vector.prototype.getOpacity);
  77058. goog.exportProperty(
  77059. ol.layer.Vector.prototype,
  77060. 'getVisible',
  77061. ol.layer.Vector.prototype.getVisible);
  77062. goog.exportProperty(
  77063. ol.layer.Vector.prototype,
  77064. 'getZIndex',
  77065. ol.layer.Vector.prototype.getZIndex);
  77066. goog.exportProperty(
  77067. ol.layer.Vector.prototype,
  77068. 'setExtent',
  77069. ol.layer.Vector.prototype.setExtent);
  77070. goog.exportProperty(
  77071. ol.layer.Vector.prototype,
  77072. 'setMaxResolution',
  77073. ol.layer.Vector.prototype.setMaxResolution);
  77074. goog.exportProperty(
  77075. ol.layer.Vector.prototype,
  77076. 'setMinResolution',
  77077. ol.layer.Vector.prototype.setMinResolution);
  77078. goog.exportProperty(
  77079. ol.layer.Vector.prototype,
  77080. 'setOpacity',
  77081. ol.layer.Vector.prototype.setOpacity);
  77082. goog.exportProperty(
  77083. ol.layer.Vector.prototype,
  77084. 'setVisible',
  77085. ol.layer.Vector.prototype.setVisible);
  77086. goog.exportProperty(
  77087. ol.layer.Vector.prototype,
  77088. 'setZIndex',
  77089. ol.layer.Vector.prototype.setZIndex);
  77090. goog.exportProperty(
  77091. ol.layer.Vector.prototype,
  77092. 'get',
  77093. ol.layer.Vector.prototype.get);
  77094. goog.exportProperty(
  77095. ol.layer.Vector.prototype,
  77096. 'getKeys',
  77097. ol.layer.Vector.prototype.getKeys);
  77098. goog.exportProperty(
  77099. ol.layer.Vector.prototype,
  77100. 'getProperties',
  77101. ol.layer.Vector.prototype.getProperties);
  77102. goog.exportProperty(
  77103. ol.layer.Vector.prototype,
  77104. 'set',
  77105. ol.layer.Vector.prototype.set);
  77106. goog.exportProperty(
  77107. ol.layer.Vector.prototype,
  77108. 'setProperties',
  77109. ol.layer.Vector.prototype.setProperties);
  77110. goog.exportProperty(
  77111. ol.layer.Vector.prototype,
  77112. 'unset',
  77113. ol.layer.Vector.prototype.unset);
  77114. goog.exportProperty(
  77115. ol.layer.Vector.prototype,
  77116. 'changed',
  77117. ol.layer.Vector.prototype.changed);
  77118. goog.exportProperty(
  77119. ol.layer.Vector.prototype,
  77120. 'dispatchEvent',
  77121. ol.layer.Vector.prototype.dispatchEvent);
  77122. goog.exportProperty(
  77123. ol.layer.Vector.prototype,
  77124. 'getRevision',
  77125. ol.layer.Vector.prototype.getRevision);
  77126. goog.exportProperty(
  77127. ol.layer.Vector.prototype,
  77128. 'on',
  77129. ol.layer.Vector.prototype.on);
  77130. goog.exportProperty(
  77131. ol.layer.Vector.prototype,
  77132. 'once',
  77133. ol.layer.Vector.prototype.once);
  77134. goog.exportProperty(
  77135. ol.layer.Vector.prototype,
  77136. 'un',
  77137. ol.layer.Vector.prototype.un);
  77138. goog.exportProperty(
  77139. ol.layer.Heatmap.prototype,
  77140. 'getSource',
  77141. ol.layer.Heatmap.prototype.getSource);
  77142. goog.exportProperty(
  77143. ol.layer.Heatmap.prototype,
  77144. 'getStyle',
  77145. ol.layer.Heatmap.prototype.getStyle);
  77146. goog.exportProperty(
  77147. ol.layer.Heatmap.prototype,
  77148. 'getStyleFunction',
  77149. ol.layer.Heatmap.prototype.getStyleFunction);
  77150. goog.exportProperty(
  77151. ol.layer.Heatmap.prototype,
  77152. 'setStyle',
  77153. ol.layer.Heatmap.prototype.setStyle);
  77154. goog.exportProperty(
  77155. ol.layer.Heatmap.prototype,
  77156. 'setMap',
  77157. ol.layer.Heatmap.prototype.setMap);
  77158. goog.exportProperty(
  77159. ol.layer.Heatmap.prototype,
  77160. 'setSource',
  77161. ol.layer.Heatmap.prototype.setSource);
  77162. goog.exportProperty(
  77163. ol.layer.Heatmap.prototype,
  77164. 'getExtent',
  77165. ol.layer.Heatmap.prototype.getExtent);
  77166. goog.exportProperty(
  77167. ol.layer.Heatmap.prototype,
  77168. 'getMaxResolution',
  77169. ol.layer.Heatmap.prototype.getMaxResolution);
  77170. goog.exportProperty(
  77171. ol.layer.Heatmap.prototype,
  77172. 'getMinResolution',
  77173. ol.layer.Heatmap.prototype.getMinResolution);
  77174. goog.exportProperty(
  77175. ol.layer.Heatmap.prototype,
  77176. 'getOpacity',
  77177. ol.layer.Heatmap.prototype.getOpacity);
  77178. goog.exportProperty(
  77179. ol.layer.Heatmap.prototype,
  77180. 'getVisible',
  77181. ol.layer.Heatmap.prototype.getVisible);
  77182. goog.exportProperty(
  77183. ol.layer.Heatmap.prototype,
  77184. 'getZIndex',
  77185. ol.layer.Heatmap.prototype.getZIndex);
  77186. goog.exportProperty(
  77187. ol.layer.Heatmap.prototype,
  77188. 'setExtent',
  77189. ol.layer.Heatmap.prototype.setExtent);
  77190. goog.exportProperty(
  77191. ol.layer.Heatmap.prototype,
  77192. 'setMaxResolution',
  77193. ol.layer.Heatmap.prototype.setMaxResolution);
  77194. goog.exportProperty(
  77195. ol.layer.Heatmap.prototype,
  77196. 'setMinResolution',
  77197. ol.layer.Heatmap.prototype.setMinResolution);
  77198. goog.exportProperty(
  77199. ol.layer.Heatmap.prototype,
  77200. 'setOpacity',
  77201. ol.layer.Heatmap.prototype.setOpacity);
  77202. goog.exportProperty(
  77203. ol.layer.Heatmap.prototype,
  77204. 'setVisible',
  77205. ol.layer.Heatmap.prototype.setVisible);
  77206. goog.exportProperty(
  77207. ol.layer.Heatmap.prototype,
  77208. 'setZIndex',
  77209. ol.layer.Heatmap.prototype.setZIndex);
  77210. goog.exportProperty(
  77211. ol.layer.Heatmap.prototype,
  77212. 'get',
  77213. ol.layer.Heatmap.prototype.get);
  77214. goog.exportProperty(
  77215. ol.layer.Heatmap.prototype,
  77216. 'getKeys',
  77217. ol.layer.Heatmap.prototype.getKeys);
  77218. goog.exportProperty(
  77219. ol.layer.Heatmap.prototype,
  77220. 'getProperties',
  77221. ol.layer.Heatmap.prototype.getProperties);
  77222. goog.exportProperty(
  77223. ol.layer.Heatmap.prototype,
  77224. 'set',
  77225. ol.layer.Heatmap.prototype.set);
  77226. goog.exportProperty(
  77227. ol.layer.Heatmap.prototype,
  77228. 'setProperties',
  77229. ol.layer.Heatmap.prototype.setProperties);
  77230. goog.exportProperty(
  77231. ol.layer.Heatmap.prototype,
  77232. 'unset',
  77233. ol.layer.Heatmap.prototype.unset);
  77234. goog.exportProperty(
  77235. ol.layer.Heatmap.prototype,
  77236. 'changed',
  77237. ol.layer.Heatmap.prototype.changed);
  77238. goog.exportProperty(
  77239. ol.layer.Heatmap.prototype,
  77240. 'dispatchEvent',
  77241. ol.layer.Heatmap.prototype.dispatchEvent);
  77242. goog.exportProperty(
  77243. ol.layer.Heatmap.prototype,
  77244. 'getRevision',
  77245. ol.layer.Heatmap.prototype.getRevision);
  77246. goog.exportProperty(
  77247. ol.layer.Heatmap.prototype,
  77248. 'on',
  77249. ol.layer.Heatmap.prototype.on);
  77250. goog.exportProperty(
  77251. ol.layer.Heatmap.prototype,
  77252. 'once',
  77253. ol.layer.Heatmap.prototype.once);
  77254. goog.exportProperty(
  77255. ol.layer.Heatmap.prototype,
  77256. 'un',
  77257. ol.layer.Heatmap.prototype.un);
  77258. goog.exportProperty(
  77259. ol.layer.Image.prototype,
  77260. 'setMap',
  77261. ol.layer.Image.prototype.setMap);
  77262. goog.exportProperty(
  77263. ol.layer.Image.prototype,
  77264. 'setSource',
  77265. ol.layer.Image.prototype.setSource);
  77266. goog.exportProperty(
  77267. ol.layer.Image.prototype,
  77268. 'getExtent',
  77269. ol.layer.Image.prototype.getExtent);
  77270. goog.exportProperty(
  77271. ol.layer.Image.prototype,
  77272. 'getMaxResolution',
  77273. ol.layer.Image.prototype.getMaxResolution);
  77274. goog.exportProperty(
  77275. ol.layer.Image.prototype,
  77276. 'getMinResolution',
  77277. ol.layer.Image.prototype.getMinResolution);
  77278. goog.exportProperty(
  77279. ol.layer.Image.prototype,
  77280. 'getOpacity',
  77281. ol.layer.Image.prototype.getOpacity);
  77282. goog.exportProperty(
  77283. ol.layer.Image.prototype,
  77284. 'getVisible',
  77285. ol.layer.Image.prototype.getVisible);
  77286. goog.exportProperty(
  77287. ol.layer.Image.prototype,
  77288. 'getZIndex',
  77289. ol.layer.Image.prototype.getZIndex);
  77290. goog.exportProperty(
  77291. ol.layer.Image.prototype,
  77292. 'setExtent',
  77293. ol.layer.Image.prototype.setExtent);
  77294. goog.exportProperty(
  77295. ol.layer.Image.prototype,
  77296. 'setMaxResolution',
  77297. ol.layer.Image.prototype.setMaxResolution);
  77298. goog.exportProperty(
  77299. ol.layer.Image.prototype,
  77300. 'setMinResolution',
  77301. ol.layer.Image.prototype.setMinResolution);
  77302. goog.exportProperty(
  77303. ol.layer.Image.prototype,
  77304. 'setOpacity',
  77305. ol.layer.Image.prototype.setOpacity);
  77306. goog.exportProperty(
  77307. ol.layer.Image.prototype,
  77308. 'setVisible',
  77309. ol.layer.Image.prototype.setVisible);
  77310. goog.exportProperty(
  77311. ol.layer.Image.prototype,
  77312. 'setZIndex',
  77313. ol.layer.Image.prototype.setZIndex);
  77314. goog.exportProperty(
  77315. ol.layer.Image.prototype,
  77316. 'get',
  77317. ol.layer.Image.prototype.get);
  77318. goog.exportProperty(
  77319. ol.layer.Image.prototype,
  77320. 'getKeys',
  77321. ol.layer.Image.prototype.getKeys);
  77322. goog.exportProperty(
  77323. ol.layer.Image.prototype,
  77324. 'getProperties',
  77325. ol.layer.Image.prototype.getProperties);
  77326. goog.exportProperty(
  77327. ol.layer.Image.prototype,
  77328. 'set',
  77329. ol.layer.Image.prototype.set);
  77330. goog.exportProperty(
  77331. ol.layer.Image.prototype,
  77332. 'setProperties',
  77333. ol.layer.Image.prototype.setProperties);
  77334. goog.exportProperty(
  77335. ol.layer.Image.prototype,
  77336. 'unset',
  77337. ol.layer.Image.prototype.unset);
  77338. goog.exportProperty(
  77339. ol.layer.Image.prototype,
  77340. 'changed',
  77341. ol.layer.Image.prototype.changed);
  77342. goog.exportProperty(
  77343. ol.layer.Image.prototype,
  77344. 'dispatchEvent',
  77345. ol.layer.Image.prototype.dispatchEvent);
  77346. goog.exportProperty(
  77347. ol.layer.Image.prototype,
  77348. 'getRevision',
  77349. ol.layer.Image.prototype.getRevision);
  77350. goog.exportProperty(
  77351. ol.layer.Image.prototype,
  77352. 'on',
  77353. ol.layer.Image.prototype.on);
  77354. goog.exportProperty(
  77355. ol.layer.Image.prototype,
  77356. 'once',
  77357. ol.layer.Image.prototype.once);
  77358. goog.exportProperty(
  77359. ol.layer.Image.prototype,
  77360. 'un',
  77361. ol.layer.Image.prototype.un);
  77362. goog.exportProperty(
  77363. ol.layer.Tile.prototype,
  77364. 'setMap',
  77365. ol.layer.Tile.prototype.setMap);
  77366. goog.exportProperty(
  77367. ol.layer.Tile.prototype,
  77368. 'setSource',
  77369. ol.layer.Tile.prototype.setSource);
  77370. goog.exportProperty(
  77371. ol.layer.Tile.prototype,
  77372. 'getExtent',
  77373. ol.layer.Tile.prototype.getExtent);
  77374. goog.exportProperty(
  77375. ol.layer.Tile.prototype,
  77376. 'getMaxResolution',
  77377. ol.layer.Tile.prototype.getMaxResolution);
  77378. goog.exportProperty(
  77379. ol.layer.Tile.prototype,
  77380. 'getMinResolution',
  77381. ol.layer.Tile.prototype.getMinResolution);
  77382. goog.exportProperty(
  77383. ol.layer.Tile.prototype,
  77384. 'getOpacity',
  77385. ol.layer.Tile.prototype.getOpacity);
  77386. goog.exportProperty(
  77387. ol.layer.Tile.prototype,
  77388. 'getVisible',
  77389. ol.layer.Tile.prototype.getVisible);
  77390. goog.exportProperty(
  77391. ol.layer.Tile.prototype,
  77392. 'getZIndex',
  77393. ol.layer.Tile.prototype.getZIndex);
  77394. goog.exportProperty(
  77395. ol.layer.Tile.prototype,
  77396. 'setExtent',
  77397. ol.layer.Tile.prototype.setExtent);
  77398. goog.exportProperty(
  77399. ol.layer.Tile.prototype,
  77400. 'setMaxResolution',
  77401. ol.layer.Tile.prototype.setMaxResolution);
  77402. goog.exportProperty(
  77403. ol.layer.Tile.prototype,
  77404. 'setMinResolution',
  77405. ol.layer.Tile.prototype.setMinResolution);
  77406. goog.exportProperty(
  77407. ol.layer.Tile.prototype,
  77408. 'setOpacity',
  77409. ol.layer.Tile.prototype.setOpacity);
  77410. goog.exportProperty(
  77411. ol.layer.Tile.prototype,
  77412. 'setVisible',
  77413. ol.layer.Tile.prototype.setVisible);
  77414. goog.exportProperty(
  77415. ol.layer.Tile.prototype,
  77416. 'setZIndex',
  77417. ol.layer.Tile.prototype.setZIndex);
  77418. goog.exportProperty(
  77419. ol.layer.Tile.prototype,
  77420. 'get',
  77421. ol.layer.Tile.prototype.get);
  77422. goog.exportProperty(
  77423. ol.layer.Tile.prototype,
  77424. 'getKeys',
  77425. ol.layer.Tile.prototype.getKeys);
  77426. goog.exportProperty(
  77427. ol.layer.Tile.prototype,
  77428. 'getProperties',
  77429. ol.layer.Tile.prototype.getProperties);
  77430. goog.exportProperty(
  77431. ol.layer.Tile.prototype,
  77432. 'set',
  77433. ol.layer.Tile.prototype.set);
  77434. goog.exportProperty(
  77435. ol.layer.Tile.prototype,
  77436. 'setProperties',
  77437. ol.layer.Tile.prototype.setProperties);
  77438. goog.exportProperty(
  77439. ol.layer.Tile.prototype,
  77440. 'unset',
  77441. ol.layer.Tile.prototype.unset);
  77442. goog.exportProperty(
  77443. ol.layer.Tile.prototype,
  77444. 'changed',
  77445. ol.layer.Tile.prototype.changed);
  77446. goog.exportProperty(
  77447. ol.layer.Tile.prototype,
  77448. 'dispatchEvent',
  77449. ol.layer.Tile.prototype.dispatchEvent);
  77450. goog.exportProperty(
  77451. ol.layer.Tile.prototype,
  77452. 'getRevision',
  77453. ol.layer.Tile.prototype.getRevision);
  77454. goog.exportProperty(
  77455. ol.layer.Tile.prototype,
  77456. 'on',
  77457. ol.layer.Tile.prototype.on);
  77458. goog.exportProperty(
  77459. ol.layer.Tile.prototype,
  77460. 'once',
  77461. ol.layer.Tile.prototype.once);
  77462. goog.exportProperty(
  77463. ol.layer.Tile.prototype,
  77464. 'un',
  77465. ol.layer.Tile.prototype.un);
  77466. goog.exportProperty(
  77467. ol.layer.VectorTile.prototype,
  77468. 'getStyle',
  77469. ol.layer.VectorTile.prototype.getStyle);
  77470. goog.exportProperty(
  77471. ol.layer.VectorTile.prototype,
  77472. 'getStyleFunction',
  77473. ol.layer.VectorTile.prototype.getStyleFunction);
  77474. goog.exportProperty(
  77475. ol.layer.VectorTile.prototype,
  77476. 'setStyle',
  77477. ol.layer.VectorTile.prototype.setStyle);
  77478. goog.exportProperty(
  77479. ol.layer.VectorTile.prototype,
  77480. 'setMap',
  77481. ol.layer.VectorTile.prototype.setMap);
  77482. goog.exportProperty(
  77483. ol.layer.VectorTile.prototype,
  77484. 'setSource',
  77485. ol.layer.VectorTile.prototype.setSource);
  77486. goog.exportProperty(
  77487. ol.layer.VectorTile.prototype,
  77488. 'getExtent',
  77489. ol.layer.VectorTile.prototype.getExtent);
  77490. goog.exportProperty(
  77491. ol.layer.VectorTile.prototype,
  77492. 'getMaxResolution',
  77493. ol.layer.VectorTile.prototype.getMaxResolution);
  77494. goog.exportProperty(
  77495. ol.layer.VectorTile.prototype,
  77496. 'getMinResolution',
  77497. ol.layer.VectorTile.prototype.getMinResolution);
  77498. goog.exportProperty(
  77499. ol.layer.VectorTile.prototype,
  77500. 'getOpacity',
  77501. ol.layer.VectorTile.prototype.getOpacity);
  77502. goog.exportProperty(
  77503. ol.layer.VectorTile.prototype,
  77504. 'getVisible',
  77505. ol.layer.VectorTile.prototype.getVisible);
  77506. goog.exportProperty(
  77507. ol.layer.VectorTile.prototype,
  77508. 'getZIndex',
  77509. ol.layer.VectorTile.prototype.getZIndex);
  77510. goog.exportProperty(
  77511. ol.layer.VectorTile.prototype,
  77512. 'setExtent',
  77513. ol.layer.VectorTile.prototype.setExtent);
  77514. goog.exportProperty(
  77515. ol.layer.VectorTile.prototype,
  77516. 'setMaxResolution',
  77517. ol.layer.VectorTile.prototype.setMaxResolution);
  77518. goog.exportProperty(
  77519. ol.layer.VectorTile.prototype,
  77520. 'setMinResolution',
  77521. ol.layer.VectorTile.prototype.setMinResolution);
  77522. goog.exportProperty(
  77523. ol.layer.VectorTile.prototype,
  77524. 'setOpacity',
  77525. ol.layer.VectorTile.prototype.setOpacity);
  77526. goog.exportProperty(
  77527. ol.layer.VectorTile.prototype,
  77528. 'setVisible',
  77529. ol.layer.VectorTile.prototype.setVisible);
  77530. goog.exportProperty(
  77531. ol.layer.VectorTile.prototype,
  77532. 'setZIndex',
  77533. ol.layer.VectorTile.prototype.setZIndex);
  77534. goog.exportProperty(
  77535. ol.layer.VectorTile.prototype,
  77536. 'get',
  77537. ol.layer.VectorTile.prototype.get);
  77538. goog.exportProperty(
  77539. ol.layer.VectorTile.prototype,
  77540. 'getKeys',
  77541. ol.layer.VectorTile.prototype.getKeys);
  77542. goog.exportProperty(
  77543. ol.layer.VectorTile.prototype,
  77544. 'getProperties',
  77545. ol.layer.VectorTile.prototype.getProperties);
  77546. goog.exportProperty(
  77547. ol.layer.VectorTile.prototype,
  77548. 'set',
  77549. ol.layer.VectorTile.prototype.set);
  77550. goog.exportProperty(
  77551. ol.layer.VectorTile.prototype,
  77552. 'setProperties',
  77553. ol.layer.VectorTile.prototype.setProperties);
  77554. goog.exportProperty(
  77555. ol.layer.VectorTile.prototype,
  77556. 'unset',
  77557. ol.layer.VectorTile.prototype.unset);
  77558. goog.exportProperty(
  77559. ol.layer.VectorTile.prototype,
  77560. 'changed',
  77561. ol.layer.VectorTile.prototype.changed);
  77562. goog.exportProperty(
  77563. ol.layer.VectorTile.prototype,
  77564. 'dispatchEvent',
  77565. ol.layer.VectorTile.prototype.dispatchEvent);
  77566. goog.exportProperty(
  77567. ol.layer.VectorTile.prototype,
  77568. 'getRevision',
  77569. ol.layer.VectorTile.prototype.getRevision);
  77570. goog.exportProperty(
  77571. ol.layer.VectorTile.prototype,
  77572. 'on',
  77573. ol.layer.VectorTile.prototype.on);
  77574. goog.exportProperty(
  77575. ol.layer.VectorTile.prototype,
  77576. 'once',
  77577. ol.layer.VectorTile.prototype.once);
  77578. goog.exportProperty(
  77579. ol.layer.VectorTile.prototype,
  77580. 'un',
  77581. ol.layer.VectorTile.prototype.un);
  77582. goog.exportProperty(
  77583. ol.interaction.Interaction.prototype,
  77584. 'get',
  77585. ol.interaction.Interaction.prototype.get);
  77586. goog.exportProperty(
  77587. ol.interaction.Interaction.prototype,
  77588. 'getKeys',
  77589. ol.interaction.Interaction.prototype.getKeys);
  77590. goog.exportProperty(
  77591. ol.interaction.Interaction.prototype,
  77592. 'getProperties',
  77593. ol.interaction.Interaction.prototype.getProperties);
  77594. goog.exportProperty(
  77595. ol.interaction.Interaction.prototype,
  77596. 'set',
  77597. ol.interaction.Interaction.prototype.set);
  77598. goog.exportProperty(
  77599. ol.interaction.Interaction.prototype,
  77600. 'setProperties',
  77601. ol.interaction.Interaction.prototype.setProperties);
  77602. goog.exportProperty(
  77603. ol.interaction.Interaction.prototype,
  77604. 'unset',
  77605. ol.interaction.Interaction.prototype.unset);
  77606. goog.exportProperty(
  77607. ol.interaction.Interaction.prototype,
  77608. 'changed',
  77609. ol.interaction.Interaction.prototype.changed);
  77610. goog.exportProperty(
  77611. ol.interaction.Interaction.prototype,
  77612. 'dispatchEvent',
  77613. ol.interaction.Interaction.prototype.dispatchEvent);
  77614. goog.exportProperty(
  77615. ol.interaction.Interaction.prototype,
  77616. 'getRevision',
  77617. ol.interaction.Interaction.prototype.getRevision);
  77618. goog.exportProperty(
  77619. ol.interaction.Interaction.prototype,
  77620. 'on',
  77621. ol.interaction.Interaction.prototype.on);
  77622. goog.exportProperty(
  77623. ol.interaction.Interaction.prototype,
  77624. 'once',
  77625. ol.interaction.Interaction.prototype.once);
  77626. goog.exportProperty(
  77627. ol.interaction.Interaction.prototype,
  77628. 'un',
  77629. ol.interaction.Interaction.prototype.un);
  77630. goog.exportProperty(
  77631. ol.interaction.DoubleClickZoom.prototype,
  77632. 'getActive',
  77633. ol.interaction.DoubleClickZoom.prototype.getActive);
  77634. goog.exportProperty(
  77635. ol.interaction.DoubleClickZoom.prototype,
  77636. 'getMap',
  77637. ol.interaction.DoubleClickZoom.prototype.getMap);
  77638. goog.exportProperty(
  77639. ol.interaction.DoubleClickZoom.prototype,
  77640. 'setActive',
  77641. ol.interaction.DoubleClickZoom.prototype.setActive);
  77642. goog.exportProperty(
  77643. ol.interaction.DoubleClickZoom.prototype,
  77644. 'get',
  77645. ol.interaction.DoubleClickZoom.prototype.get);
  77646. goog.exportProperty(
  77647. ol.interaction.DoubleClickZoom.prototype,
  77648. 'getKeys',
  77649. ol.interaction.DoubleClickZoom.prototype.getKeys);
  77650. goog.exportProperty(
  77651. ol.interaction.DoubleClickZoom.prototype,
  77652. 'getProperties',
  77653. ol.interaction.DoubleClickZoom.prototype.getProperties);
  77654. goog.exportProperty(
  77655. ol.interaction.DoubleClickZoom.prototype,
  77656. 'set',
  77657. ol.interaction.DoubleClickZoom.prototype.set);
  77658. goog.exportProperty(
  77659. ol.interaction.DoubleClickZoom.prototype,
  77660. 'setProperties',
  77661. ol.interaction.DoubleClickZoom.prototype.setProperties);
  77662. goog.exportProperty(
  77663. ol.interaction.DoubleClickZoom.prototype,
  77664. 'unset',
  77665. ol.interaction.DoubleClickZoom.prototype.unset);
  77666. goog.exportProperty(
  77667. ol.interaction.DoubleClickZoom.prototype,
  77668. 'changed',
  77669. ol.interaction.DoubleClickZoom.prototype.changed);
  77670. goog.exportProperty(
  77671. ol.interaction.DoubleClickZoom.prototype,
  77672. 'dispatchEvent',
  77673. ol.interaction.DoubleClickZoom.prototype.dispatchEvent);
  77674. goog.exportProperty(
  77675. ol.interaction.DoubleClickZoom.prototype,
  77676. 'getRevision',
  77677. ol.interaction.DoubleClickZoom.prototype.getRevision);
  77678. goog.exportProperty(
  77679. ol.interaction.DoubleClickZoom.prototype,
  77680. 'on',
  77681. ol.interaction.DoubleClickZoom.prototype.on);
  77682. goog.exportProperty(
  77683. ol.interaction.DoubleClickZoom.prototype,
  77684. 'once',
  77685. ol.interaction.DoubleClickZoom.prototype.once);
  77686. goog.exportProperty(
  77687. ol.interaction.DoubleClickZoom.prototype,
  77688. 'un',
  77689. ol.interaction.DoubleClickZoom.prototype.un);
  77690. goog.exportProperty(
  77691. ol.interaction.DragAndDrop.prototype,
  77692. 'getActive',
  77693. ol.interaction.DragAndDrop.prototype.getActive);
  77694. goog.exportProperty(
  77695. ol.interaction.DragAndDrop.prototype,
  77696. 'getMap',
  77697. ol.interaction.DragAndDrop.prototype.getMap);
  77698. goog.exportProperty(
  77699. ol.interaction.DragAndDrop.prototype,
  77700. 'setActive',
  77701. ol.interaction.DragAndDrop.prototype.setActive);
  77702. goog.exportProperty(
  77703. ol.interaction.DragAndDrop.prototype,
  77704. 'get',
  77705. ol.interaction.DragAndDrop.prototype.get);
  77706. goog.exportProperty(
  77707. ol.interaction.DragAndDrop.prototype,
  77708. 'getKeys',
  77709. ol.interaction.DragAndDrop.prototype.getKeys);
  77710. goog.exportProperty(
  77711. ol.interaction.DragAndDrop.prototype,
  77712. 'getProperties',
  77713. ol.interaction.DragAndDrop.prototype.getProperties);
  77714. goog.exportProperty(
  77715. ol.interaction.DragAndDrop.prototype,
  77716. 'set',
  77717. ol.interaction.DragAndDrop.prototype.set);
  77718. goog.exportProperty(
  77719. ol.interaction.DragAndDrop.prototype,
  77720. 'setProperties',
  77721. ol.interaction.DragAndDrop.prototype.setProperties);
  77722. goog.exportProperty(
  77723. ol.interaction.DragAndDrop.prototype,
  77724. 'unset',
  77725. ol.interaction.DragAndDrop.prototype.unset);
  77726. goog.exportProperty(
  77727. ol.interaction.DragAndDrop.prototype,
  77728. 'changed',
  77729. ol.interaction.DragAndDrop.prototype.changed);
  77730. goog.exportProperty(
  77731. ol.interaction.DragAndDrop.prototype,
  77732. 'dispatchEvent',
  77733. ol.interaction.DragAndDrop.prototype.dispatchEvent);
  77734. goog.exportProperty(
  77735. ol.interaction.DragAndDrop.prototype,
  77736. 'getRevision',
  77737. ol.interaction.DragAndDrop.prototype.getRevision);
  77738. goog.exportProperty(
  77739. ol.interaction.DragAndDrop.prototype,
  77740. 'on',
  77741. ol.interaction.DragAndDrop.prototype.on);
  77742. goog.exportProperty(
  77743. ol.interaction.DragAndDrop.prototype,
  77744. 'once',
  77745. ol.interaction.DragAndDrop.prototype.once);
  77746. goog.exportProperty(
  77747. ol.interaction.DragAndDrop.prototype,
  77748. 'un',
  77749. ol.interaction.DragAndDrop.prototype.un);
  77750. goog.exportProperty(
  77751. ol.interaction.DragAndDrop.Event.prototype,
  77752. 'type',
  77753. ol.interaction.DragAndDrop.Event.prototype.type);
  77754. goog.exportProperty(
  77755. ol.interaction.DragAndDrop.Event.prototype,
  77756. 'target',
  77757. ol.interaction.DragAndDrop.Event.prototype.target);
  77758. goog.exportProperty(
  77759. ol.interaction.DragAndDrop.Event.prototype,
  77760. 'preventDefault',
  77761. ol.interaction.DragAndDrop.Event.prototype.preventDefault);
  77762. goog.exportProperty(
  77763. ol.interaction.DragAndDrop.Event.prototype,
  77764. 'stopPropagation',
  77765. ol.interaction.DragAndDrop.Event.prototype.stopPropagation);
  77766. goog.exportProperty(
  77767. ol.interaction.Pointer.prototype,
  77768. 'getActive',
  77769. ol.interaction.Pointer.prototype.getActive);
  77770. goog.exportProperty(
  77771. ol.interaction.Pointer.prototype,
  77772. 'getMap',
  77773. ol.interaction.Pointer.prototype.getMap);
  77774. goog.exportProperty(
  77775. ol.interaction.Pointer.prototype,
  77776. 'setActive',
  77777. ol.interaction.Pointer.prototype.setActive);
  77778. goog.exportProperty(
  77779. ol.interaction.Pointer.prototype,
  77780. 'get',
  77781. ol.interaction.Pointer.prototype.get);
  77782. goog.exportProperty(
  77783. ol.interaction.Pointer.prototype,
  77784. 'getKeys',
  77785. ol.interaction.Pointer.prototype.getKeys);
  77786. goog.exportProperty(
  77787. ol.interaction.Pointer.prototype,
  77788. 'getProperties',
  77789. ol.interaction.Pointer.prototype.getProperties);
  77790. goog.exportProperty(
  77791. ol.interaction.Pointer.prototype,
  77792. 'set',
  77793. ol.interaction.Pointer.prototype.set);
  77794. goog.exportProperty(
  77795. ol.interaction.Pointer.prototype,
  77796. 'setProperties',
  77797. ol.interaction.Pointer.prototype.setProperties);
  77798. goog.exportProperty(
  77799. ol.interaction.Pointer.prototype,
  77800. 'unset',
  77801. ol.interaction.Pointer.prototype.unset);
  77802. goog.exportProperty(
  77803. ol.interaction.Pointer.prototype,
  77804. 'changed',
  77805. ol.interaction.Pointer.prototype.changed);
  77806. goog.exportProperty(
  77807. ol.interaction.Pointer.prototype,
  77808. 'dispatchEvent',
  77809. ol.interaction.Pointer.prototype.dispatchEvent);
  77810. goog.exportProperty(
  77811. ol.interaction.Pointer.prototype,
  77812. 'getRevision',
  77813. ol.interaction.Pointer.prototype.getRevision);
  77814. goog.exportProperty(
  77815. ol.interaction.Pointer.prototype,
  77816. 'on',
  77817. ol.interaction.Pointer.prototype.on);
  77818. goog.exportProperty(
  77819. ol.interaction.Pointer.prototype,
  77820. 'once',
  77821. ol.interaction.Pointer.prototype.once);
  77822. goog.exportProperty(
  77823. ol.interaction.Pointer.prototype,
  77824. 'un',
  77825. ol.interaction.Pointer.prototype.un);
  77826. goog.exportProperty(
  77827. ol.interaction.DragBox.prototype,
  77828. 'getActive',
  77829. ol.interaction.DragBox.prototype.getActive);
  77830. goog.exportProperty(
  77831. ol.interaction.DragBox.prototype,
  77832. 'getMap',
  77833. ol.interaction.DragBox.prototype.getMap);
  77834. goog.exportProperty(
  77835. ol.interaction.DragBox.prototype,
  77836. 'setActive',
  77837. ol.interaction.DragBox.prototype.setActive);
  77838. goog.exportProperty(
  77839. ol.interaction.DragBox.prototype,
  77840. 'get',
  77841. ol.interaction.DragBox.prototype.get);
  77842. goog.exportProperty(
  77843. ol.interaction.DragBox.prototype,
  77844. 'getKeys',
  77845. ol.interaction.DragBox.prototype.getKeys);
  77846. goog.exportProperty(
  77847. ol.interaction.DragBox.prototype,
  77848. 'getProperties',
  77849. ol.interaction.DragBox.prototype.getProperties);
  77850. goog.exportProperty(
  77851. ol.interaction.DragBox.prototype,
  77852. 'set',
  77853. ol.interaction.DragBox.prototype.set);
  77854. goog.exportProperty(
  77855. ol.interaction.DragBox.prototype,
  77856. 'setProperties',
  77857. ol.interaction.DragBox.prototype.setProperties);
  77858. goog.exportProperty(
  77859. ol.interaction.DragBox.prototype,
  77860. 'unset',
  77861. ol.interaction.DragBox.prototype.unset);
  77862. goog.exportProperty(
  77863. ol.interaction.DragBox.prototype,
  77864. 'changed',
  77865. ol.interaction.DragBox.prototype.changed);
  77866. goog.exportProperty(
  77867. ol.interaction.DragBox.prototype,
  77868. 'dispatchEvent',
  77869. ol.interaction.DragBox.prototype.dispatchEvent);
  77870. goog.exportProperty(
  77871. ol.interaction.DragBox.prototype,
  77872. 'getRevision',
  77873. ol.interaction.DragBox.prototype.getRevision);
  77874. goog.exportProperty(
  77875. ol.interaction.DragBox.prototype,
  77876. 'on',
  77877. ol.interaction.DragBox.prototype.on);
  77878. goog.exportProperty(
  77879. ol.interaction.DragBox.prototype,
  77880. 'once',
  77881. ol.interaction.DragBox.prototype.once);
  77882. goog.exportProperty(
  77883. ol.interaction.DragBox.prototype,
  77884. 'un',
  77885. ol.interaction.DragBox.prototype.un);
  77886. goog.exportProperty(
  77887. ol.interaction.DragBox.Event.prototype,
  77888. 'type',
  77889. ol.interaction.DragBox.Event.prototype.type);
  77890. goog.exportProperty(
  77891. ol.interaction.DragBox.Event.prototype,
  77892. 'target',
  77893. ol.interaction.DragBox.Event.prototype.target);
  77894. goog.exportProperty(
  77895. ol.interaction.DragBox.Event.prototype,
  77896. 'preventDefault',
  77897. ol.interaction.DragBox.Event.prototype.preventDefault);
  77898. goog.exportProperty(
  77899. ol.interaction.DragBox.Event.prototype,
  77900. 'stopPropagation',
  77901. ol.interaction.DragBox.Event.prototype.stopPropagation);
  77902. goog.exportProperty(
  77903. ol.interaction.DragPan.prototype,
  77904. 'getActive',
  77905. ol.interaction.DragPan.prototype.getActive);
  77906. goog.exportProperty(
  77907. ol.interaction.DragPan.prototype,
  77908. 'getMap',
  77909. ol.interaction.DragPan.prototype.getMap);
  77910. goog.exportProperty(
  77911. ol.interaction.DragPan.prototype,
  77912. 'setActive',
  77913. ol.interaction.DragPan.prototype.setActive);
  77914. goog.exportProperty(
  77915. ol.interaction.DragPan.prototype,
  77916. 'get',
  77917. ol.interaction.DragPan.prototype.get);
  77918. goog.exportProperty(
  77919. ol.interaction.DragPan.prototype,
  77920. 'getKeys',
  77921. ol.interaction.DragPan.prototype.getKeys);
  77922. goog.exportProperty(
  77923. ol.interaction.DragPan.prototype,
  77924. 'getProperties',
  77925. ol.interaction.DragPan.prototype.getProperties);
  77926. goog.exportProperty(
  77927. ol.interaction.DragPan.prototype,
  77928. 'set',
  77929. ol.interaction.DragPan.prototype.set);
  77930. goog.exportProperty(
  77931. ol.interaction.DragPan.prototype,
  77932. 'setProperties',
  77933. ol.interaction.DragPan.prototype.setProperties);
  77934. goog.exportProperty(
  77935. ol.interaction.DragPan.prototype,
  77936. 'unset',
  77937. ol.interaction.DragPan.prototype.unset);
  77938. goog.exportProperty(
  77939. ol.interaction.DragPan.prototype,
  77940. 'changed',
  77941. ol.interaction.DragPan.prototype.changed);
  77942. goog.exportProperty(
  77943. ol.interaction.DragPan.prototype,
  77944. 'dispatchEvent',
  77945. ol.interaction.DragPan.prototype.dispatchEvent);
  77946. goog.exportProperty(
  77947. ol.interaction.DragPan.prototype,
  77948. 'getRevision',
  77949. ol.interaction.DragPan.prototype.getRevision);
  77950. goog.exportProperty(
  77951. ol.interaction.DragPan.prototype,
  77952. 'on',
  77953. ol.interaction.DragPan.prototype.on);
  77954. goog.exportProperty(
  77955. ol.interaction.DragPan.prototype,
  77956. 'once',
  77957. ol.interaction.DragPan.prototype.once);
  77958. goog.exportProperty(
  77959. ol.interaction.DragPan.prototype,
  77960. 'un',
  77961. ol.interaction.DragPan.prototype.un);
  77962. goog.exportProperty(
  77963. ol.interaction.DragRotate.prototype,
  77964. 'getActive',
  77965. ol.interaction.DragRotate.prototype.getActive);
  77966. goog.exportProperty(
  77967. ol.interaction.DragRotate.prototype,
  77968. 'getMap',
  77969. ol.interaction.DragRotate.prototype.getMap);
  77970. goog.exportProperty(
  77971. ol.interaction.DragRotate.prototype,
  77972. 'setActive',
  77973. ol.interaction.DragRotate.prototype.setActive);
  77974. goog.exportProperty(
  77975. ol.interaction.DragRotate.prototype,
  77976. 'get',
  77977. ol.interaction.DragRotate.prototype.get);
  77978. goog.exportProperty(
  77979. ol.interaction.DragRotate.prototype,
  77980. 'getKeys',
  77981. ol.interaction.DragRotate.prototype.getKeys);
  77982. goog.exportProperty(
  77983. ol.interaction.DragRotate.prototype,
  77984. 'getProperties',
  77985. ol.interaction.DragRotate.prototype.getProperties);
  77986. goog.exportProperty(
  77987. ol.interaction.DragRotate.prototype,
  77988. 'set',
  77989. ol.interaction.DragRotate.prototype.set);
  77990. goog.exportProperty(
  77991. ol.interaction.DragRotate.prototype,
  77992. 'setProperties',
  77993. ol.interaction.DragRotate.prototype.setProperties);
  77994. goog.exportProperty(
  77995. ol.interaction.DragRotate.prototype,
  77996. 'unset',
  77997. ol.interaction.DragRotate.prototype.unset);
  77998. goog.exportProperty(
  77999. ol.interaction.DragRotate.prototype,
  78000. 'changed',
  78001. ol.interaction.DragRotate.prototype.changed);
  78002. goog.exportProperty(
  78003. ol.interaction.DragRotate.prototype,
  78004. 'dispatchEvent',
  78005. ol.interaction.DragRotate.prototype.dispatchEvent);
  78006. goog.exportProperty(
  78007. ol.interaction.DragRotate.prototype,
  78008. 'getRevision',
  78009. ol.interaction.DragRotate.prototype.getRevision);
  78010. goog.exportProperty(
  78011. ol.interaction.DragRotate.prototype,
  78012. 'on',
  78013. ol.interaction.DragRotate.prototype.on);
  78014. goog.exportProperty(
  78015. ol.interaction.DragRotate.prototype,
  78016. 'once',
  78017. ol.interaction.DragRotate.prototype.once);
  78018. goog.exportProperty(
  78019. ol.interaction.DragRotate.prototype,
  78020. 'un',
  78021. ol.interaction.DragRotate.prototype.un);
  78022. goog.exportProperty(
  78023. ol.interaction.DragRotateAndZoom.prototype,
  78024. 'getActive',
  78025. ol.interaction.DragRotateAndZoom.prototype.getActive);
  78026. goog.exportProperty(
  78027. ol.interaction.DragRotateAndZoom.prototype,
  78028. 'getMap',
  78029. ol.interaction.DragRotateAndZoom.prototype.getMap);
  78030. goog.exportProperty(
  78031. ol.interaction.DragRotateAndZoom.prototype,
  78032. 'setActive',
  78033. ol.interaction.DragRotateAndZoom.prototype.setActive);
  78034. goog.exportProperty(
  78035. ol.interaction.DragRotateAndZoom.prototype,
  78036. 'get',
  78037. ol.interaction.DragRotateAndZoom.prototype.get);
  78038. goog.exportProperty(
  78039. ol.interaction.DragRotateAndZoom.prototype,
  78040. 'getKeys',
  78041. ol.interaction.DragRotateAndZoom.prototype.getKeys);
  78042. goog.exportProperty(
  78043. ol.interaction.DragRotateAndZoom.prototype,
  78044. 'getProperties',
  78045. ol.interaction.DragRotateAndZoom.prototype.getProperties);
  78046. goog.exportProperty(
  78047. ol.interaction.DragRotateAndZoom.prototype,
  78048. 'set',
  78049. ol.interaction.DragRotateAndZoom.prototype.set);
  78050. goog.exportProperty(
  78051. ol.interaction.DragRotateAndZoom.prototype,
  78052. 'setProperties',
  78053. ol.interaction.DragRotateAndZoom.prototype.setProperties);
  78054. goog.exportProperty(
  78055. ol.interaction.DragRotateAndZoom.prototype,
  78056. 'unset',
  78057. ol.interaction.DragRotateAndZoom.prototype.unset);
  78058. goog.exportProperty(
  78059. ol.interaction.DragRotateAndZoom.prototype,
  78060. 'changed',
  78061. ol.interaction.DragRotateAndZoom.prototype.changed);
  78062. goog.exportProperty(
  78063. ol.interaction.DragRotateAndZoom.prototype,
  78064. 'dispatchEvent',
  78065. ol.interaction.DragRotateAndZoom.prototype.dispatchEvent);
  78066. goog.exportProperty(
  78067. ol.interaction.DragRotateAndZoom.prototype,
  78068. 'getRevision',
  78069. ol.interaction.DragRotateAndZoom.prototype.getRevision);
  78070. goog.exportProperty(
  78071. ol.interaction.DragRotateAndZoom.prototype,
  78072. 'on',
  78073. ol.interaction.DragRotateAndZoom.prototype.on);
  78074. goog.exportProperty(
  78075. ol.interaction.DragRotateAndZoom.prototype,
  78076. 'once',
  78077. ol.interaction.DragRotateAndZoom.prototype.once);
  78078. goog.exportProperty(
  78079. ol.interaction.DragRotateAndZoom.prototype,
  78080. 'un',
  78081. ol.interaction.DragRotateAndZoom.prototype.un);
  78082. goog.exportProperty(
  78083. ol.interaction.DragZoom.prototype,
  78084. 'getGeometry',
  78085. ol.interaction.DragZoom.prototype.getGeometry);
  78086. goog.exportProperty(
  78087. ol.interaction.DragZoom.prototype,
  78088. 'getActive',
  78089. ol.interaction.DragZoom.prototype.getActive);
  78090. goog.exportProperty(
  78091. ol.interaction.DragZoom.prototype,
  78092. 'getMap',
  78093. ol.interaction.DragZoom.prototype.getMap);
  78094. goog.exportProperty(
  78095. ol.interaction.DragZoom.prototype,
  78096. 'setActive',
  78097. ol.interaction.DragZoom.prototype.setActive);
  78098. goog.exportProperty(
  78099. ol.interaction.DragZoom.prototype,
  78100. 'get',
  78101. ol.interaction.DragZoom.prototype.get);
  78102. goog.exportProperty(
  78103. ol.interaction.DragZoom.prototype,
  78104. 'getKeys',
  78105. ol.interaction.DragZoom.prototype.getKeys);
  78106. goog.exportProperty(
  78107. ol.interaction.DragZoom.prototype,
  78108. 'getProperties',
  78109. ol.interaction.DragZoom.prototype.getProperties);
  78110. goog.exportProperty(
  78111. ol.interaction.DragZoom.prototype,
  78112. 'set',
  78113. ol.interaction.DragZoom.prototype.set);
  78114. goog.exportProperty(
  78115. ol.interaction.DragZoom.prototype,
  78116. 'setProperties',
  78117. ol.interaction.DragZoom.prototype.setProperties);
  78118. goog.exportProperty(
  78119. ol.interaction.DragZoom.prototype,
  78120. 'unset',
  78121. ol.interaction.DragZoom.prototype.unset);
  78122. goog.exportProperty(
  78123. ol.interaction.DragZoom.prototype,
  78124. 'changed',
  78125. ol.interaction.DragZoom.prototype.changed);
  78126. goog.exportProperty(
  78127. ol.interaction.DragZoom.prototype,
  78128. 'dispatchEvent',
  78129. ol.interaction.DragZoom.prototype.dispatchEvent);
  78130. goog.exportProperty(
  78131. ol.interaction.DragZoom.prototype,
  78132. 'getRevision',
  78133. ol.interaction.DragZoom.prototype.getRevision);
  78134. goog.exportProperty(
  78135. ol.interaction.DragZoom.prototype,
  78136. 'on',
  78137. ol.interaction.DragZoom.prototype.on);
  78138. goog.exportProperty(
  78139. ol.interaction.DragZoom.prototype,
  78140. 'once',
  78141. ol.interaction.DragZoom.prototype.once);
  78142. goog.exportProperty(
  78143. ol.interaction.DragZoom.prototype,
  78144. 'un',
  78145. ol.interaction.DragZoom.prototype.un);
  78146. goog.exportProperty(
  78147. ol.interaction.Draw.prototype,
  78148. 'getActive',
  78149. ol.interaction.Draw.prototype.getActive);
  78150. goog.exportProperty(
  78151. ol.interaction.Draw.prototype,
  78152. 'getMap',
  78153. ol.interaction.Draw.prototype.getMap);
  78154. goog.exportProperty(
  78155. ol.interaction.Draw.prototype,
  78156. 'setActive',
  78157. ol.interaction.Draw.prototype.setActive);
  78158. goog.exportProperty(
  78159. ol.interaction.Draw.prototype,
  78160. 'get',
  78161. ol.interaction.Draw.prototype.get);
  78162. goog.exportProperty(
  78163. ol.interaction.Draw.prototype,
  78164. 'getKeys',
  78165. ol.interaction.Draw.prototype.getKeys);
  78166. goog.exportProperty(
  78167. ol.interaction.Draw.prototype,
  78168. 'getProperties',
  78169. ol.interaction.Draw.prototype.getProperties);
  78170. goog.exportProperty(
  78171. ol.interaction.Draw.prototype,
  78172. 'set',
  78173. ol.interaction.Draw.prototype.set);
  78174. goog.exportProperty(
  78175. ol.interaction.Draw.prototype,
  78176. 'setProperties',
  78177. ol.interaction.Draw.prototype.setProperties);
  78178. goog.exportProperty(
  78179. ol.interaction.Draw.prototype,
  78180. 'unset',
  78181. ol.interaction.Draw.prototype.unset);
  78182. goog.exportProperty(
  78183. ol.interaction.Draw.prototype,
  78184. 'changed',
  78185. ol.interaction.Draw.prototype.changed);
  78186. goog.exportProperty(
  78187. ol.interaction.Draw.prototype,
  78188. 'dispatchEvent',
  78189. ol.interaction.Draw.prototype.dispatchEvent);
  78190. goog.exportProperty(
  78191. ol.interaction.Draw.prototype,
  78192. 'getRevision',
  78193. ol.interaction.Draw.prototype.getRevision);
  78194. goog.exportProperty(
  78195. ol.interaction.Draw.prototype,
  78196. 'on',
  78197. ol.interaction.Draw.prototype.on);
  78198. goog.exportProperty(
  78199. ol.interaction.Draw.prototype,
  78200. 'once',
  78201. ol.interaction.Draw.prototype.once);
  78202. goog.exportProperty(
  78203. ol.interaction.Draw.prototype,
  78204. 'un',
  78205. ol.interaction.Draw.prototype.un);
  78206. goog.exportProperty(
  78207. ol.interaction.Draw.Event.prototype,
  78208. 'type',
  78209. ol.interaction.Draw.Event.prototype.type);
  78210. goog.exportProperty(
  78211. ol.interaction.Draw.Event.prototype,
  78212. 'target',
  78213. ol.interaction.Draw.Event.prototype.target);
  78214. goog.exportProperty(
  78215. ol.interaction.Draw.Event.prototype,
  78216. 'preventDefault',
  78217. ol.interaction.Draw.Event.prototype.preventDefault);
  78218. goog.exportProperty(
  78219. ol.interaction.Draw.Event.prototype,
  78220. 'stopPropagation',
  78221. ol.interaction.Draw.Event.prototype.stopPropagation);
  78222. goog.exportProperty(
  78223. ol.interaction.Extent.prototype,
  78224. 'getActive',
  78225. ol.interaction.Extent.prototype.getActive);
  78226. goog.exportProperty(
  78227. ol.interaction.Extent.prototype,
  78228. 'getMap',
  78229. ol.interaction.Extent.prototype.getMap);
  78230. goog.exportProperty(
  78231. ol.interaction.Extent.prototype,
  78232. 'setActive',
  78233. ol.interaction.Extent.prototype.setActive);
  78234. goog.exportProperty(
  78235. ol.interaction.Extent.prototype,
  78236. 'get',
  78237. ol.interaction.Extent.prototype.get);
  78238. goog.exportProperty(
  78239. ol.interaction.Extent.prototype,
  78240. 'getKeys',
  78241. ol.interaction.Extent.prototype.getKeys);
  78242. goog.exportProperty(
  78243. ol.interaction.Extent.prototype,
  78244. 'getProperties',
  78245. ol.interaction.Extent.prototype.getProperties);
  78246. goog.exportProperty(
  78247. ol.interaction.Extent.prototype,
  78248. 'set',
  78249. ol.interaction.Extent.prototype.set);
  78250. goog.exportProperty(
  78251. ol.interaction.Extent.prototype,
  78252. 'setProperties',
  78253. ol.interaction.Extent.prototype.setProperties);
  78254. goog.exportProperty(
  78255. ol.interaction.Extent.prototype,
  78256. 'unset',
  78257. ol.interaction.Extent.prototype.unset);
  78258. goog.exportProperty(
  78259. ol.interaction.Extent.prototype,
  78260. 'changed',
  78261. ol.interaction.Extent.prototype.changed);
  78262. goog.exportProperty(
  78263. ol.interaction.Extent.prototype,
  78264. 'dispatchEvent',
  78265. ol.interaction.Extent.prototype.dispatchEvent);
  78266. goog.exportProperty(
  78267. ol.interaction.Extent.prototype,
  78268. 'getRevision',
  78269. ol.interaction.Extent.prototype.getRevision);
  78270. goog.exportProperty(
  78271. ol.interaction.Extent.prototype,
  78272. 'on',
  78273. ol.interaction.Extent.prototype.on);
  78274. goog.exportProperty(
  78275. ol.interaction.Extent.prototype,
  78276. 'once',
  78277. ol.interaction.Extent.prototype.once);
  78278. goog.exportProperty(
  78279. ol.interaction.Extent.prototype,
  78280. 'un',
  78281. ol.interaction.Extent.prototype.un);
  78282. goog.exportProperty(
  78283. ol.interaction.Extent.Event.prototype,
  78284. 'type',
  78285. ol.interaction.Extent.Event.prototype.type);
  78286. goog.exportProperty(
  78287. ol.interaction.Extent.Event.prototype,
  78288. 'target',
  78289. ol.interaction.Extent.Event.prototype.target);
  78290. goog.exportProperty(
  78291. ol.interaction.Extent.Event.prototype,
  78292. 'preventDefault',
  78293. ol.interaction.Extent.Event.prototype.preventDefault);
  78294. goog.exportProperty(
  78295. ol.interaction.Extent.Event.prototype,
  78296. 'stopPropagation',
  78297. ol.interaction.Extent.Event.prototype.stopPropagation);
  78298. goog.exportProperty(
  78299. ol.interaction.KeyboardPan.prototype,
  78300. 'getActive',
  78301. ol.interaction.KeyboardPan.prototype.getActive);
  78302. goog.exportProperty(
  78303. ol.interaction.KeyboardPan.prototype,
  78304. 'getMap',
  78305. ol.interaction.KeyboardPan.prototype.getMap);
  78306. goog.exportProperty(
  78307. ol.interaction.KeyboardPan.prototype,
  78308. 'setActive',
  78309. ol.interaction.KeyboardPan.prototype.setActive);
  78310. goog.exportProperty(
  78311. ol.interaction.KeyboardPan.prototype,
  78312. 'get',
  78313. ol.interaction.KeyboardPan.prototype.get);
  78314. goog.exportProperty(
  78315. ol.interaction.KeyboardPan.prototype,
  78316. 'getKeys',
  78317. ol.interaction.KeyboardPan.prototype.getKeys);
  78318. goog.exportProperty(
  78319. ol.interaction.KeyboardPan.prototype,
  78320. 'getProperties',
  78321. ol.interaction.KeyboardPan.prototype.getProperties);
  78322. goog.exportProperty(
  78323. ol.interaction.KeyboardPan.prototype,
  78324. 'set',
  78325. ol.interaction.KeyboardPan.prototype.set);
  78326. goog.exportProperty(
  78327. ol.interaction.KeyboardPan.prototype,
  78328. 'setProperties',
  78329. ol.interaction.KeyboardPan.prototype.setProperties);
  78330. goog.exportProperty(
  78331. ol.interaction.KeyboardPan.prototype,
  78332. 'unset',
  78333. ol.interaction.KeyboardPan.prototype.unset);
  78334. goog.exportProperty(
  78335. ol.interaction.KeyboardPan.prototype,
  78336. 'changed',
  78337. ol.interaction.KeyboardPan.prototype.changed);
  78338. goog.exportProperty(
  78339. ol.interaction.KeyboardPan.prototype,
  78340. 'dispatchEvent',
  78341. ol.interaction.KeyboardPan.prototype.dispatchEvent);
  78342. goog.exportProperty(
  78343. ol.interaction.KeyboardPan.prototype,
  78344. 'getRevision',
  78345. ol.interaction.KeyboardPan.prototype.getRevision);
  78346. goog.exportProperty(
  78347. ol.interaction.KeyboardPan.prototype,
  78348. 'on',
  78349. ol.interaction.KeyboardPan.prototype.on);
  78350. goog.exportProperty(
  78351. ol.interaction.KeyboardPan.prototype,
  78352. 'once',
  78353. ol.interaction.KeyboardPan.prototype.once);
  78354. goog.exportProperty(
  78355. ol.interaction.KeyboardPan.prototype,
  78356. 'un',
  78357. ol.interaction.KeyboardPan.prototype.un);
  78358. goog.exportProperty(
  78359. ol.interaction.KeyboardZoom.prototype,
  78360. 'getActive',
  78361. ol.interaction.KeyboardZoom.prototype.getActive);
  78362. goog.exportProperty(
  78363. ol.interaction.KeyboardZoom.prototype,
  78364. 'getMap',
  78365. ol.interaction.KeyboardZoom.prototype.getMap);
  78366. goog.exportProperty(
  78367. ol.interaction.KeyboardZoom.prototype,
  78368. 'setActive',
  78369. ol.interaction.KeyboardZoom.prototype.setActive);
  78370. goog.exportProperty(
  78371. ol.interaction.KeyboardZoom.prototype,
  78372. 'get',
  78373. ol.interaction.KeyboardZoom.prototype.get);
  78374. goog.exportProperty(
  78375. ol.interaction.KeyboardZoom.prototype,
  78376. 'getKeys',
  78377. ol.interaction.KeyboardZoom.prototype.getKeys);
  78378. goog.exportProperty(
  78379. ol.interaction.KeyboardZoom.prototype,
  78380. 'getProperties',
  78381. ol.interaction.KeyboardZoom.prototype.getProperties);
  78382. goog.exportProperty(
  78383. ol.interaction.KeyboardZoom.prototype,
  78384. 'set',
  78385. ol.interaction.KeyboardZoom.prototype.set);
  78386. goog.exportProperty(
  78387. ol.interaction.KeyboardZoom.prototype,
  78388. 'setProperties',
  78389. ol.interaction.KeyboardZoom.prototype.setProperties);
  78390. goog.exportProperty(
  78391. ol.interaction.KeyboardZoom.prototype,
  78392. 'unset',
  78393. ol.interaction.KeyboardZoom.prototype.unset);
  78394. goog.exportProperty(
  78395. ol.interaction.KeyboardZoom.prototype,
  78396. 'changed',
  78397. ol.interaction.KeyboardZoom.prototype.changed);
  78398. goog.exportProperty(
  78399. ol.interaction.KeyboardZoom.prototype,
  78400. 'dispatchEvent',
  78401. ol.interaction.KeyboardZoom.prototype.dispatchEvent);
  78402. goog.exportProperty(
  78403. ol.interaction.KeyboardZoom.prototype,
  78404. 'getRevision',
  78405. ol.interaction.KeyboardZoom.prototype.getRevision);
  78406. goog.exportProperty(
  78407. ol.interaction.KeyboardZoom.prototype,
  78408. 'on',
  78409. ol.interaction.KeyboardZoom.prototype.on);
  78410. goog.exportProperty(
  78411. ol.interaction.KeyboardZoom.prototype,
  78412. 'once',
  78413. ol.interaction.KeyboardZoom.prototype.once);
  78414. goog.exportProperty(
  78415. ol.interaction.KeyboardZoom.prototype,
  78416. 'un',
  78417. ol.interaction.KeyboardZoom.prototype.un);
  78418. goog.exportProperty(
  78419. ol.interaction.Modify.prototype,
  78420. 'getActive',
  78421. ol.interaction.Modify.prototype.getActive);
  78422. goog.exportProperty(
  78423. ol.interaction.Modify.prototype,
  78424. 'getMap',
  78425. ol.interaction.Modify.prototype.getMap);
  78426. goog.exportProperty(
  78427. ol.interaction.Modify.prototype,
  78428. 'setActive',
  78429. ol.interaction.Modify.prototype.setActive);
  78430. goog.exportProperty(
  78431. ol.interaction.Modify.prototype,
  78432. 'get',
  78433. ol.interaction.Modify.prototype.get);
  78434. goog.exportProperty(
  78435. ol.interaction.Modify.prototype,
  78436. 'getKeys',
  78437. ol.interaction.Modify.prototype.getKeys);
  78438. goog.exportProperty(
  78439. ol.interaction.Modify.prototype,
  78440. 'getProperties',
  78441. ol.interaction.Modify.prototype.getProperties);
  78442. goog.exportProperty(
  78443. ol.interaction.Modify.prototype,
  78444. 'set',
  78445. ol.interaction.Modify.prototype.set);
  78446. goog.exportProperty(
  78447. ol.interaction.Modify.prototype,
  78448. 'setProperties',
  78449. ol.interaction.Modify.prototype.setProperties);
  78450. goog.exportProperty(
  78451. ol.interaction.Modify.prototype,
  78452. 'unset',
  78453. ol.interaction.Modify.prototype.unset);
  78454. goog.exportProperty(
  78455. ol.interaction.Modify.prototype,
  78456. 'changed',
  78457. ol.interaction.Modify.prototype.changed);
  78458. goog.exportProperty(
  78459. ol.interaction.Modify.prototype,
  78460. 'dispatchEvent',
  78461. ol.interaction.Modify.prototype.dispatchEvent);
  78462. goog.exportProperty(
  78463. ol.interaction.Modify.prototype,
  78464. 'getRevision',
  78465. ol.interaction.Modify.prototype.getRevision);
  78466. goog.exportProperty(
  78467. ol.interaction.Modify.prototype,
  78468. 'on',
  78469. ol.interaction.Modify.prototype.on);
  78470. goog.exportProperty(
  78471. ol.interaction.Modify.prototype,
  78472. 'once',
  78473. ol.interaction.Modify.prototype.once);
  78474. goog.exportProperty(
  78475. ol.interaction.Modify.prototype,
  78476. 'un',
  78477. ol.interaction.Modify.prototype.un);
  78478. goog.exportProperty(
  78479. ol.interaction.Modify.Event.prototype,
  78480. 'type',
  78481. ol.interaction.Modify.Event.prototype.type);
  78482. goog.exportProperty(
  78483. ol.interaction.Modify.Event.prototype,
  78484. 'target',
  78485. ol.interaction.Modify.Event.prototype.target);
  78486. goog.exportProperty(
  78487. ol.interaction.Modify.Event.prototype,
  78488. 'preventDefault',
  78489. ol.interaction.Modify.Event.prototype.preventDefault);
  78490. goog.exportProperty(
  78491. ol.interaction.Modify.Event.prototype,
  78492. 'stopPropagation',
  78493. ol.interaction.Modify.Event.prototype.stopPropagation);
  78494. goog.exportProperty(
  78495. ol.interaction.MouseWheelZoom.prototype,
  78496. 'getActive',
  78497. ol.interaction.MouseWheelZoom.prototype.getActive);
  78498. goog.exportProperty(
  78499. ol.interaction.MouseWheelZoom.prototype,
  78500. 'getMap',
  78501. ol.interaction.MouseWheelZoom.prototype.getMap);
  78502. goog.exportProperty(
  78503. ol.interaction.MouseWheelZoom.prototype,
  78504. 'setActive',
  78505. ol.interaction.MouseWheelZoom.prototype.setActive);
  78506. goog.exportProperty(
  78507. ol.interaction.MouseWheelZoom.prototype,
  78508. 'get',
  78509. ol.interaction.MouseWheelZoom.prototype.get);
  78510. goog.exportProperty(
  78511. ol.interaction.MouseWheelZoom.prototype,
  78512. 'getKeys',
  78513. ol.interaction.MouseWheelZoom.prototype.getKeys);
  78514. goog.exportProperty(
  78515. ol.interaction.MouseWheelZoom.prototype,
  78516. 'getProperties',
  78517. ol.interaction.MouseWheelZoom.prototype.getProperties);
  78518. goog.exportProperty(
  78519. ol.interaction.MouseWheelZoom.prototype,
  78520. 'set',
  78521. ol.interaction.MouseWheelZoom.prototype.set);
  78522. goog.exportProperty(
  78523. ol.interaction.MouseWheelZoom.prototype,
  78524. 'setProperties',
  78525. ol.interaction.MouseWheelZoom.prototype.setProperties);
  78526. goog.exportProperty(
  78527. ol.interaction.MouseWheelZoom.prototype,
  78528. 'unset',
  78529. ol.interaction.MouseWheelZoom.prototype.unset);
  78530. goog.exportProperty(
  78531. ol.interaction.MouseWheelZoom.prototype,
  78532. 'changed',
  78533. ol.interaction.MouseWheelZoom.prototype.changed);
  78534. goog.exportProperty(
  78535. ol.interaction.MouseWheelZoom.prototype,
  78536. 'dispatchEvent',
  78537. ol.interaction.MouseWheelZoom.prototype.dispatchEvent);
  78538. goog.exportProperty(
  78539. ol.interaction.MouseWheelZoom.prototype,
  78540. 'getRevision',
  78541. ol.interaction.MouseWheelZoom.prototype.getRevision);
  78542. goog.exportProperty(
  78543. ol.interaction.MouseWheelZoom.prototype,
  78544. 'on',
  78545. ol.interaction.MouseWheelZoom.prototype.on);
  78546. goog.exportProperty(
  78547. ol.interaction.MouseWheelZoom.prototype,
  78548. 'once',
  78549. ol.interaction.MouseWheelZoom.prototype.once);
  78550. goog.exportProperty(
  78551. ol.interaction.MouseWheelZoom.prototype,
  78552. 'un',
  78553. ol.interaction.MouseWheelZoom.prototype.un);
  78554. goog.exportProperty(
  78555. ol.interaction.PinchRotate.prototype,
  78556. 'getActive',
  78557. ol.interaction.PinchRotate.prototype.getActive);
  78558. goog.exportProperty(
  78559. ol.interaction.PinchRotate.prototype,
  78560. 'getMap',
  78561. ol.interaction.PinchRotate.prototype.getMap);
  78562. goog.exportProperty(
  78563. ol.interaction.PinchRotate.prototype,
  78564. 'setActive',
  78565. ol.interaction.PinchRotate.prototype.setActive);
  78566. goog.exportProperty(
  78567. ol.interaction.PinchRotate.prototype,
  78568. 'get',
  78569. ol.interaction.PinchRotate.prototype.get);
  78570. goog.exportProperty(
  78571. ol.interaction.PinchRotate.prototype,
  78572. 'getKeys',
  78573. ol.interaction.PinchRotate.prototype.getKeys);
  78574. goog.exportProperty(
  78575. ol.interaction.PinchRotate.prototype,
  78576. 'getProperties',
  78577. ol.interaction.PinchRotate.prototype.getProperties);
  78578. goog.exportProperty(
  78579. ol.interaction.PinchRotate.prototype,
  78580. 'set',
  78581. ol.interaction.PinchRotate.prototype.set);
  78582. goog.exportProperty(
  78583. ol.interaction.PinchRotate.prototype,
  78584. 'setProperties',
  78585. ol.interaction.PinchRotate.prototype.setProperties);
  78586. goog.exportProperty(
  78587. ol.interaction.PinchRotate.prototype,
  78588. 'unset',
  78589. ol.interaction.PinchRotate.prototype.unset);
  78590. goog.exportProperty(
  78591. ol.interaction.PinchRotate.prototype,
  78592. 'changed',
  78593. ol.interaction.PinchRotate.prototype.changed);
  78594. goog.exportProperty(
  78595. ol.interaction.PinchRotate.prototype,
  78596. 'dispatchEvent',
  78597. ol.interaction.PinchRotate.prototype.dispatchEvent);
  78598. goog.exportProperty(
  78599. ol.interaction.PinchRotate.prototype,
  78600. 'getRevision',
  78601. ol.interaction.PinchRotate.prototype.getRevision);
  78602. goog.exportProperty(
  78603. ol.interaction.PinchRotate.prototype,
  78604. 'on',
  78605. ol.interaction.PinchRotate.prototype.on);
  78606. goog.exportProperty(
  78607. ol.interaction.PinchRotate.prototype,
  78608. 'once',
  78609. ol.interaction.PinchRotate.prototype.once);
  78610. goog.exportProperty(
  78611. ol.interaction.PinchRotate.prototype,
  78612. 'un',
  78613. ol.interaction.PinchRotate.prototype.un);
  78614. goog.exportProperty(
  78615. ol.interaction.PinchZoom.prototype,
  78616. 'getActive',
  78617. ol.interaction.PinchZoom.prototype.getActive);
  78618. goog.exportProperty(
  78619. ol.interaction.PinchZoom.prototype,
  78620. 'getMap',
  78621. ol.interaction.PinchZoom.prototype.getMap);
  78622. goog.exportProperty(
  78623. ol.interaction.PinchZoom.prototype,
  78624. 'setActive',
  78625. ol.interaction.PinchZoom.prototype.setActive);
  78626. goog.exportProperty(
  78627. ol.interaction.PinchZoom.prototype,
  78628. 'get',
  78629. ol.interaction.PinchZoom.prototype.get);
  78630. goog.exportProperty(
  78631. ol.interaction.PinchZoom.prototype,
  78632. 'getKeys',
  78633. ol.interaction.PinchZoom.prototype.getKeys);
  78634. goog.exportProperty(
  78635. ol.interaction.PinchZoom.prototype,
  78636. 'getProperties',
  78637. ol.interaction.PinchZoom.prototype.getProperties);
  78638. goog.exportProperty(
  78639. ol.interaction.PinchZoom.prototype,
  78640. 'set',
  78641. ol.interaction.PinchZoom.prototype.set);
  78642. goog.exportProperty(
  78643. ol.interaction.PinchZoom.prototype,
  78644. 'setProperties',
  78645. ol.interaction.PinchZoom.prototype.setProperties);
  78646. goog.exportProperty(
  78647. ol.interaction.PinchZoom.prototype,
  78648. 'unset',
  78649. ol.interaction.PinchZoom.prototype.unset);
  78650. goog.exportProperty(
  78651. ol.interaction.PinchZoom.prototype,
  78652. 'changed',
  78653. ol.interaction.PinchZoom.prototype.changed);
  78654. goog.exportProperty(
  78655. ol.interaction.PinchZoom.prototype,
  78656. 'dispatchEvent',
  78657. ol.interaction.PinchZoom.prototype.dispatchEvent);
  78658. goog.exportProperty(
  78659. ol.interaction.PinchZoom.prototype,
  78660. 'getRevision',
  78661. ol.interaction.PinchZoom.prototype.getRevision);
  78662. goog.exportProperty(
  78663. ol.interaction.PinchZoom.prototype,
  78664. 'on',
  78665. ol.interaction.PinchZoom.prototype.on);
  78666. goog.exportProperty(
  78667. ol.interaction.PinchZoom.prototype,
  78668. 'once',
  78669. ol.interaction.PinchZoom.prototype.once);
  78670. goog.exportProperty(
  78671. ol.interaction.PinchZoom.prototype,
  78672. 'un',
  78673. ol.interaction.PinchZoom.prototype.un);
  78674. goog.exportProperty(
  78675. ol.interaction.Select.prototype,
  78676. 'getActive',
  78677. ol.interaction.Select.prototype.getActive);
  78678. goog.exportProperty(
  78679. ol.interaction.Select.prototype,
  78680. 'getMap',
  78681. ol.interaction.Select.prototype.getMap);
  78682. goog.exportProperty(
  78683. ol.interaction.Select.prototype,
  78684. 'setActive',
  78685. ol.interaction.Select.prototype.setActive);
  78686. goog.exportProperty(
  78687. ol.interaction.Select.prototype,
  78688. 'get',
  78689. ol.interaction.Select.prototype.get);
  78690. goog.exportProperty(
  78691. ol.interaction.Select.prototype,
  78692. 'getKeys',
  78693. ol.interaction.Select.prototype.getKeys);
  78694. goog.exportProperty(
  78695. ol.interaction.Select.prototype,
  78696. 'getProperties',
  78697. ol.interaction.Select.prototype.getProperties);
  78698. goog.exportProperty(
  78699. ol.interaction.Select.prototype,
  78700. 'set',
  78701. ol.interaction.Select.prototype.set);
  78702. goog.exportProperty(
  78703. ol.interaction.Select.prototype,
  78704. 'setProperties',
  78705. ol.interaction.Select.prototype.setProperties);
  78706. goog.exportProperty(
  78707. ol.interaction.Select.prototype,
  78708. 'unset',
  78709. ol.interaction.Select.prototype.unset);
  78710. goog.exportProperty(
  78711. ol.interaction.Select.prototype,
  78712. 'changed',
  78713. ol.interaction.Select.prototype.changed);
  78714. goog.exportProperty(
  78715. ol.interaction.Select.prototype,
  78716. 'dispatchEvent',
  78717. ol.interaction.Select.prototype.dispatchEvent);
  78718. goog.exportProperty(
  78719. ol.interaction.Select.prototype,
  78720. 'getRevision',
  78721. ol.interaction.Select.prototype.getRevision);
  78722. goog.exportProperty(
  78723. ol.interaction.Select.prototype,
  78724. 'on',
  78725. ol.interaction.Select.prototype.on);
  78726. goog.exportProperty(
  78727. ol.interaction.Select.prototype,
  78728. 'once',
  78729. ol.interaction.Select.prototype.once);
  78730. goog.exportProperty(
  78731. ol.interaction.Select.prototype,
  78732. 'un',
  78733. ol.interaction.Select.prototype.un);
  78734. goog.exportProperty(
  78735. ol.interaction.Select.Event.prototype,
  78736. 'type',
  78737. ol.interaction.Select.Event.prototype.type);
  78738. goog.exportProperty(
  78739. ol.interaction.Select.Event.prototype,
  78740. 'target',
  78741. ol.interaction.Select.Event.prototype.target);
  78742. goog.exportProperty(
  78743. ol.interaction.Select.Event.prototype,
  78744. 'preventDefault',
  78745. ol.interaction.Select.Event.prototype.preventDefault);
  78746. goog.exportProperty(
  78747. ol.interaction.Select.Event.prototype,
  78748. 'stopPropagation',
  78749. ol.interaction.Select.Event.prototype.stopPropagation);
  78750. goog.exportProperty(
  78751. ol.interaction.Snap.prototype,
  78752. 'getActive',
  78753. ol.interaction.Snap.prototype.getActive);
  78754. goog.exportProperty(
  78755. ol.interaction.Snap.prototype,
  78756. 'getMap',
  78757. ol.interaction.Snap.prototype.getMap);
  78758. goog.exportProperty(
  78759. ol.interaction.Snap.prototype,
  78760. 'setActive',
  78761. ol.interaction.Snap.prototype.setActive);
  78762. goog.exportProperty(
  78763. ol.interaction.Snap.prototype,
  78764. 'get',
  78765. ol.interaction.Snap.prototype.get);
  78766. goog.exportProperty(
  78767. ol.interaction.Snap.prototype,
  78768. 'getKeys',
  78769. ol.interaction.Snap.prototype.getKeys);
  78770. goog.exportProperty(
  78771. ol.interaction.Snap.prototype,
  78772. 'getProperties',
  78773. ol.interaction.Snap.prototype.getProperties);
  78774. goog.exportProperty(
  78775. ol.interaction.Snap.prototype,
  78776. 'set',
  78777. ol.interaction.Snap.prototype.set);
  78778. goog.exportProperty(
  78779. ol.interaction.Snap.prototype,
  78780. 'setProperties',
  78781. ol.interaction.Snap.prototype.setProperties);
  78782. goog.exportProperty(
  78783. ol.interaction.Snap.prototype,
  78784. 'unset',
  78785. ol.interaction.Snap.prototype.unset);
  78786. goog.exportProperty(
  78787. ol.interaction.Snap.prototype,
  78788. 'changed',
  78789. ol.interaction.Snap.prototype.changed);
  78790. goog.exportProperty(
  78791. ol.interaction.Snap.prototype,
  78792. 'dispatchEvent',
  78793. ol.interaction.Snap.prototype.dispatchEvent);
  78794. goog.exportProperty(
  78795. ol.interaction.Snap.prototype,
  78796. 'getRevision',
  78797. ol.interaction.Snap.prototype.getRevision);
  78798. goog.exportProperty(
  78799. ol.interaction.Snap.prototype,
  78800. 'on',
  78801. ol.interaction.Snap.prototype.on);
  78802. goog.exportProperty(
  78803. ol.interaction.Snap.prototype,
  78804. 'once',
  78805. ol.interaction.Snap.prototype.once);
  78806. goog.exportProperty(
  78807. ol.interaction.Snap.prototype,
  78808. 'un',
  78809. ol.interaction.Snap.prototype.un);
  78810. goog.exportProperty(
  78811. ol.interaction.Translate.prototype,
  78812. 'getActive',
  78813. ol.interaction.Translate.prototype.getActive);
  78814. goog.exportProperty(
  78815. ol.interaction.Translate.prototype,
  78816. 'getMap',
  78817. ol.interaction.Translate.prototype.getMap);
  78818. goog.exportProperty(
  78819. ol.interaction.Translate.prototype,
  78820. 'setActive',
  78821. ol.interaction.Translate.prototype.setActive);
  78822. goog.exportProperty(
  78823. ol.interaction.Translate.prototype,
  78824. 'get',
  78825. ol.interaction.Translate.prototype.get);
  78826. goog.exportProperty(
  78827. ol.interaction.Translate.prototype,
  78828. 'getKeys',
  78829. ol.interaction.Translate.prototype.getKeys);
  78830. goog.exportProperty(
  78831. ol.interaction.Translate.prototype,
  78832. 'getProperties',
  78833. ol.interaction.Translate.prototype.getProperties);
  78834. goog.exportProperty(
  78835. ol.interaction.Translate.prototype,
  78836. 'set',
  78837. ol.interaction.Translate.prototype.set);
  78838. goog.exportProperty(
  78839. ol.interaction.Translate.prototype,
  78840. 'setProperties',
  78841. ol.interaction.Translate.prototype.setProperties);
  78842. goog.exportProperty(
  78843. ol.interaction.Translate.prototype,
  78844. 'unset',
  78845. ol.interaction.Translate.prototype.unset);
  78846. goog.exportProperty(
  78847. ol.interaction.Translate.prototype,
  78848. 'changed',
  78849. ol.interaction.Translate.prototype.changed);
  78850. goog.exportProperty(
  78851. ol.interaction.Translate.prototype,
  78852. 'dispatchEvent',
  78853. ol.interaction.Translate.prototype.dispatchEvent);
  78854. goog.exportProperty(
  78855. ol.interaction.Translate.prototype,
  78856. 'getRevision',
  78857. ol.interaction.Translate.prototype.getRevision);
  78858. goog.exportProperty(
  78859. ol.interaction.Translate.prototype,
  78860. 'on',
  78861. ol.interaction.Translate.prototype.on);
  78862. goog.exportProperty(
  78863. ol.interaction.Translate.prototype,
  78864. 'once',
  78865. ol.interaction.Translate.prototype.once);
  78866. goog.exportProperty(
  78867. ol.interaction.Translate.prototype,
  78868. 'un',
  78869. ol.interaction.Translate.prototype.un);
  78870. goog.exportProperty(
  78871. ol.interaction.Translate.Event.prototype,
  78872. 'type',
  78873. ol.interaction.Translate.Event.prototype.type);
  78874. goog.exportProperty(
  78875. ol.interaction.Translate.Event.prototype,
  78876. 'target',
  78877. ol.interaction.Translate.Event.prototype.target);
  78878. goog.exportProperty(
  78879. ol.interaction.Translate.Event.prototype,
  78880. 'preventDefault',
  78881. ol.interaction.Translate.Event.prototype.preventDefault);
  78882. goog.exportProperty(
  78883. ol.interaction.Translate.Event.prototype,
  78884. 'stopPropagation',
  78885. ol.interaction.Translate.Event.prototype.stopPropagation);
  78886. goog.exportProperty(
  78887. ol.geom.Geometry.prototype,
  78888. 'get',
  78889. ol.geom.Geometry.prototype.get);
  78890. goog.exportProperty(
  78891. ol.geom.Geometry.prototype,
  78892. 'getKeys',
  78893. ol.geom.Geometry.prototype.getKeys);
  78894. goog.exportProperty(
  78895. ol.geom.Geometry.prototype,
  78896. 'getProperties',
  78897. ol.geom.Geometry.prototype.getProperties);
  78898. goog.exportProperty(
  78899. ol.geom.Geometry.prototype,
  78900. 'set',
  78901. ol.geom.Geometry.prototype.set);
  78902. goog.exportProperty(
  78903. ol.geom.Geometry.prototype,
  78904. 'setProperties',
  78905. ol.geom.Geometry.prototype.setProperties);
  78906. goog.exportProperty(
  78907. ol.geom.Geometry.prototype,
  78908. 'unset',
  78909. ol.geom.Geometry.prototype.unset);
  78910. goog.exportProperty(
  78911. ol.geom.Geometry.prototype,
  78912. 'changed',
  78913. ol.geom.Geometry.prototype.changed);
  78914. goog.exportProperty(
  78915. ol.geom.Geometry.prototype,
  78916. 'dispatchEvent',
  78917. ol.geom.Geometry.prototype.dispatchEvent);
  78918. goog.exportProperty(
  78919. ol.geom.Geometry.prototype,
  78920. 'getRevision',
  78921. ol.geom.Geometry.prototype.getRevision);
  78922. goog.exportProperty(
  78923. ol.geom.Geometry.prototype,
  78924. 'on',
  78925. ol.geom.Geometry.prototype.on);
  78926. goog.exportProperty(
  78927. ol.geom.Geometry.prototype,
  78928. 'once',
  78929. ol.geom.Geometry.prototype.once);
  78930. goog.exportProperty(
  78931. ol.geom.Geometry.prototype,
  78932. 'un',
  78933. ol.geom.Geometry.prototype.un);
  78934. goog.exportProperty(
  78935. ol.geom.SimpleGeometry.prototype,
  78936. 'getClosestPoint',
  78937. ol.geom.SimpleGeometry.prototype.getClosestPoint);
  78938. goog.exportProperty(
  78939. ol.geom.SimpleGeometry.prototype,
  78940. 'intersectsCoordinate',
  78941. ol.geom.SimpleGeometry.prototype.intersectsCoordinate);
  78942. goog.exportProperty(
  78943. ol.geom.SimpleGeometry.prototype,
  78944. 'getExtent',
  78945. ol.geom.SimpleGeometry.prototype.getExtent);
  78946. goog.exportProperty(
  78947. ol.geom.SimpleGeometry.prototype,
  78948. 'rotate',
  78949. ol.geom.SimpleGeometry.prototype.rotate);
  78950. goog.exportProperty(
  78951. ol.geom.SimpleGeometry.prototype,
  78952. 'scale',
  78953. ol.geom.SimpleGeometry.prototype.scale);
  78954. goog.exportProperty(
  78955. ol.geom.SimpleGeometry.prototype,
  78956. 'simplify',
  78957. ol.geom.SimpleGeometry.prototype.simplify);
  78958. goog.exportProperty(
  78959. ol.geom.SimpleGeometry.prototype,
  78960. 'transform',
  78961. ol.geom.SimpleGeometry.prototype.transform);
  78962. goog.exportProperty(
  78963. ol.geom.SimpleGeometry.prototype,
  78964. 'get',
  78965. ol.geom.SimpleGeometry.prototype.get);
  78966. goog.exportProperty(
  78967. ol.geom.SimpleGeometry.prototype,
  78968. 'getKeys',
  78969. ol.geom.SimpleGeometry.prototype.getKeys);
  78970. goog.exportProperty(
  78971. ol.geom.SimpleGeometry.prototype,
  78972. 'getProperties',
  78973. ol.geom.SimpleGeometry.prototype.getProperties);
  78974. goog.exportProperty(
  78975. ol.geom.SimpleGeometry.prototype,
  78976. 'set',
  78977. ol.geom.SimpleGeometry.prototype.set);
  78978. goog.exportProperty(
  78979. ol.geom.SimpleGeometry.prototype,
  78980. 'setProperties',
  78981. ol.geom.SimpleGeometry.prototype.setProperties);
  78982. goog.exportProperty(
  78983. ol.geom.SimpleGeometry.prototype,
  78984. 'unset',
  78985. ol.geom.SimpleGeometry.prototype.unset);
  78986. goog.exportProperty(
  78987. ol.geom.SimpleGeometry.prototype,
  78988. 'changed',
  78989. ol.geom.SimpleGeometry.prototype.changed);
  78990. goog.exportProperty(
  78991. ol.geom.SimpleGeometry.prototype,
  78992. 'dispatchEvent',
  78993. ol.geom.SimpleGeometry.prototype.dispatchEvent);
  78994. goog.exportProperty(
  78995. ol.geom.SimpleGeometry.prototype,
  78996. 'getRevision',
  78997. ol.geom.SimpleGeometry.prototype.getRevision);
  78998. goog.exportProperty(
  78999. ol.geom.SimpleGeometry.prototype,
  79000. 'on',
  79001. ol.geom.SimpleGeometry.prototype.on);
  79002. goog.exportProperty(
  79003. ol.geom.SimpleGeometry.prototype,
  79004. 'once',
  79005. ol.geom.SimpleGeometry.prototype.once);
  79006. goog.exportProperty(
  79007. ol.geom.SimpleGeometry.prototype,
  79008. 'un',
  79009. ol.geom.SimpleGeometry.prototype.un);
  79010. goog.exportProperty(
  79011. ol.geom.Circle.prototype,
  79012. 'getFirstCoordinate',
  79013. ol.geom.Circle.prototype.getFirstCoordinate);
  79014. goog.exportProperty(
  79015. ol.geom.Circle.prototype,
  79016. 'getLastCoordinate',
  79017. ol.geom.Circle.prototype.getLastCoordinate);
  79018. goog.exportProperty(
  79019. ol.geom.Circle.prototype,
  79020. 'getLayout',
  79021. ol.geom.Circle.prototype.getLayout);
  79022. goog.exportProperty(
  79023. ol.geom.Circle.prototype,
  79024. 'rotate',
  79025. ol.geom.Circle.prototype.rotate);
  79026. goog.exportProperty(
  79027. ol.geom.Circle.prototype,
  79028. 'scale',
  79029. ol.geom.Circle.prototype.scale);
  79030. goog.exportProperty(
  79031. ol.geom.Circle.prototype,
  79032. 'getClosestPoint',
  79033. ol.geom.Circle.prototype.getClosestPoint);
  79034. goog.exportProperty(
  79035. ol.geom.Circle.prototype,
  79036. 'intersectsCoordinate',
  79037. ol.geom.Circle.prototype.intersectsCoordinate);
  79038. goog.exportProperty(
  79039. ol.geom.Circle.prototype,
  79040. 'getExtent',
  79041. ol.geom.Circle.prototype.getExtent);
  79042. goog.exportProperty(
  79043. ol.geom.Circle.prototype,
  79044. 'simplify',
  79045. ol.geom.Circle.prototype.simplify);
  79046. goog.exportProperty(
  79047. ol.geom.Circle.prototype,
  79048. 'get',
  79049. ol.geom.Circle.prototype.get);
  79050. goog.exportProperty(
  79051. ol.geom.Circle.prototype,
  79052. 'getKeys',
  79053. ol.geom.Circle.prototype.getKeys);
  79054. goog.exportProperty(
  79055. ol.geom.Circle.prototype,
  79056. 'getProperties',
  79057. ol.geom.Circle.prototype.getProperties);
  79058. goog.exportProperty(
  79059. ol.geom.Circle.prototype,
  79060. 'set',
  79061. ol.geom.Circle.prototype.set);
  79062. goog.exportProperty(
  79063. ol.geom.Circle.prototype,
  79064. 'setProperties',
  79065. ol.geom.Circle.prototype.setProperties);
  79066. goog.exportProperty(
  79067. ol.geom.Circle.prototype,
  79068. 'unset',
  79069. ol.geom.Circle.prototype.unset);
  79070. goog.exportProperty(
  79071. ol.geom.Circle.prototype,
  79072. 'changed',
  79073. ol.geom.Circle.prototype.changed);
  79074. goog.exportProperty(
  79075. ol.geom.Circle.prototype,
  79076. 'dispatchEvent',
  79077. ol.geom.Circle.prototype.dispatchEvent);
  79078. goog.exportProperty(
  79079. ol.geom.Circle.prototype,
  79080. 'getRevision',
  79081. ol.geom.Circle.prototype.getRevision);
  79082. goog.exportProperty(
  79083. ol.geom.Circle.prototype,
  79084. 'on',
  79085. ol.geom.Circle.prototype.on);
  79086. goog.exportProperty(
  79087. ol.geom.Circle.prototype,
  79088. 'once',
  79089. ol.geom.Circle.prototype.once);
  79090. goog.exportProperty(
  79091. ol.geom.Circle.prototype,
  79092. 'un',
  79093. ol.geom.Circle.prototype.un);
  79094. goog.exportProperty(
  79095. ol.geom.GeometryCollection.prototype,
  79096. 'getClosestPoint',
  79097. ol.geom.GeometryCollection.prototype.getClosestPoint);
  79098. goog.exportProperty(
  79099. ol.geom.GeometryCollection.prototype,
  79100. 'intersectsCoordinate',
  79101. ol.geom.GeometryCollection.prototype.intersectsCoordinate);
  79102. goog.exportProperty(
  79103. ol.geom.GeometryCollection.prototype,
  79104. 'getExtent',
  79105. ol.geom.GeometryCollection.prototype.getExtent);
  79106. goog.exportProperty(
  79107. ol.geom.GeometryCollection.prototype,
  79108. 'rotate',
  79109. ol.geom.GeometryCollection.prototype.rotate);
  79110. goog.exportProperty(
  79111. ol.geom.GeometryCollection.prototype,
  79112. 'scale',
  79113. ol.geom.GeometryCollection.prototype.scale);
  79114. goog.exportProperty(
  79115. ol.geom.GeometryCollection.prototype,
  79116. 'simplify',
  79117. ol.geom.GeometryCollection.prototype.simplify);
  79118. goog.exportProperty(
  79119. ol.geom.GeometryCollection.prototype,
  79120. 'transform',
  79121. ol.geom.GeometryCollection.prototype.transform);
  79122. goog.exportProperty(
  79123. ol.geom.GeometryCollection.prototype,
  79124. 'get',
  79125. ol.geom.GeometryCollection.prototype.get);
  79126. goog.exportProperty(
  79127. ol.geom.GeometryCollection.prototype,
  79128. 'getKeys',
  79129. ol.geom.GeometryCollection.prototype.getKeys);
  79130. goog.exportProperty(
  79131. ol.geom.GeometryCollection.prototype,
  79132. 'getProperties',
  79133. ol.geom.GeometryCollection.prototype.getProperties);
  79134. goog.exportProperty(
  79135. ol.geom.GeometryCollection.prototype,
  79136. 'set',
  79137. ol.geom.GeometryCollection.prototype.set);
  79138. goog.exportProperty(
  79139. ol.geom.GeometryCollection.prototype,
  79140. 'setProperties',
  79141. ol.geom.GeometryCollection.prototype.setProperties);
  79142. goog.exportProperty(
  79143. ol.geom.GeometryCollection.prototype,
  79144. 'unset',
  79145. ol.geom.GeometryCollection.prototype.unset);
  79146. goog.exportProperty(
  79147. ol.geom.GeometryCollection.prototype,
  79148. 'changed',
  79149. ol.geom.GeometryCollection.prototype.changed);
  79150. goog.exportProperty(
  79151. ol.geom.GeometryCollection.prototype,
  79152. 'dispatchEvent',
  79153. ol.geom.GeometryCollection.prototype.dispatchEvent);
  79154. goog.exportProperty(
  79155. ol.geom.GeometryCollection.prototype,
  79156. 'getRevision',
  79157. ol.geom.GeometryCollection.prototype.getRevision);
  79158. goog.exportProperty(
  79159. ol.geom.GeometryCollection.prototype,
  79160. 'on',
  79161. ol.geom.GeometryCollection.prototype.on);
  79162. goog.exportProperty(
  79163. ol.geom.GeometryCollection.prototype,
  79164. 'once',
  79165. ol.geom.GeometryCollection.prototype.once);
  79166. goog.exportProperty(
  79167. ol.geom.GeometryCollection.prototype,
  79168. 'un',
  79169. ol.geom.GeometryCollection.prototype.un);
  79170. goog.exportProperty(
  79171. ol.geom.LinearRing.prototype,
  79172. 'getFirstCoordinate',
  79173. ol.geom.LinearRing.prototype.getFirstCoordinate);
  79174. goog.exportProperty(
  79175. ol.geom.LinearRing.prototype,
  79176. 'getLastCoordinate',
  79177. ol.geom.LinearRing.prototype.getLastCoordinate);
  79178. goog.exportProperty(
  79179. ol.geom.LinearRing.prototype,
  79180. 'getLayout',
  79181. ol.geom.LinearRing.prototype.getLayout);
  79182. goog.exportProperty(
  79183. ol.geom.LinearRing.prototype,
  79184. 'rotate',
  79185. ol.geom.LinearRing.prototype.rotate);
  79186. goog.exportProperty(
  79187. ol.geom.LinearRing.prototype,
  79188. 'scale',
  79189. ol.geom.LinearRing.prototype.scale);
  79190. goog.exportProperty(
  79191. ol.geom.LinearRing.prototype,
  79192. 'getClosestPoint',
  79193. ol.geom.LinearRing.prototype.getClosestPoint);
  79194. goog.exportProperty(
  79195. ol.geom.LinearRing.prototype,
  79196. 'intersectsCoordinate',
  79197. ol.geom.LinearRing.prototype.intersectsCoordinate);
  79198. goog.exportProperty(
  79199. ol.geom.LinearRing.prototype,
  79200. 'getExtent',
  79201. ol.geom.LinearRing.prototype.getExtent);
  79202. goog.exportProperty(
  79203. ol.geom.LinearRing.prototype,
  79204. 'simplify',
  79205. ol.geom.LinearRing.prototype.simplify);
  79206. goog.exportProperty(
  79207. ol.geom.LinearRing.prototype,
  79208. 'transform',
  79209. ol.geom.LinearRing.prototype.transform);
  79210. goog.exportProperty(
  79211. ol.geom.LinearRing.prototype,
  79212. 'get',
  79213. ol.geom.LinearRing.prototype.get);
  79214. goog.exportProperty(
  79215. ol.geom.LinearRing.prototype,
  79216. 'getKeys',
  79217. ol.geom.LinearRing.prototype.getKeys);
  79218. goog.exportProperty(
  79219. ol.geom.LinearRing.prototype,
  79220. 'getProperties',
  79221. ol.geom.LinearRing.prototype.getProperties);
  79222. goog.exportProperty(
  79223. ol.geom.LinearRing.prototype,
  79224. 'set',
  79225. ol.geom.LinearRing.prototype.set);
  79226. goog.exportProperty(
  79227. ol.geom.LinearRing.prototype,
  79228. 'setProperties',
  79229. ol.geom.LinearRing.prototype.setProperties);
  79230. goog.exportProperty(
  79231. ol.geom.LinearRing.prototype,
  79232. 'unset',
  79233. ol.geom.LinearRing.prototype.unset);
  79234. goog.exportProperty(
  79235. ol.geom.LinearRing.prototype,
  79236. 'changed',
  79237. ol.geom.LinearRing.prototype.changed);
  79238. goog.exportProperty(
  79239. ol.geom.LinearRing.prototype,
  79240. 'dispatchEvent',
  79241. ol.geom.LinearRing.prototype.dispatchEvent);
  79242. goog.exportProperty(
  79243. ol.geom.LinearRing.prototype,
  79244. 'getRevision',
  79245. ol.geom.LinearRing.prototype.getRevision);
  79246. goog.exportProperty(
  79247. ol.geom.LinearRing.prototype,
  79248. 'on',
  79249. ol.geom.LinearRing.prototype.on);
  79250. goog.exportProperty(
  79251. ol.geom.LinearRing.prototype,
  79252. 'once',
  79253. ol.geom.LinearRing.prototype.once);
  79254. goog.exportProperty(
  79255. ol.geom.LinearRing.prototype,
  79256. 'un',
  79257. ol.geom.LinearRing.prototype.un);
  79258. goog.exportProperty(
  79259. ol.geom.LineString.prototype,
  79260. 'getFirstCoordinate',
  79261. ol.geom.LineString.prototype.getFirstCoordinate);
  79262. goog.exportProperty(
  79263. ol.geom.LineString.prototype,
  79264. 'getLastCoordinate',
  79265. ol.geom.LineString.prototype.getLastCoordinate);
  79266. goog.exportProperty(
  79267. ol.geom.LineString.prototype,
  79268. 'getLayout',
  79269. ol.geom.LineString.prototype.getLayout);
  79270. goog.exportProperty(
  79271. ol.geom.LineString.prototype,
  79272. 'rotate',
  79273. ol.geom.LineString.prototype.rotate);
  79274. goog.exportProperty(
  79275. ol.geom.LineString.prototype,
  79276. 'scale',
  79277. ol.geom.LineString.prototype.scale);
  79278. goog.exportProperty(
  79279. ol.geom.LineString.prototype,
  79280. 'getClosestPoint',
  79281. ol.geom.LineString.prototype.getClosestPoint);
  79282. goog.exportProperty(
  79283. ol.geom.LineString.prototype,
  79284. 'intersectsCoordinate',
  79285. ol.geom.LineString.prototype.intersectsCoordinate);
  79286. goog.exportProperty(
  79287. ol.geom.LineString.prototype,
  79288. 'getExtent',
  79289. ol.geom.LineString.prototype.getExtent);
  79290. goog.exportProperty(
  79291. ol.geom.LineString.prototype,
  79292. 'simplify',
  79293. ol.geom.LineString.prototype.simplify);
  79294. goog.exportProperty(
  79295. ol.geom.LineString.prototype,
  79296. 'transform',
  79297. ol.geom.LineString.prototype.transform);
  79298. goog.exportProperty(
  79299. ol.geom.LineString.prototype,
  79300. 'get',
  79301. ol.geom.LineString.prototype.get);
  79302. goog.exportProperty(
  79303. ol.geom.LineString.prototype,
  79304. 'getKeys',
  79305. ol.geom.LineString.prototype.getKeys);
  79306. goog.exportProperty(
  79307. ol.geom.LineString.prototype,
  79308. 'getProperties',
  79309. ol.geom.LineString.prototype.getProperties);
  79310. goog.exportProperty(
  79311. ol.geom.LineString.prototype,
  79312. 'set',
  79313. ol.geom.LineString.prototype.set);
  79314. goog.exportProperty(
  79315. ol.geom.LineString.prototype,
  79316. 'setProperties',
  79317. ol.geom.LineString.prototype.setProperties);
  79318. goog.exportProperty(
  79319. ol.geom.LineString.prototype,
  79320. 'unset',
  79321. ol.geom.LineString.prototype.unset);
  79322. goog.exportProperty(
  79323. ol.geom.LineString.prototype,
  79324. 'changed',
  79325. ol.geom.LineString.prototype.changed);
  79326. goog.exportProperty(
  79327. ol.geom.LineString.prototype,
  79328. 'dispatchEvent',
  79329. ol.geom.LineString.prototype.dispatchEvent);
  79330. goog.exportProperty(
  79331. ol.geom.LineString.prototype,
  79332. 'getRevision',
  79333. ol.geom.LineString.prototype.getRevision);
  79334. goog.exportProperty(
  79335. ol.geom.LineString.prototype,
  79336. 'on',
  79337. ol.geom.LineString.prototype.on);
  79338. goog.exportProperty(
  79339. ol.geom.LineString.prototype,
  79340. 'once',
  79341. ol.geom.LineString.prototype.once);
  79342. goog.exportProperty(
  79343. ol.geom.LineString.prototype,
  79344. 'un',
  79345. ol.geom.LineString.prototype.un);
  79346. goog.exportProperty(
  79347. ol.geom.MultiLineString.prototype,
  79348. 'getFirstCoordinate',
  79349. ol.geom.MultiLineString.prototype.getFirstCoordinate);
  79350. goog.exportProperty(
  79351. ol.geom.MultiLineString.prototype,
  79352. 'getLastCoordinate',
  79353. ol.geom.MultiLineString.prototype.getLastCoordinate);
  79354. goog.exportProperty(
  79355. ol.geom.MultiLineString.prototype,
  79356. 'getLayout',
  79357. ol.geom.MultiLineString.prototype.getLayout);
  79358. goog.exportProperty(
  79359. ol.geom.MultiLineString.prototype,
  79360. 'rotate',
  79361. ol.geom.MultiLineString.prototype.rotate);
  79362. goog.exportProperty(
  79363. ol.geom.MultiLineString.prototype,
  79364. 'scale',
  79365. ol.geom.MultiLineString.prototype.scale);
  79366. goog.exportProperty(
  79367. ol.geom.MultiLineString.prototype,
  79368. 'getClosestPoint',
  79369. ol.geom.MultiLineString.prototype.getClosestPoint);
  79370. goog.exportProperty(
  79371. ol.geom.MultiLineString.prototype,
  79372. 'intersectsCoordinate',
  79373. ol.geom.MultiLineString.prototype.intersectsCoordinate);
  79374. goog.exportProperty(
  79375. ol.geom.MultiLineString.prototype,
  79376. 'getExtent',
  79377. ol.geom.MultiLineString.prototype.getExtent);
  79378. goog.exportProperty(
  79379. ol.geom.MultiLineString.prototype,
  79380. 'simplify',
  79381. ol.geom.MultiLineString.prototype.simplify);
  79382. goog.exportProperty(
  79383. ol.geom.MultiLineString.prototype,
  79384. 'transform',
  79385. ol.geom.MultiLineString.prototype.transform);
  79386. goog.exportProperty(
  79387. ol.geom.MultiLineString.prototype,
  79388. 'get',
  79389. ol.geom.MultiLineString.prototype.get);
  79390. goog.exportProperty(
  79391. ol.geom.MultiLineString.prototype,
  79392. 'getKeys',
  79393. ol.geom.MultiLineString.prototype.getKeys);
  79394. goog.exportProperty(
  79395. ol.geom.MultiLineString.prototype,
  79396. 'getProperties',
  79397. ol.geom.MultiLineString.prototype.getProperties);
  79398. goog.exportProperty(
  79399. ol.geom.MultiLineString.prototype,
  79400. 'set',
  79401. ol.geom.MultiLineString.prototype.set);
  79402. goog.exportProperty(
  79403. ol.geom.MultiLineString.prototype,
  79404. 'setProperties',
  79405. ol.geom.MultiLineString.prototype.setProperties);
  79406. goog.exportProperty(
  79407. ol.geom.MultiLineString.prototype,
  79408. 'unset',
  79409. ol.geom.MultiLineString.prototype.unset);
  79410. goog.exportProperty(
  79411. ol.geom.MultiLineString.prototype,
  79412. 'changed',
  79413. ol.geom.MultiLineString.prototype.changed);
  79414. goog.exportProperty(
  79415. ol.geom.MultiLineString.prototype,
  79416. 'dispatchEvent',
  79417. ol.geom.MultiLineString.prototype.dispatchEvent);
  79418. goog.exportProperty(
  79419. ol.geom.MultiLineString.prototype,
  79420. 'getRevision',
  79421. ol.geom.MultiLineString.prototype.getRevision);
  79422. goog.exportProperty(
  79423. ol.geom.MultiLineString.prototype,
  79424. 'on',
  79425. ol.geom.MultiLineString.prototype.on);
  79426. goog.exportProperty(
  79427. ol.geom.MultiLineString.prototype,
  79428. 'once',
  79429. ol.geom.MultiLineString.prototype.once);
  79430. goog.exportProperty(
  79431. ol.geom.MultiLineString.prototype,
  79432. 'un',
  79433. ol.geom.MultiLineString.prototype.un);
  79434. goog.exportProperty(
  79435. ol.geom.MultiPoint.prototype,
  79436. 'getFirstCoordinate',
  79437. ol.geom.MultiPoint.prototype.getFirstCoordinate);
  79438. goog.exportProperty(
  79439. ol.geom.MultiPoint.prototype,
  79440. 'getLastCoordinate',
  79441. ol.geom.MultiPoint.prototype.getLastCoordinate);
  79442. goog.exportProperty(
  79443. ol.geom.MultiPoint.prototype,
  79444. 'getLayout',
  79445. ol.geom.MultiPoint.prototype.getLayout);
  79446. goog.exportProperty(
  79447. ol.geom.MultiPoint.prototype,
  79448. 'rotate',
  79449. ol.geom.MultiPoint.prototype.rotate);
  79450. goog.exportProperty(
  79451. ol.geom.MultiPoint.prototype,
  79452. 'scale',
  79453. ol.geom.MultiPoint.prototype.scale);
  79454. goog.exportProperty(
  79455. ol.geom.MultiPoint.prototype,
  79456. 'getClosestPoint',
  79457. ol.geom.MultiPoint.prototype.getClosestPoint);
  79458. goog.exportProperty(
  79459. ol.geom.MultiPoint.prototype,
  79460. 'intersectsCoordinate',
  79461. ol.geom.MultiPoint.prototype.intersectsCoordinate);
  79462. goog.exportProperty(
  79463. ol.geom.MultiPoint.prototype,
  79464. 'getExtent',
  79465. ol.geom.MultiPoint.prototype.getExtent);
  79466. goog.exportProperty(
  79467. ol.geom.MultiPoint.prototype,
  79468. 'simplify',
  79469. ol.geom.MultiPoint.prototype.simplify);
  79470. goog.exportProperty(
  79471. ol.geom.MultiPoint.prototype,
  79472. 'transform',
  79473. ol.geom.MultiPoint.prototype.transform);
  79474. goog.exportProperty(
  79475. ol.geom.MultiPoint.prototype,
  79476. 'get',
  79477. ol.geom.MultiPoint.prototype.get);
  79478. goog.exportProperty(
  79479. ol.geom.MultiPoint.prototype,
  79480. 'getKeys',
  79481. ol.geom.MultiPoint.prototype.getKeys);
  79482. goog.exportProperty(
  79483. ol.geom.MultiPoint.prototype,
  79484. 'getProperties',
  79485. ol.geom.MultiPoint.prototype.getProperties);
  79486. goog.exportProperty(
  79487. ol.geom.MultiPoint.prototype,
  79488. 'set',
  79489. ol.geom.MultiPoint.prototype.set);
  79490. goog.exportProperty(
  79491. ol.geom.MultiPoint.prototype,
  79492. 'setProperties',
  79493. ol.geom.MultiPoint.prototype.setProperties);
  79494. goog.exportProperty(
  79495. ol.geom.MultiPoint.prototype,
  79496. 'unset',
  79497. ol.geom.MultiPoint.prototype.unset);
  79498. goog.exportProperty(
  79499. ol.geom.MultiPoint.prototype,
  79500. 'changed',
  79501. ol.geom.MultiPoint.prototype.changed);
  79502. goog.exportProperty(
  79503. ol.geom.MultiPoint.prototype,
  79504. 'dispatchEvent',
  79505. ol.geom.MultiPoint.prototype.dispatchEvent);
  79506. goog.exportProperty(
  79507. ol.geom.MultiPoint.prototype,
  79508. 'getRevision',
  79509. ol.geom.MultiPoint.prototype.getRevision);
  79510. goog.exportProperty(
  79511. ol.geom.MultiPoint.prototype,
  79512. 'on',
  79513. ol.geom.MultiPoint.prototype.on);
  79514. goog.exportProperty(
  79515. ol.geom.MultiPoint.prototype,
  79516. 'once',
  79517. ol.geom.MultiPoint.prototype.once);
  79518. goog.exportProperty(
  79519. ol.geom.MultiPoint.prototype,
  79520. 'un',
  79521. ol.geom.MultiPoint.prototype.un);
  79522. goog.exportProperty(
  79523. ol.geom.MultiPolygon.prototype,
  79524. 'getFirstCoordinate',
  79525. ol.geom.MultiPolygon.prototype.getFirstCoordinate);
  79526. goog.exportProperty(
  79527. ol.geom.MultiPolygon.prototype,
  79528. 'getLastCoordinate',
  79529. ol.geom.MultiPolygon.prototype.getLastCoordinate);
  79530. goog.exportProperty(
  79531. ol.geom.MultiPolygon.prototype,
  79532. 'getLayout',
  79533. ol.geom.MultiPolygon.prototype.getLayout);
  79534. goog.exportProperty(
  79535. ol.geom.MultiPolygon.prototype,
  79536. 'rotate',
  79537. ol.geom.MultiPolygon.prototype.rotate);
  79538. goog.exportProperty(
  79539. ol.geom.MultiPolygon.prototype,
  79540. 'scale',
  79541. ol.geom.MultiPolygon.prototype.scale);
  79542. goog.exportProperty(
  79543. ol.geom.MultiPolygon.prototype,
  79544. 'getClosestPoint',
  79545. ol.geom.MultiPolygon.prototype.getClosestPoint);
  79546. goog.exportProperty(
  79547. ol.geom.MultiPolygon.prototype,
  79548. 'intersectsCoordinate',
  79549. ol.geom.MultiPolygon.prototype.intersectsCoordinate);
  79550. goog.exportProperty(
  79551. ol.geom.MultiPolygon.prototype,
  79552. 'getExtent',
  79553. ol.geom.MultiPolygon.prototype.getExtent);
  79554. goog.exportProperty(
  79555. ol.geom.MultiPolygon.prototype,
  79556. 'simplify',
  79557. ol.geom.MultiPolygon.prototype.simplify);
  79558. goog.exportProperty(
  79559. ol.geom.MultiPolygon.prototype,
  79560. 'transform',
  79561. ol.geom.MultiPolygon.prototype.transform);
  79562. goog.exportProperty(
  79563. ol.geom.MultiPolygon.prototype,
  79564. 'get',
  79565. ol.geom.MultiPolygon.prototype.get);
  79566. goog.exportProperty(
  79567. ol.geom.MultiPolygon.prototype,
  79568. 'getKeys',
  79569. ol.geom.MultiPolygon.prototype.getKeys);
  79570. goog.exportProperty(
  79571. ol.geom.MultiPolygon.prototype,
  79572. 'getProperties',
  79573. ol.geom.MultiPolygon.prototype.getProperties);
  79574. goog.exportProperty(
  79575. ol.geom.MultiPolygon.prototype,
  79576. 'set',
  79577. ol.geom.MultiPolygon.prototype.set);
  79578. goog.exportProperty(
  79579. ol.geom.MultiPolygon.prototype,
  79580. 'setProperties',
  79581. ol.geom.MultiPolygon.prototype.setProperties);
  79582. goog.exportProperty(
  79583. ol.geom.MultiPolygon.prototype,
  79584. 'unset',
  79585. ol.geom.MultiPolygon.prototype.unset);
  79586. goog.exportProperty(
  79587. ol.geom.MultiPolygon.prototype,
  79588. 'changed',
  79589. ol.geom.MultiPolygon.prototype.changed);
  79590. goog.exportProperty(
  79591. ol.geom.MultiPolygon.prototype,
  79592. 'dispatchEvent',
  79593. ol.geom.MultiPolygon.prototype.dispatchEvent);
  79594. goog.exportProperty(
  79595. ol.geom.MultiPolygon.prototype,
  79596. 'getRevision',
  79597. ol.geom.MultiPolygon.prototype.getRevision);
  79598. goog.exportProperty(
  79599. ol.geom.MultiPolygon.prototype,
  79600. 'on',
  79601. ol.geom.MultiPolygon.prototype.on);
  79602. goog.exportProperty(
  79603. ol.geom.MultiPolygon.prototype,
  79604. 'once',
  79605. ol.geom.MultiPolygon.prototype.once);
  79606. goog.exportProperty(
  79607. ol.geom.MultiPolygon.prototype,
  79608. 'un',
  79609. ol.geom.MultiPolygon.prototype.un);
  79610. goog.exportProperty(
  79611. ol.geom.Point.prototype,
  79612. 'getFirstCoordinate',
  79613. ol.geom.Point.prototype.getFirstCoordinate);
  79614. goog.exportProperty(
  79615. ol.geom.Point.prototype,
  79616. 'getLastCoordinate',
  79617. ol.geom.Point.prototype.getLastCoordinate);
  79618. goog.exportProperty(
  79619. ol.geom.Point.prototype,
  79620. 'getLayout',
  79621. ol.geom.Point.prototype.getLayout);
  79622. goog.exportProperty(
  79623. ol.geom.Point.prototype,
  79624. 'rotate',
  79625. ol.geom.Point.prototype.rotate);
  79626. goog.exportProperty(
  79627. ol.geom.Point.prototype,
  79628. 'scale',
  79629. ol.geom.Point.prototype.scale);
  79630. goog.exportProperty(
  79631. ol.geom.Point.prototype,
  79632. 'getClosestPoint',
  79633. ol.geom.Point.prototype.getClosestPoint);
  79634. goog.exportProperty(
  79635. ol.geom.Point.prototype,
  79636. 'intersectsCoordinate',
  79637. ol.geom.Point.prototype.intersectsCoordinate);
  79638. goog.exportProperty(
  79639. ol.geom.Point.prototype,
  79640. 'getExtent',
  79641. ol.geom.Point.prototype.getExtent);
  79642. goog.exportProperty(
  79643. ol.geom.Point.prototype,
  79644. 'simplify',
  79645. ol.geom.Point.prototype.simplify);
  79646. goog.exportProperty(
  79647. ol.geom.Point.prototype,
  79648. 'transform',
  79649. ol.geom.Point.prototype.transform);
  79650. goog.exportProperty(
  79651. ol.geom.Point.prototype,
  79652. 'get',
  79653. ol.geom.Point.prototype.get);
  79654. goog.exportProperty(
  79655. ol.geom.Point.prototype,
  79656. 'getKeys',
  79657. ol.geom.Point.prototype.getKeys);
  79658. goog.exportProperty(
  79659. ol.geom.Point.prototype,
  79660. 'getProperties',
  79661. ol.geom.Point.prototype.getProperties);
  79662. goog.exportProperty(
  79663. ol.geom.Point.prototype,
  79664. 'set',
  79665. ol.geom.Point.prototype.set);
  79666. goog.exportProperty(
  79667. ol.geom.Point.prototype,
  79668. 'setProperties',
  79669. ol.geom.Point.prototype.setProperties);
  79670. goog.exportProperty(
  79671. ol.geom.Point.prototype,
  79672. 'unset',
  79673. ol.geom.Point.prototype.unset);
  79674. goog.exportProperty(
  79675. ol.geom.Point.prototype,
  79676. 'changed',
  79677. ol.geom.Point.prototype.changed);
  79678. goog.exportProperty(
  79679. ol.geom.Point.prototype,
  79680. 'dispatchEvent',
  79681. ol.geom.Point.prototype.dispatchEvent);
  79682. goog.exportProperty(
  79683. ol.geom.Point.prototype,
  79684. 'getRevision',
  79685. ol.geom.Point.prototype.getRevision);
  79686. goog.exportProperty(
  79687. ol.geom.Point.prototype,
  79688. 'on',
  79689. ol.geom.Point.prototype.on);
  79690. goog.exportProperty(
  79691. ol.geom.Point.prototype,
  79692. 'once',
  79693. ol.geom.Point.prototype.once);
  79694. goog.exportProperty(
  79695. ol.geom.Point.prototype,
  79696. 'un',
  79697. ol.geom.Point.prototype.un);
  79698. goog.exportProperty(
  79699. ol.geom.Polygon.prototype,
  79700. 'getFirstCoordinate',
  79701. ol.geom.Polygon.prototype.getFirstCoordinate);
  79702. goog.exportProperty(
  79703. ol.geom.Polygon.prototype,
  79704. 'getLastCoordinate',
  79705. ol.geom.Polygon.prototype.getLastCoordinate);
  79706. goog.exportProperty(
  79707. ol.geom.Polygon.prototype,
  79708. 'getLayout',
  79709. ol.geom.Polygon.prototype.getLayout);
  79710. goog.exportProperty(
  79711. ol.geom.Polygon.prototype,
  79712. 'rotate',
  79713. ol.geom.Polygon.prototype.rotate);
  79714. goog.exportProperty(
  79715. ol.geom.Polygon.prototype,
  79716. 'scale',
  79717. ol.geom.Polygon.prototype.scale);
  79718. goog.exportProperty(
  79719. ol.geom.Polygon.prototype,
  79720. 'getClosestPoint',
  79721. ol.geom.Polygon.prototype.getClosestPoint);
  79722. goog.exportProperty(
  79723. ol.geom.Polygon.prototype,
  79724. 'intersectsCoordinate',
  79725. ol.geom.Polygon.prototype.intersectsCoordinate);
  79726. goog.exportProperty(
  79727. ol.geom.Polygon.prototype,
  79728. 'getExtent',
  79729. ol.geom.Polygon.prototype.getExtent);
  79730. goog.exportProperty(
  79731. ol.geom.Polygon.prototype,
  79732. 'simplify',
  79733. ol.geom.Polygon.prototype.simplify);
  79734. goog.exportProperty(
  79735. ol.geom.Polygon.prototype,
  79736. 'transform',
  79737. ol.geom.Polygon.prototype.transform);
  79738. goog.exportProperty(
  79739. ol.geom.Polygon.prototype,
  79740. 'get',
  79741. ol.geom.Polygon.prototype.get);
  79742. goog.exportProperty(
  79743. ol.geom.Polygon.prototype,
  79744. 'getKeys',
  79745. ol.geom.Polygon.prototype.getKeys);
  79746. goog.exportProperty(
  79747. ol.geom.Polygon.prototype,
  79748. 'getProperties',
  79749. ol.geom.Polygon.prototype.getProperties);
  79750. goog.exportProperty(
  79751. ol.geom.Polygon.prototype,
  79752. 'set',
  79753. ol.geom.Polygon.prototype.set);
  79754. goog.exportProperty(
  79755. ol.geom.Polygon.prototype,
  79756. 'setProperties',
  79757. ol.geom.Polygon.prototype.setProperties);
  79758. goog.exportProperty(
  79759. ol.geom.Polygon.prototype,
  79760. 'unset',
  79761. ol.geom.Polygon.prototype.unset);
  79762. goog.exportProperty(
  79763. ol.geom.Polygon.prototype,
  79764. 'changed',
  79765. ol.geom.Polygon.prototype.changed);
  79766. goog.exportProperty(
  79767. ol.geom.Polygon.prototype,
  79768. 'dispatchEvent',
  79769. ol.geom.Polygon.prototype.dispatchEvent);
  79770. goog.exportProperty(
  79771. ol.geom.Polygon.prototype,
  79772. 'getRevision',
  79773. ol.geom.Polygon.prototype.getRevision);
  79774. goog.exportProperty(
  79775. ol.geom.Polygon.prototype,
  79776. 'on',
  79777. ol.geom.Polygon.prototype.on);
  79778. goog.exportProperty(
  79779. ol.geom.Polygon.prototype,
  79780. 'once',
  79781. ol.geom.Polygon.prototype.once);
  79782. goog.exportProperty(
  79783. ol.geom.Polygon.prototype,
  79784. 'un',
  79785. ol.geom.Polygon.prototype.un);
  79786. goog.exportProperty(
  79787. ol.format.GML.prototype,
  79788. 'readFeatures',
  79789. ol.format.GML.prototype.readFeatures);
  79790. goog.exportProperty(
  79791. ol.format.GML2.prototype,
  79792. 'readFeatures',
  79793. ol.format.GML2.prototype.readFeatures);
  79794. goog.exportProperty(
  79795. ol.format.GML3.prototype,
  79796. 'readFeatures',
  79797. ol.format.GML3.prototype.readFeatures);
  79798. goog.exportProperty(
  79799. ol.control.Control.prototype,
  79800. 'get',
  79801. ol.control.Control.prototype.get);
  79802. goog.exportProperty(
  79803. ol.control.Control.prototype,
  79804. 'getKeys',
  79805. ol.control.Control.prototype.getKeys);
  79806. goog.exportProperty(
  79807. ol.control.Control.prototype,
  79808. 'getProperties',
  79809. ol.control.Control.prototype.getProperties);
  79810. goog.exportProperty(
  79811. ol.control.Control.prototype,
  79812. 'set',
  79813. ol.control.Control.prototype.set);
  79814. goog.exportProperty(
  79815. ol.control.Control.prototype,
  79816. 'setProperties',
  79817. ol.control.Control.prototype.setProperties);
  79818. goog.exportProperty(
  79819. ol.control.Control.prototype,
  79820. 'unset',
  79821. ol.control.Control.prototype.unset);
  79822. goog.exportProperty(
  79823. ol.control.Control.prototype,
  79824. 'changed',
  79825. ol.control.Control.prototype.changed);
  79826. goog.exportProperty(
  79827. ol.control.Control.prototype,
  79828. 'dispatchEvent',
  79829. ol.control.Control.prototype.dispatchEvent);
  79830. goog.exportProperty(
  79831. ol.control.Control.prototype,
  79832. 'getRevision',
  79833. ol.control.Control.prototype.getRevision);
  79834. goog.exportProperty(
  79835. ol.control.Control.prototype,
  79836. 'on',
  79837. ol.control.Control.prototype.on);
  79838. goog.exportProperty(
  79839. ol.control.Control.prototype,
  79840. 'once',
  79841. ol.control.Control.prototype.once);
  79842. goog.exportProperty(
  79843. ol.control.Control.prototype,
  79844. 'un',
  79845. ol.control.Control.prototype.un);
  79846. goog.exportProperty(
  79847. ol.control.Attribution.prototype,
  79848. 'getMap',
  79849. ol.control.Attribution.prototype.getMap);
  79850. goog.exportProperty(
  79851. ol.control.Attribution.prototype,
  79852. 'setMap',
  79853. ol.control.Attribution.prototype.setMap);
  79854. goog.exportProperty(
  79855. ol.control.Attribution.prototype,
  79856. 'setTarget',
  79857. ol.control.Attribution.prototype.setTarget);
  79858. goog.exportProperty(
  79859. ol.control.Attribution.prototype,
  79860. 'get',
  79861. ol.control.Attribution.prototype.get);
  79862. goog.exportProperty(
  79863. ol.control.Attribution.prototype,
  79864. 'getKeys',
  79865. ol.control.Attribution.prototype.getKeys);
  79866. goog.exportProperty(
  79867. ol.control.Attribution.prototype,
  79868. 'getProperties',
  79869. ol.control.Attribution.prototype.getProperties);
  79870. goog.exportProperty(
  79871. ol.control.Attribution.prototype,
  79872. 'set',
  79873. ol.control.Attribution.prototype.set);
  79874. goog.exportProperty(
  79875. ol.control.Attribution.prototype,
  79876. 'setProperties',
  79877. ol.control.Attribution.prototype.setProperties);
  79878. goog.exportProperty(
  79879. ol.control.Attribution.prototype,
  79880. 'unset',
  79881. ol.control.Attribution.prototype.unset);
  79882. goog.exportProperty(
  79883. ol.control.Attribution.prototype,
  79884. 'changed',
  79885. ol.control.Attribution.prototype.changed);
  79886. goog.exportProperty(
  79887. ol.control.Attribution.prototype,
  79888. 'dispatchEvent',
  79889. ol.control.Attribution.prototype.dispatchEvent);
  79890. goog.exportProperty(
  79891. ol.control.Attribution.prototype,
  79892. 'getRevision',
  79893. ol.control.Attribution.prototype.getRevision);
  79894. goog.exportProperty(
  79895. ol.control.Attribution.prototype,
  79896. 'on',
  79897. ol.control.Attribution.prototype.on);
  79898. goog.exportProperty(
  79899. ol.control.Attribution.prototype,
  79900. 'once',
  79901. ol.control.Attribution.prototype.once);
  79902. goog.exportProperty(
  79903. ol.control.Attribution.prototype,
  79904. 'un',
  79905. ol.control.Attribution.prototype.un);
  79906. goog.exportProperty(
  79907. ol.control.FullScreen.prototype,
  79908. 'getMap',
  79909. ol.control.FullScreen.prototype.getMap);
  79910. goog.exportProperty(
  79911. ol.control.FullScreen.prototype,
  79912. 'setMap',
  79913. ol.control.FullScreen.prototype.setMap);
  79914. goog.exportProperty(
  79915. ol.control.FullScreen.prototype,
  79916. 'setTarget',
  79917. ol.control.FullScreen.prototype.setTarget);
  79918. goog.exportProperty(
  79919. ol.control.FullScreen.prototype,
  79920. 'get',
  79921. ol.control.FullScreen.prototype.get);
  79922. goog.exportProperty(
  79923. ol.control.FullScreen.prototype,
  79924. 'getKeys',
  79925. ol.control.FullScreen.prototype.getKeys);
  79926. goog.exportProperty(
  79927. ol.control.FullScreen.prototype,
  79928. 'getProperties',
  79929. ol.control.FullScreen.prototype.getProperties);
  79930. goog.exportProperty(
  79931. ol.control.FullScreen.prototype,
  79932. 'set',
  79933. ol.control.FullScreen.prototype.set);
  79934. goog.exportProperty(
  79935. ol.control.FullScreen.prototype,
  79936. 'setProperties',
  79937. ol.control.FullScreen.prototype.setProperties);
  79938. goog.exportProperty(
  79939. ol.control.FullScreen.prototype,
  79940. 'unset',
  79941. ol.control.FullScreen.prototype.unset);
  79942. goog.exportProperty(
  79943. ol.control.FullScreen.prototype,
  79944. 'changed',
  79945. ol.control.FullScreen.prototype.changed);
  79946. goog.exportProperty(
  79947. ol.control.FullScreen.prototype,
  79948. 'dispatchEvent',
  79949. ol.control.FullScreen.prototype.dispatchEvent);
  79950. goog.exportProperty(
  79951. ol.control.FullScreen.prototype,
  79952. 'getRevision',
  79953. ol.control.FullScreen.prototype.getRevision);
  79954. goog.exportProperty(
  79955. ol.control.FullScreen.prototype,
  79956. 'on',
  79957. ol.control.FullScreen.prototype.on);
  79958. goog.exportProperty(
  79959. ol.control.FullScreen.prototype,
  79960. 'once',
  79961. ol.control.FullScreen.prototype.once);
  79962. goog.exportProperty(
  79963. ol.control.FullScreen.prototype,
  79964. 'un',
  79965. ol.control.FullScreen.prototype.un);
  79966. goog.exportProperty(
  79967. ol.control.MousePosition.prototype,
  79968. 'getMap',
  79969. ol.control.MousePosition.prototype.getMap);
  79970. goog.exportProperty(
  79971. ol.control.MousePosition.prototype,
  79972. 'setMap',
  79973. ol.control.MousePosition.prototype.setMap);
  79974. goog.exportProperty(
  79975. ol.control.MousePosition.prototype,
  79976. 'setTarget',
  79977. ol.control.MousePosition.prototype.setTarget);
  79978. goog.exportProperty(
  79979. ol.control.MousePosition.prototype,
  79980. 'get',
  79981. ol.control.MousePosition.prototype.get);
  79982. goog.exportProperty(
  79983. ol.control.MousePosition.prototype,
  79984. 'getKeys',
  79985. ol.control.MousePosition.prototype.getKeys);
  79986. goog.exportProperty(
  79987. ol.control.MousePosition.prototype,
  79988. 'getProperties',
  79989. ol.control.MousePosition.prototype.getProperties);
  79990. goog.exportProperty(
  79991. ol.control.MousePosition.prototype,
  79992. 'set',
  79993. ol.control.MousePosition.prototype.set);
  79994. goog.exportProperty(
  79995. ol.control.MousePosition.prototype,
  79996. 'setProperties',
  79997. ol.control.MousePosition.prototype.setProperties);
  79998. goog.exportProperty(
  79999. ol.control.MousePosition.prototype,
  80000. 'unset',
  80001. ol.control.MousePosition.prototype.unset);
  80002. goog.exportProperty(
  80003. ol.control.MousePosition.prototype,
  80004. 'changed',
  80005. ol.control.MousePosition.prototype.changed);
  80006. goog.exportProperty(
  80007. ol.control.MousePosition.prototype,
  80008. 'dispatchEvent',
  80009. ol.control.MousePosition.prototype.dispatchEvent);
  80010. goog.exportProperty(
  80011. ol.control.MousePosition.prototype,
  80012. 'getRevision',
  80013. ol.control.MousePosition.prototype.getRevision);
  80014. goog.exportProperty(
  80015. ol.control.MousePosition.prototype,
  80016. 'on',
  80017. ol.control.MousePosition.prototype.on);
  80018. goog.exportProperty(
  80019. ol.control.MousePosition.prototype,
  80020. 'once',
  80021. ol.control.MousePosition.prototype.once);
  80022. goog.exportProperty(
  80023. ol.control.MousePosition.prototype,
  80024. 'un',
  80025. ol.control.MousePosition.prototype.un);
  80026. goog.exportProperty(
  80027. ol.control.OverviewMap.prototype,
  80028. 'getMap',
  80029. ol.control.OverviewMap.prototype.getMap);
  80030. goog.exportProperty(
  80031. ol.control.OverviewMap.prototype,
  80032. 'setMap',
  80033. ol.control.OverviewMap.prototype.setMap);
  80034. goog.exportProperty(
  80035. ol.control.OverviewMap.prototype,
  80036. 'setTarget',
  80037. ol.control.OverviewMap.prototype.setTarget);
  80038. goog.exportProperty(
  80039. ol.control.OverviewMap.prototype,
  80040. 'get',
  80041. ol.control.OverviewMap.prototype.get);
  80042. goog.exportProperty(
  80043. ol.control.OverviewMap.prototype,
  80044. 'getKeys',
  80045. ol.control.OverviewMap.prototype.getKeys);
  80046. goog.exportProperty(
  80047. ol.control.OverviewMap.prototype,
  80048. 'getProperties',
  80049. ol.control.OverviewMap.prototype.getProperties);
  80050. goog.exportProperty(
  80051. ol.control.OverviewMap.prototype,
  80052. 'set',
  80053. ol.control.OverviewMap.prototype.set);
  80054. goog.exportProperty(
  80055. ol.control.OverviewMap.prototype,
  80056. 'setProperties',
  80057. ol.control.OverviewMap.prototype.setProperties);
  80058. goog.exportProperty(
  80059. ol.control.OverviewMap.prototype,
  80060. 'unset',
  80061. ol.control.OverviewMap.prototype.unset);
  80062. goog.exportProperty(
  80063. ol.control.OverviewMap.prototype,
  80064. 'changed',
  80065. ol.control.OverviewMap.prototype.changed);
  80066. goog.exportProperty(
  80067. ol.control.OverviewMap.prototype,
  80068. 'dispatchEvent',
  80069. ol.control.OverviewMap.prototype.dispatchEvent);
  80070. goog.exportProperty(
  80071. ol.control.OverviewMap.prototype,
  80072. 'getRevision',
  80073. ol.control.OverviewMap.prototype.getRevision);
  80074. goog.exportProperty(
  80075. ol.control.OverviewMap.prototype,
  80076. 'on',
  80077. ol.control.OverviewMap.prototype.on);
  80078. goog.exportProperty(
  80079. ol.control.OverviewMap.prototype,
  80080. 'once',
  80081. ol.control.OverviewMap.prototype.once);
  80082. goog.exportProperty(
  80083. ol.control.OverviewMap.prototype,
  80084. 'un',
  80085. ol.control.OverviewMap.prototype.un);
  80086. goog.exportProperty(
  80087. ol.control.Rotate.prototype,
  80088. 'getMap',
  80089. ol.control.Rotate.prototype.getMap);
  80090. goog.exportProperty(
  80091. ol.control.Rotate.prototype,
  80092. 'setMap',
  80093. ol.control.Rotate.prototype.setMap);
  80094. goog.exportProperty(
  80095. ol.control.Rotate.prototype,
  80096. 'setTarget',
  80097. ol.control.Rotate.prototype.setTarget);
  80098. goog.exportProperty(
  80099. ol.control.Rotate.prototype,
  80100. 'get',
  80101. ol.control.Rotate.prototype.get);
  80102. goog.exportProperty(
  80103. ol.control.Rotate.prototype,
  80104. 'getKeys',
  80105. ol.control.Rotate.prototype.getKeys);
  80106. goog.exportProperty(
  80107. ol.control.Rotate.prototype,
  80108. 'getProperties',
  80109. ol.control.Rotate.prototype.getProperties);
  80110. goog.exportProperty(
  80111. ol.control.Rotate.prototype,
  80112. 'set',
  80113. ol.control.Rotate.prototype.set);
  80114. goog.exportProperty(
  80115. ol.control.Rotate.prototype,
  80116. 'setProperties',
  80117. ol.control.Rotate.prototype.setProperties);
  80118. goog.exportProperty(
  80119. ol.control.Rotate.prototype,
  80120. 'unset',
  80121. ol.control.Rotate.prototype.unset);
  80122. goog.exportProperty(
  80123. ol.control.Rotate.prototype,
  80124. 'changed',
  80125. ol.control.Rotate.prototype.changed);
  80126. goog.exportProperty(
  80127. ol.control.Rotate.prototype,
  80128. 'dispatchEvent',
  80129. ol.control.Rotate.prototype.dispatchEvent);
  80130. goog.exportProperty(
  80131. ol.control.Rotate.prototype,
  80132. 'getRevision',
  80133. ol.control.Rotate.prototype.getRevision);
  80134. goog.exportProperty(
  80135. ol.control.Rotate.prototype,
  80136. 'on',
  80137. ol.control.Rotate.prototype.on);
  80138. goog.exportProperty(
  80139. ol.control.Rotate.prototype,
  80140. 'once',
  80141. ol.control.Rotate.prototype.once);
  80142. goog.exportProperty(
  80143. ol.control.Rotate.prototype,
  80144. 'un',
  80145. ol.control.Rotate.prototype.un);
  80146. goog.exportProperty(
  80147. ol.control.ScaleLine.prototype,
  80148. 'getMap',
  80149. ol.control.ScaleLine.prototype.getMap);
  80150. goog.exportProperty(
  80151. ol.control.ScaleLine.prototype,
  80152. 'setMap',
  80153. ol.control.ScaleLine.prototype.setMap);
  80154. goog.exportProperty(
  80155. ol.control.ScaleLine.prototype,
  80156. 'setTarget',
  80157. ol.control.ScaleLine.prototype.setTarget);
  80158. goog.exportProperty(
  80159. ol.control.ScaleLine.prototype,
  80160. 'get',
  80161. ol.control.ScaleLine.prototype.get);
  80162. goog.exportProperty(
  80163. ol.control.ScaleLine.prototype,
  80164. 'getKeys',
  80165. ol.control.ScaleLine.prototype.getKeys);
  80166. goog.exportProperty(
  80167. ol.control.ScaleLine.prototype,
  80168. 'getProperties',
  80169. ol.control.ScaleLine.prototype.getProperties);
  80170. goog.exportProperty(
  80171. ol.control.ScaleLine.prototype,
  80172. 'set',
  80173. ol.control.ScaleLine.prototype.set);
  80174. goog.exportProperty(
  80175. ol.control.ScaleLine.prototype,
  80176. 'setProperties',
  80177. ol.control.ScaleLine.prototype.setProperties);
  80178. goog.exportProperty(
  80179. ol.control.ScaleLine.prototype,
  80180. 'unset',
  80181. ol.control.ScaleLine.prototype.unset);
  80182. goog.exportProperty(
  80183. ol.control.ScaleLine.prototype,
  80184. 'changed',
  80185. ol.control.ScaleLine.prototype.changed);
  80186. goog.exportProperty(
  80187. ol.control.ScaleLine.prototype,
  80188. 'dispatchEvent',
  80189. ol.control.ScaleLine.prototype.dispatchEvent);
  80190. goog.exportProperty(
  80191. ol.control.ScaleLine.prototype,
  80192. 'getRevision',
  80193. ol.control.ScaleLine.prototype.getRevision);
  80194. goog.exportProperty(
  80195. ol.control.ScaleLine.prototype,
  80196. 'on',
  80197. ol.control.ScaleLine.prototype.on);
  80198. goog.exportProperty(
  80199. ol.control.ScaleLine.prototype,
  80200. 'once',
  80201. ol.control.ScaleLine.prototype.once);
  80202. goog.exportProperty(
  80203. ol.control.ScaleLine.prototype,
  80204. 'un',
  80205. ol.control.ScaleLine.prototype.un);
  80206. goog.exportProperty(
  80207. ol.control.Zoom.prototype,
  80208. 'getMap',
  80209. ol.control.Zoom.prototype.getMap);
  80210. goog.exportProperty(
  80211. ol.control.Zoom.prototype,
  80212. 'setMap',
  80213. ol.control.Zoom.prototype.setMap);
  80214. goog.exportProperty(
  80215. ol.control.Zoom.prototype,
  80216. 'setTarget',
  80217. ol.control.Zoom.prototype.setTarget);
  80218. goog.exportProperty(
  80219. ol.control.Zoom.prototype,
  80220. 'get',
  80221. ol.control.Zoom.prototype.get);
  80222. goog.exportProperty(
  80223. ol.control.Zoom.prototype,
  80224. 'getKeys',
  80225. ol.control.Zoom.prototype.getKeys);
  80226. goog.exportProperty(
  80227. ol.control.Zoom.prototype,
  80228. 'getProperties',
  80229. ol.control.Zoom.prototype.getProperties);
  80230. goog.exportProperty(
  80231. ol.control.Zoom.prototype,
  80232. 'set',
  80233. ol.control.Zoom.prototype.set);
  80234. goog.exportProperty(
  80235. ol.control.Zoom.prototype,
  80236. 'setProperties',
  80237. ol.control.Zoom.prototype.setProperties);
  80238. goog.exportProperty(
  80239. ol.control.Zoom.prototype,
  80240. 'unset',
  80241. ol.control.Zoom.prototype.unset);
  80242. goog.exportProperty(
  80243. ol.control.Zoom.prototype,
  80244. 'changed',
  80245. ol.control.Zoom.prototype.changed);
  80246. goog.exportProperty(
  80247. ol.control.Zoom.prototype,
  80248. 'dispatchEvent',
  80249. ol.control.Zoom.prototype.dispatchEvent);
  80250. goog.exportProperty(
  80251. ol.control.Zoom.prototype,
  80252. 'getRevision',
  80253. ol.control.Zoom.prototype.getRevision);
  80254. goog.exportProperty(
  80255. ol.control.Zoom.prototype,
  80256. 'on',
  80257. ol.control.Zoom.prototype.on);
  80258. goog.exportProperty(
  80259. ol.control.Zoom.prototype,
  80260. 'once',
  80261. ol.control.Zoom.prototype.once);
  80262. goog.exportProperty(
  80263. ol.control.Zoom.prototype,
  80264. 'un',
  80265. ol.control.Zoom.prototype.un);
  80266. goog.exportProperty(
  80267. ol.control.ZoomSlider.prototype,
  80268. 'getMap',
  80269. ol.control.ZoomSlider.prototype.getMap);
  80270. goog.exportProperty(
  80271. ol.control.ZoomSlider.prototype,
  80272. 'setMap',
  80273. ol.control.ZoomSlider.prototype.setMap);
  80274. goog.exportProperty(
  80275. ol.control.ZoomSlider.prototype,
  80276. 'setTarget',
  80277. ol.control.ZoomSlider.prototype.setTarget);
  80278. goog.exportProperty(
  80279. ol.control.ZoomSlider.prototype,
  80280. 'get',
  80281. ol.control.ZoomSlider.prototype.get);
  80282. goog.exportProperty(
  80283. ol.control.ZoomSlider.prototype,
  80284. 'getKeys',
  80285. ol.control.ZoomSlider.prototype.getKeys);
  80286. goog.exportProperty(
  80287. ol.control.ZoomSlider.prototype,
  80288. 'getProperties',
  80289. ol.control.ZoomSlider.prototype.getProperties);
  80290. goog.exportProperty(
  80291. ol.control.ZoomSlider.prototype,
  80292. 'set',
  80293. ol.control.ZoomSlider.prototype.set);
  80294. goog.exportProperty(
  80295. ol.control.ZoomSlider.prototype,
  80296. 'setProperties',
  80297. ol.control.ZoomSlider.prototype.setProperties);
  80298. goog.exportProperty(
  80299. ol.control.ZoomSlider.prototype,
  80300. 'unset',
  80301. ol.control.ZoomSlider.prototype.unset);
  80302. goog.exportProperty(
  80303. ol.control.ZoomSlider.prototype,
  80304. 'changed',
  80305. ol.control.ZoomSlider.prototype.changed);
  80306. goog.exportProperty(
  80307. ol.control.ZoomSlider.prototype,
  80308. 'dispatchEvent',
  80309. ol.control.ZoomSlider.prototype.dispatchEvent);
  80310. goog.exportProperty(
  80311. ol.control.ZoomSlider.prototype,
  80312. 'getRevision',
  80313. ol.control.ZoomSlider.prototype.getRevision);
  80314. goog.exportProperty(
  80315. ol.control.ZoomSlider.prototype,
  80316. 'on',
  80317. ol.control.ZoomSlider.prototype.on);
  80318. goog.exportProperty(
  80319. ol.control.ZoomSlider.prototype,
  80320. 'once',
  80321. ol.control.ZoomSlider.prototype.once);
  80322. goog.exportProperty(
  80323. ol.control.ZoomSlider.prototype,
  80324. 'un',
  80325. ol.control.ZoomSlider.prototype.un);
  80326. goog.exportProperty(
  80327. ol.control.ZoomToExtent.prototype,
  80328. 'getMap',
  80329. ol.control.ZoomToExtent.prototype.getMap);
  80330. goog.exportProperty(
  80331. ol.control.ZoomToExtent.prototype,
  80332. 'setMap',
  80333. ol.control.ZoomToExtent.prototype.setMap);
  80334. goog.exportProperty(
  80335. ol.control.ZoomToExtent.prototype,
  80336. 'setTarget',
  80337. ol.control.ZoomToExtent.prototype.setTarget);
  80338. goog.exportProperty(
  80339. ol.control.ZoomToExtent.prototype,
  80340. 'get',
  80341. ol.control.ZoomToExtent.prototype.get);
  80342. goog.exportProperty(
  80343. ol.control.ZoomToExtent.prototype,
  80344. 'getKeys',
  80345. ol.control.ZoomToExtent.prototype.getKeys);
  80346. goog.exportProperty(
  80347. ol.control.ZoomToExtent.prototype,
  80348. 'getProperties',
  80349. ol.control.ZoomToExtent.prototype.getProperties);
  80350. goog.exportProperty(
  80351. ol.control.ZoomToExtent.prototype,
  80352. 'set',
  80353. ol.control.ZoomToExtent.prototype.set);
  80354. goog.exportProperty(
  80355. ol.control.ZoomToExtent.prototype,
  80356. 'setProperties',
  80357. ol.control.ZoomToExtent.prototype.setProperties);
  80358. goog.exportProperty(
  80359. ol.control.ZoomToExtent.prototype,
  80360. 'unset',
  80361. ol.control.ZoomToExtent.prototype.unset);
  80362. goog.exportProperty(
  80363. ol.control.ZoomToExtent.prototype,
  80364. 'changed',
  80365. ol.control.ZoomToExtent.prototype.changed);
  80366. goog.exportProperty(
  80367. ol.control.ZoomToExtent.prototype,
  80368. 'dispatchEvent',
  80369. ol.control.ZoomToExtent.prototype.dispatchEvent);
  80370. goog.exportProperty(
  80371. ol.control.ZoomToExtent.prototype,
  80372. 'getRevision',
  80373. ol.control.ZoomToExtent.prototype.getRevision);
  80374. goog.exportProperty(
  80375. ol.control.ZoomToExtent.prototype,
  80376. 'on',
  80377. ol.control.ZoomToExtent.prototype.on);
  80378. goog.exportProperty(
  80379. ol.control.ZoomToExtent.prototype,
  80380. 'once',
  80381. ol.control.ZoomToExtent.prototype.once);
  80382. goog.exportProperty(
  80383. ol.control.ZoomToExtent.prototype,
  80384. 'un',
  80385. ol.control.ZoomToExtent.prototype.un);
  80386. ol.VERSION = 'v4.3.3';
  80387. OPENLAYERS.ol = ol;
  80388. return OPENLAYERS.ol;
  80389. }));