1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334 |
- /**
- * Cesium - https://github.com/AnalyticalGraphicsInc/cesium
- *
- * Copyright 2011-2017 Cesium Contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Columbus View (Pat. Pend.)
- *
- * Portions licensed separately.
- * See https://github.com/AnalyticalGraphicsInc/cesium/blob/master/LICENSE.md for full licensing details.
- */
- define(['./when-8d13db60', './Check-70bec281', './Math-61ede240', './FeatureDetection-7bd32c34', './createTaskProcessorWorker', './Color-69f1845f', './pbf-9fe59c76'], function (when, Check, _Math, FeatureDetection, createTaskProcessorWorker, Color, pbf) { 'use strict';
- // 用来根据Mapbox style标准构建过滤器和定义过滤方法
- function MvtFilter() {
- }
- /**
- * 根据根据Mapbox style的过滤器对象构造过滤条件
- * @param filter 输入过滤器
- * @returns 返回过滤条件数组
- */
- MvtFilter.parseLayerFilter = function(filter) {
- if (!when.defined(filter) || !(filter instanceof Array)) {
- return null;
- }
- var filterArray = [];
- var condition;
- if (isOperator(filter[0])) {
- condition = parseSingleFilterArray(filter);
- if(when.defined(condition)){
- filterArray.push(condition);
- }
- }
- else{
- for (var fi = 0; fi < filter.length; fi++) {
- if (!(filter[fi] instanceof Array)) {
- continue;
- }
- if (filter[fi].length !== 3) {
- for (var fj = 0; fj < filter[fi].length; fj++) {
- if (filter[fi][fj] instanceof Array && filter[fi][fj].length === 3) {
- condition = parseSingleFilterArray(filter[fi][fj]);
- if(when.defined(condition)){
- filterArray.push(condition);
- }
- }
- }
- } else {
- condition = parseSingleFilterArray(filter[fi]);
- if(when.defined(condition)){
- filterArray.push(condition);
- }
- }
- }
- }
- return filterArray;
- };
- /**
- * 根据对象的属性进行过滤条件测试
- * @param filterArray 过滤条件数组
- * @param properties 对象属性
- * @returns 通过过滤条件返回true
- */
- MvtFilter.filterTest = function(properties, filterArray) {
- for(var filterIdx = 0, filterCount = filterArray.length; filterIdx < filterCount; filterIdx++){
- var filter = filterArray[filterIdx];
- if(!compareFunctions[filter.filterOperator](properties, filter.filterFieldName, filter.filterCompareValue)){
- return false;
- }
- }
- return true;
- };
- function parseSingleFilterArray(filterArray){
- var filterCompareValue = null;
- var filterFieldName = null;
- var filterOperator = null;
- if (isOperator(filterArray[0])) {
- filterOperator = filterArray[0];
- }
- else{
- return null;
- }
- if(filterArray.length > 1){
- filterFieldName = filterArray[1];
- // TODO: 系统字段暂不处理
- if(filterFieldName[0] === "$" ){
- return null;
- }
- }
- if(filterArray.length > 2){
- filterCompareValue = filterArray[2];
- }
- return {
- filterOperator : filterOperator,
- filterFieldName : filterFieldName,
- filterCompareValue : filterCompareValue
- };
- }
- function isOperator(key) {
- return ["==", "===", ">=", "<=", ">", "<", "!=", "has"].indexOf(key) !== -1;
- }
- function equalFunction(properties, fieldName, testValue){
- return properties[fieldName] == testValue;
- }
- function greaterFunction(properties, fieldName, testValue){
- return properties[fieldName] > testValue;
- }
- function lessFunction(properties, fieldName, testValue){
- return properties[fieldName] < testValue;
- }
- function greaterEqualFunction(properties, fieldName, testValue){
- return properties[fieldName] >= testValue;
- }
- function lessEqualFunction(properties, fieldName, testValue){
- return properties[fieldName] <= testValue;
- }
- function notEqualFunction(properties, fieldName, testValue){
- return properties[fieldName] != testValue;
- }
- function hasFunction(properties, fieldName){
- return when.defined(properties[fieldName]);
- }
- var compareFunctions = {
- "==" : equalFunction,
- "===" : equalFunction,
- ">" : greaterFunction,
- "<" : lessFunction,
- ">=" : greaterEqualFunction,
- "<=" : lessEqualFunction,
- "!=" : notEqualFunction,
- "has" : hasFunction
- };
- function MvtStyle(openlayer, useOffscreen) {
- if(!openlayer){
- throw new Check.DeveloperError('need include ol-debug.js');
- }
- this._useOffscreen = useOffscreen;
- this._openlayer = openlayer;
- }
- Object.defineProperties(MvtStyle.prototype, {
- proxy: {
- get: function() {}
- }
- });
- MvtStyle.prototype.getStyle = function() {
- var openlayer = this._openlayer;
- var fill = new openlayer.style.Fill({
- color: ""
- });
- fill.setColor("#ffffff");
- var stroke = new openlayer.style.Stroke({
- color: "",
- width: 1
- });
- stroke.setWidth(1);
- stroke.setColor("#000000");
- var fillAndOutlineStyle = new openlayer.style.Style({
- fill: fill,
- stroke: stroke
- });
- return fillAndOutlineStyle;
- };
- function parseMapboxColorString(colorString){
- var tempS = colorString.substring(colorString.indexOf("(") + 1, colorString.indexOf(")"));
- tempS = tempS.split(",");
- var resultColor = [];
- resultColor.push(parseFloat(tempS[0]));
- resultColor.push(parseFloat(tempS[1]));
- resultColor.push(parseFloat(tempS[2]));
- resultColor.push(parseFloat(tempS[3]));
- return resultColor;
- }
- function colorWithOpacity(color, opacity) {
- if (color && opacity !== undefined) {
- var colorData = {
- color: [
- color[0] * 255 / color[3],
- color[1] * 255 / color[3],
- color[2] * 255 / color[3],
- color[3]
- ],
- opacity: color[3]
- };
- color = colorData.color;
- color[3] = colorData.opacity * opacity;
- if (color[3] === 0) {
- color = undefined;
- }
- }
- return color;
- }
- MvtStyle.prototype.getStyleByMapboxStyle = function(mapboxStyle) {
- var openlayer = this._openlayer;
- var type = mapboxStyle.type;
- var paint = mapboxStyle.paint;
- var layout = mapboxStyle.layout;
- if(!when.defined(type) || !when.defined(paint)){
- return this.getStyle();
- }
- if(type == "fill"){
- var fillStyle = new openlayer.style.Style({
- });
- var fill = new openlayer.style.Fill({
- color: "[255,255,255,1]"
- });
- fillStyle.setFill(fill);
- var fillOpcatiy = paint["fill-opacity"];
- if (when.defined(paint["fill-color"])) {
- var fillColor = parseMapboxColorString(paint["fill-color"]);
- if(when.defined(fillOpcatiy)){
- fillColor[3] *= fillOpcatiy;
- }
- fill.setColor(fillColor);
- }
- if (when.defined(paint["fill-outline-color"])) {
- var fillOutlineStroke = new openlayer.style.Stroke({
- color: "",
- width: 1
- });
- fillOutlineStroke.setColor(paint["fill-outline-color"]);
- fillStyle.setStroke(fillOutlineStroke);
- }
- if (when.defined(paint["fill-pattern"])) {
- fillStyle.fillPatternName = paint["fill-pattern"];
- }
- return fillStyle;
- }
- else if(type == "line"){
- var lineStyle = new openlayer.style.Style({
- });
- var lineStroke = new openlayer.style.Stroke({
- color: "#000000",
- width: 1
- });
- lineStyle.setStroke(lineStroke);
- var lineOpcatiy = paint["line-opacity"];
- if (when.defined(paint["line-color"])) {
- var lineColor = parseMapboxColorString(paint["line-color"]);
- if(when.defined(lineOpcatiy)){
- lineColor[3] *= lineOpcatiy;
- }
- }
- if (when.defined(paint["line-width"])) {
- var lineWidth = paint["line-width"];
- lineStroke.setWidth(lineWidth);
- }
- if (when.defined(paint["line-dasharray"])) {
- var lineDasharray = paint["line-dasharray"];
- lineStroke.setLineDash(lineDasharray);
- }
- if(when.defined(layout)){
- if (when.defined(layout["line-cap"])) {
- var lineCap = layout["line-cap"];
- lineStroke.setLineCap(lineCap);
- }
- if (when.defined(layout["line-join"])) {
- var lineJoin = layout["line-join"];
- lineStroke.setLineJoin(lineJoin);
- }
- if (when.defined(layout["line-miter-limit"])) {
- var lineMiterLimit = layout["line-miter-limit"];
- lineStroke.setMiterLimit(lineMiterLimit);
- }
- }
- lineStroke.setColor(lineColor);
- return lineStyle;
- }
- else if(type == "symbol"){
- var iconStyle = new openlayer.style.Style({
- });
- if(when.defined(layout) && when.defined(layout["icon-image"])){
- iconStyle.hasIconImage = true;
- }
- if(when.defined(layout) && when.defined(layout["text-field"])){
- iconStyle.hasTextStyle = true;
- }
- return iconStyle;
- }
- else if(type == "circle"){
- var circleRadius = paint["circle-radius"];
- var circleColor = paint["circle-color"];
- var circleStrokeColor = paint["circle-stroke-color"];
- var circleOpacity = paint["circle-opacity"];
- var circleStrokeOpacity = paint["circle-stroke-opacity"];
- var circleStrokeWidth = paint["circle-stroke-width"];
- var iconImg = new openlayer.style.Circle({
- radius: circleRadius,
- stroke: circleStrokeWidth === 0 ? undefined : new openlayer.style.Stroke({
- width: circleStrokeWidth,
- color: colorWithOpacity(circleStrokeColor, circleStrokeOpacity)
- }),
- fill: new openlayer.style.Fill({
- color: colorWithOpacity(circleColor, circleOpacity)
- })
- });
- var circleStyle = new openlayer.style.Style({
- });
- circleStyle.setImage(iconImg);
- return circleStyle;
- }
- else{
- return this.getStyle();
- }
- };
- var scratchIDColor = new Color.Color();
- function convertIDtoColor(id, layerID){
- var colorB = Math.floor(id / 65536);
- var d = id - colorB * 65536;
- var colorG = Math.floor(d / 256);
- var colorR = d - colorG * 256;
- var alpha = 1;
- scratchIDColor.red = colorR / 256;
- scratchIDColor.green = colorG / 256;
- scratchIDColor.blue = colorB / 256;
- scratchIDColor.alpha = alpha;
- return scratchIDColor;
- }
- MvtStyle.prototype.getIDColorStyle = function(geometryType, id, layerID, lineWidth, radius, lineWidthExpand) {
- var openlayer = this._openlayer;
- var idColor = convertIDtoColor(id);
- var cssColor = idColor.toCssColorString();
- if(geometryType == 'LineString' || geometryType == 'LinearRing' || geometryType == 'MultiLineString'){
- var expandWidth = 4;
- if (when.defined(lineWidth)) {
- expandWidth = lineWidth * 2 + lineWidthExpand;
- }
- var scratchIDStroke = new openlayer.style.Stroke({
- color: "",
- width: expandWidth
- });
- scratchIDStroke.setColor(cssColor);
- return new openlayer.style.Style({
- stroke: scratchIDStroke
- });
- }
- else if(geometryType == 'Point' || geometryType == 'MultiPoint'){
- var iconImg = new openlayer.style.Circle({
- radius: (radius - 0.5),
- fill: new openlayer.style.Fill({
- color: cssColor
- })
- });
- var circleStyle = new openlayer.style.Style({
- });
- circleStyle.setImage(iconImg);
- return circleStyle;
- }
- else{
- var scratchIDFill = new openlayer.style.Fill({
- color: ""
- });
- scratchIDFill.setColor(cssColor);
- var resultStyle = new openlayer.style.Style({
- fill: scratchIDFill
- });
- if(when.defined(lineWidth)){
- var scratchIDStroke = new openlayer.style.Stroke({
- color: "",
- width: when.defined(lineWidth) ? lineWidth * 2 : 4
- });
- scratchIDStroke.setColor(cssColor);
- resultStyle.setStroke(scratchIDStroke);
- }
- return resultStyle;
- }
- };
- var templateRegEx = /^([^]*)\{(.*)\}([^]*)$/;
- function fromTemplate(text, properties) {
- var parts;
- do {
- parts = text.match(templateRegEx);
- if (parts) {
- const value = properties[parts[2]] || '';
- text = parts[1] + value + parts[3];
- }
- } while (parts);
- return text;
- }
- MvtStyle.prototype.getTextStyle = function(oldStyle, feature, mapboxStyleLayer) {
- var openlayer = this._openlayer;
- var paint = mapboxStyleLayer.paint;
- var layout = mapboxStyleLayer.layout;
- var textField = layout['text-field'];
- var label = fromTemplate(textField, feature.getProperties());
- if(!when.defined(label)){
- return;
- }
- var style = new openlayer.style.Style();
- var text = new openlayer.style.Text();
- style.setText(text);
- var textSize = layout['text-size'];
- var font = when.defaultValue(layout['text-font'], ['Open Sans Regular', 'Arial Unicode MS Regular']);
- var textTransform = layout['text-transform'];
- if (textTransform == 'uppercase') {
- label = label.toUpperCase();
- } else if (textTransform == 'lowercase') {
- label = label.toLowerCase();
- }
- var textMaxWidth = when.defaultValue(layout['text-max-width'], 10);
- //var wrappedLabel = wrapText(label, font, textMaxWidth);
- var wrappedLabel = label;
- text.setText(wrappedLabel);
- text.setFont(font);
- text.setRotation(0);
- var textAnchor = when.defaultValue(layout['text-anchor'], 'center');
- var placement = when.defaultValue(layout['symbol-placement'], 'point');
- text.setPlacement(placement);
- if (placement == 'point') {
- var textAlign = 'center';
- if (textAnchor.indexOf('left') !== -1) {
- textAlign = 'left';
- } else if (textAnchor.indexOf('right') !== -1) {
- textAlign = 'right';
- }
- text.setTextAlign(textAlign);
- } else {
- text.setTextAlign();
- }
- var textBaseline = 'middle';
- if (textAnchor.indexOf('bottom') == 0) {
- textBaseline = 'bottom';
- } else if (textAnchor.indexOf('top') == 0) {
- textBaseline = 'top';
- }
- text.setTextBaseline(textBaseline);
- var textOffset = when.defaultValue(layout['text-offset'], [0.0, 0.0]);
- var textTranslate = when.defaultValue(layout['text-translate'], [0.0, 0.0]);
- text.setOffsetX(textOffset[0] * textSize + textTranslate[0]);
- text.setOffsetY(textOffset[1] * textSize + textTranslate[1]);
- var opacity = paint['text-opacity'];
- var textColorFill = new openlayer.style.Fill();
- var textColor = paint["text-color"];
- if(when.defined(textColor)){
- textColor = parseMapboxColorString(textColor);
- textColorFill.setColor(textColor);
- }
- text.setFill(textColorFill);
- var textHaloColor = paint["text-halo-color"];
- if (when.defined(textHaloColor)) {
- var textHalo = new openlayer.style.Stroke();
- textHaloColor = parseMapboxColorString(textHaloColor);
- textHalo.setColor(textHaloColor);
- textHalo.setWidth(paint['text-halo-width']);
- text.setStroke(textHalo);
- } else {
- text.setStroke(undefined);
- }
- style.setZIndex(oldStyle.getZIndex());
- style.hasIconImage = oldStyle.hasIconImage;
- style.textSize = textSize;
- return style;
- };
- function covertIconAnchor(iconAnchor) {
- var anchorOffset = [0.5, 0.5];
- if (['top-left', 'top-right', 'bottom-left', 'bottom-right'].includes(iconAnchor)) {
- anchorOffset = [0, 0];
- }
- if (iconAnchor === 'left') {
- iconAnchor = 'top-left';
- anchorOffset = [0, 0.5];
- }
- if (iconAnchor === 'right') {
- iconAnchor = 'top-left';
- anchorOffset = [1, 0.5];
- }
- if (iconAnchor === 'bottom') {
- iconAnchor = 'top-left';
- anchorOffset = [0.5, 1];
- }
- if (iconAnchor === 'top') {
- iconAnchor = 'top-left';
- anchorOffset = [0.5, 0];
- }
- return {
- anchorOffset: anchorOffset,
- iconAnchor: iconAnchor
- };
- }
- var iconImageCache = {};
- MvtStyle.prototype.setIconImageForStyle = function(spriteImageDatas, style, mapboxStyleLayer){
- var openlayer = this._openlayer;
- var paint = mapboxStyleLayer.paint;
- var layout = mapboxStyleLayer.layout;
- var iconSize = when.defaultValue(layout["icon-size"], 1);
- var iconColor = paint['icon-color'];
- var iconTranslate = when.defaultValue(paint['icon-translate'], [0.0, 0.0]);
- var iconTranslateAnchor = when.defaultValue(paint['icon-translate-anchor'], 'map');
- var iconAnchor = when.defaultValue(layout['icon-anchor'], 'center');
- var anchorOffsetAndIconAnchor = covertIconAnchor(iconAnchor);
- var anchorOffset = anchorOffsetAndIconAnchor.anchorOffset;
- var iconOffset = when.defaultValue(layout['iconoffset'], [0.0, 0.0]);
- var iconOpacity = when.defaultValue(layout['icon-opacity'], 1.0);
- var spriteImageName = layout["icon-image"];
- if(!when.defined(spriteImageDatas[spriteImageName])){
- console.log('miss icon-image ' + spriteImageName);
- return;
- }
- var icon_cache_key = spriteImageName + '.' + iconSize + '.' + iconTranslate + '.' + iconTranslateAnchor + '.' + iconAnchor + '.' + iconOffset;
- if (when.defined(iconColor)) {
- icon_cache_key += '.' + iconColor;
- }
- var iconImg = iconImageCache[icon_cache_key];
- if(!when.defined(iconImg)){
- var spriteImage = spriteImageDatas[spriteImageName];
- var canvas;
- if(this._useOffscreen){
- canvas = new OffscreenCanvas(spriteImage.width, spriteImage.height);
- }
- else{
- canvas = document.createElement('canvas');
- canvas.width = spriteImage.width;
- canvas.height = spriteImage.height;
- }
- var ctx = canvas.getContext('2d');
- ctx.putImageData(spriteImage, 0, 0);
- var translateOffset = [iconTranslate[0] / spriteImage.width, iconTranslate[1] / spriteImage.height];
- iconImg = new openlayer.style.Icon({
- img: canvas,
- anchorOrigin: anchorOffsetAndIconAnchor.iconAnchor,
- anchor: [iconOffset[0] + anchorOffset[0] + translateOffset[0], iconOffset[1] + anchorOffset[1] - translateOffset[1]],
- imgSize: [canvas.width, canvas.height],
- scale: iconSize
- });
- iconImg.setOpacity(iconOpacity);
- iconImageCache[icon_cache_key] = iconImg;
- }
- style.setImage(iconImg);
- //style.setText(undefined);
- };
- var VALUE_EXTENT = 4096;
- var replays = ["Default", "Polygon", "LineString", "Image", "Symbol", "Text"];
- function MvtRenderer2D(options) {
- this._mvtStyleClass = options.mvtStyle;
- this._openlayer = options.openlayer;
- }
- Object.defineProperties(MvtRenderer2D.prototype, {
- });
- MvtRenderer2D.prototype.renderFeatures = function(options) {
- var canvas = options.colorCanvas;
- var idCanvas = options.idCanvas;
- var transform = options.transform;
- var layers = options.layers;
- var features = options.features;
- var tileLevel = options.tileLevel;
- var spriteImageCanvas = options.spriteImageCanvas;
- var spriteImageDatas = options.spriteImageDatas;
- var squaredTolerance = options.squaredTolerance;
- var showBillboard = options.showBillboard;
- var renderID = options.renderID;
- var renderColor = options.renderColor;
- var lineWidthExpand = options.lineWidthExpand;
- var ol = this._openlayer;
- var ctx = canvas.getContext('2d');
- var idFeatures = [];
- var iconImageObjects = [];
- var textObjects = [];
- var style = null;
- var declutterTree = ol.ext.rbush(9);
- var replayGroup = new ol.render.canvas.ReplayGroup(0, [0, 0, VALUE_EXTENT, VALUE_EXTENT], 8, 2, true, declutterTree);
- var featureLength = features.length;
- for (var r = 0; r < featureLength; r++) {
- var feature = features[r];
- var sourceLayer = feature.getProperties().layer;
- feature.index = sourceLayer + feature.getId();
- var featureHasStyle = false;
- var layerGroupById = layers[sourceLayer];
- var zIndex = 0;
- for (var layerId in layerGroupById) {
- var layerById = layerGroupById[layerId];
- var maxzoom = layerById.mapboxStyleLayer.maxzoom;
- var minzoom = layerById.mapboxStyleLayer.minzoom;
- if(tileLevel < minzoom || tileLevel > maxzoom){
- continue;
- }
- var filterArray = layerById.filterArray;
- if (!when.defined(filterArray)) {
- style = this._mvtStyleClass.getStyleByMapboxStyle(layerById.mapboxStyleLayer);
- }
- else {
- var properties = feature.getProperties();
- if (MvtFilter.filterTest(properties, filterArray)) {
- style = this._mvtStyleClass.getStyleByMapboxStyle(layerById.mapboxStyleLayer);
- }
- else {
- continue;
- }
- }
- if (!when.defined(style)) {
- continue;
- }
- this.createFillPatternForStyle(style, spriteImageCanvas, spriteImageDatas, ctx);
- if (when.defined(style.hasTextStyle)) {
- var textStyle = this._mvtStyleClass.getTextStyle(style, feature, layerById.mapboxStyleLayer);
- textStyle.setZIndex(zIndex);
- if(showBillboard){
- textObjects.push({
- feature : feature,
- style : textStyle
- });
- }
- else{
- if(renderColor){
- ol.renderer.vector.renderFeature_(replayGroup, feature, textStyle, -1);
- }
- }
- }
- if (when.defined(style.hasIconImage) && !when.defined(style.getImage())) {
- if(showBillboard){
- iconImageObjects.push({
- feature : feature,
- style : layerById.mapboxStyleLayer
- });
- continue;
- }
- else{
- this._mvtStyleClass.setIconImageForStyle(spriteImageDatas, style, layerById.mapboxStyleLayer);
- }
- }
- style.setZIndex(zIndex);
- this.setPickStyleInFeature(feature, style);
- zIndex++;
- if(renderColor){
- ol.renderer.vector.renderFeature_(replayGroup, feature, style, -1);
- }
- featureHasStyle = true;
- }
- if (featureHasStyle) {
- idFeatures.push(feature);
- }
- }
- if(renderColor){
- replayGroup.finish();
- var declutterReplays = {};
- replayGroup.replay(ctx, transform, 0, {}, replays, declutterReplays);
- if (declutterReplays) {
- ol.render.canvas.ReplayGroup.replayDeclutter(declutterReplays, ctx, 0.0);
- }
- }
- replayGroup = null;
- if(renderID){
- this.renderIDtoTexture(transform, idCanvas, idFeatures, 0, squaredTolerance, lineWidthExpand);
- }
- return {
- idFeatures : idFeatures,
- iconImageObjects : iconImageObjects,
- textObjects : textObjects
- }
- };
- MvtRenderer2D.prototype.renderIDtoTexture = function(transform, canvas, features, layerID, tileTolerance, lineWidthExpand) {
- var ol = this._openlayer;
- var ctx = canvas.getContext('2d');
- var declutterTree = ol.ext.rbush(9);
- var replayGroup = new ol.render.canvas.ReplayGroup(0, [0, 0, VALUE_EXTENT, VALUE_EXTENT], 8, 2, true, declutterTree);
- var featureLength = features.length;
- for (var r = 0; r < featureLength; r++) {
- var feature = features[r];
- var id = getFeatureID(feature);
- var idStyle = this._mvtStyleClass.getIDColorStyle(feature.getGeometry().getType(), id, layerID, feature.lineWidth, feature.radius, lineWidthExpand);
- idStyle.setZIndex(feature.zIndex);
- ol.renderer.vector.renderFeature_(replayGroup, feature, idStyle, -1);
- }
- replayGroup.finish();
- var declutterReplays = {};
- replayGroup.replay(ctx, transform, 0, {}, replays, declutterReplays);
- if (declutterReplays) {
- ol.render.canvas.ReplayGroup.replayDeclutter(declutterReplays, ctx, 0.0);
- }
- replayGroup = null;
- };
- MvtRenderer2D.prototype.createFillPatternForStyle = function(style, spriteImageCanvas, subSpriteImage, ctx){
- if(!when.defined(style.fillPatternName)){
- return;
- }
- var patternName = style.fillPatternName;
- var patternCanvas = null;
- if (when.defined(spriteImageCanvas[patternName])) {
- patternCanvas = spriteImageCanvas[patternName];
- }
- else {
- var imageData = subSpriteImage[patternName];
- if (!when.defined(imageData)) {
- console.log('miss sprite ' + patternName);
- return;
- }
- patternCanvas = document.createElement('canvas');
- patternCanvas.width = imageData.width;
- patternCanvas.height = imageData.height;
- var spriteCtx = patternCanvas.getContext('2d');
- spriteCtx.putImageData(imageData, 0, 0);
- spriteImageCanvas[patternName] = patternCanvas;
- }
- style.fill_.color_ = ctx.createPattern(patternCanvas, 'repeat');
- };
- MvtRenderer2D.prototype.setPickStyleInFeature = function(feature, style){
- var ol = this._openlayer;
- feature.zIndex = style.getZIndex();
- if(when.defined(style.getStroke())){
- var styleLineWidth = style.getStroke().getWidth();
- if(when.defined(feature.lineWidth)){
- feature.lineWidth = Math.max(feature.lineWidth, styleLineWidth);
- }
- else{
- feature.lineWidth = styleLineWidth;
- }
- }
- if(when.defined(style.getImage())){
- var imageStyle = style.getImage();
- var radius = 1.0;
- if(imageStyle instanceof ol.style.Icon ){
- var imageSize = imageStyle.getImageSize();
- radius = Math.max(imageSize[0], imageSize[1]) / 2.0;
- radius -= 1.0;
- }
- else if(imageStyle instanceof ol.style.Circle ){
- radius = imageStyle.getRadius();
- }
- if(when.defined(feature.radius)){
- feature.radius = Math.max(feature.radius, radius);
- }
- else{
- feature.radius = radius;
- }
- }
- };
- function getFeatureID(feature) {
- var id = feature.getId();
- // 只在颜色中记录256*256*256这么大范围的ID,超过这个范围的ID舍去
- var discard = Math.floor(id / 16777216);
- id = id - discard * 16777216;
- return id;
- }
- function ol() {
- }
- ol.array = {};
- /**
- * 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.
- * https://github.com/darkskyapp/binary-search
- *
- * @param {Array.<*>} haystack Items to search through.
- * @param {*} needle The item to look for.
- * @param {Function=} opt_comparator Comparator function.
- * @return {number} The index of the item if found, -1 if not.
- */
- ol.array.binarySearch = function(haystack, needle, opt_comparator) {
- var mid, cmp;
- var comparator = opt_comparator || ol.array.numberSafeCompareFunction;
- var low = 0;
- var high = haystack.length;
- var found = false;
- while (low < high) {
- /* Note that "(low + high) >>> 1" may overflow, and results in a typecast
- * to double (which gives the wrong results). */
- mid = low + (high - low >> 1);
- cmp = +comparator(haystack[mid], needle);
- if (cmp < 0.0) { /* Too low. */
- low = mid + 1;
- } else { /* Key found or too high */
- high = mid;
- found = !cmp;
- }
- }
- /* Key not found. */
- return found ? low : ~low;
- };
- /**
- * Compare function for array sort that is safe for numbers.
- * @param {*} a The first object to be compared.
- * @param {*} b The second object to be compared.
- * @return {number} A negative number, zero, or a positive number as the first
- * argument is less than, equal to, or greater than the second.
- */
- ol.array.numberSafeCompareFunction = function(a, b) {
- return a > b ? 1 : a < b ? -1 : 0;
- };
- /**
- * Whether the array contains the given object.
- * @param {Array.<*>} arr The array to test for the presence of the element.
- * @param {*} obj The object for which to test.
- * @return {boolean} The object is in the array.
- */
- ol.array.includes = function(arr, obj) {
- return arr.indexOf(obj) >= 0;
- };
- /**
- * @param {Array.<number>} arr Array.
- * @param {number} target Target.
- * @param {number} direction 0 means return the nearest, > 0
- * means return the largest nearest, < 0 means return the
- * smallest nearest.
- * @return {number} Index.
- */
- ol.array.linearFindNearest = function(arr, target, direction) {
- var n = arr.length;
- if (arr[0] <= target) {
- return 0;
- } else if (target <= arr[n - 1]) {
- return n - 1;
- } else {
- var i;
- if (direction > 0) {
- for (i = 1; i < n; ++i) {
- if (arr[i] < target) {
- return i - 1;
- }
- }
- } else if (direction < 0) {
- for (i = 1; i < n; ++i) {
- if (arr[i] <= target) {
- return i;
- }
- }
- } else {
- for (i = 1; i < n; ++i) {
- if (arr[i] == target) {
- return i;
- } else if (arr[i] < target) {
- if (arr[i - 1] - target < target - arr[i]) {
- return i - 1;
- } else {
- return i;
- }
- }
- }
- }
- return n - 1;
- }
- };
- /**
- * @param {Array.<*>} arr Array.
- * @param {number} begin Begin index.
- * @param {number} end End index.
- */
- ol.array.reverseSubArray = function(arr, begin, end) {
- while (begin < end) {
- var tmp = arr[begin];
- arr[begin] = arr[end];
- arr[end] = tmp;
- ++begin;
- --end;
- }
- };
- /**
- * @param {Array.<VALUE>} arr The array to modify.
- * @param {Array.<VALUE>|VALUE} data The elements or arrays of elements
- * to add to arr.
- * @template VALUE
- */
- ol.array.extend = function(arr, data) {
- var i;
- var extension = Array.isArray(data) ? data : [data];
- var length = extension.length;
- for (i = 0; i < length; i++) {
- arr[arr.length] = extension[i];
- }
- };
- /**
- * @param {Array.<VALUE>} arr The array to modify.
- * @param {VALUE} obj The element to remove.
- * @template VALUE
- * @return {boolean} If the element was removed.
- */
- ol.array.remove = function(arr, obj) {
- var i = arr.indexOf(obj);
- var found = i > -1;
- if (found) {
- arr.splice(i, 1);
- }
- return found;
- };
- /**
- * @param {Array.<VALUE>} arr The array to search in.
- * @param {function(VALUE, number, ?) : boolean} func The function to compare.
- * @template VALUE
- * @return {VALUE} The element found.
- */
- ol.array.find = function(arr, func) {
- var length = arr.length >>> 0;
- var value;
- for (var i = 0; i < length; i++) {
- value = arr[i];
- if (func(value, i, arr)) {
- return value;
- }
- }
- return null;
- };
- /**
- * @param {Array|Uint8ClampedArray} arr1 The first array to compare.
- * @param {Array|Uint8ClampedArray} arr2 The second array to compare.
- * @return {boolean} Whether the two arrays are equal.
- */
- ol.array.equals = function(arr1, arr2) {
- var len1 = arr1.length;
- if (len1 !== arr2.length) {
- return false;
- }
- for (var i = 0; i < len1; i++) {
- if (arr1[i] !== arr2[i]) {
- return false;
- }
- }
- return true;
- };
- /**
- * @param {Array.<*>} arr The array to sort (modifies original).
- * @param {Function} compareFnc Comparison function.
- */
- ol.array.stableSort = function(arr, compareFnc) {
- var length = arr.length;
- var tmp = Array(arr.length);
- var i;
- for (i = 0; i < length; i++) {
- tmp[i] = {index: i, value: arr[i]};
- }
- tmp.sort(function(a, b) {
- return compareFnc(a.value, b.value) || a.index - b.index;
- });
- for (i = 0; i < arr.length; i++) {
- arr[i] = tmp[i].value;
- }
- };
- /**
- * @param {Array.<*>} arr The array to search in.
- * @param {Function} func Comparison function.
- * @return {number} Return index.
- */
- ol.array.findIndex = function(arr, func) {
- var index;
- var found = !arr.every(function(el, idx) {
- index = idx;
- return !func(el, idx, arr);
- });
- return found ? index : -1;
- };
- /**
- * @param {Array.<*>} arr The array to test.
- * @param {Function=} opt_func Comparison function.
- * @param {boolean=} opt_strict Strictly sorted (default false).
- * @return {boolean} Return index.
- */
- ol.array.isSorted = function(arr, opt_func, opt_strict) {
- var compare = opt_func || ol.array.numberSafeCompareFunction;
- return arr.every(function(currentVal, index) {
- if (index === 0) {
- return true;
- }
- var res = compare(arr[index - 1], currentVal);
- return !(res > 0 || opt_strict && res === 0);
- });
- };
- ol.ASSUME_TOUCH = false;
- ol.DEFAULT_MAX_ZOOM = 42;
- ol.DEFAULT_MIN_ZOOM = 0;
- ol.DEFAULT_RASTER_REPROJECTION_ERROR_THRESHOLD = 0.5;
- ol.DEFAULT_TILE_SIZE = 256;
- ol.DEFAULT_WMS_VERSION = '1.3.0';
- ol.ENABLE_CANVAS = true;
- ol.ENABLE_PROJ4JS = true;
- ol.ENABLE_RASTER_REPROJECTION = true;
- ol.ENABLE_WEBGL = true;
- ol.DEBUG_WEBGL = true;
- ol.INITIAL_ATLAS_SIZE = 256;
- ol.MAX_ATLAS_SIZE = -1;
- ol.MOUSEWHEELZOOM_MAXDELTA = 1;
- ol.OVERVIEWMAP_MAX_RATIO = 0.75;
- ol.OVERVIEWMAP_MIN_RATIO = 0.1;
- ol.RASTER_REPROJECTION_MAX_SOURCE_TILES = 100;
- ol.RASTER_REPROJECTION_MAX_SUBDIVISION = 10;
- ol.RASTER_REPROJECTION_MAX_TRIANGLE_WIDTH = 0.25;
- ol.SIMPLIFY_TOLERANCE = 0.5;
- ol.WEBGL_TEXTURE_CACHE_HIGH_WATER_MARK = 1024;
- ol.VERSION = '';
- ol.inherits = function(childCtor, parentCtor) {
- childCtor.prototype = Object.create(parentCtor.prototype);
- childCtor.prototype.constructor = childCtor;
- };
- ol.nullFunction = function() {};
- ol.getUid = function(obj) {
- return obj.ol_uid ||
- (obj.ol_uid = ++ol.uidCounter_);
- };
- ol.asserts = {};
- ol.asserts.assert = function(assertion, errorCode) {
- };
- ol.has = {};
- var ua = typeof navigator !== 'undefined' ?
- navigator.userAgent.toLowerCase() : '';
- ol.has.FIREFOX = ua.indexOf('firefox') !== -1;
- ol.has.SAFARI = ua.indexOf('safari') !== -1 && ua.indexOf('chrom') == -1;
- ol.has.WEBKIT = ua.indexOf('webkit') !== -1 && ua.indexOf('edge') == -1;
- ol.has.MAC = ua.indexOf('macintosh') !== -1;
- ol.has.DEVICE_PIXEL_RATIO = 1;
- ol.has.CANVAS_LINE_DASH = true;
- ol.structs = {};
- /**
- * @enum {string}
- */
- ol.CollectionEventType = {
- ADD: 'add',
- REMOVE: 'remove'
- };
- /**
- * @enum {string}
- */
- ol.ObjectEventType = {
- PROPERTYCHANGE: 'propertychange'
- };
- ol.events = {};
- /**
- * @param {ol.EventsKey} listenerObj Listener object.
- * @return {ol.EventsListenerFunctionType} Bound listener.
- */
- ol.events.bindListener_ = function(listenerObj) {
- var boundListener = function(evt) {
- var listener = listenerObj.listener;
- var bindTo = listenerObj.bindTo || listenerObj.target;
- if (listenerObj.callOnce) {
- ol.events.unlistenByKey(listenerObj);
- }
- return listener.call(bindTo, evt);
- };
- listenerObj.boundListener = boundListener;
- return boundListener;
- };
- ol.events.findListener_ = function(listeners, listener, opt_this,
- opt_setDeleteIndex) {
- var listenerObj;
- for (var i = 0, ii = listeners.length; i < ii; ++i) {
- listenerObj = listeners[i];
- if (listenerObj.listener === listener &&
- listenerObj.bindTo === opt_this) {
- if (opt_setDeleteIndex) {
- listenerObj.deleteIndex = i;
- }
- return listenerObj;
- }
- }
- return undefined;
- };
- /**
- * @param {ol.EventTargetLike} target Target.
- * @param {string} type Type.
- * @return {Array.<ol.EventsKey>|undefined} Listeners.
- */
- ol.events.getListeners = function(target, type) {
- var listenerMap = target.ol_lm;
- return listenerMap ? listenerMap[type] : undefined;
- };
- /**
- * Get the lookup of listeners. If one does not exist on the target, it is
- * created.
- * @param {ol.EventTargetLike} target Target.
- * @return {!Object.<string, Array.<ol.EventsKey>>} Map of
- * listeners by event type.
- * @private
- */
- ol.events.getListenerMap_ = function(target) {
- var listenerMap = target.ol_lm;
- if (!listenerMap) {
- listenerMap = target.ol_lm = {};
- }
- return listenerMap;
- };
- /**
- * Clean up all listener objects of the given type. All properties on the
- * listener objects will be removed, and if no listeners remain in the listener
- * map, it will be removed from the target.
- * @param {ol.EventTargetLike} target Target.
- * @param {string} type Type.
- * @private
- */
- ol.events.removeListeners_ = function(target, type) {
- var listeners = ol.events.getListeners(target, type);
- if (listeners) {
- for (var i = 0, ii = listeners.length; i < ii; ++i) {
- target.removeEventListener(type, listeners[i].boundListener);
- ol.obj.clear(listeners[i]);
- }
- listeners.length = 0;
- var listenerMap = target.ol_lm;
- if (listenerMap) {
- delete listenerMap[type];
- if (Object.keys(listenerMap).length === 0) {
- delete target.ol_lm;
- }
- }
- }
- };
- ol.events.listen = function(target, type, listener, opt_this, opt_once) {
- var listenerMap = ol.events.getListenerMap_(target);
- var listeners = listenerMap[type];
- if (!listeners) {
- listeners = listenerMap[type] = [];
- }
- var listenerObj = ol.events.findListener_(listeners, listener, opt_this,
- false);
- if (listenerObj) {
- if (!opt_once) {
- // Turn one-off listener into a permanent one.
- listenerObj.callOnce = false;
- }
- } else {
- listenerObj = /** @type {ol.EventsKey} */ ({
- bindTo: opt_this,
- callOnce: !!opt_once,
- listener: listener,
- target: target,
- type: type
- });
- target.addEventListener(type, ol.events.bindListener_(listenerObj));
- listeners.push(listenerObj);
- }
- return listenerObj;
- };
- ol.events.listenOnce = function(target, type, listener, opt_this) {
- return ol.events.listen(target, type, listener, opt_this, true);
- };
- ol.events.unlisten = function(target, type, listener, opt_this) {
- var listeners = ol.events.getListeners(target, type);
- if (listeners) {
- var listenerObj = ol.events.findListener_(listeners, listener, opt_this,
- true);
- if (listenerObj) {
- ol.events.unlistenByKey(listenerObj);
- }
- }
- };
- ol.events.unlistenByKey = function(key) {
- if (key && key.target) {
- key.target.removeEventListener(key.type, key.boundListener);
- var listeners = ol.events.getListeners(key.target, key.type);
- if (listeners) {
- var i = 'deleteIndex' in key ? key.deleteIndex : listeners.indexOf(key);
- if (i !== -1) {
- listeners.splice(i, 1);
- }
- if (listeners.length === 0) {
- ol.events.removeListeners_(key.target, key.type);
- }
- }
- ol.obj.clear(key);
- }
- };
- ol.events.unlistenAll = function(target) {
- var listenerMap = ol.events.getListenerMap_(target);
- for (var type in listenerMap) {
- ol.events.removeListeners_(target, type);
- }
- };
- /**
- * Objects that need to clean up after themselves.
- * @constructor
- */
- ol.Disposable = function() {};
- ol.Disposable.prototype.disposed_ = false;
- ol.Disposable.prototype.dispose = function() {
- if (!this.disposed_) {
- this.disposed_ = true;
- this.disposeInternal();
- }
- };
- ol.Disposable.prototype.disposeInternal = ol.nullFunction;
- ol.events.Event = {};
- ol.events.Event = function(type) {
- this.propagationStopped;
- this.type = type;
- this.target = null;
- };
- ol.events.Event.prototype.preventDefault =
- /**
- * Stop event propagation.
- * @function
- * @override
- * @api
- */
- ol.events.Event.prototype.stopPropagation = function() {
- this.propagationStopped = true;
- };
- /**
- * @param {Event|ol.events.Event} evt Event
- */
- ol.events.Event.stopPropagation = function(evt) {
- evt.stopPropagation();
- };
- /**
- * @param {Event|ol.events.Event} evt Event
- */
- ol.events.Event.preventDefault = function(evt) {
- evt.preventDefault();
- };
- ol.events.EventTarget = {};
- ol.events.EventTarget = function() {
- ol.Disposable.call(this);
- this.pendingRemovals_ = {};
- this.dispatching_ = {};
- this.listeners_ = {};
- };
- ol.inherits(ol.events.EventTarget, ol.Disposable);
- /**
- * @param {string} type Type.
- * @param {ol.EventsListenerFunctionType} listener Listener.
- */
- ol.events.EventTarget.prototype.addEventListener = function(type, listener) {
- var listeners = this.listeners_[type];
- if (!listeners) {
- listeners = this.listeners_[type] = [];
- }
- if (listeners.indexOf(listener) === -1) {
- listeners.push(listener);
- }
- };
- ol.events.EventTarget.prototype.dispatchEvent = function(event) {
- var evt = typeof event === 'string' ? new ol.events.Event(event) : event;
- var type = evt.type;
- evt.target = this;
- var listeners = this.listeners_[type];
- var propagate;
- if (listeners) {
- if (!(type in this.dispatching_)) {
- this.dispatching_[type] = 0;
- this.pendingRemovals_[type] = 0;
- }
- ++this.dispatching_[type];
- for (var i = 0, ii = listeners.length; i < ii; ++i) {
- if (listeners[i].call(this, evt) === false || evt.propagationStopped) {
- propagate = false;
- break;
- }
- }
- --this.dispatching_[type];
- if (this.dispatching_[type] === 0) {
- var pendingRemovals = this.pendingRemovals_[type];
- delete this.pendingRemovals_[type];
- while (pendingRemovals--) {
- this.removeEventListener(type, ol.nullFunction);
- }
- delete this.dispatching_[type];
- }
- return propagate;
- }
- };
- /**
- * @inheritDoc
- */
- ol.events.EventTarget.prototype.disposeInternal = function() {
- ol.events.unlistenAll(this);
- };
- /**
- * Get the listeners for a specified event type. Listeners are returned in the
- * order that they will be called in.
- *
- * @param {string} type Type.
- * @return {Array.<ol.EventsListenerFunctionType>} Listeners.
- */
- ol.events.EventTarget.prototype.getListeners = function(type) {
- return this.listeners_[type];
- };
- /**
- * @param {string=} opt_type Type. If not provided,
- * `true` will be returned if this EventTarget has any listeners.
- * @return {boolean} Has listeners.
- */
- ol.events.EventTarget.prototype.hasListener = function(opt_type) {
- return opt_type ?
- opt_type in this.listeners_ :
- Object.keys(this.listeners_).length > 0;
- };
- /**
- * @param {string} type Type.
- * @param {ol.EventsListenerFunctionType} listener Listener.
- */
- ol.events.EventTarget.prototype.removeEventListener = function(type, listener) {
- var listeners = this.listeners_[type];
- if (listeners) {
- var index = listeners.indexOf(listener);
- if (type in this.pendingRemovals_) {
- // make listener a no-op, and remove later in #dispatchEvent()
- listeners[index] = ol.nullFunction;
- ++this.pendingRemovals_[type];
- } else {
- listeners.splice(index, 1);
- if (listeners.length === 0) {
- delete this.listeners_[type];
- }
- }
- }
- };
- /**
- * @enum {string}
- * @const
- */
- ol.events.EventType = {
- CHANGE: 'change',
- CLEAR: 'clear',
- CLICK: 'click',
- DBLCLICK: 'dblclick',
- DRAGENTER: 'dragenter',
- DRAGOVER: 'dragover',
- DROP: 'drop',
- ERROR: 'error',
- KEYDOWN: 'keydown',
- KEYPRESS: 'keypress',
- LOAD: 'load',
- MOUSEDOWN: 'mousedown',
- MOUSEMOVE: 'mousemove',
- MOUSEOUT: 'mouseout',
- MOUSEUP: 'mouseup',
- MOUSEWHEEL: 'mousewheel',
- MSPOINTERDOWN: 'MSPointerDown',
- RESIZE: 'resize',
- TOUCHSTART: 'touchstart',
- TOUCHMOVE: 'touchmove',
- TOUCHEND: 'touchend',
- WHEEL: 'wheel'
- };
- ol.Observable = function() {
- this.revision_ = 0;
- };
- ol.inherits(ol.Observable, ol.events.EventTarget);
- ol.Observable.unByKey = function(key) {
- if (Array.isArray(key)) {
- for (var i = 0, ii = key.length; i < ii; ++i) {
- ol.events.unlistenByKey(key[i]);
- }
- } else {
- ol.events.unlistenByKey(/** @type {ol.EventsKey} */ (key));
- }
- };
- /**
- * Increases the revision counter and dispatches a 'change' event.
- * @api
- */
- ol.Observable.prototype.changed = function() {
- ++this.revision_;
- //this.dispatchEvent(ol.events.EventType.CHANGE);
- };
- /**
- * Dispatches an event and calls all listeners listening for events
- * of this type. The event parameter can either be a string or an
- * Object with a `type` property.
- *
- * @param {{type: string,
- * target: (EventTarget|ol.events.EventTarget|undefined)}|ol.events.Event|
- * string} event Event object.
- * @function
- * @api
- */
- ol.Observable.prototype.dispatchEvent;
- /**
- * Get the version number for this object. Each time the object is modified,
- * its version number will be incremented.
- * @return {number} Revision.
- * @api
- */
- ol.Observable.prototype.getRevision = function() {
- return this.revision_;
- };
- /**
- * Listen for a certain type of event.
- * @param {string|Array.<string>} type The event type or array of event types.
- * @param {function(?): ?} listener The listener function.
- * @param {Object=} opt_this The object to use as `this` in `listener`.
- * @return {ol.EventsKey|Array.<ol.EventsKey>} Unique key for the listener. If
- * called with an array of event types as the first argument, the return
- * will be an array of keys.
- * @api
- */
- ol.Observable.prototype.on = function(type, listener, opt_this) {
- if (Array.isArray(type)) {
- var len = type.length;
- var keys = new Array(len);
- for (var i = 0; i < len; ++i) {
- keys[i] = ol.events.listen(this, type[i], listener, opt_this);
- }
- return keys;
- } else {
- return ol.events.listen(
- this, /** @type {string} */ (type), listener, opt_this);
- }
- };
- /**
- * Listen once for a certain type of event.
- * @param {string|Array.<string>} type The event type or array of event types.
- * @param {function(?): ?} listener The listener function.
- * @param {Object=} opt_this The object to use as `this` in `listener`.
- * @return {ol.EventsKey|Array.<ol.EventsKey>} Unique key for the listener. If
- * called with an array of event types as the first argument, the return
- * will be an array of keys.
- * @api
- */
- ol.Observable.prototype.once = function(type, listener, opt_this) {
- if (Array.isArray(type)) {
- var len = type.length;
- var keys = new Array(len);
- for (var i = 0; i < len; ++i) {
- keys[i] = ol.events.listenOnce(this, type[i], listener, opt_this);
- }
- return keys;
- } else {
- return ol.events.listenOnce(
- this, /** @type {string} */ (type), listener, opt_this);
- }
- };
- /**
- * Unlisten for a certain type of event.
- * @param {string|Array.<string>} type The event type or array of event types.
- * @param {function(?): ?} listener The listener function.
- * @param {Object=} opt_this The object which was used as `this` by the
- * `listener`.
- * @api
- */
- ol.Observable.prototype.un = function(type, listener, opt_this) {
- if (Array.isArray(type)) {
- for (var i = 0, ii = type.length; i < ii; ++i) {
- ol.events.unlisten(this, type[i], listener, opt_this);
- }
- return;
- } else {
- ol.events.unlisten(this, /** @type {string} */ (type), listener, opt_this);
- }
- };
- ol.uidCounter_ = 0;
- ol.Object = function(opt_values) {
- ol.Observable.call(this);
- // Call ol.getUid to ensure that the order of objects' ids is the same as
- // the order in which they were created. This also helps to ensure that
- // object properties are always added in the same order, which helps many
- // JavaScript engines generate faster code.
- ol.getUid(this);
- /**
- * @private
- * @type {!Object.<string, *>}
- */
- this.values_ = {};
- if (opt_values !== undefined) {
- this.setProperties(opt_values);
- }
- };
- ol.inherits(ol.Object, ol.Observable);
- /**
- * @private
- * @type {Object.<string, string>}
- */
- ol.Object.changeEventTypeCache_ = {};
- /**
- * @param {string} key Key name.
- * @return {string} Change name.
- */
- ol.Object.getChangeEventType = function(key) {
- return ol.Object.changeEventTypeCache_.hasOwnProperty(key) ?
- ol.Object.changeEventTypeCache_[key] :
- (ol.Object.changeEventTypeCache_[key] = 'change:' + key);
- };
- /**
- * Gets a value.
- * @param {string} key Key name.
- * @return {*} Value.
- * @api
- */
- ol.Object.prototype.get = function(key) {
- var value;
- if (this.values_.hasOwnProperty(key)) {
- value = this.values_[key];
- }
- return value;
- };
- /**
- * Get a list of object property names.
- * @return {Array.<string>} List of property names.
- * @api
- */
- ol.Object.prototype.getKeys = function() {
- return Object.keys(this.values_);
- };
- /**
- * Get an object of all property names and values.
- * @return {Object.<string, *>} Object.
- * @api
- */
- ol.Object.prototype.getProperties = function() {
- return ol.obj.assign({}, this.values_);
- };
- /**
- * @param {string} key Key name.
- * @param {*} oldValue Old value.
- */
- ol.Object.prototype.notify = function(key, oldValue) {
- // FIX ME
- return;
- };
- /**
- * Sets a value.
- * @param {string} key Key name.
- * @param {*} value Value.
- * @param {boolean=} opt_silent Update without triggering an event.
- * @api
- */
- ol.Object.prototype.set = function(key, value, opt_silent) {
- if (opt_silent) {
- this.values_[key] = value;
- } else {
- var oldValue = this.values_[key];
- this.values_[key] = value;
- if (oldValue !== value) {
- this.notify(key, oldValue);
- }
- }
- };
- /**
- * Sets a collection of key-value pairs. Note that this changes any existing
- * properties and adds new ones (it does not remove any existing properties).
- * @param {Object.<string, *>} values Values.
- * @param {boolean=} opt_silent Update without triggering an event.
- * @api
- */
- ol.Object.prototype.setProperties = function(values, opt_silent) {
- var key;
- for (key in values) {
- this.set(key, values[key], opt_silent);
- }
- };
- /**
- * Unsets a property.
- * @param {string} key Key name.
- * @param {boolean=} opt_silent Unset without triggering an event.
- * @api
- */
- ol.Object.prototype.unset = function(key, opt_silent) {
- if (key in this.values_) {
- var oldValue = this.values_[key];
- delete this.values_[key];
- if (!opt_silent) {
- this.notify(key, oldValue);
- }
- }
- };
- ol.Object.Event = function(type, key, oldValue) {
- ol.events.Event.call(this, type);
- this.key = key;
- this.oldValue = oldValue;
- };
- ol.inherits(ol.Object.Event, ol.events.Event);
- ol.functions = {};
- /**
- * Always returns true.
- * @returns {boolean} true.
- */
- ol.functions.TRUE = function() {
- return true;
- };
- /**
- * Always returns false.
- * @returns {boolean} false.
- */
- ol.functions.FALSE = function() {
- return false;
- };
- ol.math = {};
- ol.math.clamp = function(value, min, max) {
- return Math.min(Math.max(value, min), max);
- };
- ol.math.cosh = (function() {
- // Wrapped in a iife, to save the overhead of checking for the native
- // implementation on every invocation.
- var cosh;
- if ('cosh' in Math) {
- // The environment supports the native Math.cosh function, use it…
- cosh = Math.cosh;
- } else {
- // … else, use the reference implementation of MDN:
- cosh = function(x) {
- var y = Math.exp(x);
- return (y + 1 / y) / 2;
- };
- }
- return cosh;
- }());
- /**
- * @param {number} x X.
- * @return {number} The smallest power of two greater than or equal to x.
- */
- ol.math.roundUpToPowerOfTwo = function(x) {
- ol.asserts.assert(0 < x, 29); // `x` must be greater than `0`
- return Math.pow(2, Math.ceil(Math.log(x) / Math.LN2));
- };
- ol.math.squaredSegmentDistance = function(x, y, x1, y1, x2, y2) {
- var dx = x2 - x1;
- var dy = y2 - y1;
- if (dx !== 0 || dy !== 0) {
- var t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy);
- if (t > 1) {
- x1 = x2;
- y1 = y2;
- } else if (t > 0) {
- x1 += dx * t;
- y1 += dy * t;
- }
- }
- return ol.math.squaredDistance(x, y, x1, y1);
- };
- ol.math.squaredDistance = function(x1, y1, x2, y2) {
- var dx = x2 - x1;
- var dy = y2 - y1;
- return dx * dx + dy * dy;
- };
- ol.math.solveLinearSystem = function(mat) {
- var n = mat.length;
- for (var i = 0; i < n; i++) {
- // Find max in the i-th column (ignoring i - 1 first rows)
- var maxRow = i;
- var maxEl = Math.abs(mat[i][i]);
- for (var r = i + 1; r < n; r++) {
- var absValue = Math.abs(mat[r][i]);
- if (absValue > maxEl) {
- maxEl = absValue;
- maxRow = r;
- }
- }
- if (maxEl === 0) {
- return null; // matrix is singular
- }
- // Swap max row with i-th (current) row
- var tmp = mat[maxRow];
- mat[maxRow] = mat[i];
- mat[i] = tmp;
- // Subtract the i-th row to make all the remaining rows 0 in the i-th column
- for (var j = i + 1; j < n; j++) {
- var coef = -mat[j][i] / mat[i][i];
- for (var k = i; k < n + 1; k++) {
- if (i == k) {
- mat[j][k] = 0;
- } else {
- mat[j][k] += coef * mat[i][k];
- }
- }
- }
- }
- // Solve Ax=b for upper triangular matrix A (mat)
- var x = new Array(n);
- for (var l = n - 1; l >= 0; l--) {
- x[l] = mat[l][n] / mat[l][l];
- for (var m = l - 1; m >= 0; m--) {
- mat[m][n] -= mat[m][l] * x[l];
- }
- }
- return x;
- };
- ol.math.toDegrees = function(angleInRadians) {
- return angleInRadians * 180 / Math.PI;
- };
- ol.math.toRadians = function(angleInDegrees) {
- return angleInDegrees * Math.PI / 180;
- };
- ol.math.modulo = function(a, b) {
- var r = a % b;
- return r * b < 0 ? r + b : r;
- };
- ol.math.lerp = function(a, b, x) {
- return a + x * (b - a);
- };
- ol.ImageState = {
- IDLE: 0,
- LOADING: 1,
- LOADED: 2,
- ERROR: 3
- };
- ol.color = {};
- ol.color.HEX_COLOR_RE_ = /^#(?:[0-9a-f]{3,4}){1,2}$/i;
- ol.color.NAMED_COLOR_RE_ = /^([a-z]*)$/i;
- ol.color.asArray = function(color) {
- if (Array.isArray(color)) {
- return color;
- } else {
- return ol.color.fromString(/** @type {string} */ (color));
- }
- };
- ol.color.asString = function(color) {
- if (typeof color === 'string') {
- return color;
- } else {
- return ol.color.toString(color);
- }
- };
- ol.color.fromNamed = function(color) {
- var el = document.createElement('div');
- el.style.color = color;
- document.body.appendChild(el);
- var rgb = getComputedStyle(el).color;
- document.body.removeChild(el);
- return rgb;
- };
- ol.color.fromString = (
- function() {
- // We maintain a small cache of parsed strings. To provide cheap LRU-like
- // semantics, whenever the cache grows too large we simply delete an
- // arbitrary 25% of the entries.
- /**
- * @const
- * @type {number}
- */
- var MAX_CACHE_SIZE = 1024;
- /**
- * @type {Object.<string, ol.Color>}
- */
- var cache = {};
- /**
- * @type {number}
- */
- var cacheSize = 0;
- return (
- /**
- * @param {string} s String.
- * @return {ol.Color} Color.
- */
- function(s) {
- var color;
- if (cache.hasOwnProperty(s)) {
- color = cache[s];
- } else {
- if (cacheSize >= MAX_CACHE_SIZE) {
- var i = 0;
- var key;
- for (key in cache) {
- if ((i++ & 3) === 0) {
- delete cache[key];
- --cacheSize;
- }
- }
- }
- color = ol.color.fromStringInternal_(s);
- cache[s] = color;
- ++cacheSize;
- }
- return color;
- });
- })();
- ol.color.fromStringInternal_ = function(s) {
- var r, g, b, a, color, parts;
- if (ol.color.NAMED_COLOR_RE_.exec(s)) {
- s = ol.color.fromNamed(s);
- }
- if (ol.color.HEX_COLOR_RE_.exec(s)) { // hex
- var n = s.length - 1; // number of hex digits
- var d; // number of digits per channel
- if (n <= 4) {
- d = 1;
- } else {
- d = 2;
- }
- var hasAlpha = n === 4 || n === 8;
- r = parseInt(s.substr(1 + 0 * d, d), 16);
- g = parseInt(s.substr(1 + 1 * d, d), 16);
- b = parseInt(s.substr(1 + 2 * d, d), 16);
- if (hasAlpha) {
- a = parseInt(s.substr(1 + 3 * d, d), 16);
- } else {
- a = 255;
- }
- if (d == 1) {
- r = (r << 4) + r;
- g = (g << 4) + g;
- b = (b << 4) + b;
- if (hasAlpha) {
- a = (a << 4) + a;
- }
- }
- color = [r, g, b, a / 255];
- } else if (s.indexOf('rgba(') == 0) { // rgba()
- parts = s.slice(5, -1).split(',').map(Number);
- color = ol.color.normalize(parts);
- } else if (s.indexOf('rgb(') == 0) { // rgb()
- parts = s.slice(4, -1).split(',').map(Number);
- parts.push(1);
- color = ol.color.normalize(parts);
- } else {
- ol.asserts.assert(false, 14); // Invalid color
- }
- return /** @type {ol.Color} */ (color);
- };
- /**
- * @param {ol.Color} color Color.
- * @param {ol.Color=} opt_color Color.
- * @return {ol.Color} Clamped color.
- */
- ol.color.normalize = function(color, opt_color) {
- var result = opt_color || [];
- result[0] = ol.math.clamp((color[0] + 0.5) | 0, 0, 255);
- result[1] = ol.math.clamp((color[1] + 0.5) | 0, 0, 255);
- result[2] = ol.math.clamp((color[2] + 0.5) | 0, 0, 255);
- result[3] = ol.math.clamp(color[3], 0, 1);
- return result;
- };
- /**
- * @param {ol.Color} color Color.
- * @return {string} String.
- */
- ol.color.toString = function(color) {
- var r = color[0];
- if (r != (r | 0)) {
- r = (r + 0.5) | 0;
- }
- var g = color[1];
- if (g != (g | 0)) {
- g = (g + 0.5) | 0;
- }
- var b = color[2];
- if (b != (b | 0)) {
- b = (b + 0.5) | 0;
- }
- var a = color[3] === undefined ? 1 : color[3];
- return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
- };
- ol.colorlike = {};
- ol.colorlike.asColorLike = function(color) {
- if (ol.colorlike.isColorLike(color)) {
- return /** @type {string|CanvasPattern|CanvasGradient} */ (color);
- } else {
- return ol.color.asString(/** @type {ol.Color} */ (color));
- }
- };
- ol.colorlike.isColorLike = function(color) {
- return (
- typeof color === 'string' ||
- color instanceof CanvasPattern ||
- color instanceof CanvasGradient
- );
- };
- ol.css = {};
- ol.css.CLASS_HIDDEN = 'ol-hidden';
- ol.css.CLASS_SELECTABLE = 'ol-selectable';
- ol.css.CLASS_UNSELECTABLE = 'ol-unselectable';
- ol.css.CLASS_UNSUPPORTED = 'ol-unsupported';
- ol.css.CLASS_CONTROL = 'ol-control';
- ol.css.getFontFamilies = (function() {
- var style;
- var cache = {};
- return function(font) {
- if (!style) {
- style = document.createElement('div').style;
- }
- if (!(font in cache)) {
- style.font = font;
- var family = style.fontFamily;
- style.font = '';
- if (!family) {
- return null;
- }
- cache[font] = family.split(/,\s?/);
- }
- return cache[font];
- };
- })();
- ol.dom = {};
- /**
- * Create an html canvas element and returns its 2d context.
- * @param {number=} opt_width Canvas width.
- * @param {number=} opt_height Canvas height.
- * @return {CanvasRenderingContext2D} The context.
- */
- ol.dom.createCanvasContext2D = function(opt_width, opt_height) {
- //var canvas = document.createElement('CANVAS');
- var canvas;
- if (opt_width && opt_height) {
- canvas = new OffscreenCanvas(opt_width, opt_height);
- }
- else{
- canvas = new OffscreenCanvas(1, 1);
- }
- return canvas.getContext('2d');
- };
- /**
- * Get the current computed width for the given element including margin,
- * padding and border.
- * Equivalent to jQuery's `$(el).outerWidth(true)`.
- * @param {!Element} element Element.
- * @return {number} The width.
- */
- ol.dom.outerWidth = function(element) {
- var width = element.offsetWidth;
- var style = getComputedStyle(element);
- width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10);
- return width;
- };
- /**
- * Get the current computed height for the given element including margin,
- * padding and border.
- * Equivalent to jQuery's `$(el).outerHeight(true)`.
- * @param {!Element} element Element.
- * @return {number} The height.
- */
- ol.dom.outerHeight = function(element) {
- var height = element.offsetHeight;
- var style = getComputedStyle(element);
- height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10);
- return height;
- };
- /**
- * @param {Node} newNode Node to replace old node
- * @param {Node} oldNode The node to be replaced
- */
- ol.dom.replaceNode = function(newNode, oldNode) {
- var parent = oldNode.parentNode;
- if (parent) {
- parent.replaceChild(newNode, oldNode);
- }
- };
- /**
- * @param {Node} node The node to remove.
- * @returns {Node} The node that was removed or null.
- */
- ol.dom.removeNode = function(node) {
- return node && node.parentNode ? node.parentNode.removeChild(node) : null;
- };
- /**
- * @param {Node} node The node to remove the children from.
- */
- ol.dom.removeChildren = function(node) {
- while (node.lastChild) {
- node.removeChild(node.lastChild);
- }
- };
- ol.extent = {};
- ol.extent.Corner = {
- BOTTOM_LEFT: 'bottom-left',
- BOTTOM_RIGHT: 'bottom-right',
- TOP_LEFT: 'top-left',
- TOP_RIGHT: 'top-right'
- };
- /**
- * Relationship to an extent.
- * @enum {number}
- */
- ol.extent.Relationship = {
- UNKNOWN: 0,
- INTERSECTING: 1,
- ABOVE: 2,
- RIGHT: 4,
- BELOW: 8,
- LEFT: 16
- };
- /**
- * Build an extent that includes all given coordinates.
- *
- * @param {Array.<ol.Coordinate>} coordinates Coordinates.
- * @return {ol.Extent} Bounding extent.
- * @api
- */
- ol.extent.boundingExtent = function(coordinates) {
- var extent = ol.extent.createEmpty();
- for (var i = 0, ii = coordinates.length; i < ii; ++i) {
- ol.extent.extendCoordinate(extent, coordinates[i]);
- }
- return extent;
- };
- ol.extent.boundingExtentXYs_ = function(xs, ys, opt_extent) {
- var minX = Math.min.apply(null, xs);
- var minY = Math.min.apply(null, ys);
- var maxX = Math.max.apply(null, xs);
- var maxY = Math.max.apply(null, ys);
- return ol.extent.createOrUpdate(minX, minY, maxX, maxY, opt_extent);
- };
- ol.extent.buffer = function(extent, value, opt_extent) {
- if (opt_extent) {
- opt_extent[0] = extent[0] - value;
- opt_extent[1] = extent[1] - value;
- opt_extent[2] = extent[2] + value;
- opt_extent[3] = extent[3] + value;
- return opt_extent;
- } else {
- return [
- extent[0] - value,
- extent[1] - value,
- extent[2] + value,
- extent[3] + value
- ];
- }
- };
- ol.extent.clone = function(extent, opt_extent) {
- if (opt_extent) {
- opt_extent[0] = extent[0];
- opt_extent[1] = extent[1];
- opt_extent[2] = extent[2];
- opt_extent[3] = extent[3];
- return opt_extent;
- } else {
- return extent.slice();
- }
- };
- ol.extent.closestSquaredDistanceXY = function(extent, x, y) {
- var dx, dy;
- if (x < extent[0]) {
- dx = extent[0] - x;
- } else if (extent[2] < x) {
- dx = x - extent[2];
- } else {
- dx = 0;
- }
- if (y < extent[1]) {
- dy = extent[1] - y;
- } else if (extent[3] < y) {
- dy = y - extent[3];
- } else {
- dy = 0;
- }
- return dx * dx + dy * dy;
- };
- /**
- * Check if the passed coordinate is contained or on the edge of the extent.
- *
- * @param {ol.Extent} extent Extent.
- * @param {ol.Coordinate} coordinate Coordinate.
- * @return {boolean} The coordinate is contained in the extent.
- * @api
- */
- ol.extent.containsCoordinate = function(extent, coordinate) {
- return ol.extent.containsXY(extent, coordinate[0], coordinate[1]);
- };
- /**
- * Check if one extent contains another.
- *
- * An extent is deemed contained if it lies completely within the other extent,
- * including if they share one or more edges.
- *
- * @param {ol.Extent} extent1 Extent 1.
- * @param {ol.Extent} extent2 Extent 2.
- * @return {boolean} The second extent is contained by or on the edge of the
- * first.
- * @api
- */
- ol.extent.containsExtent = function(extent1, extent2) {
- return extent1[0] <= extent2[0] && extent2[2] <= extent1[2] &&
- extent1[1] <= extent2[1] && extent2[3] <= extent1[3];
- };
- /**
- * Check if the passed coordinate is contained or on the edge of the extent.
- *
- * @param {ol.Extent} extent Extent.
- * @param {number} x X coordinate.
- * @param {number} y Y coordinate.
- * @return {boolean} The x, y values are contained in the extent.
- * @api
- */
- ol.extent.containsXY = function(extent, x, y) {
- return extent[0] <= x && x <= extent[2] && extent[1] <= y && y <= extent[3];
- };
- /**
- * Get the relationship between a coordinate and extent.
- * @param {ol.Extent} extent The extent.
- * @param {ol.Coordinate} coordinate The coordinate.
- * @return {number} The relationship (bitwise compare with
- * ol.extent.Relationship).
- */
- ol.extent.coordinateRelationship = function(extent, coordinate) {
- var minX = extent[0];
- var minY = extent[1];
- var maxX = extent[2];
- var maxY = extent[3];
- var x = coordinate[0];
- var y = coordinate[1];
- var relationship = ol.extent.Relationship.UNKNOWN;
- if (x < minX) {
- relationship = relationship | ol.extent.Relationship.LEFT;
- } else if (x > maxX) {
- relationship = relationship | ol.extent.Relationship.RIGHT;
- }
- if (y < minY) {
- relationship = relationship | ol.extent.Relationship.BELOW;
- } else if (y > maxY) {
- relationship = relationship | ol.extent.Relationship.ABOVE;
- }
- if (relationship === ol.extent.Relationship.UNKNOWN) {
- relationship = ol.extent.Relationship.INTERSECTING;
- }
- return relationship;
- };
- /**
- * Create an empty extent.
- * @return {ol.Extent} Empty extent.
- * @api
- */
- ol.extent.createEmpty = function() {
- return [Infinity, Infinity, -Infinity, -Infinity];
- };
- /**
- * Create a new extent or update the provided extent.
- * @param {number} minX Minimum X.
- * @param {number} minY Minimum Y.
- * @param {number} maxX Maximum X.
- * @param {number} maxY Maximum Y.
- * @param {ol.Extent=} opt_extent Destination extent.
- * @return {ol.Extent} Extent.
- */
- ol.extent.createOrUpdate = function(minX, minY, maxX, maxY, opt_extent) {
- if (opt_extent) {
- opt_extent[0] = minX;
- opt_extent[1] = minY;
- opt_extent[2] = maxX;
- opt_extent[3] = maxY;
- return opt_extent;
- } else {
- return [minX, minY, maxX, maxY];
- }
- };
- /**
- * Create a new empty extent or make the provided one empty.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} Extent.
- */
- ol.extent.createOrUpdateEmpty = function(opt_extent) {
- return ol.extent.createOrUpdate(
- Infinity, Infinity, -Infinity, -Infinity, opt_extent);
- };
- /**
- * @param {ol.Coordinate} coordinate Coordinate.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} Extent.
- */
- ol.extent.createOrUpdateFromCoordinate = function(coordinate, opt_extent) {
- var x = coordinate[0];
- var y = coordinate[1];
- return ol.extent.createOrUpdate(x, y, x, y, opt_extent);
- };
- /**
- * @param {Array.<ol.Coordinate>} coordinates Coordinates.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} Extent.
- */
- ol.extent.createOrUpdateFromCoordinates = function(coordinates, opt_extent) {
- var extent = ol.extent.createOrUpdateEmpty(opt_extent);
- return ol.extent.extendCoordinates(extent, coordinates);
- };
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {number} end End.
- * @param {number} stride Stride.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} Extent.
- */
- ol.extent.createOrUpdateFromFlatCoordinates = function(flatCoordinates, offset, end, stride, opt_extent) {
- var extent = ol.extent.createOrUpdateEmpty(opt_extent);
- return ol.extent.extendFlatCoordinates(
- extent, flatCoordinates, offset, end, stride);
- };
- /**
- * @param {Array.<Array.<ol.Coordinate>>} rings Rings.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} Extent.
- */
- ol.extent.createOrUpdateFromRings = function(rings, opt_extent) {
- var extent = ol.extent.createOrUpdateEmpty(opt_extent);
- return ol.extent.extendRings(extent, rings);
- };
- /**
- * Determine if two extents are equivalent.
- * @param {ol.Extent} extent1 Extent 1.
- * @param {ol.Extent} extent2 Extent 2.
- * @return {boolean} The two extents are equivalent.
- * @api
- */
- ol.extent.equals = function(extent1, extent2) {
- return extent1[0] == extent2[0] && extent1[2] == extent2[2] &&
- extent1[1] == extent2[1] && extent1[3] == extent2[3];
- };
- /**
- * Modify an extent to include another extent.
- * @param {ol.Extent} extent1 The extent to be modified.
- * @param {ol.Extent} extent2 The extent that will be included in the first.
- * @return {ol.Extent} A reference to the first (extended) extent.
- * @api
- */
- ol.extent.extend = function(extent1, extent2) {
- if (extent2[0] < extent1[0]) {
- extent1[0] = extent2[0];
- }
- if (extent2[2] > extent1[2]) {
- extent1[2] = extent2[2];
- }
- if (extent2[1] < extent1[1]) {
- extent1[1] = extent2[1];
- }
- if (extent2[3] > extent1[3]) {
- extent1[3] = extent2[3];
- }
- return extent1;
- };
- /**
- * @param {ol.Extent} extent Extent.
- * @param {ol.Coordinate} coordinate Coordinate.
- */
- ol.extent.extendCoordinate = function(extent, coordinate) {
- if (coordinate[0] < extent[0]) {
- extent[0] = coordinate[0];
- }
- if (coordinate[0] > extent[2]) {
- extent[2] = coordinate[0];
- }
- if (coordinate[1] < extent[1]) {
- extent[1] = coordinate[1];
- }
- if (coordinate[1] > extent[3]) {
- extent[3] = coordinate[1];
- }
- };
- /**
- * @param {ol.Extent} extent Extent.
- * @param {Array.<ol.Coordinate>} coordinates Coordinates.
- * @return {ol.Extent} Extent.
- */
- ol.extent.extendCoordinates = function(extent, coordinates) {
- var i, ii;
- for (i = 0, ii = coordinates.length; i < ii; ++i) {
- ol.extent.extendCoordinate(extent, coordinates[i]);
- }
- return extent;
- };
- /**
- * @param {ol.Extent} extent Extent.
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {number} end End.
- * @param {number} stride Stride.
- * @return {ol.Extent} Extent.
- */
- ol.extent.extendFlatCoordinates = function(extent, flatCoordinates, offset, end, stride) {
- for (; offset < end; offset += stride) {
- ol.extent.extendXY(
- extent, flatCoordinates[offset], flatCoordinates[offset + 1]);
- }
- return extent;
- };
- /**
- * @param {ol.Extent} extent Extent.
- * @param {Array.<Array.<ol.Coordinate>>} rings Rings.
- * @return {ol.Extent} Extent.
- */
- ol.extent.extendRings = function(extent, rings) {
- var i, ii;
- for (i = 0, ii = rings.length; i < ii; ++i) {
- ol.extent.extendCoordinates(extent, rings[i]);
- }
- return extent;
- };
- /**
- * @param {ol.Extent} extent Extent.
- * @param {number} x X.
- * @param {number} y Y.
- */
- ol.extent.extendXY = function(extent, x, y) {
- extent[0] = Math.min(extent[0], x);
- extent[1] = Math.min(extent[1], y);
- extent[2] = Math.max(extent[2], x);
- extent[3] = Math.max(extent[3], y);
- };
- /**
- * This function calls `callback` for each corner of the extent. If the
- * callback returns a truthy value the function returns that value
- * immediately. Otherwise the function returns `false`.
- * @param {ol.Extent} extent Extent.
- * @param {function(this:T, ol.Coordinate): S} callback Callback.
- * @param {T=} opt_this Value to use as `this` when executing `callback`.
- * @return {S|boolean} Value.
- * @template S, T
- */
- ol.extent.forEachCorner = function(extent, callback, opt_this) {
- var val;
- val = callback.call(opt_this, ol.extent.getBottomLeft(extent));
- if (val) {
- return val;
- }
- val = callback.call(opt_this, ol.extent.getBottomRight(extent));
- if (val) {
- return val;
- }
- val = callback.call(opt_this, ol.extent.getTopRight(extent));
- if (val) {
- return val;
- }
- val = callback.call(opt_this, ol.extent.getTopLeft(extent));
- if (val) {
- return val;
- }
- return false;
- };
- /**
- * Get the size of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {number} Area.
- * @api
- */
- ol.extent.getArea = function(extent) {
- var area = 0;
- if (!ol.extent.isEmpty(extent)) {
- area = ol.extent.getWidth(extent) * ol.extent.getHeight(extent);
- }
- return area;
- };
- /**
- * Get the bottom left coordinate of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {ol.Coordinate} Bottom left coordinate.
- * @api
- */
- ol.extent.getBottomLeft = function(extent) {
- return [extent[0], extent[1]];
- };
- /**
- * Get the bottom right coordinate of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {ol.Coordinate} Bottom right coordinate.
- * @api
- */
- ol.extent.getBottomRight = function(extent) {
- return [extent[2], extent[1]];
- };
- /**
- * Get the center coordinate of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {ol.Coordinate} Center.
- * @api
- */
- ol.extent.getCenter = function(extent) {
- return [(extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2];
- };
- /**
- * Get a corner coordinate of an extent.
- * @param {ol.Extent} extent Extent.
- * @param {ol.extent.Corner} corner Corner.
- * @return {ol.Coordinate} Corner coordinate.
- */
- ol.extent.getCorner = function(extent, corner) {
- var coordinate;
- if (corner === ol.extent.Corner.BOTTOM_LEFT) {
- coordinate = ol.extent.getBottomLeft(extent);
- } else if (corner === ol.extent.Corner.BOTTOM_RIGHT) {
- coordinate = ol.extent.getBottomRight(extent);
- } else if (corner === ol.extent.Corner.TOP_LEFT) {
- coordinate = ol.extent.getTopLeft(extent);
- } else if (corner === ol.extent.Corner.TOP_RIGHT) {
- coordinate = ol.extent.getTopRight(extent);
- } else {
- ol.asserts.assert(false, 13); // Invalid corner
- }
- return /** @type {!ol.Coordinate} */ (coordinate);
- };
- /**
- * @param {ol.Extent} extent1 Extent 1.
- * @param {ol.Extent} extent2 Extent 2.
- * @return {number} Enlarged area.
- */
- ol.extent.getEnlargedArea = function(extent1, extent2) {
- var minX = Math.min(extent1[0], extent2[0]);
- var minY = Math.min(extent1[1], extent2[1]);
- var maxX = Math.max(extent1[2], extent2[2]);
- var maxY = Math.max(extent1[3], extent2[3]);
- return (maxX - minX) * (maxY - minY);
- };
- /**
- * @param {ol.Coordinate} center Center.
- * @param {number} resolution Resolution.
- * @param {number} rotation Rotation.
- * @param {ol.Size} size Size.
- * @param {ol.Extent=} opt_extent Destination extent.
- * @return {ol.Extent} Extent.
- */
- ol.extent.getForViewAndSize = function(center, resolution, rotation, size, opt_extent) {
- var dx = resolution * size[0] / 2;
- var dy = resolution * size[1] / 2;
- var cosRotation = Math.cos(rotation);
- var sinRotation = Math.sin(rotation);
- var xCos = dx * cosRotation;
- var xSin = dx * sinRotation;
- var yCos = dy * cosRotation;
- var ySin = dy * sinRotation;
- var x = center[0];
- var y = center[1];
- var x0 = x - xCos + ySin;
- var x1 = x - xCos - ySin;
- var x2 = x + xCos - ySin;
- var x3 = x + xCos + ySin;
- var y0 = y - xSin - yCos;
- var y1 = y - xSin + yCos;
- var y2 = y + xSin + yCos;
- var y3 = y + xSin - yCos;
- return ol.extent.createOrUpdate(
- Math.min(x0, x1, x2, x3), Math.min(y0, y1, y2, y3),
- Math.max(x0, x1, x2, x3), Math.max(y0, y1, y2, y3),
- opt_extent);
- };
- /**
- * Get the height of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {number} Height.
- * @api
- */
- ol.extent.getHeight = function(extent) {
- return extent[3] - extent[1];
- };
- /**
- * @param {ol.Extent} extent1 Extent 1.
- * @param {ol.Extent} extent2 Extent 2.
- * @return {number} Intersection area.
- */
- ol.extent.getIntersectionArea = function(extent1, extent2) {
- var intersection = ol.extent.getIntersection(extent1, extent2);
- return ol.extent.getArea(intersection);
- };
- /**
- * Get the intersection of two extents.
- * @param {ol.Extent} extent1 Extent 1.
- * @param {ol.Extent} extent2 Extent 2.
- * @param {ol.Extent=} opt_extent Optional extent to populate with intersection.
- * @return {ol.Extent} Intersecting extent.
- * @api
- */
- ol.extent.getIntersection = function(extent1, extent2, opt_extent) {
- var intersection = opt_extent ? opt_extent : ol.extent.createEmpty();
- if (ol.extent.intersects(extent1, extent2)) {
- if (extent1[0] > extent2[0]) {
- intersection[0] = extent1[0];
- } else {
- intersection[0] = extent2[0];
- }
- if (extent1[1] > extent2[1]) {
- intersection[1] = extent1[1];
- } else {
- intersection[1] = extent2[1];
- }
- if (extent1[2] < extent2[2]) {
- intersection[2] = extent1[2];
- } else {
- intersection[2] = extent2[2];
- }
- if (extent1[3] < extent2[3]) {
- intersection[3] = extent1[3];
- } else {
- intersection[3] = extent2[3];
- }
- }
- return intersection;
- };
- /**
- * @param {ol.Extent} extent Extent.
- * @return {number} Margin.
- */
- ol.extent.getMargin = function(extent) {
- return ol.extent.getWidth(extent) + ol.extent.getHeight(extent);
- };
- /**
- * Get the size (width, height) of an extent.
- * @param {ol.Extent} extent The extent.
- * @return {ol.Size} The extent size.
- * @api
- */
- ol.extent.getSize = function(extent) {
- return [extent[2] - extent[0], extent[3] - extent[1]];
- };
- /**
- * Get the top left coordinate of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {ol.Coordinate} Top left coordinate.
- * @api
- */
- ol.extent.getTopLeft = function(extent) {
- return [extent[0], extent[3]];
- };
- /**
- * Get the top right coordinate of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {ol.Coordinate} Top right coordinate.
- * @api
- */
- ol.extent.getTopRight = function(extent) {
- return [extent[2], extent[3]];
- };
- /**
- * Get the width of an extent.
- * @param {ol.Extent} extent Extent.
- * @return {number} Width.
- * @api
- */
- ol.extent.getWidth = function(extent) {
- return extent[2] - extent[0];
- };
- /**
- * Determine if one extent intersects another.
- * @param {ol.Extent} extent1 Extent 1.
- * @param {ol.Extent} extent2 Extent.
- * @return {boolean} The two extents intersect.
- * @api
- */
- ol.extent.intersects = function(extent1, extent2) {
- return extent1[0] <= extent2[2] &&
- extent1[2] >= extent2[0] &&
- extent1[1] <= extent2[3] &&
- extent1[3] >= extent2[1];
- };
- /**
- * Determine if an extent is empty.
- * @param {ol.Extent} extent Extent.
- * @return {boolean} Is empty.
- * @api
- */
- ol.extent.isEmpty = function(extent) {
- return extent[2] < extent[0] || extent[3] < extent[1];
- };
- /**
- * @param {ol.Extent} extent Extent.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} Extent.
- */
- ol.extent.returnOrUpdate = function(extent, opt_extent) {
- if (opt_extent) {
- opt_extent[0] = extent[0];
- opt_extent[1] = extent[1];
- opt_extent[2] = extent[2];
- opt_extent[3] = extent[3];
- return opt_extent;
- } else {
- return extent;
- }
- };
- /**
- * @param {ol.Extent} extent Extent.
- * @param {number} value Value.
- */
- ol.extent.scaleFromCenter = function(extent, value) {
- var deltaX = ((extent[2] - extent[0]) / 2) * (value - 1);
- var deltaY = ((extent[3] - extent[1]) / 2) * (value - 1);
- extent[0] -= deltaX;
- extent[2] += deltaX;
- extent[1] -= deltaY;
- extent[3] += deltaY;
- };
- /**
- * Determine if the segment between two coordinates intersects (crosses,
- * touches, or is contained by) the provided extent.
- * @param {ol.Extent} extent The extent.
- * @param {ol.Coordinate} start Segment start coordinate.
- * @param {ol.Coordinate} end Segment end coordinate.
- * @return {boolean} The segment intersects the extent.
- */
- ol.extent.intersectsSegment = function(extent, start, end) {
- var intersects = false;
- var startRel = ol.extent.coordinateRelationship(extent, start);
- var endRel = ol.extent.coordinateRelationship(extent, end);
- if (startRel === ol.extent.Relationship.INTERSECTING ||
- endRel === ol.extent.Relationship.INTERSECTING) {
- intersects = true;
- } else {
- var minX = extent[0];
- var minY = extent[1];
- var maxX = extent[2];
- var maxY = extent[3];
- var startX = start[0];
- var startY = start[1];
- var endX = end[0];
- var endY = end[1];
- var slope = (endY - startY) / (endX - startX);
- var x, y;
- if (!!(endRel & ol.extent.Relationship.ABOVE) &&
- !(startRel & ol.extent.Relationship.ABOVE)) {
- // potentially intersects top
- x = endX - ((endY - maxY) / slope);
- intersects = x >= minX && x <= maxX;
- }
- if (!intersects && !!(endRel & ol.extent.Relationship.RIGHT) &&
- !(startRel & ol.extent.Relationship.RIGHT)) {
- // potentially intersects right
- y = endY - ((endX - maxX) * slope);
- intersects = y >= minY && y <= maxY;
- }
- if (!intersects && !!(endRel & ol.extent.Relationship.BELOW) &&
- !(startRel & ol.extent.Relationship.BELOW)) {
- // potentially intersects bottom
- x = endX - ((endY - minY) / slope);
- intersects = x >= minX && x <= maxX;
- }
- if (!intersects && !!(endRel & ol.extent.Relationship.LEFT) &&
- !(startRel & ol.extent.Relationship.LEFT)) {
- // potentially intersects left
- y = endY - ((endX - minX) * slope);
- intersects = y >= minY && y <= maxY;
- }
- }
- return intersects;
- };
- /**
- * Apply a transform function to the extent.
- * @param {ol.Extent} extent Extent.
- * @param {ol.TransformFunction} transformFn Transform function. Called with
- * [minX, minY, maxX, maxY] extent coordinates.
- * @param {ol.Extent=} opt_extent Destination extent.
- * @return {ol.Extent} Extent.
- * @api
- */
- ol.extent.applyTransform = function(extent, transformFn, opt_extent) {
- var coordinates = [
- extent[0], extent[1],
- extent[0], extent[3],
- extent[2], extent[1],
- extent[2], extent[3]
- ];
- transformFn(coordinates, coordinates, 2);
- var xs = [coordinates[0], coordinates[2], coordinates[4], coordinates[6]];
- var ys = [coordinates[1], coordinates[3], coordinates[5], coordinates[7]];
- return ol.extent.boundingExtentXYs_(xs, ys, opt_extent);
- };
- ol.obj = {};
- /**
- * Polyfill for Object.assign(). Assigns enumerable and own properties from
- * one or more source objects to a target object.
- *
- * @see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
- * @param {!Object} target The target object.
- * @param {...Object} var_sources The source object(s).
- * @return {!Object} The modified target object.
- */
- ol.obj.assign = (typeof Object.assign === 'function') ? Object.assign : function(target, var_sources) {
- if (target === undefined || target === null) {
- throw new TypeError('Cannot convert undefined or null to object');
- }
- var output = Object(target);
- for (var i = 1, ii = arguments.length; i < ii; ++i) {
- var source = arguments[i];
- if (source !== undefined && source !== null) {
- for (var key in source) {
- if (source.hasOwnProperty(key)) {
- output[key] = source[key];
- }
- }
- }
- }
- return output;
- };
- /**
- * Removes all properties from an object.
- * @param {Object} object The object to clear.
- */
- ol.obj.clear = function(object) {
- for (var property in object) {
- delete object[property];
- }
- };
- /**
- * Get an array of property values from an object.
- * @param {Object<K,V>} object The object from which to get the values.
- * @return {!Array<V>} The property values.
- * @template K,V
- */
- ol.obj.getValues = function(object) {
- var values = [];
- for (var property in object) {
- values.push(object[property]);
- }
- return values;
- };
- /**
- * Determine if an object has any properties.
- * @param {Object} object The object to check.
- * @return {boolean} The object is empty.
- */
- ol.obj.isEmpty = function(object) {
- var property;
- for (property in object) {
- return false;
- }
- return !property;
- };
- ol.transform = {};
- /**
- * @private
- * @type {ol.Transform}
- */
- ol.transform.tmp_ = new Array(6);
- /**
- * Create an identity transform.
- * @return {!ol.Transform} Identity transform.
- */
- ol.transform.create = function() {
- return [1, 0, 0, 1, 0, 0];
- };
- /**
- * Resets the given transform to an identity transform.
- * @param {!ol.Transform} transform Transform.
- * @return {!ol.Transform} Transform.
- */
- ol.transform.reset = function(transform) {
- return ol.transform.set(transform, 1, 0, 0, 1, 0, 0);
- };
- /**
- * Multiply the underlying matrices of two transforms and return the result in
- * the first transform.
- * @param {!ol.Transform} transform1 Transform parameters of matrix 1.
- * @param {!ol.Transform} transform2 Transform parameters of matrix 2.
- * @return {!ol.Transform} transform1 multiplied with transform2.
- */
- ol.transform.multiply = function(transform1, transform2) {
- var a1 = transform1[0];
- var b1 = transform1[1];
- var c1 = transform1[2];
- var d1 = transform1[3];
- var e1 = transform1[4];
- var f1 = transform1[5];
- var a2 = transform2[0];
- var b2 = transform2[1];
- var c2 = transform2[2];
- var d2 = transform2[3];
- var e2 = transform2[4];
- var f2 = transform2[5];
- transform1[0] = a1 * a2 + c1 * b2;
- transform1[1] = b1 * a2 + d1 * b2;
- transform1[2] = a1 * c2 + c1 * d2;
- transform1[3] = b1 * c2 + d1 * d2;
- transform1[4] = a1 * e2 + c1 * f2 + e1;
- transform1[5] = b1 * e2 + d1 * f2 + f1;
- return transform1;
- };
- /**
- * Set the transform components a-f on a given transform.
- * @param {!ol.Transform} transform Transform.
- * @param {number} a The a component of the transform.
- * @param {number} b The b component of the transform.
- * @param {number} c The c component of the transform.
- * @param {number} d The d component of the transform.
- * @param {number} e The e component of the transform.
- * @param {number} f The f component of the transform.
- * @return {!ol.Transform} Matrix with transform applied.
- */
- ol.transform.set = function(transform, a, b, c, d, e, f) {
- transform[0] = a;
- transform[1] = b;
- transform[2] = c;
- transform[3] = d;
- transform[4] = e;
- transform[5] = f;
- return transform;
- };
- /**
- * Set transform on one matrix from another matrix.
- * @param {!ol.Transform} transform1 Matrix to set transform to.
- * @param {!ol.Transform} transform2 Matrix to set transform from.
- * @return {!ol.Transform} transform1 with transform from transform2 applied.
- */
- ol.transform.setFromArray = function(transform1, transform2) {
- transform1[0] = transform2[0];
- transform1[1] = transform2[1];
- transform1[2] = transform2[2];
- transform1[3] = transform2[3];
- transform1[4] = transform2[4];
- transform1[5] = transform2[5];
- return transform1;
- };
- /**
- * Transforms the given coordinate with the given transform returning the
- * resulting, transformed coordinate. The coordinate will be modified in-place.
- *
- * @param {ol.Transform} transform The transformation.
- * @param {ol.Coordinate|ol.Pixel} coordinate The coordinate to transform.
- * @return {ol.Coordinate|ol.Pixel} return coordinate so that operations can be
- * chained together.
- */
- ol.transform.apply = function(transform, coordinate) {
- var x = coordinate[0], y = coordinate[1];
- coordinate[0] = transform[0] * x + transform[2] * y + transform[4];
- coordinate[1] = transform[1] * x + transform[3] * y + transform[5];
- return coordinate;
- };
- /**
- * Applies rotation to the given transform.
- * @param {!ol.Transform} transform Transform.
- * @param {number} angle Angle in radians.
- * @return {!ol.Transform} The rotated transform.
- */
- ol.transform.rotate = function(transform, angle) {
- var cos = Math.cos(angle);
- var sin = Math.sin(angle);
- return ol.transform.multiply(transform,
- ol.transform.set(ol.transform.tmp_, cos, sin, -sin, cos, 0, 0));
- };
- /**
- * Applies scale to a given transform.
- * @param {!ol.Transform} transform Transform.
- * @param {number} x Scale factor x.
- * @param {number} y Scale factor y.
- * @return {!ol.Transform} The scaled transform.
- */
- ol.transform.scale = function(transform, x, y) {
- return ol.transform.multiply(transform,
- ol.transform.set(ol.transform.tmp_, x, 0, 0, y, 0, 0));
- };
- /**
- * Applies translation to the given transform.
- * @param {!ol.Transform} transform Transform.
- * @param {number} dx Translation x.
- * @param {number} dy Translation y.
- * @return {!ol.Transform} The translated transform.
- */
- ol.transform.translate = function(transform, dx, dy) {
- return ol.transform.multiply(transform,
- ol.transform.set(ol.transform.tmp_, 1, 0, 0, 1, dx, dy));
- };
- /**
- * Creates a composite transform given an initial translation, scale, rotation, and
- * final translation (in that order only, not commutative).
- * @param {!ol.Transform} transform The transform (will be modified in place).
- * @param {number} dx1 Initial translation x.
- * @param {number} dy1 Initial translation y.
- * @param {number} sx Scale factor x.
- * @param {number} sy Scale factor y.
- * @param {number} angle Rotation (in counter-clockwise radians).
- * @param {number} dx2 Final translation x.
- * @param {number} dy2 Final translation y.
- * @return {!ol.Transform} The composite transform.
- */
- ol.transform.compose = function(transform, dx1, dy1, sx, sy, angle, dx2, dy2) {
- var sin = Math.sin(angle);
- var cos = Math.cos(angle);
- transform[0] = sx * cos;
- transform[1] = sy * sin;
- transform[2] = -sx * sin;
- transform[3] = sy * cos;
- transform[4] = dx2 * sx * cos - dy2 * sx * sin + dx1;
- transform[5] = dx2 * sy * sin + dy2 * sy * cos + dy1;
- return transform;
- };
- /**
- * Invert the given transform.
- * @param {!ol.Transform} transform Transform.
- * @return {!ol.Transform} Inverse of the transform.
- */
- ol.transform.invert = function(transform) {
- var det = ol.transform.determinant(transform);
- //ol.asserts.assert(det !== 0, 32); // Transformation matrix cannot be inverted
- var a = transform[0];
- var b = transform[1];
- var c = transform[2];
- var d = transform[3];
- var e = transform[4];
- var f = transform[5];
- transform[0] = d / det;
- transform[1] = -b / det;
- transform[2] = -c / det;
- transform[3] = a / det;
- transform[4] = (c * f - d * e) / det;
- transform[5] = -(a * f - b * e) / det;
- return transform;
- };
- /**
- * Returns the determinant of the given matrix.
- * @param {!ol.Transform} mat Matrix.
- * @return {number} Determinant.
- */
- ol.transform.determinant = function(mat) {
- return mat[0] * mat[3] - mat[1] * mat[2];
- };
- ol.geom = {};
- ol.geom.flat = {};
- ol.geom.flat.center = {};
- ol.geom.flat.reverse = {};
- ol.geom.flat.orient = {};
- ol.geom.flat.transform = {};
- ol.geom.flat.transform.transform2D = function(flatCoordinates, offset, end, stride, transform, opt_dest) {
- var dest = opt_dest ? opt_dest : [];
- var i = 0;
- var j;
- for (j = offset; j < end; j += stride) {
- var x = flatCoordinates[j];
- var y = flatCoordinates[j + 1];
- dest[i++] = transform[0] * x + transform[2] * y + transform[4];
- dest[i++] = transform[1] * x + transform[3] * y + transform[5];
- }
- if (opt_dest && dest.length != i) {
- dest.length = i;
- }
- return dest;
- };
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {number} end End.
- * @param {number} stride Stride.
- * @param {number} angle Angle.
- * @param {Array.<number>} anchor Rotation anchor point.
- * @param {Array.<number>=} opt_dest Destination.
- * @return {Array.<number>} Transformed coordinates.
- */
- ol.geom.flat.transform.rotate = function(flatCoordinates, offset, end, stride, angle, anchor, opt_dest) {
- var dest = opt_dest ? opt_dest : [];
- var cos = Math.cos(angle);
- var sin = Math.sin(angle);
- var anchorX = anchor[0];
- var anchorY = anchor[1];
- var i = 0;
- for (var j = offset; j < end; j += stride) {
- var deltaX = flatCoordinates[j] - anchorX;
- var deltaY = flatCoordinates[j + 1] - anchorY;
- dest[i++] = anchorX + deltaX * cos - deltaY * sin;
- dest[i++] = anchorY + deltaX * sin + deltaY * cos;
- for (var k = j + 2; k < j + stride; ++k) {
- dest[i++] = flatCoordinates[k];
- }
- }
- if (opt_dest && dest.length != i) {
- dest.length = i;
- }
- return dest;
- };
- /**
- * Scale the coordinates.
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {number} end End.
- * @param {number} stride Stride.
- * @param {number} sx Scale factor in the x-direction.
- * @param {number} sy Scale factor in the y-direction.
- * @param {Array.<number>} anchor Scale anchor point.
- * @param {Array.<number>=} opt_dest Destination.
- * @return {Array.<number>} Transformed coordinates.
- */
- ol.geom.flat.transform.scale = function(flatCoordinates, offset, end, stride, sx, sy, anchor, opt_dest) {
- var dest = opt_dest ? opt_dest : [];
- var anchorX = anchor[0];
- var anchorY = anchor[1];
- var i = 0;
- for (var j = offset; j < end; j += stride) {
- var deltaX = flatCoordinates[j] - anchorX;
- var deltaY = flatCoordinates[j + 1] - anchorY;
- dest[i++] = anchorX + sx * deltaX;
- dest[i++] = anchorY + sy * deltaY;
- for (var k = j + 2; k < j + stride; ++k) {
- dest[i++] = flatCoordinates[k];
- }
- }
- if (opt_dest && dest.length != i) {
- dest.length = i;
- }
- return dest;
- };
- /**
- * The coordinate layout for geometries, indicating whether a 3rd or 4th z ('Z')
- * or measure ('M') coordinate is available. Supported values are `'XY'`,
- * `'XYZ'`, `'XYM'`, `'XYZM'`.
- * @enum {string}
- */
- ol.geom.GeometryLayout = {
- XY: 'XY',
- XYZ: 'XYZ',
- XYM: 'XYM',
- XYZM: 'XYZM'
- };
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {number} end End.
- * @param {number} stride Stride.
- */
- ol.geom.flat.reverse.coordinates = function(flatCoordinates, offset, end, stride) {
- while (offset < end - stride) {
- var i;
- for (i = 0; i < stride; ++i) {
- var tmp = flatCoordinates[offset + i];
- flatCoordinates[offset + i] = flatCoordinates[end - stride + i];
- flatCoordinates[end - stride + i] = tmp;
- }
- offset += stride;
- end -= stride;
- }
- };
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {number} end End.
- * @param {number} stride Stride.
- * @return {boolean} Is clockwise.
- */
- ol.geom.flat.orient.linearRingIsClockwise = function(flatCoordinates, offset, end, stride) {
- // http://tinyurl.com/clockwise-method
- // https://github.com/OSGeo/gdal/blob/trunk/gdal/ogr/ogrlinearring.cpp
- var edge = 0;
- var x1 = flatCoordinates[end - stride];
- var y1 = flatCoordinates[end - stride + 1];
- for (; offset < end; offset += stride) {
- var x2 = flatCoordinates[offset];
- var y2 = flatCoordinates[offset + 1];
- edge += (x2 - x1) * (y2 + y1);
- x1 = x2;
- y1 = y2;
- }
- return edge > 0;
- };
- /**
- * Determines if linear rings are oriented. By default, left-hand orientation
- * is tested (first ring must be clockwise, remaining rings counter-clockwise).
- * To test for right-hand orientation, use the `opt_right` argument.
- *
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {Array.<number>} ends Array of end indexes.
- * @param {number} stride Stride.
- * @param {boolean=} opt_right Test for right-hand orientation
- * (counter-clockwise exterior ring and clockwise interior rings).
- * @return {boolean} Rings are correctly oriented.
- */
- ol.geom.flat.orient.linearRingsAreOriented = function(flatCoordinates, offset, ends, stride, opt_right) {
- var right = opt_right !== undefined ? opt_right : false;
- var i, ii;
- for (i = 0, ii = ends.length; i < ii; ++i) {
- var end = ends[i];
- var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(
- flatCoordinates, offset, end, stride);
- if (i === 0) {
- if ((right && isClockwise) || (!right && !isClockwise)) {
- return false;
- }
- } else {
- if ((right && !isClockwise) || (!right && isClockwise)) {
- return false;
- }
- }
- offset = end;
- }
- return true;
- };
- /**
- * Determines if linear rings are oriented. By default, left-hand orientation
- * is tested (first ring must be clockwise, remaining rings counter-clockwise).
- * To test for right-hand orientation, use the `opt_right` argument.
- *
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {Array.<Array.<number>>} endss Array of array of end indexes.
- * @param {number} stride Stride.
- * @param {boolean=} opt_right Test for right-hand orientation
- * (counter-clockwise exterior ring and clockwise interior rings).
- * @return {boolean} Rings are correctly oriented.
- */
- ol.geom.flat.orient.linearRingssAreOriented = function(flatCoordinates, offset, endss, stride, opt_right) {
- var i, ii;
- for (i = 0, ii = endss.length; i < ii; ++i) {
- if (!ol.geom.flat.orient.linearRingsAreOriented(
- flatCoordinates, offset, endss[i], stride, opt_right)) {
- return false;
- }
- }
- return true;
- };
- /**
- * Orient coordinates in a flat array of linear rings. By default, rings
- * are oriented following the left-hand rule (clockwise for exterior and
- * counter-clockwise for interior rings). To orient according to the
- * right-hand rule, use the `opt_right` argument.
- *
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {Array.<number>} ends Ends.
- * @param {number} stride Stride.
- * @param {boolean=} opt_right Follow the right-hand rule for orientation.
- * @return {number} End.
- */
- ol.geom.flat.orient.orientLinearRings = function(flatCoordinates, offset, ends, stride, opt_right) {
- var right = opt_right !== undefined ? opt_right : false;
- var i, ii;
- for (i = 0, ii = ends.length; i < ii; ++i) {
- var end = ends[i];
- var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(
- flatCoordinates, offset, end, stride);
- var reverse = i === 0 ?
- (right && isClockwise) || (!right && !isClockwise) :
- (right && !isClockwise) || (!right && isClockwise);
- if (reverse) {
- ol.geom.flat.reverse.coordinates(flatCoordinates, offset, end, stride);
- }
- offset = end;
- }
- return offset;
- };
- /**
- * Orient coordinates in a flat array of linear rings. By default, rings
- * are oriented following the left-hand rule (clockwise for exterior and
- * counter-clockwise for interior rings). To orient according to the
- * right-hand rule, use the `opt_right` argument.
- *
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {Array.<Array.<number>>} endss Array of array of end indexes.
- * @param {number} stride Stride.
- * @param {boolean=} opt_right Follow the right-hand rule for orientation.
- * @return {number} End.
- */
- ol.geom.flat.orient.orientLinearRingss = function(flatCoordinates, offset, endss, stride, opt_right) {
- var i, ii;
- for (i = 0, ii = endss.length; i < ii; ++i) {
- offset = ol.geom.flat.orient.orientLinearRings(
- flatCoordinates, offset, endss[i], stride, opt_right);
- }
- return offset;
- };
- ol.geom.flat.simplify = {};
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {number} end End.
- * @param {number} stride Stride.
- * @param {number} squaredTolerance Squared tolerance.
- * @param {boolean} highQuality Highest quality.
- * @param {Array.<number>=} opt_simplifiedFlatCoordinates Simplified flat
- * coordinates.
- * @return {Array.<number>} Simplified line string.
- */
- ol.geom.flat.simplify.lineString = function(flatCoordinates, offset, end,
- stride, squaredTolerance, highQuality, opt_simplifiedFlatCoordinates) {
- var simplifiedFlatCoordinates = opt_simplifiedFlatCoordinates !== undefined ?
- opt_simplifiedFlatCoordinates : [];
- if (!highQuality) {
- end = ol.geom.flat.simplify.radialDistance(flatCoordinates, offset, end,
- stride, squaredTolerance,
- simplifiedFlatCoordinates, 0);
- flatCoordinates = simplifiedFlatCoordinates;
- offset = 0;
- stride = 2;
- }
- simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeucker(
- flatCoordinates, offset, end, stride, squaredTolerance,
- simplifiedFlatCoordinates, 0);
- return simplifiedFlatCoordinates;
- };
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {number} end End.
- * @param {number} stride Stride.
- * @param {number} squaredTolerance Squared tolerance.
- * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
- * coordinates.
- * @param {number} simplifiedOffset Simplified offset.
- * @return {number} Simplified offset.
- */
- ol.geom.flat.simplify.douglasPeucker = function(flatCoordinates, offset, end,
- stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset) {
- var n = (end - offset) / stride;
- if (n < 3) {
- for (; offset < end; offset += stride) {
- simplifiedFlatCoordinates[simplifiedOffset++] =
- flatCoordinates[offset];
- simplifiedFlatCoordinates[simplifiedOffset++] =
- flatCoordinates[offset + 1];
- }
- return simplifiedOffset;
- }
- /** @type {Array.<number>} */
- var markers = new Array(n);
- markers[0] = 1;
- markers[n - 1] = 1;
- /** @type {Array.<number>} */
- var stack = [offset, end - stride];
- var index = 0;
- var i;
- while (stack.length > 0) {
- var last = stack.pop();
- var first = stack.pop();
- var maxSquaredDistance = 0;
- var x1 = flatCoordinates[first];
- var y1 = flatCoordinates[first + 1];
- var x2 = flatCoordinates[last];
- var y2 = flatCoordinates[last + 1];
- for (i = first + stride; i < last; i += stride) {
- var x = flatCoordinates[i];
- var y = flatCoordinates[i + 1];
- var squaredDistance = ol.math.squaredSegmentDistance(
- x, y, x1, y1, x2, y2);
- if (squaredDistance > maxSquaredDistance) {
- index = i;
- maxSquaredDistance = squaredDistance;
- }
- }
- if (maxSquaredDistance > squaredTolerance) {
- markers[(index - offset) / stride] = 1;
- if (first + stride < index) {
- stack.push(first, index);
- }
- if (index + stride < last) {
- stack.push(index, last);
- }
- }
- }
- for (i = 0; i < n; ++i) {
- if (markers[i]) {
- simplifiedFlatCoordinates[simplifiedOffset++] =
- flatCoordinates[offset + i * stride];
- simplifiedFlatCoordinates[simplifiedOffset++] =
- flatCoordinates[offset + i * stride + 1];
- }
- }
- return simplifiedOffset;
- };
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {Array.<number>} ends Ends.
- * @param {number} stride Stride.
- * @param {number} squaredTolerance Squared tolerance.
- * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
- * coordinates.
- * @param {number} simplifiedOffset Simplified offset.
- * @param {Array.<number>} simplifiedEnds Simplified ends.
- * @return {number} Simplified offset.
- */
- ol.geom.flat.simplify.douglasPeuckers = function(flatCoordinates, offset,
- ends, stride, squaredTolerance, simplifiedFlatCoordinates,
- simplifiedOffset, simplifiedEnds) {
- var i, ii;
- for (i = 0, ii = ends.length; i < ii; ++i) {
- var end = ends[i];
- simplifiedOffset = ol.geom.flat.simplify.douglasPeucker(
- flatCoordinates, offset, end, stride, squaredTolerance,
- simplifiedFlatCoordinates, simplifiedOffset);
- simplifiedEnds.push(simplifiedOffset);
- offset = end;
- }
- return simplifiedOffset;
- };
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {Array.<Array.<number>>} endss Endss.
- * @param {number} stride Stride.
- * @param {number} squaredTolerance Squared tolerance.
- * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
- * coordinates.
- * @param {number} simplifiedOffset Simplified offset.
- * @param {Array.<Array.<number>>} simplifiedEndss Simplified endss.
- * @return {number} Simplified offset.
- */
- ol.geom.flat.simplify.douglasPeuckerss = function(
- flatCoordinates, offset, endss, stride, squaredTolerance,
- simplifiedFlatCoordinates, simplifiedOffset, simplifiedEndss) {
- var i, ii;
- for (i = 0, ii = endss.length; i < ii; ++i) {
- var ends = endss[i];
- var simplifiedEnds = [];
- simplifiedOffset = ol.geom.flat.simplify.douglasPeuckers(
- flatCoordinates, offset, ends, stride, squaredTolerance,
- simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds);
- simplifiedEndss.push(simplifiedEnds);
- offset = ends[ends.length - 1];
- }
- return simplifiedOffset;
- };
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {number} end End.
- * @param {number} stride Stride.
- * @param {number} squaredTolerance Squared tolerance.
- * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
- * coordinates.
- * @param {number} simplifiedOffset Simplified offset.
- * @return {number} Simplified offset.
- */
- ol.geom.flat.simplify.radialDistance = function(flatCoordinates, offset, end,
- stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset) {
- if (end <= offset + stride) {
- // zero or one point, no simplification possible, so copy and return
- for (; offset < end; offset += stride) {
- simplifiedFlatCoordinates[simplifiedOffset++] = flatCoordinates[offset];
- simplifiedFlatCoordinates[simplifiedOffset++] =
- flatCoordinates[offset + 1];
- }
- return simplifiedOffset;
- }
- var x1 = flatCoordinates[offset];
- var y1 = flatCoordinates[offset + 1];
- // copy first point
- simplifiedFlatCoordinates[simplifiedOffset++] = x1;
- simplifiedFlatCoordinates[simplifiedOffset++] = y1;
- var x2 = x1;
- var y2 = y1;
- for (offset += stride; offset < end; offset += stride) {
- x2 = flatCoordinates[offset];
- y2 = flatCoordinates[offset + 1];
- if (ol.math.squaredDistance(x1, y1, x2, y2) > squaredTolerance) {
- // copy point at offset
- simplifiedFlatCoordinates[simplifiedOffset++] = x2;
- simplifiedFlatCoordinates[simplifiedOffset++] = y2;
- x1 = x2;
- y1 = y2;
- }
- }
- if (x2 != x1 || y2 != y1) {
- // copy last point
- simplifiedFlatCoordinates[simplifiedOffset++] = x2;
- simplifiedFlatCoordinates[simplifiedOffset++] = y2;
- }
- return simplifiedOffset;
- };
- /**
- * @param {number} value Value.
- * @param {number} tolerance Tolerance.
- * @return {number} Rounded value.
- */
- ol.geom.flat.simplify.snap = function(value, tolerance) {
- return tolerance * Math.round(value / tolerance);
- };
- /**
- * Simplifies a line string using an algorithm designed by Tim Schaub.
- * Coordinates are snapped to the nearest value in a virtual grid and
- * consecutive duplicate coordinates are discarded. This effectively preserves
- * topology as the simplification of any subsection of a line string is
- * independent of the rest of the line string. This means that, for examples,
- * the common edge between two polygons will be simplified to the same line
- * string independently in both polygons. This implementation uses a single
- * pass over the coordinates and eliminates intermediate collinear points.
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {number} end End.
- * @param {number} stride Stride.
- * @param {number} tolerance Tolerance.
- * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
- * coordinates.
- * @param {number} simplifiedOffset Simplified offset.
- * @return {number} Simplified offset.
- */
- ol.geom.flat.simplify.quantize = function(flatCoordinates, offset, end, stride,
- tolerance, simplifiedFlatCoordinates, simplifiedOffset) {
- // do nothing if the line is empty
- if (offset == end) {
- return simplifiedOffset;
- }
- // snap the first coordinate (P1)
- var x1 = ol.geom.flat.simplify.snap(flatCoordinates[offset], tolerance);
- var y1 = ol.geom.flat.simplify.snap(flatCoordinates[offset + 1], tolerance);
- offset += stride;
- // add the first coordinate to the output
- simplifiedFlatCoordinates[simplifiedOffset++] = x1;
- simplifiedFlatCoordinates[simplifiedOffset++] = y1;
- // find the next coordinate that does not snap to the same value as the first
- // coordinate (P2)
- var x2, y2;
- do {
- x2 = ol.geom.flat.simplify.snap(flatCoordinates[offset], tolerance);
- y2 = ol.geom.flat.simplify.snap(flatCoordinates[offset + 1], tolerance);
- offset += stride;
- if (offset == end) {
- // all coordinates snap to the same value, the line collapses to a point
- // push the last snapped value anyway to ensure that the output contains
- // at least two points
- // FIXME should we really return at least two points anyway?
- simplifiedFlatCoordinates[simplifiedOffset++] = x2;
- simplifiedFlatCoordinates[simplifiedOffset++] = y2;
- return simplifiedOffset;
- }
- } while (x2 == x1 && y2 == y1);
- while (offset < end) {
- var x3, y3;
- // snap the next coordinate (P3)
- x3 = ol.geom.flat.simplify.snap(flatCoordinates[offset], tolerance);
- y3 = ol.geom.flat.simplify.snap(flatCoordinates[offset + 1], tolerance);
- offset += stride;
- // skip P3 if it is equal to P2
- if (x3 == x2 && y3 == y2) {
- continue;
- }
- // calculate the delta between P1 and P2
- var dx1 = x2 - x1;
- var dy1 = y2 - y1;
- // calculate the delta between P3 and P1
- var dx2 = x3 - x1;
- var dy2 = y3 - y1;
- // if P1, P2, and P3 are colinear and P3 is further from P1 than P2 is from
- // P1 in the same direction then P2 is on the straight line between P1 and
- // P3
- if ((dx1 * dy2 == dy1 * dx2) &&
- ((dx1 < 0 && dx2 < dx1) || dx1 == dx2 || (dx1 > 0 && dx2 > dx1)) &&
- ((dy1 < 0 && dy2 < dy1) || dy1 == dy2 || (dy1 > 0 && dy2 > dy1))) {
- // discard P2 and set P2 = P3
- x2 = x3;
- y2 = y3;
- continue;
- }
- // either P1, P2, and P3 are not colinear, or they are colinear but P3 is
- // between P3 and P1 or on the opposite half of the line to P2. add P2,
- // and continue with P1 = P2 and P2 = P3
- simplifiedFlatCoordinates[simplifiedOffset++] = x2;
- simplifiedFlatCoordinates[simplifiedOffset++] = y2;
- x1 = x2;
- y1 = y2;
- x2 = x3;
- y2 = y3;
- }
- // add the last point (P2)
- simplifiedFlatCoordinates[simplifiedOffset++] = x2;
- simplifiedFlatCoordinates[simplifiedOffset++] = y2;
- return simplifiedOffset;
- };
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {Array.<number>} ends Ends.
- * @param {number} stride Stride.
- * @param {number} tolerance Tolerance.
- * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
- * coordinates.
- * @param {number} simplifiedOffset Simplified offset.
- * @param {Array.<number>} simplifiedEnds Simplified ends.
- * @return {number} Simplified offset.
- */
- ol.geom.flat.simplify.quantizes = function(
- flatCoordinates, offset, ends, stride,
- tolerance,
- simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds) {
- var i, ii;
- for (i = 0, ii = ends.length; i < ii; ++i) {
- var end = ends[i];
- simplifiedOffset = ol.geom.flat.simplify.quantize(
- flatCoordinates, offset, end, stride,
- tolerance,
- simplifiedFlatCoordinates, simplifiedOffset);
- simplifiedEnds.push(simplifiedOffset);
- offset = end;
- }
- return simplifiedOffset;
- };
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {Array.<Array.<number>>} endss Endss.
- * @param {number} stride Stride.
- * @param {number} tolerance Tolerance.
- * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
- * coordinates.
- * @param {number} simplifiedOffset Simplified offset.
- * @param {Array.<Array.<number>>} simplifiedEndss Simplified endss.
- * @return {number} Simplified offset.
- */
- ol.geom.flat.simplify.quantizess = function(
- flatCoordinates, offset, endss, stride,
- tolerance,
- simplifiedFlatCoordinates, simplifiedOffset, simplifiedEndss) {
- var i, ii;
- for (i = 0, ii = endss.length; i < ii; ++i) {
- var ends = endss[i];
- var simplifiedEnds = [];
- simplifiedOffset = ol.geom.flat.simplify.quantizes(
- flatCoordinates, offset, ends, stride,
- tolerance,
- simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds);
- simplifiedEndss.push(simplifiedEnds);
- offset = ends[ends.length - 1];
- }
- return simplifiedOffset;
- };
- ol.geom.GeometryType = {
- POINT: 'Point',
- LINE_STRING: 'LineString',
- LINEAR_RING: 'LinearRing',
- POLYGON: 'Polygon',
- MULTI_POINT: 'MultiPoint',
- MULTI_LINE_STRING: 'MultiLineString',
- MULTI_POLYGON: 'MultiPolygon',
- GEOMETRY_COLLECTION: 'GeometryCollection',
- CIRCLE: 'Circle'
- };
- /**
- * @classdesc
- * Abstract base class; normally only used for creating subclasses and not
- * instantiated in apps.
- * Base class for vector geometries.
- *
- * To get notified of changes to the geometry, register a listener for the
- * generic `change` event on your geometry instance.
- *
- * @constructor
- * @abstract
- * @extends {ol.Object}
- * @api
- */
- ol.geom.Geometry = function() {
- ol.Object.call(this);
- /**
- * @private
- * @type {ol.Extent}
- */
- this.extent_ = ol.extent.createEmpty();
- /**
- * @private
- * @type {number}
- */
- this.extentRevision_ = -1;
- /**
- * @protected
- * @type {Object.<string, ol.geom.Geometry>}
- */
- this.simplifiedGeometryCache = {};
- /**
- * @protected
- * @type {number}
- */
- this.simplifiedGeometryMaxMinSquaredTolerance = 0;
- /**
- * @protected
- * @type {number}
- */
- this.simplifiedGeometryRevision = 0;
- /**
- * @private
- * @type {ol.Transform}
- */
- this.tmpTransform_ = ol.transform.create();
- };
- ol.inherits(ol.geom.Geometry, ol.Object);
- /**
- * Make a complete copy of the geometry.
- * @abstract
- * @return {!ol.geom.Geometry} Clone.
- */
- ol.geom.Geometry.prototype.clone = function() {};
- /**
- * @abstract
- * @param {number} x X.
- * @param {number} y Y.
- * @param {ol.Coordinate} closestPoint Closest point.
- * @param {number} minSquaredDistance Minimum squared distance.
- * @return {number} Minimum squared distance.
- */
- ol.geom.Geometry.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {};
- /**
- * Return the closest point of the geometry to the passed point as
- * {@link ol.Coordinate coordinate}.
- * @param {ol.Coordinate} point Point.
- * @param {ol.Coordinate=} opt_closestPoint Closest point.
- * @return {ol.Coordinate} Closest point.
- * @api
- */
- ol.geom.Geometry.prototype.getClosestPoint = function(point, opt_closestPoint) {
- var closestPoint = opt_closestPoint ? opt_closestPoint : [NaN, NaN];
- this.closestPointXY(point[0], point[1], closestPoint, Infinity);
- return closestPoint;
- };
- /**
- * Returns true if this geometry includes the specified coordinate. If the
- * coordinate is on the boundary of the geometry, returns false.
- * @param {ol.Coordinate} coordinate Coordinate.
- * @return {boolean} Contains coordinate.
- * @api
- */
- ol.geom.Geometry.prototype.intersectsCoordinate = function(coordinate) {
- return this.containsXY(coordinate[0], coordinate[1]);
- };
- /**
- * @abstract
- * @param {ol.Extent} extent Extent.
- * @protected
- * @return {ol.Extent} extent Extent.
- */
- ol.geom.Geometry.prototype.computeExtent = function(extent) {};
- /**
- * @param {number} x X.
- * @param {number} y Y.
- * @return {boolean} Contains (x, y).
- */
- ol.geom.Geometry.prototype.containsXY = ol.functions.FALSE;
- /**
- * Get the extent of the geometry.
- * @param {ol.Extent=} opt_extent Extent.
- * @return {ol.Extent} extent Extent.
- * @api
- */
- ol.geom.Geometry.prototype.getExtent = function(opt_extent) {
- if (this.extentRevision_ != this.getRevision()) {
- this.extent_ = this.computeExtent(this.extent_);
- this.extentRevision_ = this.getRevision();
- }
- return ol.extent.returnOrUpdate(this.extent_, opt_extent);
- };
- /**
- * Rotate the geometry around a given coordinate. This modifies the geometry
- * coordinates in place.
- * @abstract
- * @param {number} angle Rotation angle in radians.
- * @param {ol.Coordinate} anchor The rotation center.
- * @api
- */
- ol.geom.Geometry.prototype.rotate = function(angle, anchor) {};
- /**
- * Scale the geometry (with an optional origin). This modifies the geometry
- * coordinates in place.
- * @abstract
- * @param {number} sx The scaling factor in the x-direction.
- * @param {number=} opt_sy The scaling factor in the y-direction (defaults to
- * sx).
- * @param {ol.Coordinate=} opt_anchor The scale origin (defaults to the center
- * of the geometry extent).
- * @api
- */
- ol.geom.Geometry.prototype.scale = function(sx, opt_sy, opt_anchor) {};
- /**
- * Create a simplified version of this geometry. For linestrings, this uses
- * the the {@link
- * https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
- * Douglas Peucker} algorithm. For polygons, a quantization-based
- * simplification is used to preserve topology.
- * @function
- * @param {number} tolerance The tolerance distance for simplification.
- * @return {ol.geom.Geometry} A new, simplified version of the original
- * geometry.
- * @api
- */
- ol.geom.Geometry.prototype.simplify = function(tolerance) {
- return this.getSimplifiedGeometry(tolerance * tolerance);
- };
- /**
- * Create a simplified version of this geometry using the Douglas Peucker
- * algorithm.
- * @see https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
- * @abstract
- * @param {number} squaredTolerance Squared tolerance.
- * @return {ol.geom.Geometry} Simplified geometry.
- */
- ol.geom.Geometry.prototype.getSimplifiedGeometry = function(squaredTolerance) {};
- /**
- * Get the type of this geometry.
- * @abstract
- * @return {ol.geom.GeometryType} Geometry type.
- */
- ol.geom.Geometry.prototype.getType = function() {};
- /**
- * Apply a transform function to each coordinate of the geometry.
- * The geometry is modified in place.
- * If you do not want the geometry modified in place, first `clone()` it and
- * then use this function on the clone.
- * @abstract
- * @param {ol.TransformFunction} transformFn Transform.
- */
- ol.geom.Geometry.prototype.applyTransform = function(transformFn) {};
- /**
- * Test if the geometry and the passed extent intersect.
- * @abstract
- * @param {ol.Extent} extent Extent.
- * @return {boolean} `true` if the geometry and the extent intersect.
- */
- ol.geom.Geometry.prototype.intersectsExtent = function(extent) {};
- /**
- * Translate the geometry. This modifies the geometry coordinates in place. If
- * instead you want a new geometry, first `clone()` this geometry.
- * @abstract
- * @param {number} deltaX Delta X.
- * @param {number} deltaY Delta Y.
- */
- ol.geom.Geometry.prototype.translate = function(deltaX, deltaY) {};
- /**
- * Transform each coordinate of the geometry from one coordinate reference
- * system to another. The geometry is modified in place.
- * For example, a line will be transformed to a line and a circle to a circle.
- * If you do not want the geometry modified in place, first `clone()` it and
- * then use this function on the clone.
- *
- * @param {ol.ProjectionLike} source The current projection. Can be a
- * string identifier or a {@link ol.proj.Projection} object.
- * @param {ol.ProjectionLike} destination The desired projection. Can be a
- * string identifier or a {@link ol.proj.Projection} object.
- * @return {ol.geom.Geometry} This geometry. Note that original geometry is
- * modified in place.
- * @api
- */
- ol.geom.Geometry.prototype.transform = function(source, destination) {
- var tmpTransform = this.tmpTransform_;
- source = ol.proj.get(source);
- var transformFn = source.getUnits() == ol.proj.Units.TILE_PIXELS ?
- function(inCoordinates, outCoordinates, stride) {
- var pixelExtent = source.getExtent();
- var projectedExtent = source.getWorldExtent();
- var scale = ol.extent.getHeight(projectedExtent) / ol.extent.getHeight(pixelExtent);
- ol.transform.compose(tmpTransform,
- projectedExtent[0], projectedExtent[3],
- scale, -scale, 0,
- 0, 0);
- ol.geom.flat.transform.transform2D(inCoordinates, 0, inCoordinates.length, stride,
- tmpTransform, outCoordinates);
- return ol.proj.getTransform(source, destination)(inCoordinates, outCoordinates, stride);
- } :
- ol.proj.getTransform(source, destination);
- this.applyTransform(transformFn);
- return this;
- };
- /**
- * @classdesc
- * Abstract base class; only used for creating subclasses; do not instantiate
- * in apps, as cannot be rendered.
- *
- * @constructor
- * @abstract
- * @extends {ol.geom.Geometry}
- * @api
- */
- ol.geom.SimpleGeometry = function() {
- ol.geom.Geometry.call(this);
- /**
- * @protected
- * @type {ol.geom.GeometryLayout}
- */
- this.layout = ol.geom.GeometryLayout.XY;
- /**
- * @protected
- * @type {number}
- */
- this.stride = 2;
- /**
- * @protected
- * @type {Array.<number>}
- */
- this.flatCoordinates = null;
- };
- ol.inherits(ol.geom.SimpleGeometry, ol.geom.Geometry);
- /**
- * @param {number} stride Stride.
- * @private
- * @return {ol.geom.GeometryLayout} layout Layout.
- */
- ol.geom.SimpleGeometry.getLayoutForStride_ = function(stride) {
- var layout;
- if (stride == 2) {
- layout = ol.geom.GeometryLayout.XY;
- } else if (stride == 3) {
- layout = ol.geom.GeometryLayout.XYZ;
- } else if (stride == 4) {
- layout = ol.geom.GeometryLayout.XYZM;
- }
- return /** @type {ol.geom.GeometryLayout} */ (layout);
- };
- /**
- * @param {ol.geom.GeometryLayout} layout Layout.
- * @return {number} Stride.
- */
- ol.geom.SimpleGeometry.getStrideForLayout = function(layout) {
- var stride;
- if (layout == ol.geom.GeometryLayout.XY) {
- stride = 2;
- } else if (layout == ol.geom.GeometryLayout.XYZ || layout == ol.geom.GeometryLayout.XYM) {
- stride = 3;
- } else if (layout == ol.geom.GeometryLayout.XYZM) {
- stride = 4;
- }
- return /** @type {number} */ (stride);
- };
- /**
- * @inheritDoc
- */
- ol.geom.SimpleGeometry.prototype.containsXY = ol.functions.FALSE;
- /**
- * @inheritDoc
- */
- ol.geom.SimpleGeometry.prototype.computeExtent = function(extent) {
- return ol.extent.createOrUpdateFromFlatCoordinates(
- this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
- extent);
- };
- /**
- * @abstract
- * @return {Array} Coordinates.
- */
- ol.geom.SimpleGeometry.prototype.getCoordinates = function() {};
- /**
- * Return the first coordinate of the geometry.
- * @return {ol.Coordinate} First coordinate.
- * @api
- */
- ol.geom.SimpleGeometry.prototype.getFirstCoordinate = function() {
- return this.flatCoordinates.slice(0, this.stride);
- };
- /**
- * @return {Array.<number>} Flat coordinates.
- */
- ol.geom.SimpleGeometry.prototype.getFlatCoordinates = function() {
- return this.flatCoordinates;
- };
- /**
- * Return the last coordinate of the geometry.
- * @return {ol.Coordinate} Last point.
- * @api
- */
- ol.geom.SimpleGeometry.prototype.getLastCoordinate = function() {
- return this.flatCoordinates.slice(this.flatCoordinates.length - this.stride);
- };
- /**
- * Return the {@link ol.geom.GeometryLayout layout} of the geometry.
- * @return {ol.geom.GeometryLayout} Layout.
- * @api
- */
- ol.geom.SimpleGeometry.prototype.getLayout = function() {
- return this.layout;
- };
- /**
- * @inheritDoc
- */
- ol.geom.SimpleGeometry.prototype.getSimplifiedGeometry = function(squaredTolerance) {
- if (this.simplifiedGeometryRevision != this.getRevision()) {
- ol.obj.clear(this.simplifiedGeometryCache);
- this.simplifiedGeometryMaxMinSquaredTolerance = 0;
- this.simplifiedGeometryRevision = this.getRevision();
- }
- // If squaredTolerance is negative or if we know that simplification will not
- // have any effect then just return this.
- if (squaredTolerance < 0 ||
- (this.simplifiedGeometryMaxMinSquaredTolerance !== 0 &&
- squaredTolerance <= this.simplifiedGeometryMaxMinSquaredTolerance)) {
- return this;
- }
- var key = squaredTolerance.toString();
- if (this.simplifiedGeometryCache.hasOwnProperty(key)) {
- return this.simplifiedGeometryCache[key];
- } else {
- var simplifiedGeometry =
- this.getSimplifiedGeometryInternal(squaredTolerance);
- var simplifiedFlatCoordinates = simplifiedGeometry.getFlatCoordinates();
- if (simplifiedFlatCoordinates.length < this.flatCoordinates.length) {
- this.simplifiedGeometryCache[key] = simplifiedGeometry;
- return simplifiedGeometry;
- } else {
- // Simplification did not actually remove any coordinates. We now know
- // that any calls to getSimplifiedGeometry with a squaredTolerance less
- // than or equal to the current squaredTolerance will also not have any
- // effect. This allows us to short circuit simplification (saving CPU
- // cycles) and prevents the cache of simplified geometries from filling
- // up with useless identical copies of this geometry (saving memory).
- this.simplifiedGeometryMaxMinSquaredTolerance = squaredTolerance;
- return this;
- }
- }
- };
- /**
- * @param {number} squaredTolerance Squared tolerance.
- * @return {ol.geom.SimpleGeometry} Simplified geometry.
- * @protected
- */
- ol.geom.SimpleGeometry.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
- return this;
- };
- /**
- * @return {number} Stride.
- */
- ol.geom.SimpleGeometry.prototype.getStride = function() {
- return this.stride;
- };
- /**
- * @param {ol.geom.GeometryLayout} layout Layout.
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @protected
- */
- ol.geom.SimpleGeometry.prototype.setFlatCoordinatesInternal = function(layout, flatCoordinates) {
- this.stride = ol.geom.SimpleGeometry.getStrideForLayout(layout);
- this.layout = layout;
- this.flatCoordinates = flatCoordinates;
- };
- /**
- * @abstract
- * @param {Array} coordinates Coordinates.
- * @param {ol.geom.GeometryLayout=} opt_layout Layout.
- */
- ol.geom.SimpleGeometry.prototype.setCoordinates = function(coordinates, opt_layout) {};
- /**
- * @param {ol.geom.GeometryLayout|undefined} layout Layout.
- * @param {Array} coordinates Coordinates.
- * @param {number} nesting Nesting.
- * @protected
- */
- ol.geom.SimpleGeometry.prototype.setLayout = function(layout, coordinates, nesting) {
- /** @type {number} */
- var stride;
- if (layout) {
- stride = ol.geom.SimpleGeometry.getStrideForLayout(layout);
- } else {
- var i;
- for (i = 0; i < nesting; ++i) {
- if (coordinates.length === 0) {
- this.layout = ol.geom.GeometryLayout.XY;
- this.stride = 2;
- return;
- } else {
- coordinates = /** @type {Array} */ (coordinates[0]);
- }
- }
- stride = coordinates.length;
- layout = ol.geom.SimpleGeometry.getLayoutForStride_(stride);
- }
- this.layout = layout;
- this.stride = stride;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.geom.SimpleGeometry.prototype.applyTransform = function(transformFn) {
- if (this.flatCoordinates) {
- transformFn(this.flatCoordinates, this.flatCoordinates, this.stride);
- this.changed();
- }
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.geom.SimpleGeometry.prototype.rotate = function(angle, anchor) {
- var flatCoordinates = this.getFlatCoordinates();
- if (flatCoordinates) {
- var stride = this.getStride();
- ol.geom.flat.transform.rotate(
- flatCoordinates, 0, flatCoordinates.length,
- stride, angle, anchor, flatCoordinates);
- this.changed();
- }
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.geom.SimpleGeometry.prototype.scale = function(sx, opt_sy, opt_anchor) {
- var sy = opt_sy;
- if (sy === undefined) {
- sy = sx;
- }
- var anchor = opt_anchor;
- if (!anchor) {
- anchor = ol.extent.getCenter(this.getExtent());
- }
- var flatCoordinates = this.getFlatCoordinates();
- if (flatCoordinates) {
- var stride = this.getStride();
- ol.geom.flat.transform.scale(
- flatCoordinates, 0, flatCoordinates.length,
- stride, sx, sy, anchor, flatCoordinates);
- this.changed();
- }
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.geom.SimpleGeometry.prototype.translate = function(deltaX, deltaY) {
- var flatCoordinates = this.getFlatCoordinates();
- if (flatCoordinates) {
- var stride = this.getStride();
- ol.geom.flat.transform.translate(
- flatCoordinates, 0, flatCoordinates.length, stride,
- deltaX, deltaY, flatCoordinates);
- this.changed();
- }
- };
- /**
- * @param {ol.geom.SimpleGeometry} simpleGeometry Simple geometry.
- * @param {ol.Transform} transform Transform.
- * @param {Array.<number>=} opt_dest Destination.
- * @return {Array.<number>} Transformed flat coordinates.
- */
- ol.geom.SimpleGeometry.transform2D = function(simpleGeometry, transform, opt_dest) {
- var flatCoordinates = simpleGeometry.getFlatCoordinates();
- if (!flatCoordinates) {
- return null;
- } else {
- var stride = simpleGeometry.getStride();
- return ol.geom.flat.transform.transform2D(
- flatCoordinates, 0, flatCoordinates.length, stride,
- transform, opt_dest);
- }
- };
- ol.geom.Polygon = function(coordinates, opt_layout) {
- ol.geom.SimpleGeometry.call(this);
- /**
- * @type {Array.<number>}
- * @private
- */
- this.ends_ = [];
- /**
- * @private
- * @type {number}
- */
- this.flatInteriorPointRevision_ = -1;
- /**
- * @private
- * @type {ol.Coordinate}
- */
- this.flatInteriorPoint_ = null;
- /**
- * @private
- * @type {number}
- */
- this.maxDelta_ = -1;
- /**
- * @private
- * @type {number}
- */
- this.maxDeltaRevision_ = -1;
- /**
- * @private
- * @type {number}
- */
- this.orientedRevision_ = -1;
- /**
- * @private
- * @type {Array.<number>}
- */
- this.orientedFlatCoordinates_ = null;
- this.setCoordinates(coordinates, opt_layout);
- };
- ol.inherits(ol.geom.Polygon, ol.geom.SimpleGeometry);
- /**
- * Append the passed linear ring to this polygon.
- * @param {ol.geom.LinearRing} linearRing Linear ring.
- * @api
- */
- ol.geom.Polygon.prototype.appendLinearRing = function(linearRing) {
- if (!this.flatCoordinates) {
- this.flatCoordinates = linearRing.getFlatCoordinates().slice();
- } else {
- ol.array.extend(this.flatCoordinates, linearRing.getFlatCoordinates());
- }
- this.ends_.push(this.flatCoordinates.length);
- this.changed();
- };
- /**
- * Make a complete copy of the geometry.
- * @return {!ol.geom.Polygon} Clone.
- * @override
- * @api
- */
- ol.geom.Polygon.prototype.clone = function() {
- var polygon = new ol.geom.Polygon(null);
- polygon.setFlatCoordinates(
- this.layout, this.flatCoordinates.slice(), this.ends_.slice());
- return polygon;
- };
- /**
- * @inheritDoc
- */
- ol.geom.Polygon.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
- if (minSquaredDistance <
- ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
- return minSquaredDistance;
- }
- if (this.maxDeltaRevision_ != this.getRevision()) {
- this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getsMaxSquaredDelta(
- this.flatCoordinates, 0, this.ends_, this.stride, 0));
- this.maxDeltaRevision_ = this.getRevision();
- }
- return ol.geom.flat.closest.getsClosestPoint(
- this.flatCoordinates, 0, this.ends_, this.stride,
- this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);
- };
- /**
- * @inheritDoc
- */
- ol.geom.Polygon.prototype.containsXY = function(x, y) {
- return ol.geom.flat.contains.linearRingsContainsXY(
- this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, x, y);
- };
- /**
- * Return the area of the polygon on projected plane.
- * @return {number} Area (on projected plane).
- * @api
- */
- ol.geom.Polygon.prototype.getArea = function() {
- return ol.geom.flat.area.linearRings(
- this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride);
- };
- /**
- * Get the coordinate array for this geometry. This array has the structure
- * of a GeoJSON coordinate array for polygons.
- *
- * @param {boolean=} opt_right Orient coordinates according to the right-hand
- * rule (counter-clockwise for exterior and clockwise for interior rings).
- * If `false`, coordinates will be oriented according to the left-hand rule
- * (clockwise for exterior and counter-clockwise for interior rings).
- * By default, coordinate orientation will depend on how the geometry was
- * constructed.
- * @return {Array.<Array.<ol.Coordinate>>} Coordinates.
- * @override
- * @api
- */
- ol.geom.Polygon.prototype.getCoordinates = function(opt_right) {
- var flatCoordinates;
- if (opt_right !== undefined) {
- flatCoordinates = this.getOrientedFlatCoordinates().slice();
- ol.geom.flat.orient.orientLinearRings(
- flatCoordinates, 0, this.ends_, this.stride, opt_right);
- } else {
- flatCoordinates = this.flatCoordinates;
- }
- return ol.geom.flat.inflate.coordinatess(
- flatCoordinates, 0, this.ends_, this.stride);
- };
- /**
- * @return {Array.<number>} Ends.
- */
- ol.geom.Polygon.prototype.getEnds = function() {
- return this.ends_;
- };
- /**
- * @return {Array.<number>} Interior point.
- */
- ol.geom.Polygon.prototype.getFlatInteriorPoint = function() {
- if (this.flatInteriorPointRevision_ != this.getRevision()) {
- var flatCenter = ol.extent.getCenter(this.getExtent());
- this.flatInteriorPoint_ = ol.geom.flat.interiorpoint.linearRings(
- this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride,
- flatCenter, 0);
- this.flatInteriorPointRevision_ = this.getRevision();
- }
- return this.flatInteriorPoint_;
- };
- /**
- * Return an interior point of the polygon.
- * @return {ol.geom.Point} Interior point as XYM coordinate, where M is the
- * length of the horizontal intersection that the point belongs to.
- * @api
- */
- ol.geom.Polygon.prototype.getInteriorPoint = function() {
- return new ol.geom.Point(this.getFlatInteriorPoint(), ol.geom.GeometryLayout.XYM);
- };
- /**
- * Return the number of rings of the polygon, this includes the exterior
- * ring and any interior rings.
- *
- * @return {number} Number of rings.
- * @api
- */
- ol.geom.Polygon.prototype.getLinearRingCount = function() {
- return this.ends_.length;
- };
- /**
- * Return the Nth linear ring of the polygon geometry. Return `null` if the
- * given index is out of range.
- * The exterior linear ring is available at index `0` and the interior rings
- * at index `1` and beyond.
- *
- * @param {number} index Index.
- * @return {ol.geom.LinearRing} Linear ring.
- * @api
- */
- ol.geom.Polygon.prototype.getLinearRing = function(index) {
- if (index < 0 || this.ends_.length <= index) {
- return null;
- }
- var linearRing = new ol.geom.LinearRing(null);
- linearRing.setFlatCoordinates(this.layout, this.flatCoordinates.slice(
- index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]));
- return linearRing;
- };
- /**
- * Return the linear rings of the polygon.
- * @return {Array.<ol.geom.LinearRing>} Linear rings.
- * @api
- */
- ol.geom.Polygon.prototype.getLinearRings = function() {
- var layout = this.layout;
- var flatCoordinates = this.flatCoordinates;
- var ends = this.ends_;
- var linearRings = [];
- var offset = 0;
- var i, ii;
- for (i = 0, ii = ends.length; i < ii; ++i) {
- var end = ends[i];
- var linearRing = new ol.geom.LinearRing(null);
- linearRing.setFlatCoordinates(layout, flatCoordinates.slice(offset, end));
- linearRings.push(linearRing);
- offset = end;
- }
- return linearRings;
- };
- /**
- * @return {Array.<number>} Oriented flat coordinates.
- */
- ol.geom.Polygon.prototype.getOrientedFlatCoordinates = function() {
- if (this.orientedRevision_ != this.getRevision()) {
- var flatCoordinates = this.flatCoordinates;
- if (ol.geom.flat.orient.linearRingsAreOriented(
- flatCoordinates, 0, this.ends_, this.stride)) {
- this.orientedFlatCoordinates_ = flatCoordinates;
- } else {
- this.orientedFlatCoordinates_ = flatCoordinates.slice();
- this.orientedFlatCoordinates_.length =
- ol.geom.flat.orient.orientLinearRings(
- this.orientedFlatCoordinates_, 0, this.ends_, this.stride);
- }
- this.orientedRevision_ = this.getRevision();
- }
- return this.orientedFlatCoordinates_;
- };
- /**
- * @inheritDoc
- */
- ol.geom.Polygon.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
- var simplifiedFlatCoordinates = [];
- var simplifiedEnds = [];
- simplifiedFlatCoordinates.length = ol.geom.flat.simplify.quantizes(
- this.flatCoordinates, 0, this.ends_, this.stride,
- Math.sqrt(squaredTolerance),
- simplifiedFlatCoordinates, 0, simplifiedEnds);
- var simplifiedPolygon = new ol.geom.Polygon(null);
- simplifiedPolygon.setFlatCoordinates(
- ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates, simplifiedEnds);
- return simplifiedPolygon;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.geom.Polygon.prototype.getType = function() {
- return ol.geom.GeometryType.POLYGON;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.geom.Polygon.prototype.intersectsExtent = function(extent) {
- return ol.geom.flat.intersectsextent.linearRings(
- this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, extent);
- };
- /**
- * Set the coordinates of the polygon.
- * @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
- * @param {ol.geom.GeometryLayout=} opt_layout Layout.
- * @override
- * @api
- */
- ol.geom.Polygon.prototype.setCoordinates = function(coordinates, opt_layout) {
- if (!coordinates) {
- this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.ends_);
- } else {
- this.setLayout(opt_layout, coordinates, 2);
- if (!this.flatCoordinates) {
- this.flatCoordinates = [];
- }
- var ends = ol.geom.flat.deflate.coordinatess(
- this.flatCoordinates, 0, coordinates, this.stride, this.ends_);
- this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1];
- //this.changed();
- }
- };
- /**
- * @param {ol.geom.GeometryLayout} layout Layout.
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {Array.<number>} ends Ends.
- */
- ol.geom.Polygon.prototype.setFlatCoordinates = function(layout, flatCoordinates, ends) {
- this.setFlatCoordinatesInternal(layout, flatCoordinates);
- this.ends_ = ends;
- //this.changed();
- };
- /**
- * Create an approximation of a circle on the surface of a sphere.
- * @param {ol.Sphere} sphere The sphere.
- * @param {ol.Coordinate} center Center (`[lon, lat]` in degrees).
- * @param {number} radius The great-circle distance from the center to
- * the polygon vertices.
- * @param {number=} opt_n Optional number of vertices for the resulting
- * polygon. Default is `32`.
- * @return {ol.geom.Polygon} The "circular" polygon.
- * @api
- */
- ol.geom.Polygon.circular = function(sphere, center, radius, opt_n) {
- var n = opt_n ? opt_n : 32;
- /** @type {Array.<number>} */
- var flatCoordinates = [];
- var i;
- for (i = 0; i < n; ++i) {
- ol.array.extend(
- flatCoordinates, sphere.offset(center, radius, 2 * Math.PI * i / n));
- }
- flatCoordinates.push(flatCoordinates[0], flatCoordinates[1]);
- var polygon = new ol.geom.Polygon(null);
- polygon.setFlatCoordinates(
- ol.geom.GeometryLayout.XY, flatCoordinates, [flatCoordinates.length]);
- return polygon;
- };
- /**
- * Create a polygon from an extent. The layout used is `XY`.
- * @param {ol.Extent} extent The extent.
- * @return {ol.geom.Polygon} The polygon.
- * @api
- */
- ol.geom.Polygon.fromExtent = function(extent) {
- var minX = extent[0];
- var minY = extent[1];
- var maxX = extent[2];
- var maxY = extent[3];
- var flatCoordinates =
- [minX, minY, minX, maxY, maxX, maxY, maxX, minY, minX, minY];
- var polygon = new ol.geom.Polygon(null);
- polygon.setFlatCoordinates(
- ol.geom.GeometryLayout.XY, flatCoordinates, [flatCoordinates.length]);
- return polygon;
- };
- /**
- * Create a regular polygon from a circle.
- * @param {ol.geom.Circle} circle Circle geometry.
- * @param {number=} opt_sides Number of sides of the polygon. Default is 32.
- * @param {number=} opt_angle Start angle for the first vertex of the polygon in
- * radians. Default is 0.
- * @return {ol.geom.Polygon} Polygon geometry.
- * @api
- */
- ol.geom.Polygon.fromCircle = function(circle, opt_sides, opt_angle) {
- var sides = opt_sides ? opt_sides : 32;
- var stride = circle.getStride();
- var layout = circle.getLayout();
- var polygon = new ol.geom.Polygon(null, layout);
- var arrayLength = stride * (sides + 1);
- var flatCoordinates = new Array(arrayLength);
- for (var i = 0; i < arrayLength; i++) {
- flatCoordinates[i] = 0;
- }
- var ends = [flatCoordinates.length];
- polygon.setFlatCoordinates(layout, flatCoordinates, ends);
- ol.geom.Polygon.makeRegular(
- polygon, circle.getCenter(), circle.getRadius(), opt_angle);
- return polygon;
- };
- /**
- * Modify the coordinates of a polygon to make it a regular polygon.
- * @param {ol.geom.Polygon} polygon Polygon geometry.
- * @param {ol.Coordinate} center Center of the regular polygon.
- * @param {number} radius Radius of the regular polygon.
- * @param {number=} opt_angle Start angle for the first vertex of the polygon in
- * radians. Default is 0.
- */
- ol.geom.Polygon.makeRegular = function(polygon, center, radius, opt_angle) {
- var flatCoordinates = polygon.getFlatCoordinates();
- var layout = polygon.getLayout();
- var stride = polygon.getStride();
- var ends = polygon.getEnds();
- var sides = flatCoordinates.length / stride - 1;
- var startAngle = opt_angle ? opt_angle : 0;
- var angle, offset;
- for (var i = 0; i <= sides; ++i) {
- offset = i * stride;
- angle = startAngle + (ol.math.modulo(i, sides) * 2 * Math.PI / sides);
- flatCoordinates[offset] = center[0] + (radius * Math.cos(angle));
- flatCoordinates[offset + 1] = center[1] + (radius * Math.sin(angle));
- }
- polygon.setFlatCoordinates(layout, flatCoordinates, ends);
- };
- /**
- * @classdesc
- * Linestring geometry.
- *
- * @constructor
- * @extends {ol.geom.SimpleGeometry}
- * @param {Array.<ol.Coordinate>} coordinates Coordinates.
- * @param {ol.geom.GeometryLayout=} opt_layout Layout.
- * @api
- */
- ol.geom.LineString = function(coordinates, opt_layout) {
- ol.geom.SimpleGeometry.call(this);
- /**
- * @private
- * @type {ol.Coordinate}
- */
- this.flatMidpoint_ = null;
- /**
- * @private
- * @type {number}
- */
- this.flatMidpointRevision_ = -1;
- /**
- * @private
- * @type {number}
- */
- this.maxDelta_ = -1;
- /**
- * @private
- * @type {number}
- */
- this.maxDeltaRevision_ = -1;
- this.setCoordinates(coordinates, opt_layout);
- };
- ol.inherits(ol.geom.LineString, ol.geom.SimpleGeometry);
- /**
- * Append the passed coordinate to the coordinates of the linestring.
- * @param {ol.Coordinate} coordinate Coordinate.
- * @api
- */
- ol.geom.LineString.prototype.appendCoordinate = function(coordinate) {
- if (!this.flatCoordinates) {
- this.flatCoordinates = coordinate.slice();
- } else {
- ol.array.extend(this.flatCoordinates, coordinate);
- }
- this.changed();
- };
- /**
- * Make a complete copy of the geometry.
- * @return {!ol.geom.LineString} Clone.
- * @override
- * @api
- */
- ol.geom.LineString.prototype.clone = function() {
- var lineString = new ol.geom.LineString(null);
- lineString.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
- return lineString;
- };
- /**
- * @inheritDoc
- */
- ol.geom.LineString.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
- if (minSquaredDistance <
- ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
- return minSquaredDistance;
- }
- if (this.maxDeltaRevision_ != this.getRevision()) {
- this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getMaxSquaredDelta(
- this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, 0));
- this.maxDeltaRevision_ = this.getRevision();
- }
- return ol.geom.flat.closest.getClosestPoint(
- this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
- this.maxDelta_, false, x, y, closestPoint, minSquaredDistance);
- };
- /**
- * Iterate over each segment, calling the provided callback.
- * If the callback returns a truthy value the function returns that
- * value immediately. Otherwise the function returns `false`.
- *
- * @param {function(this: S, ol.Coordinate, ol.Coordinate): T} callback Function
- * called for each segment.
- * @param {S=} opt_this The object to be used as the value of 'this'
- * within callback.
- * @return {T|boolean} Value.
- * @template T,S
- * @api
- */
- ol.geom.LineString.prototype.forEachSegment = function(callback, opt_this) {
- return ol.geom.flat.segments.forEach(this.flatCoordinates, 0,
- this.flatCoordinates.length, this.stride, callback, opt_this);
- };
- /**
- * Returns the coordinate at `m` using linear interpolation, or `null` if no
- * such coordinate exists.
- *
- * `opt_extrapolate` controls extrapolation beyond the range of Ms in the
- * MultiLineString. If `opt_extrapolate` is `true` then Ms less than the first
- * M will return the first coordinate and Ms greater than the last M will
- * return the last coordinate.
- *
- * @param {number} m M.
- * @param {boolean=} opt_extrapolate Extrapolate. Default is `false`.
- * @return {ol.Coordinate} Coordinate.
- * @api
- */
- ol.geom.LineString.prototype.getCoordinateAtM = function(m, opt_extrapolate) {
- if (this.layout != ol.geom.GeometryLayout.XYM &&
- this.layout != ol.geom.GeometryLayout.XYZM) {
- return null;
- }
- var extrapolate = opt_extrapolate !== undefined ? opt_extrapolate : false;
- return ol.geom.flat.interpolate.lineStringCoordinateAtM(this.flatCoordinates, 0,
- this.flatCoordinates.length, this.stride, m, extrapolate);
- };
- /**
- * Return the coordinates of the linestring.
- * @return {Array.<ol.Coordinate>} Coordinates.
- * @override
- * @api
- */
- ol.geom.LineString.prototype.getCoordinates = function() {
- return ol.geom.flat.inflate.coordinates(
- this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
- };
- /**
- * Return the coordinate at the provided fraction along the linestring.
- * The `fraction` is a number between 0 and 1, where 0 is the start of the
- * linestring and 1 is the end.
- * @param {number} fraction Fraction.
- * @param {ol.Coordinate=} opt_dest Optional coordinate whose values will
- * be modified. If not provided, a new coordinate will be returned.
- * @return {ol.Coordinate} Coordinate of the interpolated point.
- * @api
- */
- ol.geom.LineString.prototype.getCoordinateAt = function(fraction, opt_dest) {
- return ol.geom.flat.interpolate.lineString(
- this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
- fraction, opt_dest);
- };
- /**
- * Return the length of the linestring on projected plane.
- * @return {number} Length (on projected plane).
- * @api
- */
- ol.geom.LineString.prototype.getLength = function() {
- return ol.geom.flat.length.lineString(
- this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
- };
- /**
- * @return {Array.<number>} Flat midpoint.
- */
- ol.geom.LineString.prototype.getFlatMidpoint = function() {
- if (this.flatMidpointRevision_ != this.getRevision()) {
- this.flatMidpoint_ = this.getCoordinateAt(0.5, this.flatMidpoint_);
- this.flatMidpointRevision_ = this.getRevision();
- }
- return this.flatMidpoint_;
- };
- /**
- * @inheritDoc
- */
- ol.geom.LineString.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
- var simplifiedFlatCoordinates = [];
- simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeucker(
- this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
- squaredTolerance, simplifiedFlatCoordinates, 0);
- var simplifiedLineString = new ol.geom.LineString(null);
- simplifiedLineString.setFlatCoordinates(
- ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates);
- return simplifiedLineString;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.geom.LineString.prototype.getType = function() {
- return ol.geom.GeometryType.LINE_STRING;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.geom.LineString.prototype.intersectsExtent = function(extent) {
- return ol.geom.flat.intersectsextent.lineString(
- this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
- extent);
- };
- /**
- * Set the coordinates of the linestring.
- * @param {Array.<ol.Coordinate>} coordinates Coordinates.
- * @param {ol.geom.GeometryLayout=} opt_layout Layout.
- * @override
- * @api
- */
- ol.geom.LineString.prototype.setCoordinates = function(coordinates, opt_layout) {
- if (!coordinates) {
- this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
- } else {
- this.setLayout(opt_layout, coordinates, 1);
- if (!this.flatCoordinates) {
- this.flatCoordinates = [];
- }
- this.flatCoordinates.length = ol.geom.flat.deflate.coordinates(
- this.flatCoordinates, 0, coordinates, this.stride);
- this.changed();
- }
- };
- /**
- * @param {ol.geom.GeometryLayout} layout Layout.
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- */
- ol.geom.LineString.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
- this.setFlatCoordinatesInternal(layout, flatCoordinates);
- this.changed();
- };
- ol.geom.Point = function(coordinates, opt_layout) {
- ol.geom.SimpleGeometry.call(this);
- this.setCoordinates(coordinates, opt_layout);
- };
- ol.inherits(ol.geom.Point, ol.geom.SimpleGeometry);
- ol.geom.Point.prototype.clone = function() {
- var point = new ol.geom.Point(null);
- point.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
- return point;
- };
- /**
- * @inheritDoc
- */
- ol.geom.Point.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
- var flatCoordinates = this.flatCoordinates;
- var squaredDistance = ol.math.squaredDistance(
- x, y, flatCoordinates[0], flatCoordinates[1]);
- if (squaredDistance < minSquaredDistance) {
- var stride = this.stride;
- var i;
- for (i = 0; i < stride; ++i) {
- closestPoint[i] = flatCoordinates[i];
- }
- closestPoint.length = stride;
- return squaredDistance;
- } else {
- return minSquaredDistance;
- }
- };
- ol.geom.Point.prototype.getCoordinates = function() {
- return !this.flatCoordinates ? [] : this.flatCoordinates.slice();
- };
- ol.geom.Point.prototype.computeExtent = function(extent) {
- return ol.extent.createOrUpdateFromCoordinate(this.flatCoordinates, extent);
- };
- ol.geom.Point.prototype.getType = function() {
- return ol.geom.GeometryType.POINT;
- };
- ol.geom.Point.prototype.intersectsExtent = function(extent) {
- return ol.extent.containsXY(extent,
- this.flatCoordinates[0], this.flatCoordinates[1]);
- };
- ol.geom.Point.prototype.setCoordinates = function(coordinates, opt_layout) {
- if (!coordinates) {
- this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
- } else {
- this.setLayout(opt_layout, coordinates, 0);
- if (!this.flatCoordinates) {
- this.flatCoordinates = [];
- }
- this.flatCoordinates.length = ol.geom.flat.deflate.coordinate(
- this.flatCoordinates, 0, coordinates, this.stride);
- this.changed();
- }
- };
- ol.geom.Point.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
- this.setFlatCoordinatesInternal(layout, flatCoordinates);
- this.changed();
- };
- /**
- * @classdesc
- * Multi-linestring geometry.
- *
- * @constructor
- * @extends {ol.geom.SimpleGeometry}
- * @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
- * @param {ol.geom.GeometryLayout=} opt_layout Layout.
- * @api
- */
- ol.geom.MultiLineString = function(coordinates, opt_layout) {
- ol.geom.SimpleGeometry.call(this);
- /**
- * @type {Array.<number>}
- * @private
- */
- this.ends_ = [];
- /**
- * @private
- * @type {number}
- */
- this.maxDelta_ = -1;
- /**
- * @private
- * @type {number}
- */
- this.maxDeltaRevision_ = -1;
- this.setCoordinates(coordinates, opt_layout);
- };
- ol.inherits(ol.geom.MultiLineString, ol.geom.SimpleGeometry);
- /**
- * Append the passed linestring to the multilinestring.
- * @param {ol.geom.LineString} lineString LineString.
- * @api
- */
- ol.geom.MultiLineString.prototype.appendLineString = function(lineString) {
- if (!this.flatCoordinates) {
- this.flatCoordinates = lineString.getFlatCoordinates().slice();
- } else {
- ol.array.extend(
- this.flatCoordinates, lineString.getFlatCoordinates().slice());
- }
- this.ends_.push(this.flatCoordinates.length);
- this.changed();
- };
- /**
- * Make a complete copy of the geometry.
- * @return {!ol.geom.MultiLineString} Clone.
- * @override
- * @api
- */
- ol.geom.MultiLineString.prototype.clone = function() {
- var multiLineString = new ol.geom.MultiLineString(null);
- multiLineString.setFlatCoordinates(
- this.layout, this.flatCoordinates.slice(), this.ends_.slice());
- return multiLineString;
- };
- /**
- * @inheritDoc
- */
- ol.geom.MultiLineString.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
- if (minSquaredDistance <
- ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
- return minSquaredDistance;
- }
- if (this.maxDeltaRevision_ != this.getRevision()) {
- this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getsMaxSquaredDelta(
- this.flatCoordinates, 0, this.ends_, this.stride, 0));
- this.maxDeltaRevision_ = this.getRevision();
- }
- return ol.geom.flat.closest.getsClosestPoint(
- this.flatCoordinates, 0, this.ends_, this.stride,
- this.maxDelta_, false, x, y, closestPoint, minSquaredDistance);
- };
- /**
- * Returns the coordinate at `m` using linear interpolation, or `null` if no
- * such coordinate exists.
- *
- * `opt_extrapolate` controls extrapolation beyond the range of Ms in the
- * MultiLineString. If `opt_extrapolate` is `true` then Ms less than the first
- * M will return the first coordinate and Ms greater than the last M will
- * return the last coordinate.
- *
- * `opt_interpolate` controls interpolation between consecutive LineStrings
- * within the MultiLineString. If `opt_interpolate` is `true` the coordinates
- * will be linearly interpolated between the last coordinate of one LineString
- * and the first coordinate of the next LineString. If `opt_interpolate` is
- * `false` then the function will return `null` for Ms falling between
- * LineStrings.
- *
- * @param {number} m M.
- * @param {boolean=} opt_extrapolate Extrapolate. Default is `false`.
- * @param {boolean=} opt_interpolate Interpolate. Default is `false`.
- * @return {ol.Coordinate} Coordinate.
- * @api
- */
- ol.geom.MultiLineString.prototype.getCoordinateAtM = function(m, opt_extrapolate, opt_interpolate) {
- if ((this.layout != ol.geom.GeometryLayout.XYM &&
- this.layout != ol.geom.GeometryLayout.XYZM) ||
- this.flatCoordinates.length === 0) {
- return null;
- }
- var extrapolate = opt_extrapolate !== undefined ? opt_extrapolate : false;
- var interpolate = opt_interpolate !== undefined ? opt_interpolate : false;
- return ol.geom.flat.interpolate.lineStringsCoordinateAtM(this.flatCoordinates, 0,
- this.ends_, this.stride, m, extrapolate, interpolate);
- };
- /**
- * Return the coordinates of the multilinestring.
- * @return {Array.<Array.<ol.Coordinate>>} Coordinates.
- * @override
- * @api
- */
- ol.geom.MultiLineString.prototype.getCoordinates = function() {
- return ol.geom.flat.inflate.coordinatess(
- this.flatCoordinates, 0, this.ends_, this.stride);
- };
- /**
- * @return {Array.<number>} Ends.
- */
- ol.geom.MultiLineString.prototype.getEnds = function() {
- return this.ends_;
- };
- /**
- * Return the linestring at the specified index.
- * @param {number} index Index.
- * @return {ol.geom.LineString} LineString.
- * @api
- */
- ol.geom.MultiLineString.prototype.getLineString = function(index) {
- if (index < 0 || this.ends_.length <= index) {
- return null;
- }
- var lineString = new ol.geom.LineString(null);
- lineString.setFlatCoordinates(this.layout, this.flatCoordinates.slice(
- index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]));
- return lineString;
- };
- /**
- * Return the linestrings of this multilinestring.
- * @return {Array.<ol.geom.LineString>} LineStrings.
- * @api
- */
- ol.geom.MultiLineString.prototype.getLineStrings = function() {
- var flatCoordinates = this.flatCoordinates;
- var ends = this.ends_;
- var layout = this.layout;
- /** @type {Array.<ol.geom.LineString>} */
- var lineStrings = [];
- var offset = 0;
- var i, ii;
- for (i = 0, ii = ends.length; i < ii; ++i) {
- var end = ends[i];
- var lineString = new ol.geom.LineString(null);
- lineString.setFlatCoordinates(layout, flatCoordinates.slice(offset, end));
- lineStrings.push(lineString);
- offset = end;
- }
- return lineStrings;
- };
- /**
- * @return {Array.<number>} Flat midpoints.
- */
- ol.geom.MultiLineString.prototype.getFlatMidpoints = function() {
- var midpoints = [];
- var flatCoordinates = this.flatCoordinates;
- var offset = 0;
- var ends = this.ends_;
- var stride = this.stride;
- var i, ii;
- for (i = 0, ii = ends.length; i < ii; ++i) {
- var end = ends[i];
- var midpoint = ol.geom.flat.interpolate.lineString(
- flatCoordinates, offset, end, stride, 0.5);
- ol.array.extend(midpoints, midpoint);
- offset = end;
- }
- return midpoints;
- };
- /**
- * @inheritDoc
- */
- ol.geom.MultiLineString.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
- var simplifiedFlatCoordinates = [];
- var simplifiedEnds = [];
- simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeuckers(
- this.flatCoordinates, 0, this.ends_, this.stride, squaredTolerance,
- simplifiedFlatCoordinates, 0, simplifiedEnds);
- var simplifiedMultiLineString = new ol.geom.MultiLineString(null);
- simplifiedMultiLineString.setFlatCoordinates(
- ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates, simplifiedEnds);
- return simplifiedMultiLineString;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.geom.MultiLineString.prototype.getType = function() {
- return ol.geom.GeometryType.MULTI_LINE_STRING;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.geom.MultiLineString.prototype.intersectsExtent = function(extent) {
- return ol.geom.flat.intersectsextent.lineStrings(
- this.flatCoordinates, 0, this.ends_, this.stride, extent);
- };
- /**
- * Set the coordinates of the multilinestring.
- * @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
- * @param {ol.geom.GeometryLayout=} opt_layout Layout.
- * @override
- * @api
- */
- ol.geom.MultiLineString.prototype.setCoordinates = function(coordinates, opt_layout) {
- if (!coordinates) {
- this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.ends_);
- } else {
- this.setLayout(opt_layout, coordinates, 2);
- if (!this.flatCoordinates) {
- this.flatCoordinates = [];
- }
- var ends = ol.geom.flat.deflate.coordinatess(
- this.flatCoordinates, 0, coordinates, this.stride, this.ends_);
- this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1];
- this.changed();
- }
- };
- /**
- * @param {ol.geom.GeometryLayout} layout Layout.
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {Array.<number>} ends Ends.
- */
- ol.geom.MultiLineString.prototype.setFlatCoordinates = function(layout, flatCoordinates, ends) {
- this.setFlatCoordinatesInternal(layout, flatCoordinates);
- this.ends_ = ends;
- this.changed();
- };
- /**
- * @param {Array.<ol.geom.LineString>} lineStrings LineStrings.
- */
- ol.geom.MultiLineString.prototype.setLineStrings = function(lineStrings) {
- var layout = this.getLayout();
- var flatCoordinates = [];
- var ends = [];
- var i, ii;
- for (i = 0, ii = lineStrings.length; i < ii; ++i) {
- var lineString = lineStrings[i];
- if (i === 0) {
- layout = lineString.getLayout();
- }
- ol.array.extend(flatCoordinates, lineString.getFlatCoordinates());
- ends.push(flatCoordinates.length);
- }
- this.setFlatCoordinates(layout, flatCoordinates, ends);
- };
- /**
- * @classdesc
- * Multi-point geometry.
- *
- * @constructor
- * @extends {ol.geom.SimpleGeometry}
- * @param {Array.<ol.Coordinate>} coordinates Coordinates.
- * @param {ol.geom.GeometryLayout=} opt_layout Layout.
- * @api
- */
- ol.geom.MultiPoint = function(coordinates, opt_layout) {
- ol.geom.SimpleGeometry.call(this);
- this.setCoordinates(coordinates, opt_layout);
- };
- ol.inherits(ol.geom.MultiPoint, ol.geom.SimpleGeometry);
- /**
- * Append the passed point to this multipoint.
- * @param {ol.geom.Point} point Point.
- * @api
- */
- ol.geom.MultiPoint.prototype.appendPoint = function(point) {
- if (!this.flatCoordinates) {
- this.flatCoordinates = point.getFlatCoordinates().slice();
- } else {
- ol.array.extend(this.flatCoordinates, point.getFlatCoordinates());
- }
- this.changed();
- };
- /**
- * Make a complete copy of the geometry.
- * @return {!ol.geom.MultiPoint} Clone.
- * @override
- * @api
- */
- ol.geom.MultiPoint.prototype.clone = function() {
- var multiPoint = new ol.geom.MultiPoint(null);
- multiPoint.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
- return multiPoint;
- };
- /**
- * @inheritDoc
- */
- ol.geom.MultiPoint.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
- if (minSquaredDistance <
- ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
- return minSquaredDistance;
- }
- var flatCoordinates = this.flatCoordinates;
- var stride = this.stride;
- var i, ii, j;
- for (i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
- var squaredDistance = ol.math.squaredDistance(
- x, y, flatCoordinates[i], flatCoordinates[i + 1]);
- if (squaredDistance < minSquaredDistance) {
- minSquaredDistance = squaredDistance;
- for (j = 0; j < stride; ++j) {
- closestPoint[j] = flatCoordinates[i + j];
- }
- closestPoint.length = stride;
- }
- }
- return minSquaredDistance;
- };
- /**
- * Return the coordinates of the multipoint.
- * @return {Array.<ol.Coordinate>} Coordinates.
- * @override
- * @api
- */
- ol.geom.MultiPoint.prototype.getCoordinates = function() {
- return ol.geom.flat.inflate.coordinates(
- this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
- };
- /**
- * Return the point at the specified index.
- * @param {number} index Index.
- * @return {ol.geom.Point} Point.
- * @api
- */
- ol.geom.MultiPoint.prototype.getPoint = function(index) {
- var n = !this.flatCoordinates ?
- 0 : this.flatCoordinates.length / this.stride;
- if (index < 0 || n <= index) {
- return null;
- }
- var point = new ol.geom.Point(null);
- point.setFlatCoordinates(this.layout, this.flatCoordinates.slice(
- index * this.stride, (index + 1) * this.stride));
- return point;
- };
- /**
- * Return the points of this multipoint.
- * @return {Array.<ol.geom.Point>} Points.
- * @api
- */
- ol.geom.MultiPoint.prototype.getPoints = function() {
- var flatCoordinates = this.flatCoordinates;
- var layout = this.layout;
- var stride = this.stride;
- /** @type {Array.<ol.geom.Point>} */
- var points = [];
- var i, ii;
- for (i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
- var point = new ol.geom.Point(null);
- point.setFlatCoordinates(layout, flatCoordinates.slice(i, i + stride));
- points.push(point);
- }
- return points;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.geom.MultiPoint.prototype.getType = function() {
- return ol.geom.GeometryType.MULTI_POINT;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.geom.MultiPoint.prototype.intersectsExtent = function(extent) {
- var flatCoordinates = this.flatCoordinates;
- var stride = this.stride;
- var i, ii, x, y;
- for (i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
- x = flatCoordinates[i];
- y = flatCoordinates[i + 1];
- if (ol.extent.containsXY(extent, x, y)) {
- return true;
- }
- }
- return false;
- };
- /**
- * Set the coordinates of the multipoint.
- * @param {Array.<ol.Coordinate>} coordinates Coordinates.
- * @param {ol.geom.GeometryLayout=} opt_layout Layout.
- * @override
- * @api
- */
- ol.geom.MultiPoint.prototype.setCoordinates = function(coordinates, opt_layout) {
- if (!coordinates) {
- this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
- } else {
- this.setLayout(opt_layout, coordinates, 1);
- if (!this.flatCoordinates) {
- this.flatCoordinates = [];
- }
- this.flatCoordinates.length = ol.geom.flat.deflate.coordinates(
- this.flatCoordinates, 0, coordinates, this.stride);
- this.changed();
- }
- };
- /**
- * @param {ol.geom.GeometryLayout} layout Layout.
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- */
- ol.geom.MultiPoint.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
- this.setFlatCoordinatesInternal(layout, flatCoordinates);
- this.changed();
- };
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {Array.<Array.<number>>} endss Endss.
- * @param {number} stride Stride.
- * @return {Array.<number>} Flat centers.
- */
- ol.geom.flat.center.linearRingss = {};
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {Array.<Array.<number>>} endss Endss.
- * @param {number} stride Stride.
- * @return {Array.<number>} Flat centers.
- */
- ol.geom.flat.center.linearRingss = function(flatCoordinates, offset, endss, stride) {
- var flatCenters = [];
- var i, ii;
- var extent = ol.extent.createEmpty();
- for (i = 0, ii = endss.length; i < ii; ++i) {
- var ends = endss[i];
- extent = ol.extent.createOrUpdateFromFlatCoordinates(
- flatCoordinates, offset, ends[0], stride);
- flatCenters.push((extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2);
- offset = ends[ends.length - 1];
- }
- return flatCenters;
- };
- /**
- * @classdesc
- * Multi-polygon geometry.
- *
- * @constructor
- * @extends {ol.geom.SimpleGeometry}
- * @param {Array.<Array.<Array.<ol.Coordinate>>>} coordinates Coordinates.
- * @param {ol.geom.GeometryLayout=} opt_layout Layout.
- * @api
- */
- ol.geom.MultiPolygon = function(coordinates, opt_layout) {
- ol.geom.SimpleGeometry.call(this);
- /**
- * @type {Array.<Array.<number>>}
- * @private
- */
- this.endss_ = [];
- /**
- * @private
- * @type {number}
- */
- this.flatInteriorPointsRevision_ = -1;
- /**
- * @private
- * @type {Array.<number>}
- */
- this.flatInteriorPoints_ = null;
- /**
- * @private
- * @type {number}
- */
- this.maxDelta_ = -1;
- /**
- * @private
- * @type {number}
- */
- this.maxDeltaRevision_ = -1;
- /**
- * @private
- * @type {number}
- */
- this.orientedRevision_ = -1;
- /**
- * @private
- * @type {Array.<number>}
- */
- this.orientedFlatCoordinates_ = null;
- this.setCoordinates(coordinates, opt_layout);
- };
- ol.inherits(ol.geom.MultiPolygon, ol.geom.SimpleGeometry);
- /**
- * Append the passed polygon to this multipolygon.
- * @param {ol.geom.Polygon} polygon Polygon.
- * @api
- */
- ol.geom.MultiPolygon.prototype.appendPolygon = function(polygon) {
- /** @type {Array.<number>} */
- var ends;
- if (!this.flatCoordinates) {
- this.flatCoordinates = polygon.getFlatCoordinates().slice();
- ends = polygon.getEnds().slice();
- this.endss_.push();
- } else {
- var offset = this.flatCoordinates.length;
- ol.array.extend(this.flatCoordinates, polygon.getFlatCoordinates());
- ends = polygon.getEnds().slice();
- var i, ii;
- for (i = 0, ii = ends.length; i < ii; ++i) {
- ends[i] += offset;
- }
- }
- this.endss_.push(ends);
- this.changed();
- };
- /**
- * Make a complete copy of the geometry.
- * @return {!ol.geom.MultiPolygon} Clone.
- * @override
- * @api
- */
- ol.geom.MultiPolygon.prototype.clone = function() {
- var multiPolygon = new ol.geom.MultiPolygon(null);
- var len = this.endss_.length;
- var newEndss = new Array(len);
- for (var i = 0; i < len; ++i) {
- newEndss[i] = this.endss_[i].slice();
- }
- multiPolygon.setFlatCoordinates(
- this.layout, this.flatCoordinates.slice(), newEndss);
- return multiPolygon;
- };
- /**
- * @inheritDoc
- */
- ol.geom.MultiPolygon.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
- if (minSquaredDistance <
- ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
- return minSquaredDistance;
- }
- if (this.maxDeltaRevision_ != this.getRevision()) {
- this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getssMaxSquaredDelta(
- this.flatCoordinates, 0, this.endss_, this.stride, 0));
- this.maxDeltaRevision_ = this.getRevision();
- }
- return ol.geom.flat.closest.getssClosestPoint(
- this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride,
- this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);
- };
- /**
- * @inheritDoc
- */
- ol.geom.MultiPolygon.prototype.containsXY = function(x, y) {
- return ol.geom.flat.contains.linearRingssContainsXY(
- this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, x, y);
- };
- /**
- * Return the area of the multipolygon on projected plane.
- * @return {number} Area (on projected plane).
- * @api
- */
- ol.geom.MultiPolygon.prototype.getArea = function() {
- return ol.geom.flat.area.linearRingss(
- this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride);
- };
- /**
- * Get the coordinate array for this geometry. This array has the structure
- * of a GeoJSON coordinate array for multi-polygons.
- *
- * @param {boolean=} opt_right Orient coordinates according to the right-hand
- * rule (counter-clockwise for exterior and clockwise for interior rings).
- * If `false`, coordinates will be oriented according to the left-hand rule
- * (clockwise for exterior and counter-clockwise for interior rings).
- * By default, coordinate orientation will depend on how the geometry was
- * constructed.
- * @return {Array.<Array.<Array.<ol.Coordinate>>>} Coordinates.
- * @override
- * @api
- */
- ol.geom.MultiPolygon.prototype.getCoordinates = function(opt_right) {
- var flatCoordinates;
- if (opt_right !== undefined) {
- flatCoordinates = this.getOrientedFlatCoordinates().slice();
- ol.geom.flat.orient.orientLinearRingss(
- flatCoordinates, 0, this.endss_, this.stride, opt_right);
- } else {
- flatCoordinates = this.flatCoordinates;
- }
- return ol.geom.flat.inflate.coordinatesss(
- flatCoordinates, 0, this.endss_, this.stride);
- };
- /**
- * @return {Array.<Array.<number>>} Endss.
- */
- ol.geom.MultiPolygon.prototype.getEndss = function() {
- return this.endss_;
- };
- /**
- * @return {Array.<number>} Flat interior points.
- */
- ol.geom.MultiPolygon.prototype.getFlatInteriorPoints = function() {
- if (this.flatInteriorPointsRevision_ != this.getRevision()) {
- var flatCenters = ol.geom.flat.center.linearRingss(
- this.flatCoordinates, 0, this.endss_, this.stride);
- this.flatInteriorPoints_ = ol.geom.flat.interiorpoint.linearRingss(
- this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride,
- flatCenters);
- this.flatInteriorPointsRevision_ = this.getRevision();
- }
- return this.flatInteriorPoints_;
- };
- /**
- * Return the interior points as {@link ol.geom.MultiPoint multipoint}.
- * @return {ol.geom.MultiPoint} Interior points as XYM coordinates, where M is
- * the length of the horizontal intersection that the point belongs to.
- * @api
- */
- ol.geom.MultiPolygon.prototype.getInteriorPoints = function() {
- var interiorPoints = new ol.geom.MultiPoint(null);
- interiorPoints.setFlatCoordinates(ol.geom.GeometryLayout.XYM,
- this.getFlatInteriorPoints().slice());
- return interiorPoints;
- };
- /**
- * @return {Array.<number>} Oriented flat coordinates.
- */
- ol.geom.MultiPolygon.prototype.getOrientedFlatCoordinates = function() {
- if (this.orientedRevision_ != this.getRevision()) {
- var flatCoordinates = this.flatCoordinates;
- if (ol.geom.flat.orient.linearRingssAreOriented(
- flatCoordinates, 0, this.endss_, this.stride)) {
- this.orientedFlatCoordinates_ = flatCoordinates;
- } else {
- this.orientedFlatCoordinates_ = flatCoordinates.slice();
- this.orientedFlatCoordinates_.length =
- ol.geom.flat.orient.orientLinearRingss(
- this.orientedFlatCoordinates_, 0, this.endss_, this.stride);
- }
- this.orientedRevision_ = this.getRevision();
- }
- return this.orientedFlatCoordinates_;
- };
- /**
- * @inheritDoc
- */
- ol.geom.MultiPolygon.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
- var simplifiedFlatCoordinates = [];
- var simplifiedEndss = [];
- simplifiedFlatCoordinates.length = ol.geom.flat.simplify.quantizess(
- this.flatCoordinates, 0, this.endss_, this.stride,
- Math.sqrt(squaredTolerance),
- simplifiedFlatCoordinates, 0, simplifiedEndss);
- var simplifiedMultiPolygon = new ol.geom.MultiPolygon(null);
- simplifiedMultiPolygon.setFlatCoordinates(
- ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates, simplifiedEndss);
- return simplifiedMultiPolygon;
- };
- /**
- * Return the polygon at the specified index.
- * @param {number} index Index.
- * @return {ol.geom.Polygon} Polygon.
- * @api
- */
- ol.geom.MultiPolygon.prototype.getPolygon = function(index) {
- if (index < 0 || this.endss_.length <= index) {
- return null;
- }
- var offset;
- if (index === 0) {
- offset = 0;
- } else {
- var prevEnds = this.endss_[index - 1];
- offset = prevEnds[prevEnds.length - 1];
- }
- var ends = this.endss_[index].slice();
- var end = ends[ends.length - 1];
- if (offset !== 0) {
- var i, ii;
- for (i = 0, ii = ends.length; i < ii; ++i) {
- ends[i] -= offset;
- }
- }
- var polygon = new ol.geom.Polygon(null);
- polygon.setFlatCoordinates(
- this.layout, this.flatCoordinates.slice(offset, end), ends);
- return polygon;
- };
- /**
- * Return the polygons of this multipolygon.
- * @return {Array.<ol.geom.Polygon>} Polygons.
- * @api
- */
- ol.geom.MultiPolygon.prototype.getPolygons = function() {
- var layout = this.layout;
- var flatCoordinates = this.flatCoordinates;
- var endss = this.endss_;
- var polygons = [];
- var offset = 0;
- var i, ii, j, jj;
- for (i = 0, ii = endss.length; i < ii; ++i) {
- var ends = endss[i].slice();
- var end = ends[ends.length - 1];
- if (offset !== 0) {
- for (j = 0, jj = ends.length; j < jj; ++j) {
- ends[j] -= offset;
- }
- }
- var polygon = new ol.geom.Polygon(null);
- polygon.setFlatCoordinates(
- layout, flatCoordinates.slice(offset, end), ends);
- polygons.push(polygon);
- offset = end;
- }
- return polygons;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.geom.MultiPolygon.prototype.getType = function() {
- return ol.geom.GeometryType.MULTI_POLYGON;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.geom.MultiPolygon.prototype.intersectsExtent = function(extent) {
- return ol.geom.flat.intersectsextent.linearRingss(
- this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, extent);
- };
- /**
- * Set the coordinates of the multipolygon.
- * @param {Array.<Array.<Array.<ol.Coordinate>>>} coordinates Coordinates.
- * @param {ol.geom.GeometryLayout=} opt_layout Layout.
- * @override
- * @api
- */
- ol.geom.MultiPolygon.prototype.setCoordinates = function(coordinates, opt_layout) {
- if (!coordinates) {
- this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.endss_);
- } else {
- this.setLayout(opt_layout, coordinates, 3);
- if (!this.flatCoordinates) {
- this.flatCoordinates = [];
- }
- var endss = ol.geom.flat.deflate.coordinatesss(
- this.flatCoordinates, 0, coordinates, this.stride, this.endss_);
- if (endss.length === 0) {
- this.flatCoordinates.length = 0;
- } else {
- var lastEnds = endss[endss.length - 1];
- this.flatCoordinates.length = lastEnds.length === 0 ?
- 0 : lastEnds[lastEnds.length - 1];
- }
- this.changed();
- }
- };
- /**
- * @param {ol.geom.GeometryLayout} layout Layout.
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {Array.<Array.<number>>} endss Endss.
- */
- ol.geom.MultiPolygon.prototype.setFlatCoordinates = function(layout, flatCoordinates, endss) {
- this.setFlatCoordinatesInternal(layout, flatCoordinates);
- this.endss_ = endss;
- this.changed();
- };
- /**
- * @param {Array.<ol.geom.Polygon>} polygons Polygons.
- */
- ol.geom.MultiPolygon.prototype.setPolygons = function(polygons) {
- var layout = this.getLayout();
- var flatCoordinates = [];
- var endss = [];
- var i, ii, ends;
- for (i = 0, ii = polygons.length; i < ii; ++i) {
- var polygon = polygons[i];
- if (i === 0) {
- layout = polygon.getLayout();
- }
- var offset = flatCoordinates.length;
- ends = polygon.getEnds();
- var j, jj;
- for (j = 0, jj = ends.length; j < jj; ++j) {
- ends[j] += offset;
- }
- ol.array.extend(flatCoordinates, polygon.getFlatCoordinates());
- endss.push(ends);
- }
- this.setFlatCoordinates(layout, flatCoordinates, endss);
- };
- ol.Feature = function(opt_geometryOrProperties) {
- ol.Object.call(this);
- /**
- * @private
- * @type {number|string|undefined}
- */
- this.id_ = undefined;
- /**
- * @type {string}
- * @private
- */
- this.geometryName_ = 'geometry';
- /**
- * User provided style.
- * @private
- * @type {ol.style.Style|Array.<ol.style.Style>|
- * ol.FeatureStyleFunction}
- */
- this.style_ = null;
- /**
- * @private
- * @type {ol.FeatureStyleFunction|undefined}
- */
- this.styleFunction_ = undefined;
- /**
- * @private
- * @type {?ol.EventsKey}
- */
- this.geometryChangeKey_ = null;
- // ol.events.listen(
- // this, ol.Object.getChangeEventType(this.geometryName_),
- // this.handleGeometryChanged_, this);
- if (opt_geometryOrProperties !== undefined) {
- if (opt_geometryOrProperties instanceof ol.geom.Geometry ||
- !opt_geometryOrProperties) {
- var geometry = opt_geometryOrProperties;
- this.setGeometry(geometry);
- } else {
- /** @type {Object.<string, *>} */
- var properties = opt_geometryOrProperties;
- this.setProperties(properties);
- }
- }
- };
- ol.inherits(ol.Feature, ol.Object);
- /**
- * Clone this feature. If the original feature has a geometry it
- * is also cloned. The feature id is not set in the clone.
- * @return {ol.Feature} The clone.
- * @api
- */
- ol.Feature.prototype.clone = function() {
- var clone = new ol.Feature(this.getProperties());
- clone.setGeometryName(this.getGeometryName());
- var geometry = this.getGeometry();
- if (geometry) {
- clone.setGeometry(geometry.clone());
- }
- var style = this.getStyle();
- if (style) {
- clone.setStyle(style);
- }
- return clone;
- };
- /**
- * Get the feature's default geometry. A feature may have any number of named
- * geometries. The "default" geometry (the one that is rendered by default) is
- * set when calling {@link ol.Feature#setGeometry}.
- * @return {ol.geom.Geometry|undefined} The default geometry for the feature.
- * @api
- * @observable
- */
- ol.Feature.prototype.getGeometry = function() {
- return /** @type {ol.geom.Geometry|undefined} */ (
- this.get(this.geometryName_));
- };
- /**
- * Get the feature identifier. This is a stable identifier for the feature and
- * is either set when reading data from a remote source or set explicitly by
- * calling {@link ol.Feature#setId}.
- * @return {number|string|undefined} Id.
- * @api
- */
- ol.Feature.prototype.getId = function() {
- return this.id_;
- };
- /**
- * Get the name of the feature's default geometry. By default, the default
- * geometry is named `geometry`.
- * @return {string} Get the property name associated with the default geometry
- * for this feature.
- * @api
- */
- ol.Feature.prototype.getGeometryName = function() {
- return this.geometryName_;
- };
- /**
- * Get the feature's style. Will return what was provided to the
- * {@link ol.Feature#setStyle} method.
- * @return {ol.style.Style|Array.<ol.style.Style>|
- * ol.FeatureStyleFunction|ol.StyleFunction} The feature style.
- * @api
- */
- ol.Feature.prototype.getStyle = function() {
- return this.style_;
- };
- /**
- * Get the feature's style function.
- * @return {ol.FeatureStyleFunction|undefined} Return a function
- * representing the current style of this feature.
- * @api
- */
- ol.Feature.prototype.getStyleFunction = function() {
- return this.styleFunction_;
- };
- /**
- * @private
- */
- ol.Feature.prototype.handleGeometryChange_ = function() {
- this.changed();
- };
- /**
- * @private
- */
- ol.Feature.prototype.handleGeometryChanged_ = function() {
- if (this.geometryChangeKey_) {
- ol.events.unlistenByKey(this.geometryChangeKey_);
- this.geometryChangeKey_ = null;
- }
- var geometry = this.getGeometry();
- if (geometry) {
- this.geometryChangeKey_ = ol.events.listen(geometry,
- ol.events.EventType.CHANGE, this.handleGeometryChange_, this);
- }
- this.changed();
- };
- /**
- * Set the default geometry for the feature. This will update the property
- * with the name returned by {@link ol.Feature#getGeometryName}.
- * @param {ol.geom.Geometry|undefined} geometry The new geometry.
- * @api
- * @observable
- */
- ol.Feature.prototype.setGeometry = function(geometry) {
- this.set(this.geometryName_, geometry);
- };
- /**
- * Set the style for the feature. This can be a single style object, an array
- * of styles, or a function that takes a resolution and returns an array of
- * styles. If it is `null` the feature has no style (a `null` style).
- * @param {ol.style.Style|Array.<ol.style.Style>|
- * ol.FeatureStyleFunction|ol.StyleFunction} style Style for this feature.
- * @api
- * @fires ol.events.Event#event:change
- */
- ol.Feature.prototype.setStyle = function(style) {
- this.style_ = style;
- this.styleFunction_ = !style ?
- undefined : ol.Feature.createStyleFunction(style);
- this.changed();
- };
- /**
- * Set the feature id. The feature id is considered stable and may be used when
- * requesting features or comparing identifiers returned from a remote source.
- * The feature id can be used with the {@link ol.source.Vector#getFeatureById}
- * method.
- * @param {number|string|undefined} id The feature id.
- * @api
- * @fires ol.events.Event#event:change
- */
- ol.Feature.prototype.setId = function(id) {
- this.id_ = id;
- this.changed();
- };
- /**
- * Set the property name to be used when getting the feature's default geometry.
- * When calling {@link ol.Feature#getGeometry}, the value of the property with
- * this name will be returned.
- * @param {string} name The property name of the default geometry.
- * @api
- */
- ol.Feature.prototype.setGeometryName = function(name) {
- ol.events.unlisten(
- this, ol.Object.getChangeEventType(this.geometryName_),
- this.handleGeometryChanged_, this);
- this.geometryName_ = name;
- ol.events.listen(
- this, ol.Object.getChangeEventType(this.geometryName_),
- this.handleGeometryChanged_, this);
- this.handleGeometryChanged_();
- };
- /**
- * Convert the provided object into a feature style function. Functions passed
- * through unchanged. Arrays of ol.style.Style or single style objects wrapped
- * in a new feature style function.
- * @param {ol.FeatureStyleFunction|!Array.<ol.style.Style>|!ol.style.Style} obj
- * A feature style function, a single style, or an array of styles.
- * @return {ol.FeatureStyleFunction} A style function.
- */
- ol.Feature.createStyleFunction = function(obj) {
- var styleFunction;
- if (typeof obj === 'function') {
- if (obj.length == 2) {
- styleFunction = function(resolution) {
- return /** @type {ol.StyleFunction} */ (obj)(this, resolution);
- };
- } else {
- styleFunction = obj;
- }
- } else {
- /**
- * @type {Array.<ol.style.Style>}
- */
- var styles;
- if (Array.isArray(obj)) {
- styles = obj;
- } else {
- ol.asserts.assert(obj instanceof ol.style.Style,
- 41); // Expected an `ol.style.Style` or an array of `ol.style.Style`
- styles = [obj];
- }
- styleFunction = function() {
- return styles;
- };
- }
- return styleFunction;
- };
- ol.format = {};
- ol.format.Feature = function() {
- /**
- * @protected
- * @type {ol.proj.Projection}
- */
- this.defaultDataProjection = null;
- /**
- * @protected
- * @type {ol.proj.Projection}
- */
- this.defaultFeatureProjection = null;
- };
- /**
- * Adds the data projection to the read options.
- * @param {Document|Node|Object|string} source Source.
- * @param {olx.format.ReadOptions=} opt_options Options.
- * @return {olx.format.ReadOptions|undefined} Options.
- * @protected
- */
- ol.format.Feature.prototype.getReadOptions = function(source, opt_options) {
- var options;
- if (opt_options) {
- options = {
- dataProjection: opt_options.dataProjection ?
- opt_options.dataProjection : this.readProjection(source),
- featureProjection: opt_options.featureProjection
- };
- }
- return this.adaptOptions(options);
- };
- /**
- * Sets the `defaultDataProjection` on the options, if no `dataProjection`
- * is set.
- * @param {olx.format.WriteOptions|olx.format.ReadOptions|undefined} options
- * Options.
- * @protected
- * @return {olx.format.WriteOptions|olx.format.ReadOptions|undefined}
- * Updated options.
- */
- ol.format.Feature.prototype.adaptOptions = function(options) {
- return ol.obj.assign({
- dataProjection: this.defaultDataProjection,
- featureProjection: this.defaultFeatureProjection
- }, options);
- };
- /**
- * Get the extent from the source of the last {@link readFeatures} call.
- * @return {ol.Extent} Tile extent.
- */
- ol.format.Feature.prototype.getLastExtent = function() {
- return null;
- };
- /**
- * @abstract
- * @return {ol.format.FormatType} Format.
- */
- ol.format.Feature.prototype.getType = function() {};
- /**
- * Read a single feature from a source.
- *
- * @abstract
- * @param {Document|Node|Object|string} source Source.
- * @param {olx.format.ReadOptions=} opt_options Read options.
- * @return {ol.Feature} Feature.
- */
- ol.format.Feature.prototype.readFeature = function(source, opt_options) {};
- /**
- * Read all features from a source.
- *
- * @abstract
- * @param {Document|Node|ArrayBuffer|Object|string} source Source.
- * @param {olx.format.ReadOptions=} opt_options Read options.
- * @return {Array.<ol.Feature>} Features.
- */
- ol.format.Feature.prototype.readFeatures = function(source, opt_options) {};
- /**
- * Read a single geometry from a source.
- *
- * @abstract
- * @param {Document|Node|Object|string} source Source.
- * @param {olx.format.ReadOptions=} opt_options Read options.
- * @return {ol.geom.Geometry} Geometry.
- */
- ol.format.Feature.prototype.readGeometry = function(source, opt_options) {};
- /**
- * Read the projection from a source.
- *
- * @abstract
- * @param {Document|Node|Object|string} source Source.
- * @return {ol.proj.Projection} Projection.
- */
- ol.format.Feature.prototype.readProjection = function(source) {};
- /**
- * Encode a feature in this format.
- *
- * @abstract
- * @param {ol.Feature} feature Feature.
- * @param {olx.format.WriteOptions=} opt_options Write options.
- * @return {string} Result.
- */
- ol.format.Feature.prototype.writeFeature = function(feature, opt_options) {};
- /**
- * Encode an array of features in this format.
- *
- * @abstract
- * @param {Array.<ol.Feature>} features Features.
- * @param {olx.format.WriteOptions=} opt_options Write options.
- * @return {string} Result.
- */
- ol.format.Feature.prototype.writeFeatures = function(features, opt_options) {};
- /**
- * Write a single geometry in this format.
- *
- * @abstract
- * @param {ol.geom.Geometry} geometry Geometry.
- * @param {olx.format.WriteOptions=} opt_options Write options.
- * @return {string} Result.
- */
- ol.format.Feature.prototype.writeGeometry = function(geometry, opt_options) {};
- /**
- * @param {ol.geom.Geometry|ol.Extent} geometry Geometry.
- * @param {boolean} write Set to true for writing, false for reading.
- * @param {(olx.format.WriteOptions|olx.format.ReadOptions)=} opt_options
- * Options.
- * @return {ol.geom.Geometry|ol.Extent} Transformed geometry.
- * @protected
- */
- ol.format.Feature.transformWithOptions = function(
- geometry, write, opt_options) {
- /**
- * @type {ol.geom.Geometry|ol.Extent}
- */
- var transformed;
- {
- transformed = geometry;
- }
- if (write && opt_options && opt_options.decimals !== undefined) {
- var power = Math.pow(10, opt_options.decimals);
- // if decimals option on write, round each coordinate appropriately
- /**
- * @param {Array.<number>} coordinates Coordinates.
- * @return {Array.<number>} Transformed coordinates.
- */
- var transform = function(coordinates) {
- for (var i = 0, ii = coordinates.length; i < ii; ++i) {
- coordinates[i] = Math.round(coordinates[i] * power) / power;
- }
- return coordinates;
- };
- if (transformed === geometry) {
- transformed = transformed.clone();
- }
- transformed.applyTransform(transform);
- }
- return transformed;
- };
- ol.format.MVT = function(opt_options) {
- ol.format.Feature.call(this);
- var options = opt_options ? opt_options : {};
- /**
- * @type {ol.proj.Projection}
- */
- // this.defaultDataProjection = new ol.proj.Projection({
- // code: 'EPSG:3857',
- // units: ol.proj.Units.TILE_PIXELS
- // });
- /**
- * @private
- * @type {function((ol.geom.Geometry|Object.<string,*>)=)|
- * function(ol.geom.GeometryType,Array.<number>,
- * (Array.<number>|Array.<Array.<number>>),Object.<string,*>,number)}
- */
- this.featureClass_ = options.featureClass ?
- options.featureClass : ol.render.Feature;
- /**
- * @private
- * @type {string|undefined}
- */
- this.geometryName_ = options.geometryName;
- /**
- * @private
- * @type {string}
- */
- this.layerName_ = options.layerName ? options.layerName : 'layer';
- /**
- * @private
- * @type {Array.<string>}
- */
- this.layers_ = options.layers ? options.layers : null;
- /**
- * @private
- * @type {ol.Extent}
- */
- this.extent_ = null;
- };
- ol.inherits(ol.format.MVT, ol.format.Feature);
- ol.format.MVT.pbfReaders_ = {
- layers: function (tag, layers, pbf) {
- if (tag === 3) {
- var layer = {
- keys: [],
- values: [],
- features: []
- };
- var end = pbf.readVarint() + pbf.pos;
- pbf.readFields(ol.format.MVT.pbfReaders_.layer, layer, end);
- layer.length = layer.features.length;
- if (layer.length) {
- layers[layer.name] = layer;
- }
- }
- },
- layer: function (tag, layer, pbf) {
- if (tag === 15) {
- layer.version = pbf.readVarint();
- } else if (tag === 1) {
- layer.name = pbf.readString();
- } else if (tag === 5) {
- layer.extent = pbf.readVarint();
- } else if (tag === 2) {
- layer.features.push(pbf.pos);
- } else if (tag === 3) {
- layer.keys.push(pbf.readString());
- } else if (tag === 4) {
- var value = null;
- var end = pbf.readVarint() + pbf.pos;
- while (pbf.pos < end) {
- tag = pbf.readVarint() >> 3;
- value = tag === 1 ? pbf.readString() :
- tag === 2 ? pbf.readFloat() :
- tag === 3 ? pbf.readDouble() :
- tag === 4 ? pbf.readVarint64() :
- tag === 5 ? pbf.readVarint() :
- tag === 6 ? pbf.readSVarint() :
- tag === 7 ? pbf.readBoolean() : null;
- }
- layer.values.push(value);
- }
- },
- feature: function (tag, feature, pbf) {
- if (tag == 1) {
- feature.id = pbf.readVarint();
- } else if (tag == 2) {
- var end = pbf.readVarint() + pbf.pos;
- while (pbf.pos < end) {
- var key = feature.layer.keys[pbf.readVarint()];
- var value = feature.layer.values[pbf.readVarint()];
- feature.properties[key] = value;
- }
- } else if (tag == 3) {
- feature.type = pbf.readVarint();
- } else if (tag == 4) {
- feature.geometry = pbf.pos;
- }
- }
- };
- /**
- * Read a raw feature from the pbf offset stored at index `i` in the raw layer.
- * @suppress {missingProperties}
- * @private
- * @param {ol.ext.PBF} pbf PBF.
- * @param {Object} layer Raw layer.
- * @param {number} i Index of the feature in the raw layer's `features` array.
- * @return {Object} Raw feature.
- */
- ol.format.MVT.readRawFeature_ = function (pbf, layer, i) {
- pbf.pos = layer.features[i];
- var end = pbf.readVarint() + pbf.pos;
- var feature = {
- layer: layer,
- type: 0,
- properties: {}
- };
- pbf.readFields(ol.format.MVT.pbfReaders_.feature, feature, end);
- return feature;
- };
- /**
- * Read the raw geometry from the pbf offset stored in a raw feature's geometry
- * proeprty.
- * @suppress {missingProperties}
- * @private
- * @param {ol.ext.PBF} pbf PBF.
- * @param {Object} feature Raw feature.
- * @param {Array.<number>} flatCoordinates Array to store flat coordinates in.
- * @param {Array.<number>} ends Array to store ends in.
- */
- ol.format.MVT.readRawGeometry_ = function (pbf, feature, flatCoordinates, ends) {
- pbf.pos = feature.geometry;
- var end = pbf.readVarint() + pbf.pos;
- var cmd = 1;
- var length = 0;
- var x = 0;
- var y = 0;
- var coordsLen = 0;
- var currentEnd = 0;
- while (pbf.pos < end) {
- if (!length) {
- var cmdLen = pbf.readVarint();
- cmd = cmdLen & 0x7;
- length = cmdLen >> 3;
- }
- length--;
- if (cmd === 1 || cmd === 2) {
- x += pbf.readSVarint();
- y += pbf.readSVarint();
- if (cmd === 1) { // moveTo
- if (coordsLen > currentEnd) {
- ends.push(coordsLen);
- currentEnd = coordsLen;
- }
- }
- flatCoordinates.push(x, y);
- coordsLen += 2;
- } else if (cmd === 7) {
- if (coordsLen > currentEnd) {
- // close polygon
- flatCoordinates.push(
- flatCoordinates[currentEnd], flatCoordinates[currentEnd + 1]);
- coordsLen += 2;
- }
- } else {
- ol.asserts.assert(false, 59); // Invalid command found in the PBF
- }
- }
- if (coordsLen > currentEnd) {
- ends.push(coordsLen);
- currentEnd = coordsLen;
- }
- };
- /**
- * @suppress {missingProperties}
- * @private
- * @param {number} type The raw feature's geometry type
- * @param {number} numEnds Number of ends of the flat coordinates of the
- * geometry.
- * @return {ol.geom.GeometryType} The geometry type.
- */
- ol.format.MVT.getGeometryType_ = function (type, numEnds) {
- /** @type {ol.geom.GeometryType} */
- var geometryType;
- if (type === 1) {
- geometryType = numEnds === 1 ?
- ol.geom.GeometryType.POINT : ol.geom.GeometryType.MULTI_POINT;
- } else if (type === 2) {
- geometryType = numEnds === 1 ?
- ol.geom.GeometryType.LINE_STRING :
- ol.geom.GeometryType.MULTI_LINE_STRING;
- } else if (type === 3) {
- geometryType = ol.geom.GeometryType.POLYGON;
- // MultiPolygon not relevant for rendering - winding order determines
- // outer rings of polygons.
- }
- return geometryType;
- };
- /**
- * @private
- * @param {ol.ext.PBF} pbf PBF
- * @param {Object} rawFeature Raw Mapbox feature.
- * @param {olx.format.ReadOptions=} opt_options Read options.
- * @return {ol.Feature|ol.render.Feature} Feature.
- */
- ol.format.MVT.prototype.createFeature_ = function (pbf, rawFeature, opt_options) {
- var type = rawFeature.type;
- if (type === 0) {
- return null;
- }
- var feature;
- var id = rawFeature.id;
- var values = rawFeature.properties;
- values[this.layerName_] = rawFeature.layer.name;
- var flatCoordinates = [];
- var ends = [];
- ol.format.MVT.readRawGeometry_(pbf, rawFeature, flatCoordinates, ends);
- var geometryType = ol.format.MVT.getGeometryType_(type, ends.length);
- var geom;
- if (geometryType == ol.geom.GeometryType.POLYGON) {
- var endss = [];
- var offset = 0;
- var prevEndIndex = 0;
- for (var i = 0, ii = ends.length; i < ii; ++i) {
- var end = ends[i];
- if (!ol.geom.flat.orient.linearRingIsClockwise(flatCoordinates, offset, end, 2)) {
- endss.push(ends.slice(prevEndIndex, i + 1));
- prevEndIndex = i + 1;
- }
- offset = end;
- }
- if (endss.length > 1) {
- ends = endss;
- geom = new ol.geom.MultiPolygon(null);
- } else {
- geom = new ol.geom.Polygon(null);
- }
- } else {
- geom = geometryType === ol.geom.GeometryType.POINT ? new ol.geom.Point(null) :
- geometryType === ol.geom.GeometryType.LINE_STRING ? new ol.geom.LineString(null) :
- geometryType === ol.geom.GeometryType.POLYGON ? new ol.geom.Polygon(null) :
- geometryType === ol.geom.GeometryType.MULTI_POINT ? new ol.geom.MultiPoint(null) :
- geometryType === ol.geom.GeometryType.MULTI_LINE_STRING ? new ol.geom.MultiLineString(null) :
- null;
- }
- geom.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates, ends);
- feature = new this.featureClass_();
- if (this.geometryName_) {
- feature.setGeometryName(this.geometryName_);
- }
- var geometry = ol.format.Feature.transformWithOptions(geom, false, this.adaptOptions(opt_options));
- feature.setGeometry(geometry);
- feature.setId(id);
- feature.setProperties(values);
- return feature;
- };
- ol.format.MVT.prototype.readFeatures = function (source, opt_options) {
- var layers = this.layers_;
- var pbf$1 = new pbf.Protobuf(/** @type {ArrayBuffer} */ (source));
- var pbfLayers = pbf$1.readFields(ol.format.MVT.pbfReaders_.layers, {});
- /** @type {Array.<ol.Feature|ol.render.Feature>} */
- var features = [];
- var pbfLayer;
- for (var name in pbfLayers) {
- if (layers && layers.indexOf(name) == -1) {
- continue;
- }
- if (opt_options !== undefined) {
- var needSourceLayerNames = opt_options.needSourceLayerNames;
- if (needSourceLayerNames !== undefined && needSourceLayerNames[name] === undefined) {
- continue;
- }
- }
- pbfLayer = pbfLayers[name];
- var rawFeature;
- for (var i = 0, ii = pbfLayer.length; i < ii; ++i) {
- rawFeature = ol.format.MVT.readRawFeature_(pbf$1, pbfLayer, i);
- features.push(this.createFeature_(pbf$1, rawFeature));
- }
- this.extent_ = pbfLayer ? [0, 0, pbfLayer.extent, pbfLayer.extent] : null;
- }
- return features;
- };
- ol.style = {};
- /**
- * Singleton class. Available through {@link ol.style.iconImageCache}.
- * @constructor
- */
- ol.style.IconImageCache = function() {
- this.cache_ = {};
- this.cacheSize_ = 0;
- this.maxCacheSize_ = 32;
- };
- ol.style.IconImageCache.getKey = function(src, crossOrigin, color) {
- var colorString = color ? ol.color.asString(color) : 'null';
- return crossOrigin + ':' + src + ':' + colorString;
- };
- /**
- * FIXME empty description for jsdoc
- */
- ol.style.IconImageCache.prototype.clear = function() {
- this.cache_ = {};
- this.cacheSize_ = 0;
- };
- /**
- * FIXME empty description for jsdoc
- */
- ol.style.IconImageCache.prototype.expire = function() {
- if (this.cacheSize_ > this.maxCacheSize_) {
- var i = 0;
- var key, iconImage;
- for (key in this.cache_) {
- iconImage = this.cache_[key];
- if ((i++ & 3) === 0 && !iconImage.hasListener()) {
- delete this.cache_[key];
- --this.cacheSize_;
- }
- }
- }
- };
- ol.style.IconImageCache.prototype.get = function(src, crossOrigin, color) {
- var key = ol.style.IconImageCache.getKey(src, crossOrigin, color);
- return key in this.cache_ ? this.cache_[key] : null;
- };
- ol.style.IconImageCache.prototype.set = function(src, crossOrigin, color, iconImage) {
- var key = ol.style.IconImageCache.getKey(src, crossOrigin, color);
- this.cache_[key] = iconImage;
- ++this.cacheSize_;
- };
- ol.style.IconImageCache.prototype.setSize = function(maxCacheSize) {
- this.maxCacheSize_ = maxCacheSize;
- this.expire();
- };
- /**
- * The {@link ol.style.IconImageCache} for {@link ol.style.Icon} images.
- * @api
- */
- ol.style.iconImageCache = new ol.style.IconImageCache();
- ol.style.Image = function(options) {
- /**
- * @private
- * @type {number}
- */
- this.opacity_ = options.opacity;
- /**
- * @private
- * @type {boolean}
- */
- this.rotateWithView_ = options.rotateWithView;
- /**
- * @private
- * @type {number}
- */
- this.rotation_ = options.rotation;
- /**
- * @private
- * @type {number}
- */
- this.scale_ = options.scale;
- /**
- * @private
- * @type {boolean}
- */
- this.snapToPixel_ = options.snapToPixel;
- };
- ol.style.Image.prototype.getOpacity = function() {
- return this.opacity_;
- };
- ol.style.Image.prototype.getRotateWithView = function() {
- return this.rotateWithView_;
- };
- ol.style.Image.prototype.getRotation = function() {
- return this.rotation_;
- };
- ol.style.Image.prototype.getScale = function() {
- return this.scale_;
- };
- ol.style.Image.prototype.getSnapToPixel = function() {
- return this.snapToPixel_;
- };
- ol.style.Image.prototype.getAnchor = function() {};
- ol.style.Image.prototype.getImage = function(pixelRatio) {};
- ol.style.Image.prototype.getHitDetectionImage = function(pixelRatio) {};
- ol.style.Image.prototype.getImageState = function() {};
- ol.style.Image.prototype.getImageSize = function() {};
- ol.style.Image.prototype.getHitDetectionImageSize = function() {};
- ol.style.Image.prototype.getOrigin = function() {};
- ol.style.Image.prototype.getSize = function() {};
- ol.style.Image.prototype.setOpacity = function(opacity) {
- this.opacity_ = opacity;
- };
- ol.style.Image.prototype.setRotateWithView = function(rotateWithView) {
- this.rotateWithView_ = rotateWithView;
- };
- ol.style.Image.prototype.setRotation = function(rotation) {
- this.rotation_ = rotation;
- };
- ol.style.Image.prototype.setScale = function(scale) {
- this.scale_ = scale;
- };
- ol.style.Image.prototype.setSnapToPixel = function(snapToPixel) {
- this.snapToPixel_ = snapToPixel;
- };
- ol.style.Image.prototype.listenImageChange = function(listener, thisArg) {};
- ol.style.Image.prototype.load = function() {};
- ol.style.Image.prototype.unlistenImageChange = function(listener, thisArg) {};
- /**
- * @classdesc
- * Set regular shape style for vector features. The resulting shape will be
- * a regular polygon when `radius` is provided, or a star when `radius1` and
- * `radius2` are provided.
- *
- * @constructor
- * @param {olx.style.RegularShapeOptions} options Options.
- * @extends {ol.style.Image}
- * @api
- */
- ol.style.RegularShape = function(options) {
- /**
- * @private
- * @type {Array.<string>}
- */
- this.checksums_ = null;
- /**
- * @private
- * @type {HTMLCanvasElement}
- */
- this.canvas_ = null;
- /**
- * @private
- * @type {HTMLCanvasElement}
- */
- this.hitDetectionCanvas_ = null;
- /**
- * @private
- * @type {ol.style.Fill}
- */
- this.fill_ = options.fill !== undefined ? options.fill : null;
- /**
- * @private
- * @type {Array.<number>}
- */
- this.origin_ = [0, 0];
- /**
- * @private
- * @type {number}
- */
- this.points_ = options.points;
- /**
- * @protected
- * @type {number}
- */
- this.radius_ = /** @type {number} */ (options.radius !== undefined ?
- options.radius : options.radius1);
- /**
- * @private
- * @type {number|undefined}
- */
- this.radius2_ = options.radius2;
- /**
- * @private
- * @type {number}
- */
- this.angle_ = options.angle !== undefined ? options.angle : 0;
- /**
- * @private
- * @type {ol.style.Stroke}
- */
- this.stroke_ = options.stroke !== undefined ? options.stroke : null;
- /**
- * @private
- * @type {Array.<number>}
- */
- this.anchor_ = null;
- /**
- * @private
- * @type {ol.Size}
- */
- this.size_ = null;
- /**
- * @private
- * @type {ol.Size}
- */
- this.imageSize_ = null;
- /**
- * @private
- * @type {ol.Size}
- */
- this.hitDetectionImageSize_ = null;
- /**
- * @protected
- * @type {ol.style.AtlasManager|undefined}
- */
- this.atlasManager_ = options.atlasManager;
- this.render_(this.atlasManager_);
- /**
- * @type {boolean}
- */
- var snapToPixel = options.snapToPixel !== undefined ?
- options.snapToPixel : true;
- /**
- * @type {boolean}
- */
- var rotateWithView = options.rotateWithView !== undefined ?
- options.rotateWithView : false;
- ol.style.Image.call(this, {
- opacity: 1,
- rotateWithView: rotateWithView,
- rotation: options.rotation !== undefined ? options.rotation : 0,
- scale: 1,
- snapToPixel: snapToPixel
- });
- };
- ol.inherits(ol.style.RegularShape, ol.style.Image);
- ol.style.RegularShape.prototype.clone = function() {
- var style = new ol.style.RegularShape({
- fill: this.getFill() ? this.getFill().clone() : undefined,
- points: this.getPoints(),
- radius: this.getRadius(),
- radius2: this.getRadius2(),
- angle: this.getAngle(),
- snapToPixel: this.getSnapToPixel(),
- stroke: this.getStroke() ? this.getStroke().clone() : undefined,
- rotation: this.getRotation(),
- rotateWithView: this.getRotateWithView(),
- atlasManager: this.atlasManager_
- });
- style.setOpacity(this.getOpacity());
- style.setScale(this.getScale());
- return style;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.style.RegularShape.prototype.getAnchor = function() {
- return this.anchor_;
- };
- /**
- * Get the angle used in generating the shape.
- * @return {number} Shape's rotation in radians.
- * @api
- */
- ol.style.RegularShape.prototype.getAngle = function() {
- return this.angle_;
- };
- /**
- * Get the fill style for the shape.
- * @return {ol.style.Fill} Fill style.
- * @api
- */
- ol.style.RegularShape.prototype.getFill = function() {
- return this.fill_;
- };
- /**
- * @inheritDoc
- */
- ol.style.RegularShape.prototype.getHitDetectionImage = function(pixelRatio) {
- return this.hitDetectionCanvas_;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.style.RegularShape.prototype.getImage = function(pixelRatio) {
- return this.canvas_;
- };
- /**
- * @inheritDoc
- */
- ol.style.RegularShape.prototype.getImageSize = function() {
- return this.imageSize_;
- };
- /**
- * @inheritDoc
- */
- ol.style.RegularShape.prototype.getHitDetectionImageSize = function() {
- return this.hitDetectionImageSize_;
- };
- /**
- * @inheritDoc
- */
- ol.style.RegularShape.prototype.getImageState = function() {
- return ol.ImageState.LOADED;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.style.RegularShape.prototype.getOrigin = function() {
- return this.origin_;
- };
- /**
- * Get the number of points for generating the shape.
- * @return {number} Number of points for stars and regular polygons.
- * @api
- */
- ol.style.RegularShape.prototype.getPoints = function() {
- return this.points_;
- };
- /**
- * Get the (primary) radius for the shape.
- * @return {number} Radius.
- * @api
- */
- ol.style.RegularShape.prototype.getRadius = function() {
- return this.radius_;
- };
- /**
- * Get the secondary radius for the shape.
- * @return {number|undefined} Radius2.
- * @api
- */
- ol.style.RegularShape.prototype.getRadius2 = function() {
- return this.radius2_;
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.style.RegularShape.prototype.getSize = function() {
- return this.size_;
- };
- /**
- * Get the stroke style for the shape.
- * @return {ol.style.Stroke} Stroke style.
- * @api
- */
- ol.style.RegularShape.prototype.getStroke = function() {
- return this.stroke_;
- };
- /**
- * @inheritDoc
- */
- ol.style.RegularShape.prototype.listenImageChange = function(listener, thisArg) {};
- /**
- * @inheritDoc
- */
- ol.style.RegularShape.prototype.load = function() {};
- /**
- * @inheritDoc
- */
- ol.style.RegularShape.prototype.unlistenImageChange = function(listener, thisArg) {};
- /**
- * @protected
- * @param {ol.style.AtlasManager|undefined} atlasManager An atlas manager.
- */
- ol.style.RegularShape.prototype.render_ = function(atlasManager) {
- var imageSize;
- var lineCap = '';
- var lineJoin = '';
- var miterLimit = 0;
- var lineDash = null;
- var lineDashOffset = 0;
- var strokeStyle;
- var strokeWidth = 0;
- if (this.stroke_) {
- strokeStyle = this.stroke_.getColor();
- if (strokeStyle === null) {
- strokeStyle = ol.render.canvas.defaultStrokeStyle;
- }
- strokeStyle = ol.colorlike.asColorLike(strokeStyle);
- strokeWidth = this.stroke_.getWidth();
- if (strokeWidth === undefined) {
- strokeWidth = ol.render.canvas.defaultLineWidth;
- }
- lineDash = this.stroke_.getLineDash();
- lineDashOffset = this.stroke_.getLineDashOffset();
- if (!ol.has.CANVAS_LINE_DASH) {
- lineDash = null;
- lineDashOffset = 0;
- }
- lineJoin = this.stroke_.getLineJoin();
- if (lineJoin === undefined) {
- lineJoin = ol.render.canvas.defaultLineJoin;
- }
- lineCap = this.stroke_.getLineCap();
- if (lineCap === undefined) {
- lineCap = ol.render.canvas.defaultLineCap;
- }
- miterLimit = this.stroke_.getMiterLimit();
- if (miterLimit === undefined) {
- miterLimit = ol.render.canvas.defaultMiterLimit;
- }
- }
- var size = 2 * (this.radius_ + strokeWidth) + 1;
- /** @type {ol.RegularShapeRenderOptions} */
- var renderOptions = {
- strokeStyle: strokeStyle,
- strokeWidth: strokeWidth,
- size: size,
- lineCap: lineCap,
- lineDash: lineDash,
- lineDashOffset: lineDashOffset,
- lineJoin: lineJoin,
- miterLimit: miterLimit
- };
- if (atlasManager === undefined) {
- // no atlas manager is used, create a new canvas
- var context = ol.dom.createCanvasContext2D(size, size);
- this.canvas_ = context.canvas;
- // canvas.width and height are rounded to the closest integer
- size = this.canvas_.width;
- imageSize = size;
- this.draw_(renderOptions, context, 0, 0);
- this.createHitDetectionCanvas_(renderOptions);
- } else {
- // an atlas manager is used, add the symbol to an atlas
- size = Math.round(size);
- var hasCustomHitDetectionImage = !this.fill_;
- var renderHitDetectionCallback;
- if (hasCustomHitDetectionImage) {
- // render the hit-detection image into a separate atlas image
- renderHitDetectionCallback =
- this.drawHitDetectionCanvas_.bind(this, renderOptions);
- }
- var id = this.getChecksum();
- var info = atlasManager.add(
- id, size, size, this.draw_.bind(this, renderOptions),
- renderHitDetectionCallback);
- this.canvas_ = info.image;
- this.origin_ = [info.offsetX, info.offsetY];
- imageSize = info.image.width;
- if (hasCustomHitDetectionImage) {
- this.hitDetectionCanvas_ = info.hitImage;
- this.hitDetectionImageSize_ =
- [info.hitImage.width, info.hitImage.height];
- } else {
- this.hitDetectionCanvas_ = this.canvas_;
- this.hitDetectionImageSize_ = [imageSize, imageSize];
- }
- }
- this.anchor_ = [size / 2, size / 2];
- this.size_ = [size, size];
- this.imageSize_ = [imageSize, imageSize];
- };
- /**
- * @private
- * @param {ol.RegularShapeRenderOptions} renderOptions Render options.
- * @param {CanvasRenderingContext2D} context The rendering context.
- * @param {number} x The origin for the symbol (x).
- * @param {number} y The origin for the symbol (y).
- */
- ol.style.RegularShape.prototype.draw_ = function(renderOptions, context, x, y) {
- var i, angle0, radiusC;
- // reset transform
- context.setTransform(1, 0, 0, 1, 0, 0);
- // then move to (x, y)
- context.translate(x, y);
- context.beginPath();
- var points = this.points_;
- if (points === Infinity) {
- context.arc(
- renderOptions.size / 2, renderOptions.size / 2,
- this.radius_, 0, 2 * Math.PI, true);
- } else {
- var radius2 = (this.radius2_ !== undefined) ? this.radius2_
- : this.radius_;
- if (radius2 !== this.radius_) {
- points = 2 * points;
- }
- for (i = 0; i <= points; i++) {
- angle0 = i * 2 * Math.PI / points - Math.PI / 2 + this.angle_;
- radiusC = i % 2 === 0 ? this.radius_ : radius2;
- context.lineTo(renderOptions.size / 2 + radiusC * Math.cos(angle0),
- renderOptions.size / 2 + radiusC * Math.sin(angle0));
- }
- }
- if (this.fill_) {
- var color = this.fill_.getColor();
- if (color === null) {
- color = ol.render.canvas.defaultFillStyle;
- }
- context.fillStyle = ol.colorlike.asColorLike(color);
- context.fill();
- }
- if (this.stroke_) {
- context.strokeStyle = renderOptions.strokeStyle;
- context.lineWidth = renderOptions.strokeWidth;
- if (renderOptions.lineDash) {
- context.setLineDash(renderOptions.lineDash);
- context.lineDashOffset = renderOptions.lineDashOffset;
- }
- context.lineCap = renderOptions.lineCap;
- context.lineJoin = renderOptions.lineJoin;
- context.miterLimit = renderOptions.miterLimit;
- context.stroke();
- }
- context.closePath();
- };
- /**
- * @private
- * @param {ol.RegularShapeRenderOptions} renderOptions Render options.
- */
- ol.style.RegularShape.prototype.createHitDetectionCanvas_ = function(renderOptions) {
- this.hitDetectionImageSize_ = [renderOptions.size, renderOptions.size];
- if (this.fill_) {
- this.hitDetectionCanvas_ = this.canvas_;
- return;
- }
- // if no fill style is set, create an extra hit-detection image with a
- // default fill style
- var context = ol.dom.createCanvasContext2D(renderOptions.size, renderOptions.size);
- this.hitDetectionCanvas_ = context.canvas;
- this.drawHitDetectionCanvas_(renderOptions, context, 0, 0);
- };
- /**
- * @private
- * @param {ol.RegularShapeRenderOptions} renderOptions Render options.
- * @param {CanvasRenderingContext2D} context The context.
- * @param {number} x The origin for the symbol (x).
- * @param {number} y The origin for the symbol (y).
- */
- ol.style.RegularShape.prototype.drawHitDetectionCanvas_ = function(renderOptions, context, x, y) {
- // reset transform
- context.setTransform(1, 0, 0, 1, 0, 0);
- // then move to (x, y)
- context.translate(x, y);
- context.beginPath();
- var points = this.points_;
- if (points === Infinity) {
- context.arc(
- renderOptions.size / 2, renderOptions.size / 2,
- this.radius_, 0, 2 * Math.PI, true);
- } else {
- var radius2 = (this.radius2_ !== undefined) ? this.radius2_
- : this.radius_;
- if (radius2 !== this.radius_) {
- points = 2 * points;
- }
- var i, radiusC, angle0;
- for (i = 0; i <= points; i++) {
- angle0 = i * 2 * Math.PI / points - Math.PI / 2 + this.angle_;
- radiusC = i % 2 === 0 ? this.radius_ : radius2;
- context.lineTo(renderOptions.size / 2 + radiusC * Math.cos(angle0),
- renderOptions.size / 2 + radiusC * Math.sin(angle0));
- }
- }
- context.fillStyle = ol.render.canvas.defaultFillStyle;
- context.fill();
- if (this.stroke_) {
- context.strokeStyle = renderOptions.strokeStyle;
- context.lineWidth = renderOptions.strokeWidth;
- if (renderOptions.lineDash) {
- context.setLineDash(renderOptions.lineDash);
- context.lineDashOffset = renderOptions.lineDashOffset;
- }
- context.stroke();
- }
- context.closePath();
- };
- /**
- * @return {string} The checksum.
- */
- ol.style.RegularShape.prototype.getChecksum = function() {
- var strokeChecksum = this.stroke_ ?
- this.stroke_.getChecksum() : '-';
- var fillChecksum = this.fill_ ?
- this.fill_.getChecksum() : '-';
- var recalculate = !this.checksums_ ||
- (strokeChecksum != this.checksums_[1] ||
- fillChecksum != this.checksums_[2] ||
- this.radius_ != this.checksums_[3] ||
- this.radius2_ != this.checksums_[4] ||
- this.angle_ != this.checksums_[5] ||
- this.points_ != this.checksums_[6]);
- if (recalculate) {
- var checksum = 'r' + strokeChecksum + fillChecksum +
- (this.radius_ !== undefined ? this.radius_.toString() : '-') +
- (this.radius2_ !== undefined ? this.radius2_.toString() : '-') +
- (this.angle_ !== undefined ? this.angle_.toString() : '-') +
- (this.points_ !== undefined ? this.points_.toString() : '-');
- this.checksums_ = [checksum, strokeChecksum, fillChecksum,
- this.radius_, this.radius2_, this.angle_, this.points_];
- }
- return this.checksums_[0];
- };
- /**
- * @classdesc
- * Set circle style for vector features.
- *
- * @constructor
- * @param {olx.style.CircleOptions=} opt_options Options.
- * @extends {ol.style.RegularShape}
- * @api
- */
- ol.style.Circle = function(opt_options) {
- var options = opt_options || {};
- ol.style.RegularShape.call(this, {
- points: Infinity,
- fill: options.fill,
- radius: options.radius,
- snapToPixel: options.snapToPixel,
- stroke: options.stroke,
- atlasManager: options.atlasManager
- });
- };
- ol.inherits(ol.style.Circle, ol.style.RegularShape);
- /**
- * Clones the style. If an atlasmanager was provided to the original style it will be used in the cloned style, too.
- * @return {ol.style.Circle} The cloned style.
- * @override
- * @api
- */
- ol.style.Circle.prototype.clone = function() {
- var style = new ol.style.Circle({
- fill: this.getFill() ? this.getFill().clone() : undefined,
- stroke: this.getStroke() ? this.getStroke().clone() : undefined,
- radius: this.getRadius(),
- snapToPixel: this.getSnapToPixel(),
- atlasManager: this.atlasManager_
- });
- style.setOpacity(this.getOpacity());
- style.setScale(this.getScale());
- return style;
- };
- /**
- * Set the circle radius.
- *
- * @param {number} radius Circle radius.
- * @api
- */
- ol.style.Circle.prototype.setRadius = function(radius) {
- this.radius_ = radius;
- this.render_(this.atlasManager_);
- };
- /**
- * @classdesc
- * Set fill style for vector features.
- *
- * @constructor
- * @param {olx.style.FillOptions=} opt_options Options.
- * @api
- */
- ol.style.Fill = function(opt_options) {
- var options = opt_options || {};
- /**
- * @private
- * @type {ol.Color|ol.ColorLike}
- */
- this.color_ = options.color !== undefined ? options.color : null;
- /**
- * @private
- * @type {string|undefined}
- */
- this.checksum_ = undefined;
- };
- /**
- * Clones the style. The color is not cloned if it is an {@link ol.ColorLike}.
- * @return {ol.style.Fill} The cloned style.
- * @api
- */
- ol.style.Fill.prototype.clone = function() {
- var color = this.getColor();
- return new ol.style.Fill({
- color: (color && color.slice) ? color.slice() : color || undefined
- });
- };
- /**
- * Get the fill color.
- * @return {ol.Color|ol.ColorLike} Color.
- * @api
- */
- ol.style.Fill.prototype.getColor = function() {
- return this.color_;
- };
- /**
- * Set the color.
- *
- * @param {ol.Color|ol.ColorLike} color Color.
- * @api
- */
- ol.style.Fill.prototype.setColor = function(color) {
- this.color_ = color;
- this.checksum_ = undefined;
- };
- /**
- * @return {string} The checksum.
- */
- ol.style.Fill.prototype.getChecksum = function() {
- if (this.checksum_ === undefined) {
- if (
- this.color_ instanceof CanvasPattern ||
- this.color_ instanceof CanvasGradient
- ) {
- this.checksum_ = ol.getUid(this.color_).toString();
- } else {
- this.checksum_ = 'f' + (this.color_ ?
- ol.color.asString(this.color_) : '-');
- }
- }
- return this.checksum_;
- };
- /**
- * @classdesc
- * Set stroke style for vector features.
- * Note that the defaults given are the Canvas defaults, which will be used if
- * option is not defined. The `get` functions return whatever was entered in
- * the options; they will not return the default.
- *
- * @constructor
- * @param {olx.style.StrokeOptions=} opt_options Options.
- * @api
- */
- ol.style.Stroke = function(opt_options) {
- var options = opt_options || {};
- /**
- * @private
- * @type {ol.Color|ol.ColorLike}
- */
- this.color_ = options.color !== undefined ? options.color : null;
- /**
- * @private
- * @type {string|undefined}
- */
- this.lineCap_ = options.lineCap;
- /**
- * @private
- * @type {Array.<number>}
- */
- this.lineDash_ = options.lineDash !== undefined ? options.lineDash : null;
- /**
- * @private
- * @type {number|undefined}
- */
- this.lineDashOffset_ = options.lineDashOffset;
- /**
- * @private
- * @type {string|undefined}
- */
- this.lineJoin_ = options.lineJoin;
- /**
- * @private
- * @type {number|undefined}
- */
- this.miterLimit_ = options.miterLimit;
- /**
- * @private
- * @type {number|undefined}
- */
- this.width_ = options.width;
- /**
- * @private
- * @type {string|undefined}
- */
- this.checksum_ = undefined;
- };
- /**
- * Clones the style.
- * @return {ol.style.Stroke} The cloned style.
- * @api
- */
- ol.style.Stroke.prototype.clone = function() {
- var color = this.getColor();
- return new ol.style.Stroke({
- color: (color && color.slice) ? color.slice() : color || undefined,
- lineCap: this.getLineCap(),
- lineDash: this.getLineDash() ? this.getLineDash().slice() : undefined,
- lineDashOffset: this.getLineDashOffset(),
- lineJoin: this.getLineJoin(),
- miterLimit: this.getMiterLimit(),
- width: this.getWidth()
- });
- };
- /**
- * Get the stroke color.
- * @return {ol.Color|ol.ColorLike} Color.
- * @api
- */
- ol.style.Stroke.prototype.getColor = function() {
- return this.color_;
- };
- /**
- * Get the line cap type for the stroke.
- * @return {string|undefined} Line cap.
- * @api
- */
- ol.style.Stroke.prototype.getLineCap = function() {
- return this.lineCap_;
- };
- /**
- * Get the line dash style for the stroke.
- * @return {Array.<number>} Line dash.
- * @api
- */
- ol.style.Stroke.prototype.getLineDash = function() {
- return this.lineDash_;
- };
- /**
- * Get the line dash offset for the stroke.
- * @return {number|undefined} Line dash offset.
- * @api
- */
- ol.style.Stroke.prototype.getLineDashOffset = function() {
- return this.lineDashOffset_;
- };
- /**
- * Get the line join type for the stroke.
- * @return {string|undefined} Line join.
- * @api
- */
- ol.style.Stroke.prototype.getLineJoin = function() {
- return this.lineJoin_;
- };
- /**
- * Get the miter limit for the stroke.
- * @return {number|undefined} Miter limit.
- * @api
- */
- ol.style.Stroke.prototype.getMiterLimit = function() {
- return this.miterLimit_;
- };
- /**
- * Get the stroke width.
- * @return {number|undefined} Width.
- * @api
- */
- ol.style.Stroke.prototype.getWidth = function() {
- return this.width_;
- };
- /**
- * Set the color.
- *
- * @param {ol.Color|ol.ColorLike} color Color.
- * @api
- */
- ol.style.Stroke.prototype.setColor = function(color) {
- this.color_ = color;
- this.checksum_ = undefined;
- };
- /**
- * Set the line cap.
- *
- * @param {string|undefined} lineCap Line cap.
- * @api
- */
- ol.style.Stroke.prototype.setLineCap = function(lineCap) {
- this.lineCap_ = lineCap;
- this.checksum_ = undefined;
- };
- /**
- * Set the line dash.
- *
- * Please note that Internet Explorer 10 and lower [do not support][mdn] the
- * `setLineDash` method on the `CanvasRenderingContext2D` and therefore this
- * property will have no visual effect in these browsers.
- *
- * [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility
- *
- * @param {Array.<number>} lineDash Line dash.
- * @api
- */
- ol.style.Stroke.prototype.setLineDash = function(lineDash) {
- this.lineDash_ = lineDash;
- this.checksum_ = undefined;
- };
- /**
- * Set the line dash offset.
- *
- * @param {number|undefined} lineDashOffset Line dash offset.
- * @api
- */
- ol.style.Stroke.prototype.setLineDashOffset = function(lineDashOffset) {
- this.lineDashOffset_ = lineDashOffset;
- this.checksum_ = undefined;
- };
- /**
- * Set the line join.
- *
- * @param {string|undefined} lineJoin Line join.
- * @api
- */
- ol.style.Stroke.prototype.setLineJoin = function(lineJoin) {
- this.lineJoin_ = lineJoin;
- this.checksum_ = undefined;
- };
- /**
- * Set the miter limit.
- *
- * @param {number|undefined} miterLimit Miter limit.
- * @api
- */
- ol.style.Stroke.prototype.setMiterLimit = function(miterLimit) {
- this.miterLimit_ = miterLimit;
- this.checksum_ = undefined;
- };
- /**
- * Set the width.
- *
- * @param {number|undefined} width Width.
- * @api
- */
- ol.style.Stroke.prototype.setWidth = function(width) {
- this.width_ = width;
- this.checksum_ = undefined;
- };
- /**
- * @return {string} The checksum.
- */
- ol.style.Stroke.prototype.getChecksum = function() {
- if (this.checksum_ === undefined) {
- this.checksum_ = 's';
- if (this.color_) {
- if (typeof this.color_ === 'string') {
- this.checksum_ += this.color_;
- } else {
- this.checksum_ += ol.getUid(this.color_).toString();
- }
- } else {
- this.checksum_ += '-';
- }
- this.checksum_ += ',' +
- (this.lineCap_ !== undefined ?
- this.lineCap_.toString() : '-') + ',' +
- (this.lineDash_ ?
- this.lineDash_.toString() : '-') + ',' +
- (this.lineDashOffset_ !== undefined ?
- this.lineDashOffset_ : '-') + ',' +
- (this.lineJoin_ !== undefined ?
- this.lineJoin_ : '-') + ',' +
- (this.miterLimit_ !== undefined ?
- this.miterLimit_.toString() : '-') + ',' +
- (this.width_ !== undefined ?
- this.width_.toString() : '-');
- }
- return this.checksum_;
- };
- /**
- * Icon anchor units. One of 'fraction', 'pixels'.
- * @enum {string}
- */
- ol.style.IconAnchorUnits = {
- FRACTION: 'fraction',
- PIXELS: 'pixels'
- };
- /**
- * @constructor
- * @param {Image|HTMLCanvasElement} image Image.
- * @param {string|undefined} src Src.
- * @param {ol.Size} size Size.
- * @param {?string} crossOrigin Cross origin.
- * @param {ol.ImageState} imageState Image state.
- * @param {ol.Color} color Color.
- * @extends {ol.events.EventTarget}
- */
- ol.style.IconImage = function(image, src, size, crossOrigin, imageState,
- color) {
- ol.events.EventTarget.call(this);
- /**
- * @private
- * @type {Image|HTMLCanvasElement}
- */
- this.hitDetectionImage_ = null;
- /**
- * @private
- * @type {Image|HTMLCanvasElement}
- */
- this.image_ = !image ? new Image() : image;
- if (crossOrigin !== null) {
- this.image_.crossOrigin = crossOrigin;
- }
- /**
- * @private
- * @type {HTMLCanvasElement}
- */
- this.canvas_ = color ?
- /** @type {HTMLCanvasElement} */ (document.createElement('CANVAS')) :
- null;
- /**
- * @private
- * @type {ol.Color}
- */
- this.color_ = color;
- /**
- * @private
- * @type {Array.<ol.EventsKey>}
- */
- this.imageListenerKeys_ = null;
- /**
- * @private
- * @type {ol.ImageState}
- */
- this.imageState_ = imageState;
- /**
- * @private
- * @type {ol.Size}
- */
- this.size_ = size;
- /**
- * @private
- * @type {string|undefined}
- */
- this.src_ = src;
- /**
- * @private
- * @type {boolean}
- */
- this.tainting_ = false;
- if (this.imageState_ == ol.ImageState.LOADED) {
- this.determineTainting_();
- }
- };
- ol.inherits(ol.style.IconImage, ol.events.EventTarget);
- /**
- * @param {Image|HTMLCanvasElement} image Image.
- * @param {string} src Src.
- * @param {ol.Size} size Size.
- * @param {?string} crossOrigin Cross origin.
- * @param {ol.ImageState} imageState Image state.
- * @param {ol.Color} color Color.
- * @return {ol.style.IconImage} Icon image.
- */
- ol.style.IconImage.get = function(image, src, size, crossOrigin, imageState,
- color) {
- var iconImageCache = ol.style.iconImageCache;
- var iconImage = iconImageCache.get(src, crossOrigin, color);
- if (!iconImage) {
- iconImage = new ol.style.IconImage(
- image, src, size, crossOrigin, imageState, color);
- iconImageCache.set(src, crossOrigin, color, iconImage);
- }
- return iconImage;
- };
- /**
- * @private
- */
- ol.style.IconImage.prototype.determineTainting_ = function() {
- var context = ol.dom.createCanvasContext2D(1, 1);
- try {
- context.drawImage(this.image_, 0, 0);
- context.getImageData(0, 0, 1, 1);
- } catch (e) {
- this.tainting_ = true;
- }
- };
- /**
- * @private
- */
- ol.style.IconImage.prototype.dispatchChangeEvent_ = function() {
- this.dispatchEvent(ol.events.EventType.CHANGE);
- };
- /**
- * @private
- */
- ol.style.IconImage.prototype.handleImageError_ = function() {
- this.imageState_ = ol.ImageState.ERROR;
- this.unlistenImage_();
- this.dispatchChangeEvent_();
- };
- /**
- * @private
- */
- ol.style.IconImage.prototype.handleImageLoad_ = function() {
- this.imageState_ = ol.ImageState.LOADED;
- if (this.size_) {
- this.image_.width = this.size_[0];
- this.image_.height = this.size_[1];
- }
- this.size_ = [this.image_.width, this.image_.height];
- this.unlistenImage_();
- this.determineTainting_();
- this.replaceColor_();
- this.dispatchChangeEvent_();
- };
- /**
- * @param {number} pixelRatio Pixel ratio.
- * @return {Image|HTMLCanvasElement} Image or Canvas element.
- */
- ol.style.IconImage.prototype.getImage = function(pixelRatio) {
- return this.canvas_ ? this.canvas_ : this.image_;
- };
- /**
- * @return {ol.ImageState} Image state.
- */
- ol.style.IconImage.prototype.getImageState = function() {
- return this.imageState_;
- };
- /**
- * @param {number} pixelRatio Pixel ratio.
- * @return {Image|HTMLCanvasElement} Image element.
- */
- ol.style.IconImage.prototype.getHitDetectionImage = function(pixelRatio) {
- if (!this.hitDetectionImage_) {
- if (this.tainting_) {
- var width = this.size_[0];
- var height = this.size_[1];
- var context = ol.dom.createCanvasContext2D(width, height);
- context.fillRect(0, 0, width, height);
- this.hitDetectionImage_ = context.canvas;
- } else {
- this.hitDetectionImage_ = this.image_;
- }
- }
- return this.hitDetectionImage_;
- };
- /**
- * @return {ol.Size} Image size.
- */
- ol.style.IconImage.prototype.getSize = function() {
- return this.size_;
- };
- /**
- * @return {string|undefined} Image src.
- */
- ol.style.IconImage.prototype.getSrc = function() {
- return this.src_;
- };
- /**
- * Load not yet loaded URI.
- */
- ol.style.IconImage.prototype.load = function() {
- if (this.imageState_ == ol.ImageState.IDLE) {
- this.imageState_ = ol.ImageState.LOADING;
- this.imageListenerKeys_ = [
- ol.events.listenOnce(this.image_, ol.events.EventType.ERROR,
- this.handleImageError_, this),
- ol.events.listenOnce(this.image_, ol.events.EventType.LOAD,
- this.handleImageLoad_, this)
- ];
- try {
- this.image_.src = this.src_;
- } catch (e) {
- this.handleImageError_();
- }
- }
- };
- /**
- * @private
- */
- ol.style.IconImage.prototype.replaceColor_ = function() {
- if (this.tainting_ || this.color_ === null) {
- return;
- }
- this.canvas_.width = this.image_.width;
- this.canvas_.height = this.image_.height;
- var ctx = this.canvas_.getContext('2d');
- ctx.drawImage(this.image_, 0, 0);
- var imgData = ctx.getImageData(0, 0, this.image_.width, this.image_.height);
- var data = imgData.data;
- var r = this.color_[0] / 255.0;
- var g = this.color_[1] / 255.0;
- var b = this.color_[2] / 255.0;
- for (var i = 0, ii = data.length; i < ii; i += 4) {
- data[i] *= r;
- data[i + 1] *= g;
- data[i + 2] *= b;
- }
- ctx.putImageData(imgData, 0, 0);
- };
- /**
- * Discards event handlers which listen for load completion or errors.
- *
- * @private
- */
- ol.style.IconImage.prototype.unlistenImage_ = function() {
- this.imageListenerKeys_.forEach(ol.events.unlistenByKey);
- this.imageListenerKeys_ = null;
- };
- /**
- * Icon origin. One of 'bottom-left', 'bottom-right', 'top-left', 'top-right'.
- * @enum {string}
- */
- ol.style.IconOrigin = {
- BOTTOM_LEFT: 'bottom-left',
- BOTTOM_RIGHT: 'bottom-right',
- TOP_LEFT: 'top-left',
- TOP_RIGHT: 'top-right'
- };
- /**
- * @classdesc
- * Set icon style for vector features.
- *
- * @constructor
- * @param {olx.style.IconOptions=} opt_options Options.
- * @extends {ol.style.Image}
- * @api
- */
- ol.style.Icon = function(opt_options) {
- var options = opt_options || {};
- /**
- * @private
- * @type {Array.<number>}
- */
- this.anchor_ = options.anchor !== undefined ? options.anchor : [0.5, 0.5];
- /**
- * @private
- * @type {Array.<number>}
- */
- this.normalizedAnchor_ = null;
- /**
- * @private
- * @type {ol.style.IconOrigin}
- */
- this.anchorOrigin_ = options.anchorOrigin !== undefined ?
- options.anchorOrigin : ol.style.IconOrigin.TOP_LEFT;
- /**
- * @private
- * @type {ol.style.IconAnchorUnits}
- */
- this.anchorXUnits_ = options.anchorXUnits !== undefined ?
- options.anchorXUnits : ol.style.IconAnchorUnits.FRACTION;
- /**
- * @private
- * @type {ol.style.IconAnchorUnits}
- */
- this.anchorYUnits_ = options.anchorYUnits !== undefined ?
- options.anchorYUnits : ol.style.IconAnchorUnits.FRACTION;
- /**
- * @private
- * @type {?string}
- */
- this.crossOrigin_ =
- options.crossOrigin !== undefined ? options.crossOrigin : null;
- /**
- * @type {Image|HTMLCanvasElement}
- */
- var image = options.img !== undefined ? options.img : null;
- /**
- * @type {ol.Size}
- */
- var imgSize = options.imgSize !== undefined ? options.imgSize : null;
- /**
- * @type {string|undefined}
- */
- var src = options.src;
- // ol.asserts.assert(!(src !== undefined && image),
- // 4); // `image` and `src` cannot be provided at the same time
- // ol.asserts.assert(!image || (image && imgSize),
- // 5); // `imgSize` must be set when `image` is provided
- if ((src === undefined || src.length === 0) && image) {
- src = image.src || ol.getUid(image).toString();
- }
- // ol.asserts.assert(src !== undefined && src.length > 0,
- // 6); // A defined and non-empty `src` or `image` must be provided
- /**
- * @type {ol.ImageState}
- */
- var imageState = options.src !== undefined ?
- ol.ImageState.IDLE : ol.ImageState.LOADED;
- /**
- * @private
- * @type {ol.Color}
- */
- this.color_ = options.color !== undefined ? ol.color.asArray(options.color) :
- null;
- /**
- * @private
- * @type {ol.style.IconImage}
- */
- this.iconImage_ = ol.style.IconImage.get(
- image, /** @type {string} */ (src), imgSize, this.crossOrigin_, imageState, this.color_);
- /**
- * @private
- * @type {Array.<number>}
- */
- this.offset_ = options.offset !== undefined ? options.offset : [0, 0];
- /**
- * @private
- * @type {ol.style.IconOrigin}
- */
- this.offsetOrigin_ = options.offsetOrigin !== undefined ?
- options.offsetOrigin : ol.style.IconOrigin.TOP_LEFT;
- /**
- * @private
- * @type {Array.<number>}
- */
- this.origin_ = null;
- /**
- * @private
- * @type {ol.Size}
- */
- this.size_ = options.size !== undefined ? options.size : null;
- /**
- * @type {number}
- */
- var opacity = options.opacity !== undefined ? options.opacity : 1;
- /**
- * @type {boolean}
- */
- var rotateWithView = options.rotateWithView !== undefined ?
- options.rotateWithView : false;
- /**
- * @type {number}
- */
- var rotation = options.rotation !== undefined ? options.rotation : 0;
- /**
- * @type {number}
- */
- var scale = options.scale !== undefined ? options.scale : 1;
- /**
- * @type {boolean}
- */
- var snapToPixel = options.snapToPixel !== undefined ?
- options.snapToPixel : true;
- ol.style.Image.call(this, {
- opacity: opacity,
- rotation: rotation,
- scale: scale,
- snapToPixel: snapToPixel,
- rotateWithView: rotateWithView
- });
- };
- ol.inherits(ol.style.Icon, ol.style.Image);
- /**
- * Clones the style. The underlying Image/HTMLCanvasElement is not cloned.
- * @return {ol.style.Icon} The cloned style.
- * @api
- */
- ol.style.Icon.prototype.clone = function() {
- return new ol.style.Icon({
- anchor: this.anchor_.slice(),
- anchorOrigin: this.anchorOrigin_,
- anchorXUnits: this.anchorXUnits_,
- anchorYUnits: this.anchorYUnits_,
- crossOrigin: this.crossOrigin_,
- color: (this.color_ && this.color_.slice) ? this.color_.slice() : this.color_ || undefined,
- src: this.getSrc(),
- offset: this.offset_.slice(),
- offsetOrigin: this.offsetOrigin_,
- size: this.size_ !== null ? this.size_.slice() : undefined,
- opacity: this.getOpacity(),
- scale: this.getScale(),
- snapToPixel: this.getSnapToPixel(),
- rotation: this.getRotation(),
- rotateWithView: this.getRotateWithView()
- });
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.style.Icon.prototype.getAnchor = function() {
- if (this.normalizedAnchor_) {
- return this.normalizedAnchor_;
- }
- var anchor = this.anchor_;
- var size = this.getSize();
- if (this.anchorXUnits_ == ol.style.IconAnchorUnits.FRACTION ||
- this.anchorYUnits_ == ol.style.IconAnchorUnits.FRACTION) {
- if (!size) {
- return null;
- }
- anchor = this.anchor_.slice();
- if (this.anchorXUnits_ == ol.style.IconAnchorUnits.FRACTION) {
- anchor[0] *= size[0];
- }
- if (this.anchorYUnits_ == ol.style.IconAnchorUnits.FRACTION) {
- anchor[1] *= size[1];
- }
- }
- if (this.anchorOrigin_ != ol.style.IconOrigin.TOP_LEFT) {
- if (!size) {
- return null;
- }
- if (anchor === this.anchor_) {
- anchor = this.anchor_.slice();
- }
- if (this.anchorOrigin_ == ol.style.IconOrigin.TOP_RIGHT ||
- this.anchorOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) {
- anchor[0] = -anchor[0] + size[0];
- }
- if (this.anchorOrigin_ == ol.style.IconOrigin.BOTTOM_LEFT ||
- this.anchorOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) {
- anchor[1] = -anchor[1] + size[1];
- }
- }
- this.normalizedAnchor_ = anchor;
- return this.normalizedAnchor_;
- };
- /**
- * Get the icon color.
- * @return {ol.Color} Color.
- * @api
- */
- ol.style.Icon.prototype.getColor = function() {
- return this.color_;
- };
- /**
- * Get the image icon.
- * @param {number} pixelRatio Pixel ratio.
- * @return {Image|HTMLCanvasElement} Image or Canvas element.
- * @override
- * @api
- */
- ol.style.Icon.prototype.getImage = function(pixelRatio) {
- return this.iconImage_.getImage(pixelRatio);
- };
- /**
- * @override
- */
- ol.style.Icon.prototype.getImageSize = function() {
- return this.iconImage_.getSize();
- };
- /**
- * @override
- */
- ol.style.Icon.prototype.getHitDetectionImageSize = function() {
- return this.getImageSize();
- };
- /**
- * @override
- */
- ol.style.Icon.prototype.getImageState = function() {
- return this.iconImage_.getImageState();
- };
- /**
- * @override
- */
- ol.style.Icon.prototype.getHitDetectionImage = function(pixelRatio) {
- return this.iconImage_.getHitDetectionImage(pixelRatio);
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.style.Icon.prototype.getOrigin = function() {
- if (this.origin_) {
- return this.origin_;
- }
- var offset = this.offset_;
- if (this.offsetOrigin_ != ol.style.IconOrigin.TOP_LEFT) {
- var size = this.getSize();
- var iconImageSize = this.iconImage_.getSize();
- if (!size || !iconImageSize) {
- return null;
- }
- offset = offset.slice();
- if (this.offsetOrigin_ == ol.style.IconOrigin.TOP_RIGHT ||
- this.offsetOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) {
- offset[0] = iconImageSize[0] - size[0] - offset[0];
- }
- if (this.offsetOrigin_ == ol.style.IconOrigin.BOTTOM_LEFT ||
- this.offsetOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) {
- offset[1] = iconImageSize[1] - size[1] - offset[1];
- }
- }
- this.origin_ = offset;
- return this.origin_;
- };
- /**
- * Get the image URL.
- * @return {string|undefined} Image src.
- * @api
- */
- ol.style.Icon.prototype.getSrc = function() {
- return this.iconImage_.getSrc();
- };
- /**
- * @inheritDoc
- * @api
- */
- ol.style.Icon.prototype.getSize = function() {
- return !this.size_ ? this.iconImage_.getSize() : this.size_;
- };
- /**
- * @override
- */
- ol.style.Icon.prototype.listenImageChange = function(listener, thisArg) {
- return ol.events.listen(this.iconImage_, ol.events.EventType.CHANGE,
- listener, thisArg);
- };
- /**
- * Load not yet loaded URI.
- * When rendering a feature with an icon style, the vector renderer will
- * automatically call this method. However, you might want to call this
- * method yourself for preloading or other purposes.
- * @override
- * @api
- */
- ol.style.Icon.prototype.load = function() {
- this.iconImage_.load();
- };
- /**
- * @override
- */
- ol.style.Icon.prototype.unlistenImageChange = function(listener, thisArg) {
- ol.events.unlisten(this.iconImage_, ol.events.EventType.CHANGE,
- listener, thisArg);
- };
- ol.style.Text = function(opt_options) {
- var options = opt_options || {};
- this.font_ = options.font;
- this.rotation_ = options.rotation;
- this.rotateWithView_ = options.rotateWithView;
- this.scale_ = options.scale;
- this.text_ = options.text;
- this.textAlign_ = options.textAlign;
- this.textBaseline_ = options.textBaseline;
- this.fill_ = options.fill !== undefined ? options.fill :
- new ol.style.Fill({color: ol.style.Text.DEFAULT_FILL_COLOR_});
- this.maxAngle_ = options.maxAngle !== undefined ? options.maxAngle : Math.PI / 4;
- this.placement_ = options.placement !== undefined ? options.placement : ol.style.TextPlacement.POINT;
- //TODO Use options.overflow directly after removing @deprecated exceedLength
- var overflow = options.overflow === undefined ? options.exceedLength : options.overflow;
- this.overflow_ = overflow !== undefined ? overflow : false;
- this.stroke_ = options.stroke !== undefined ? options.stroke : null;
- this.offsetX_ = options.offsetX !== undefined ? options.offsetX : 0;
- this.offsetY_ = options.offsetY !== undefined ? options.offsetY : 0;
- this.backgroundFill_ = options.backgroundFill ? options.backgroundFill : null;
- this.backgroundStroke_ = options.backgroundStroke ? options.backgroundStroke : null;
- this.padding_ = options.padding === undefined ? null : options.padding;
- };
- ol.style.Text.DEFAULT_FILL_COLOR_ = '#333';
- ol.style.Text.prototype.clone = function() {
- return new ol.style.Text({
- font: this.getFont(),
- placement: this.getPlacement(),
- maxAngle: this.getMaxAngle(),
- overflow: this.getOverflow(),
- rotation: this.getRotation(),
- rotateWithView: this.getRotateWithView(),
- scale: this.getScale(),
- text: this.getText(),
- textAlign: this.getTextAlign(),
- textBaseline: this.getTextBaseline(),
- fill: this.getFill() ? this.getFill().clone() : undefined,
- stroke: this.getStroke() ? this.getStroke().clone() : undefined,
- offsetX: this.getOffsetX(),
- offsetY: this.getOffsetY()
- });
- };
- ol.style.Text.prototype.getOverflow = function() {
- return this.overflow_;
- };
- ol.style.Text.prototype.getFont = function() {
- return this.font_;
- };
- ol.style.Text.prototype.getMaxAngle = function() {
- return this.maxAngle_;
- };
- ol.style.Text.prototype.getPlacement = function() {
- return this.placement_;
- };
- ol.style.Text.prototype.getOffsetX = function() {
- return this.offsetX_;
- };
- ol.style.Text.prototype.getOffsetY = function() {
- return this.offsetY_;
- };
- ol.style.Text.prototype.getFill = function() {
- return this.fill_;
- };
- ol.style.Text.prototype.getRotateWithView = function() {
- return this.rotateWithView_;
- };
- ol.style.Text.prototype.getRotation = function() {
- return this.rotation_;
- };
- ol.style.Text.prototype.getScale = function() {
- return this.scale_;
- };
- ol.style.Text.prototype.getStroke = function() {
- return this.stroke_;
- };
- ol.style.Text.prototype.getText = function() {
- return this.text_;
- };
- ol.style.Text.prototype.getTextAlign = function() {
- return this.textAlign_;
- };
- ol.style.Text.prototype.getTextBaseline = function() {
- return this.textBaseline_;
- };
- ol.style.Text.prototype.getBackgroundFill = function() {
- return this.backgroundFill_;
- };
- ol.style.Text.prototype.getBackgroundStroke = function() {
- return this.backgroundStroke_;
- };
- ol.style.Text.prototype.getPadding = function() {
- return this.padding_;
- };
- ol.style.Text.prototype.setOverflow = function(overflow) {
- this.overflow_ = overflow;
- };
- ol.style.Text.prototype.setFont = function(font) {
- this.font_ = font;
- };
- ol.style.Text.prototype.setMaxAngle = function(maxAngle) {
- this.maxAngle_ = maxAngle;
- };
- ol.style.Text.prototype.setOffsetX = function(offsetX) {
- this.offsetX_ = offsetX;
- };
- ol.style.Text.prototype.setOffsetY = function(offsetY) {
- this.offsetY_ = offsetY;
- };
- ol.style.Text.prototype.setPlacement = function(placement) {
- this.placement_ = placement;
- };
- ol.style.Text.prototype.setFill = function(fill) {
- this.fill_ = fill;
- };
- ol.style.Text.prototype.setRotation = function(rotation) {
- this.rotation_ = rotation;
- };
- ol.style.Text.prototype.setScale = function(scale) {
- this.scale_ = scale;
- };
- ol.style.Text.prototype.setStroke = function(stroke) {
- this.stroke_ = stroke;
- };
- ol.style.Text.prototype.setText = function(text) {
- this.text_ = text;
- };
- ol.style.Text.prototype.setTextAlign = function(textAlign) {
- this.textAlign_ = textAlign;
- };
- ol.style.Text.prototype.setTextBaseline = function(textBaseline) {
- this.textBaseline_ = textBaseline;
- };
- ol.style.Text.prototype.setBackgroundFill = function(fill) {
- this.backgroundFill_ = fill;
- };
- ol.style.Text.prototype.setBackgroundStroke = function(stroke) {
- this.backgroundStroke_ = stroke;
- };
- ol.style.Text.prototype.setPadding = function(padding) {
- this.padding_ = padding;
- };
- ol.style.Style = function(opt_options) {
- var options = opt_options || {};
- /**
- * @private
- * @type {string|ol.geom.Geometry|ol.StyleGeometryFunction}
- */
- this.geometry_ = null;
- /**
- * @private
- * @type {!ol.StyleGeometryFunction}
- */
- this.geometryFunction_ = ol.style.Style.defaultGeometryFunction;
- if (options.geometry !== undefined) {
- this.setGeometry(options.geometry);
- }
- /**
- * @private
- * @type {ol.style.Fill}
- */
- this.fill_ = options.fill !== undefined ? options.fill : null;
- /**
- * @private
- * @type {ol.style.Image}
- */
- this.image_ = options.image !== undefined ? options.image : null;
- /**
- * @private
- * @type {ol.StyleRenderFunction|null}
- */
- this.renderer_ = options.renderer !== undefined ? options.renderer : null;
- /**
- * @private
- * @type {ol.style.Stroke}
- */
- this.stroke_ = options.stroke !== undefined ? options.stroke : null;
- /**
- * @private
- * @type {ol.style.Text}
- */
- this.text_ = options.text !== undefined ? options.text : null;
- /**
- * @private
- * @type {number|undefined}
- */
- this.zIndex_ = options.zIndex;
- };
- /**
- * Clones the style.
- * @return {ol.style.Style} The cloned style.
- * @api
- */
- ol.style.Style.prototype.clone = function() {
- var geometry = this.getGeometry();
- if (geometry && geometry.clone) {
- geometry = geometry.clone();
- }
- return new ol.style.Style({
- geometry: geometry,
- fill: this.getFill() ? this.getFill().clone() : undefined,
- image: this.getImage() ? this.getImage().clone() : undefined,
- stroke: this.getStroke() ? this.getStroke().clone() : undefined,
- text: this.getText() ? this.getText().clone() : undefined,
- zIndex: this.getZIndex()
- });
- };
- /**
- * Get the custom renderer function that was configured with
- * {@link #setRenderer} or the `renderer` constructor option.
- * @return {ol.StyleRenderFunction|null} Custom renderer function.
- * @api
- */
- ol.style.Style.prototype.getRenderer = function() {
- return this.renderer_;
- };
- /**
- * Sets a custom renderer function for this style. When set, `fill`, `stroke`
- * and `image` options of the style will be ignored.
- * @param {ol.StyleRenderFunction|null} renderer Custom renderer function.
- * @api
- */
- ol.style.Style.prototype.setRenderer = function(renderer) {
- this.renderer_ = renderer;
- };
- /**
- * Get the geometry to be rendered.
- * @return {string|ol.geom.Geometry|ol.StyleGeometryFunction}
- * Feature property or geometry or function that returns the geometry that will
- * be rendered with this style.
- * @api
- */
- ol.style.Style.prototype.getGeometry = function() {
- return this.geometry_;
- };
- /**
- * Get the function used to generate a geometry for rendering.
- * @return {!ol.StyleGeometryFunction} Function that is called with a feature
- * and returns the geometry to render instead of the feature's geometry.
- * @api
- */
- ol.style.Style.prototype.getGeometryFunction = function() {
- return this.geometryFunction_;
- };
- /**
- * Get the fill style.
- * @return {ol.style.Fill} Fill style.
- * @api
- */
- ol.style.Style.prototype.getFill = function() {
- return this.fill_;
- };
- /**
- * Set the fill style.
- * @param {ol.style.Fill} fill Fill style.
- * @api
- */
- ol.style.Style.prototype.setFill = function(fill) {
- this.fill_ = fill;
- };
- /**
- * Get the image style.
- * @return {ol.style.Image} Image style.
- * @api
- */
- ol.style.Style.prototype.getImage = function() {
- return this.image_;
- };
- /**
- * Set the image style.
- * @param {ol.style.Image} image Image style.
- * @api
- */
- ol.style.Style.prototype.setImage = function(image) {
- this.image_ = image;
- };
- /**
- * Get the stroke style.
- * @return {ol.style.Stroke} Stroke style.
- * @api
- */
- ol.style.Style.prototype.getStroke = function() {
- return this.stroke_;
- };
- /**
- * Set the stroke style.
- * @param {ol.style.Stroke} stroke Stroke style.
- * @api
- */
- ol.style.Style.prototype.setStroke = function(stroke) {
- this.stroke_ = stroke;
- };
- /**
- * Get the text style.
- * @return {ol.style.Text} Text style.
- * @api
- */
- ol.style.Style.prototype.getText = function() {
- return this.text_;
- };
- /**
- * Set the text style.
- * @param {ol.style.Text} text Text style.
- * @api
- */
- ol.style.Style.prototype.setText = function(text) {
- this.text_ = text;
- };
- /**
- * Get the z-index for the style.
- * @return {number|undefined} ZIndex.
- * @api
- */
- ol.style.Style.prototype.getZIndex = function() {
- return this.zIndex_;
- };
- /**
- * Set a geometry that is rendered instead of the feature's geometry.
- *
- * @param {string|ol.geom.Geometry|ol.StyleGeometryFunction} geometry
- * Feature property or geometry or function returning a geometry to render
- * for this style.
- * @api
- */
- ol.style.Style.prototype.setGeometry = function(geometry) {
- if (typeof geometry === 'function') {
- this.geometryFunction_ = geometry;
- } else if (typeof geometry === 'string') {
- this.geometryFunction_ = function(feature) {
- return /** @type {ol.geom.Geometry} */ (feature.get(geometry));
- };
- } else if (!geometry) {
- this.geometryFunction_ = ol.style.Style.defaultGeometryFunction;
- } else if (geometry !== undefined) {
- this.geometryFunction_ = function() {
- return /** @type {ol.geom.Geometry} */ (geometry);
- };
- }
- this.geometry_ = geometry;
- };
- /**
- * Set the z-index.
- *
- * @param {number|undefined} zIndex ZIndex.
- * @api
- */
- ol.style.Style.prototype.setZIndex = function(zIndex) {
- this.zIndex_ = zIndex;
- };
- /**
- * Convert the provided object into a style function. Functions passed through
- * unchanged. Arrays of ol.style.Style or single style objects wrapped in a
- * new style function.
- * @param {ol.StyleFunction|Array.<ol.style.Style>|ol.style.Style} obj
- * A style function, a single style, or an array of styles.
- * @return {ol.StyleFunction} A style function.
- */
- ol.style.Style.createFunction = function(obj) {
- var styleFunction;
- if (typeof obj === 'function') {
- styleFunction = obj;
- } else {
- /**
- * @type {Array.<ol.style.Style>}
- */
- var styles;
- if (Array.isArray(obj)) {
- styles = obj;
- } else {
- ol.asserts.assert(obj instanceof ol.style.Style,
- 41); // Expected an `ol.style.Style` or an array of `ol.style.Style`
- styles = [obj];
- }
- styleFunction = function() {
- return styles;
- };
- }
- return styleFunction;
- };
- /**
- * @type {Array.<ol.style.Style>}
- * @private
- */
- ol.style.Style.default_ = null;
- /**
- * @param {ol.Feature|ol.render.Feature} feature Feature.
- * @param {number} resolution Resolution.
- * @return {Array.<ol.style.Style>} Style.
- */
- ol.style.Style.defaultFunction = function(feature, resolution) {
- // We don't use an immediately-invoked function
- // and a closure so we don't get an error at script evaluation time in
- // browsers that do not support Canvas. (ol.style.Circle does
- // canvas.getContext('2d') at construction time, which will cause an.error
- // in such browsers.)
- if (!ol.style.Style.default_) {
- var fill = new ol.style.Fill({
- color: 'rgba(255,255,255,0.4)'
- });
- var stroke = new ol.style.Stroke({
- color: '#3399CC',
- width: 1.25
- });
- ol.style.Style.default_ = [
- new ol.style.Style({
- image: new ol.style.Circle({
- fill: fill,
- stroke: stroke,
- radius: 5
- }),
- fill: fill,
- stroke: stroke
- })
- ];
- }
- return ol.style.Style.default_;
- };
- /**
- * Default styles for editing features.
- * @return {Object.<ol.geom.GeometryType, Array.<ol.style.Style>>} Styles
- */
- ol.style.Style.createDefaultEditing = function() {
- /** @type {Object.<ol.geom.GeometryType, Array.<ol.style.Style>>} */
- var styles = {};
- var white = [255, 255, 255, 1];
- var blue = [0, 153, 255, 1];
- var width = 3;
- styles[ol.geom.GeometryType.POLYGON] = [
- new ol.style.Style({
- fill: new ol.style.Fill({
- color: [255, 255, 255, 0.5]
- })
- })
- ];
- styles[ol.geom.GeometryType.MULTI_POLYGON] =
- styles[ol.geom.GeometryType.POLYGON];
- styles[ol.geom.GeometryType.LINE_STRING] = [
- new ol.style.Style({
- stroke: new ol.style.Stroke({
- color: white,
- width: width + 2
- })
- }),
- new ol.style.Style({
- stroke: new ol.style.Stroke({
- color: blue,
- width: width
- })
- })
- ];
- styles[ol.geom.GeometryType.MULTI_LINE_STRING] =
- styles[ol.geom.GeometryType.LINE_STRING];
- styles[ol.geom.GeometryType.CIRCLE] =
- styles[ol.geom.GeometryType.POLYGON].concat(
- styles[ol.geom.GeometryType.LINE_STRING]
- );
- styles[ol.geom.GeometryType.POINT] = [
- new ol.style.Style({
- image: new ol.style.Circle({
- radius: width * 2,
- fill: new ol.style.Fill({
- color: blue
- }),
- stroke: new ol.style.Stroke({
- color: white,
- width: width / 2
- })
- }),
- zIndex: Infinity
- })
- ];
- styles[ol.geom.GeometryType.MULTI_POINT] =
- styles[ol.geom.GeometryType.POINT];
- styles[ol.geom.GeometryType.GEOMETRY_COLLECTION] =
- styles[ol.geom.GeometryType.POLYGON].concat(
- styles[ol.geom.GeometryType.LINE_STRING],
- styles[ol.geom.GeometryType.POINT]
- );
- return styles;
- };
- /**
- * Function that is called with a feature and returns its default geometry.
- * @param {ol.Feature|ol.render.Feature} feature Feature to get the geometry
- * for.
- * @return {ol.geom.Geometry|ol.render.Feature|undefined} Geometry to render.
- */
- ol.style.Style.defaultGeometryFunction = function(feature) {
- return feature.getGeometry();
- };
- ol.ext = {};
- ol.ext.rbush = function() {};
- (function() {(function (exports) {
- var quickselect_1 = quickselect;
- var default_1 = quickselect;
- function quickselect(arr, k, left, right, compare) {
- quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare);
- }
- function quickselectStep(arr, k, left, right, compare) {
- while (right > left) {
- if (right - left > 600) {
- var n = right - left + 1;
- var m = k - left + 1;
- var z = Math.log(n);
- var s = 0.5 * Math.exp(2 * z / 3);
- var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
- var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
- var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
- quickselectStep(arr, k, newLeft, newRight, compare);
- }
- var t = arr[k];
- var i = left;
- var j = right;
- swap(arr, left, k);
- if (compare(arr[right], t) > 0) swap(arr, left, right);
- while (i < j) {
- swap(arr, i, j);
- i++;
- j--;
- while (compare(arr[i], t) < 0) i++;
- while (compare(arr[j], t) > 0) j--;
- }
- if (compare(arr[left], t) === 0) swap(arr, left, j);
- else {
- j++;
- swap(arr, j, right);
- }
- if (j <= k) left = j + 1;
- if (k <= j) right = j - 1;
- }
- }
- function swap(arr, i, j) {
- var tmp = arr[i];
- arr[i] = arr[j];
- arr[j] = tmp;
- }
- function defaultCompare(a, b) {
- return a < b ? -1 : a > b ? 1 : 0;
- }
- quickselect_1.default = default_1;
- var rbush_1 = rbush;
- function rbush(maxEntries, format) {
- if (!(this instanceof rbush)) return new rbush(maxEntries, format);
- this._maxEntries = Math.max(4, maxEntries || 9);
- this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
- if (format) {
- this._initFormat(format);
- }
- this.clear();
- }
- rbush.prototype = {
- all: function () {
- return this._all(this.data, []);
- },
- search: function (bbox) {
- var node = this.data,
- result = [],
- toBBox = this.toBBox;
- if (!intersects(bbox, node)) return result;
- var nodesToSearch = [],
- i, len, child, childBBox;
- while (node) {
- for (i = 0, len = node.children.length; i < len; i++) {
- child = node.children[i];
- childBBox = node.leaf ? toBBox(child) : child;
- if (intersects(bbox, childBBox)) {
- if (node.leaf) result.push(child);
- else if (contains(bbox, childBBox)) this._all(child, result);
- else nodesToSearch.push(child);
- }
- }
- node = nodesToSearch.pop();
- }
- return result;
- },
- collides: function (bbox) {
- var node = this.data,
- toBBox = this.toBBox;
- if (!intersects(bbox, node)) return false;
- var nodesToSearch = [],
- i, len, child, childBBox;
- while (node) {
- for (i = 0, len = node.children.length; i < len; i++) {
- child = node.children[i];
- childBBox = node.leaf ? toBBox(child) : child;
- if (intersects(bbox, childBBox)) {
- if (node.leaf || contains(bbox, childBBox)) return true;
- nodesToSearch.push(child);
- }
- }
- node = nodesToSearch.pop();
- }
- return false;
- },
- load: function (data) {
- if (!(data && data.length)) return this;
- if (data.length < this._minEntries) {
- for (var i = 0, len = data.length; i < len; i++) {
- this.insert(data[i]);
- }
- return this;
- }
- var node = this._build(data.slice(), 0, data.length - 1, 0);
- if (!this.data.children.length) {
- this.data = node;
- } else if (this.data.height === node.height) {
- this._splitRoot(this.data, node);
- } else {
- if (this.data.height < node.height) {
- var tmpNode = this.data;
- this.data = node;
- node = tmpNode;
- }
- this._insert(node, this.data.height - node.height - 1, true);
- }
- return this;
- },
- insert: function (item) {
- if (item) this._insert(item, this.data.height - 1);
- return this;
- },
- clear: function () {
- this.data = createNode([]);
- return this;
- },
- remove: function (item, equalsFn) {
- if (!item) return this;
- var node = this.data,
- bbox = this.toBBox(item),
- path = [],
- indexes = [],
- i, parent, index, goingUp;
- while (node || path.length) {
- if (!node) {
- node = path.pop();
- parent = path[path.length - 1];
- i = indexes.pop();
- goingUp = true;
- }
- if (node.leaf) {
- index = findItem(item, node.children, equalsFn);
- if (index !== -1) {
- node.children.splice(index, 1);
- path.push(node);
- this._condense(path);
- return this;
- }
- }
- if (!goingUp && !node.leaf && contains(node, bbox)) {
- path.push(node);
- indexes.push(i);
- i = 0;
- parent = node;
- node = node.children[0];
- } else if (parent) {
- i++;
- node = parent.children[i];
- goingUp = false;
- } else node = null;
- }
- return this;
- },
- toBBox: function (item) { return item; },
- compareMinX: compareNodeMinX,
- compareMinY: compareNodeMinY,
- toJSON: function () { return this.data; },
- fromJSON: function (data) {
- this.data = data;
- return this;
- },
- _all: function (node, result) {
- var nodesToSearch = [];
- while (node) {
- if (node.leaf) result.push.apply(result, node.children);
- else nodesToSearch.push.apply(nodesToSearch, node.children);
- node = nodesToSearch.pop();
- }
- return result;
- },
- _build: function (items, left, right, height) {
- var N = right - left + 1,
- M = this._maxEntries,
- node;
- if (N <= M) {
- node = createNode(items.slice(left, right + 1));
- calcBBox(node, this.toBBox);
- return node;
- }
- if (!height) {
- height = Math.ceil(Math.log(N) / Math.log(M));
- M = Math.ceil(N / Math.pow(M, height - 1));
- }
- node = createNode([]);
- node.leaf = false;
- node.height = height;
- var N2 = Math.ceil(N / M),
- N1 = N2 * Math.ceil(Math.sqrt(M)),
- i, j, right2, right3;
- multiSelect(items, left, right, N1, this.compareMinX);
- for (i = left; i <= right; i += N1) {
- right2 = Math.min(i + N1 - 1, right);
- multiSelect(items, i, right2, N2, this.compareMinY);
- for (j = i; j <= right2; j += N2) {
- right3 = Math.min(j + N2 - 1, right2);
- node.children.push(this._build(items, j, right3, height - 1));
- }
- }
- calcBBox(node, this.toBBox);
- return node;
- },
- _chooseSubtree: function (bbox, node, level, path) {
- var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
- while (true) {
- path.push(node);
- if (node.leaf || path.length - 1 === level) break;
- minArea = minEnlargement = Infinity;
- for (i = 0, len = node.children.length; i < len; i++) {
- child = node.children[i];
- area = bboxArea(child);
- enlargement = enlargedArea(bbox, child) - area;
- if (enlargement < minEnlargement) {
- minEnlargement = enlargement;
- minArea = area < minArea ? area : minArea;
- targetNode = child;
- } else if (enlargement === minEnlargement) {
- if (area < minArea) {
- minArea = area;
- targetNode = child;
- }
- }
- }
- node = targetNode || node.children[0];
- }
- return node;
- },
- _insert: function (item, level, isNode) {
- var toBBox = this.toBBox,
- bbox = isNode ? item : toBBox(item),
- insertPath = [];
- var node = this._chooseSubtree(bbox, this.data, level, insertPath);
- node.children.push(item);
- extend(node, bbox);
- while (level >= 0) {
- if (insertPath[level].children.length > this._maxEntries) {
- this._split(insertPath, level);
- level--;
- } else break;
- }
- this._adjustParentBBoxes(bbox, insertPath, level);
- },
- _split: function (insertPath, level) {
- var node = insertPath[level],
- M = node.children.length,
- m = this._minEntries;
- this._chooseSplitAxis(node, m, M);
- var splitIndex = this._chooseSplitIndex(node, m, M);
- var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
- newNode.height = node.height;
- newNode.leaf = node.leaf;
- calcBBox(node, this.toBBox);
- calcBBox(newNode, this.toBBox);
- if (level) insertPath[level - 1].children.push(newNode);
- else this._splitRoot(node, newNode);
- },
- _splitRoot: function (node, newNode) {
- this.data = createNode([node, newNode]);
- this.data.height = node.height + 1;
- this.data.leaf = false;
- calcBBox(this.data, this.toBBox);
- },
- _chooseSplitIndex: function (node, m, M) {
- var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
- minOverlap = minArea = Infinity;
- for (i = m; i <= M - m; i++) {
- bbox1 = distBBox(node, 0, i, this.toBBox);
- bbox2 = distBBox(node, i, M, this.toBBox);
- overlap = intersectionArea(bbox1, bbox2);
- area = bboxArea(bbox1) + bboxArea(bbox2);
- if (overlap < minOverlap) {
- minOverlap = overlap;
- index = i;
- minArea = area < minArea ? area : minArea;
- } else if (overlap === minOverlap) {
- if (area < minArea) {
- minArea = area;
- index = i;
- }
- }
- }
- return index;
- },
- _chooseSplitAxis: function (node, m, M) {
- var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
- compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
- xMargin = this._allDistMargin(node, m, M, compareMinX),
- yMargin = this._allDistMargin(node, m, M, compareMinY);
- if (xMargin < yMargin) node.children.sort(compareMinX);
- },
- _allDistMargin: function (node, m, M, compare) {
- node.children.sort(compare);
- var toBBox = this.toBBox,
- leftBBox = distBBox(node, 0, m, toBBox),
- rightBBox = distBBox(node, M - m, M, toBBox),
- margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
- i, child;
- for (i = m; i < M - m; i++) {
- child = node.children[i];
- extend(leftBBox, node.leaf ? toBBox(child) : child);
- margin += bboxMargin(leftBBox);
- }
- for (i = M - m - 1; i >= m; i--) {
- child = node.children[i];
- extend(rightBBox, node.leaf ? toBBox(child) : child);
- margin += bboxMargin(rightBBox);
- }
- return margin;
- },
- _adjustParentBBoxes: function (bbox, path, level) {
- for (var i = level; i >= 0; i--) {
- extend(path[i], bbox);
- }
- },
- _condense: function (path) {
- for (var i = path.length - 1, siblings; i >= 0; i--) {
- if (path[i].children.length === 0) {
- if (i > 0) {
- siblings = path[i - 1].children;
- siblings.splice(siblings.indexOf(path[i]), 1);
- } else this.clear();
- } else calcBBox(path[i], this.toBBox);
- }
- },
- _initFormat: function (format) {
- var compareArr = ['return a', ' - b', ';'];
- this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
- this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
- this.toBBox = new Function('a',
- 'return {minX: a' + format[0] +
- ', minY: a' + format[1] +
- ', maxX: a' + format[2] +
- ', maxY: a' + format[3] + '};');
- }
- };
- function findItem(item, items, equalsFn) {
- if (!equalsFn) return items.indexOf(item);
- for (var i = 0; i < items.length; i++) {
- if (equalsFn(item, items[i])) return i;
- }
- return -1;
- }
- function calcBBox(node, toBBox) {
- distBBox(node, 0, node.children.length, toBBox, node);
- }
- function distBBox(node, k, p, toBBox, destNode) {
- if (!destNode) destNode = createNode(null);
- destNode.minX = Infinity;
- destNode.minY = Infinity;
- destNode.maxX = -Infinity;
- destNode.maxY = -Infinity;
- for (var i = k, child; i < p; i++) {
- child = node.children[i];
- extend(destNode, node.leaf ? toBBox(child) : child);
- }
- return destNode;
- }
- function extend(a, b) {
- a.minX = Math.min(a.minX, b.minX);
- a.minY = Math.min(a.minY, b.minY);
- a.maxX = Math.max(a.maxX, b.maxX);
- a.maxY = Math.max(a.maxY, b.maxY);
- return a;
- }
- function compareNodeMinX(a, b) { return a.minX - b.minX; }
- function compareNodeMinY(a, b) { return a.minY - b.minY; }
- function bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }
- function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
- function enlargedArea(a, b) {
- return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
- (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
- }
- function intersectionArea(a, b) {
- var minX = Math.max(a.minX, b.minX),
- minY = Math.max(a.minY, b.minY),
- maxX = Math.min(a.maxX, b.maxX),
- maxY = Math.min(a.maxY, b.maxY);
- return Math.max(0, maxX - minX) *
- Math.max(0, maxY - minY);
- }
- function contains(a, b) {
- return a.minX <= b.minX &&
- a.minY <= b.minY &&
- b.maxX <= a.maxX &&
- b.maxY <= a.maxY;
- }
- function intersects(a, b) {
- return b.minX <= a.maxX &&
- b.minY <= a.maxY &&
- b.maxX >= a.minX &&
- b.maxY >= a.minY;
- }
- function createNode(children) {
- return {
- children: children,
- height: 1,
- leaf: true,
- minX: Infinity,
- minY: Infinity,
- maxX: -Infinity,
- maxY: -Infinity
- };
- }
- function multiSelect(arr, left, right, n, compare) {
- var stack = [left, right],
- mid;
- while (stack.length) {
- right = stack.pop();
- left = stack.pop();
- if (right - left <= n) continue;
- mid = left + Math.ceil((right - left) / n / 2) * n;
- quickselect_1(arr, mid, left, right, compare);
- stack.push(left, mid, mid, right);
- }
- }
- exports['default'] = rbush_1;
- }((this.rbush = this.rbush || {})));}).call(ol.ext);
- ol.ext.rbush = ol.ext.rbush.default;
- ol.render = {};
- /**
- * Context for drawing geometries. A vector context is available on render
- * events and does not need to be constructed directly.
- * @constructor
- * @abstract
- * @struct
- * @api
- */
- ol.render.VectorContext = function() {
- };
- ol.render.VectorContext.prototype.drawCustom = function(geometry, feature, renderer) {};
- ol.render.VectorContext.prototype.drawGeometry = function(geometry) {};
- ol.render.VectorContext.prototype.setStyle = function(style) {};
- ol.render.VectorContext.prototype.drawCircle = function(circleGeometry, feature) {};
- ol.render.VectorContext.prototype.drawFeature = function(feature, style) {};
- ol.render.VectorContext.prototype.drawGeometryCollection = function(geometryCollectionGeometry, feature) {};
- ol.render.VectorContext.prototype.drawLineString = function(lineStringGeometry, feature) {};
- ol.render.VectorContext.prototype.drawMultiLineString = function(multiLineStringGeometry, feature) {};
- ol.render.VectorContext.prototype.drawMultiPoint = function(multiPointGeometry, feature) {};
- ol.render.VectorContext.prototype.drawMultiPolygon = function(multiPolygonGeometry, feature) {};
- ol.render.VectorContext.prototype.drawPoint = function(pointGeometry, feature) {};
- ol.render.VectorContext.prototype.drawPolygon = function(polygonGeometry, feature) {};
- ol.render.VectorContext.prototype.drawText = function(geometry, feature) {};
- ol.render.VectorContext.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {};
- ol.render.VectorContext.prototype.setImageStyle = function(imageStyle, opt_declutterGroup) {};
- ol.render.VectorContext.prototype.setTextStyle = function(textStyle, opt_declutterGroup) {};
- ol.render.ReplayGroup = {};
- ol.render.ReplayGroup = function() {};
- ol.render.ReplayGroup.prototype.getReplay = function(zIndex, replayType) {};
- ol.render.ReplayGroup.prototype.isEmpty = function() {};
- ol.render.ReplayType = {
- CIRCLE: 'Circle',
- DEFAULT: 'Default',
- IMAGE: 'Image',
- LINE_STRING: 'LineString',
- POLYGON: 'Polygon',
- TEXT: 'Text'
- };
- ol.geom.flat.length = {};
- ol.geom.flat.length.lineString = function(flatCoordinates, offset, end, stride) {
- var x1 = flatCoordinates[offset];
- var y1 = flatCoordinates[offset + 1];
- var length = 0;
- var i;
- for (i = offset + stride; i < end; i += stride) {
- var x2 = flatCoordinates[i];
- var y2 = flatCoordinates[i + 1];
- length += Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
- x1 = x2;
- y1 = y2;
- }
- return length;
- };
- ol.geom.flat.length.linearRing = function(flatCoordinates, offset, end, stride) {
- var perimeter =
- ol.geom.flat.length.lineString(flatCoordinates, offset, end, stride);
- var dx = flatCoordinates[end - stride] - flatCoordinates[offset];
- var dy = flatCoordinates[end - stride + 1] - flatCoordinates[offset + 1];
- perimeter += Math.sqrt(dx * dx + dy * dy);
- return perimeter;
- };
- ol.geom.flat.textpath = {};
- ol.geom.flat.textpath.lineString = function(
- flatCoordinates, offset, end, stride, text, measure, startM, maxAngle) {
- var result = [];
- // Keep text upright
- var reverse = flatCoordinates[offset] > flatCoordinates[end - stride];
- var numChars = text.length;
- var x1 = flatCoordinates[offset];
- var y1 = flatCoordinates[offset + 1];
- offset += stride;
- var x2 = flatCoordinates[offset];
- var y2 = flatCoordinates[offset + 1];
- var segmentM = 0;
- var segmentLength = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
- var chunk = '';
- var chunkLength = 0;
- var data, index, previousAngle;
- for (var i = 0; i < numChars; ++i) {
- index = reverse ? numChars - i - 1 : i;
- var char = text.charAt(index);
- chunk = reverse ? char + chunk : chunk + char;
- var charLength = measure(chunk) - chunkLength;
- chunkLength += charLength;
- var charM = startM + charLength / 2;
- while (offset < end - stride && segmentM + segmentLength < charM) {
- x1 = x2;
- y1 = y2;
- offset += stride;
- x2 = flatCoordinates[offset];
- y2 = flatCoordinates[offset + 1];
- segmentM += segmentLength;
- segmentLength = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
- }
- var segmentPos = charM - segmentM;
- var angle = Math.atan2(y2 - y1, x2 - x1);
- if (reverse) {
- angle += angle > 0 ? -Math.PI : Math.PI;
- }
- if (previousAngle !== undefined) {
- var delta = angle - previousAngle;
- delta += (delta > Math.PI) ? -2 * Math.PI : (delta < -Math.PI) ? 2 * Math.PI : 0;
- if (Math.abs(delta) > maxAngle) {
- return null;
- }
- }
- var interpolate = segmentPos / segmentLength;
- var x = ol.math.lerp(x1, x2, interpolate);
- var y = ol.math.lerp(y1, y2, interpolate);
- if (previousAngle == angle) {
- if (reverse) {
- data[0] = x;
- data[1] = y;
- data[2] = charLength / 2;
- }
- data[4] = chunk;
- } else {
- chunk = char;
- chunkLength = charLength;
- data = [x, y, charLength / 2, angle, chunk];
- if (reverse) {
- result.unshift(data);
- } else {
- result.push(data);
- }
- previousAngle = angle;
- }
- startM += charLength;
- }
- return result;
- };
- ol.structs.LRUCache = function(opt_highWaterMark) {
- ol.events.EventTarget.call(this);
- this.highWaterMark = opt_highWaterMark !== undefined ? opt_highWaterMark : 2048;
- this.count_ = 0;
- this.entries_ = {};
- this.oldest_ = null;
- this.newest_ = null;
- };
- ol.inherits(ol.structs.LRUCache, ol.events.EventTarget);
- ol.structs.LRUCache.prototype.canExpireCache = function() {
- return this.getCount() > this.highWaterMark;
- };
- ol.structs.LRUCache.prototype.clear = function() {
- this.count_ = 0;
- this.entries_ = {};
- this.oldest_ = null;
- this.newest_ = null;
- this.dispatchEvent(ol.events.EventType.CLEAR);
- };
- ol.structs.LRUCache.prototype.containsKey = function(key) {
- return this.entries_.hasOwnProperty(key);
- };
- ol.structs.LRUCache.prototype.forEach = function(f, opt_this) {
- var entry = this.oldest_;
- while (entry) {
- f.call(opt_this, entry.value_, entry.key_, this);
- entry = entry.newer;
- }
- };
- ol.structs.LRUCache.prototype.get = function(key) {
- var entry = this.entries_[key];
- ol.asserts.assert(entry !== undefined,
- 15); // Tried to get a value for a key that does not exist in the cache
- if (entry === this.newest_) {
- return entry.value_;
- } else if (entry === this.oldest_) {
- this.oldest_ = /** @type {ol.LRUCacheEntry} */ (this.oldest_.newer);
- this.oldest_.older = null;
- } else {
- entry.newer.older = entry.older;
- entry.older.newer = entry.newer;
- }
- entry.newer = null;
- entry.older = this.newest_;
- this.newest_.newer = entry;
- this.newest_ = entry;
- return entry.value_;
- };
- ol.structs.LRUCache.prototype.remove = function(key) {
- var entry = this.entries_[key];
- ol.asserts.assert(entry !== undefined, 15); // Tried to get a value for a key that does not exist in the cache
- if (entry === this.newest_) {
- this.newest_ = /** @type {ol.LRUCacheEntry} */ (entry.older);
- if (this.newest_) {
- this.newest_.newer = null;
- }
- } else if (entry === this.oldest_) {
- this.oldest_ = /** @type {ol.LRUCacheEntry} */ (entry.newer);
- if (this.oldest_) {
- this.oldest_.older = null;
- }
- } else {
- entry.newer.older = entry.older;
- entry.older.newer = entry.newer;
- }
- delete this.entries_[key];
- --this.count_;
- return entry.value_;
- };
- ol.structs.LRUCache.prototype.getCount = function() {
- return this.count_;
- };
- ol.structs.LRUCache.prototype.getKeys = function() {
- var keys = new Array(this.count_);
- var i = 0;
- var entry;
- for (entry = this.newest_; entry; entry = entry.older) {
- keys[i++] = entry.key_;
- }
- return keys;
- };
- ol.structs.LRUCache.prototype.getValues = function() {
- var values = new Array(this.count_);
- var i = 0;
- var entry;
- for (entry = this.newest_; entry; entry = entry.older) {
- values[i++] = entry.value_;
- }
- return values;
- };
- ol.structs.LRUCache.prototype.peekLast = function() {
- return this.oldest_.value_;
- };
- ol.structs.LRUCache.prototype.peekLastKey = function() {
- return this.oldest_.key_;
- };
- ol.structs.LRUCache.prototype.peekFirstKey = function() {
- return this.newest_.key_;
- };
- ol.structs.LRUCache.prototype.pop = function() {
- var entry = this.oldest_;
- delete this.entries_[entry.key_];
- if (entry.newer) {
- entry.newer.older = null;
- }
- this.oldest_ = /** @type {ol.LRUCacheEntry} */ (entry.newer);
- if (!this.oldest_) {
- this.newest_ = null;
- }
- --this.count_;
- return entry.value_;
- };
- ol.structs.LRUCache.prototype.replace = function(key, value) {
- this.get(key); // update `newest_`
- this.entries_[key].value_ = value;
- };
- ol.structs.LRUCache.prototype.set = function(key, value) {
- ol.asserts.assert(!(key in this.entries_),
- 16); // Tried to set a value for a key that is used already
- var entry = /** @type {ol.LRUCacheEntry} */ ({
- key_: key,
- newer: null,
- older: this.newest_,
- value_: value
- });
- if (!this.newest_) {
- this.oldest_ = entry;
- } else {
- this.newest_.newer = entry;
- }
- this.newest_ = entry;
- this.entries_[key] = entry;
- ++this.count_;
- };
- ol.structs.LRUCache.prototype.prune = function() {
- while (this.canExpireCache()) {
- this.pop();
- }
- };
- ol.render.canvas = {};
- ol.render.canvas.defaultFont = '10px sans-serif';
- ol.render.canvas.defaultFillStyle = [0, 0, 0, 1];
- ol.render.canvas.defaultLineCap = 'round';
- ol.render.canvas.defaultLineDash = [];
- ol.render.canvas.defaultLineDashOffset = 0;
- ol.render.canvas.defaultLineJoin = 'round';
- ol.render.canvas.defaultMiterLimit = 10;
- ol.render.canvas.defaultStrokeStyle = [0, 0, 0, 1];
- ol.render.canvas.defaultTextAlign = 'center';
- ol.render.canvas.defaultTextBaseline = 'middle';
- ol.render.canvas.defaultPadding = [0, 0, 0, 0];
- ol.render.canvas.defaultLineWidth = 1;
- ol.render.canvas.labelCache = new ol.structs.LRUCache();
- ol.render.canvas.checkedFonts_ = {};
- ol.render.canvas.measureContext_ = null;
- ol.render.canvas.textHeights_ = {};
- /**
- * Clears the label cache when a font becomes available.
- * @param {string} fontSpec CSS font spec.
- */
- ol.render.canvas.checkFont = (function() {
- var retries = 60;
- var checked = ol.render.canvas.checkedFonts_;
- var labelCache = ol.render.canvas.labelCache;
- var font = '32px monospace';
- var text = 'wmytzilWMYTZIL@#/&?$%10';
- var interval, referenceWidth;
- function isAvailable(fontFamily) {
- var context = ol.render.canvas.getMeasureContext();
- context.font = font;
- referenceWidth = context.measureText(text).width;
- var available = true;
- if (fontFamily != 'monospace') {
- context.font = '32px ' + fontFamily + ',monospace';
- var width = context.measureText(text).width;
- // If width and referenceWidth are the same, then the 'monospace'
- // fallback was used instead of the font we wanted, so the font is not
- // available.
- available = width != referenceWidth;
- }
- return available;
- }
- function check() {
- var done = true;
- for (var font in checked) {
- if (checked[font] < retries) {
- if (isAvailable(font)) {
- checked[font] = retries;
- ol.obj.clear(ol.render.canvas.textHeights_);
- // Make sure that loaded fonts are picked up by Safari
- ol.render.canvas.measureContext_ = null;
- labelCache.clear();
- } else {
- ++checked[font];
- done = false;
- }
- }
- }
- if (done) {
- window.clearInterval(interval);
- interval = undefined;
- }
- }
- return function(fontSpec) {
- var fontFamilies = ol.css.getFontFamilies(fontSpec);
- if (!fontFamilies) {
- return;
- }
- for (var i = 0, ii = fontFamilies.length; i < ii; ++i) {
- var fontFamily = fontFamilies[i];
- if (!(fontFamily in checked)) {
- checked[fontFamily] = retries;
- if (!isAvailable(fontFamily)) {
- checked[fontFamily] = 0;
- if (interval === undefined) {
- interval = window.setInterval(check, 32);
- }
- }
- }
- }
- };
- })();
- /**
- * @return {CanvasRenderingContext2D} Measure context.
- */
- ol.render.canvas.getMeasureContext = function() {
- var context = ol.render.canvas.measureContext_;
- if (!context) {
- context = ol.render.canvas.measureContext_ = ol.dom.createCanvasContext2D(1, 1);
- }
- return context;
- };
- /**
- * @param {string} font Font to use for measuring.
- * @return {ol.Size} Measurement.
- */
- ol.render.canvas.measureTextHeight = (function() {
- var heights = ol.render.canvas.textHeights_;
- return function(font) {
- var height = heights[font];
- if (height == undefined) {
- // if (!span) {
- // span = document.createElement('span');
- // span.textContent = 'M';
- // span.style.margin = span.style.padding = '0 !important';
- // span.style.position = 'absolute !important';
- // span.style.left = '-99999px !important';
- // }
- // span.style.font = font;
- // document.body.appendChild(span);
- // height = heights[font] = span.offsetHeight;
- // document.body.removeChild(span);
- height = heights[font] = 19; // FIXME sunyl
- }
- return height;
- };
- })();
- /**
- * @param {string} font Font.
- * @param {string} text Text.
- * @return {number} Width.
- */
- ol.render.canvas.measureTextWidth = function(font, text) {
- var measureContext = ol.render.canvas.getMeasureContext();
- if (font != measureContext.font) {
- measureContext.font = font;
- }
- return measureContext.measureText(text).width;
- };
- /**
- * @param {CanvasRenderingContext2D} context Context.
- * @param {number} rotation Rotation.
- * @param {number} offsetX X offset.
- * @param {number} offsetY Y offset.
- */
- ol.render.canvas.rotateAtOffset = function(context, rotation, offsetX, offsetY) {
- if (rotation !== 0) {
- context.translate(offsetX, offsetY);
- context.rotate(rotation);
- context.translate(-offsetX, -offsetY);
- }
- };
- ol.render.canvas.resetTransform_ = ol.transform.create();
- /**
- * @param {CanvasRenderingContext2D} context Context.
- * @param {ol.Transform|null} transform Transform.
- * @param {number} opacity Opacity.
- * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} image Image.
- * @param {number} originX Origin X.
- * @param {number} originY Origin Y.
- * @param {number} w Width.
- * @param {number} h Height.
- * @param {number} x X.
- * @param {number} y Y.
- * @param {number} scale Scale.
- */
- ol.render.canvas.drawImage = function(context,
- transform, opacity, image, originX, originY, w, h, x, y, scale) {
- var alpha;
- if (opacity != 1) {
- alpha = context.globalAlpha;
- context.globalAlpha = alpha * opacity;
- }
- if (transform) {
- context.setTransform.apply(context, transform);
- }
- context.drawImage(image, originX, originY, w, h, x, y, w * scale, h * scale);
- if (alpha) {
- context.globalAlpha = alpha;
- }
- if (transform) {
- context.setTransform.apply(context, ol.render.canvas.resetTransform_);
- }
- };
- /**
- * @enum {number}
- */
- ol.render.canvas.Instruction = {
- BEGIN_GEOMETRY: 0,
- BEGIN_PATH: 1,
- CIRCLE: 2,
- CLOSE_PATH: 3,
- CUSTOM: 4,
- DRAW_CHARS: 5,
- DRAW_IMAGE: 6,
- END_GEOMETRY: 7,
- FILL: 8,
- MOVE_TO_LINE_TO: 9,
- SET_FILL_STYLE: 10,
- SET_STROKE_STYLE: 11,
- STROKE: 12
- };
- ol.render.replay = {};
- ol.render.replay.ORDER = [
- ol.render.ReplayType.POLYGON,
- ol.render.ReplayType.CIRCLE,
- ol.render.ReplayType.LINE_STRING,
- ol.render.ReplayType.IMAGE,
- ol.render.ReplayType.TEXT,
- ol.render.ReplayType.DEFAULT
- ];
- ol.render.replay.TEXT_ALIGN = {};
- ol.render.replay.TEXT_ALIGN['left'] = 0;
- ol.render.replay.TEXT_ALIGN['end'] = 0;
- ol.render.replay.TEXT_ALIGN['center'] = 0.5;
- ol.render.replay.TEXT_ALIGN['right'] = 1;
- ol.render.replay.TEXT_ALIGN['start'] = 1;
- ol.render.replay.TEXT_ALIGN['top'] = 0;
- ol.render.replay.TEXT_ALIGN['middle'] = 0.5;
- ol.render.replay.TEXT_ALIGN['hanging'] = 0.2;
- ol.render.replay.TEXT_ALIGN['alphabetic'] = 0.8;
- ol.render.replay.TEXT_ALIGN['ideographic'] = 0.8;
- ol.render.replay.TEXT_ALIGN['bottom'] = 1;
- ol.render.canvas.Replay = function(tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) {
- ol.render.VectorContext.call(this);
- /**
- * @type {?}
- */
- this.declutterTree = declutterTree;
- /**
- * @private
- * @type {ol.Extent}
- */
- this.tmpExtent_ = ol.extent.createEmpty();
- /**
- * @protected
- * @type {number}
- */
- this.tolerance = tolerance;
- /**
- * @protected
- * @const
- * @type {ol.Extent}
- */
- this.maxExtent = maxExtent;
- /**
- * @protected
- * @type {boolean}
- */
- this.overlaps = overlaps;
- /**
- * @protected
- * @type {number}
- */
- this.pixelRatio = pixelRatio;
- /**
- * @protected
- * @type {number}
- */
- this.maxLineWidth = 0;
- /**
- * @protected
- * @const
- * @type {number}
- */
- this.resolution = resolution;
- /**
- * @private
- * @type {ol.Coordinate}
- */
- this.fillOrigin_;
- /**
- * @private
- * @type {Array.<*>}
- */
- this.beginGeometryInstruction1_ = null;
- /**
- * @private
- * @type {Array.<*>}
- */
- this.beginGeometryInstruction2_ = null;
- /**
- * @private
- * @type {ol.Extent}
- */
- this.bufferedMaxExtent_ = null;
- /**
- * @protected
- * @type {Array.<*>}
- */
- this.instructions = [];
- /**
- * @protected
- * @type {Array.<number>}
- */
- this.coordinates = [];
- /**
- * @private
- * @type {Object.<number,ol.Coordinate|Array.<ol.Coordinate>|Array.<Array.<ol.Coordinate>>>}
- */
- this.coordinateCache_ = {};
- /**
- * @private
- * @type {!ol.Transform}
- */
- this.renderedTransform_ = ol.transform.create();
- /**
- * @protected
- * @type {Array.<*>}
- */
- this.hitDetectionInstructions = [];
- /**
- * @private
- * @type {Array.<number>}
- */
- this.pixelCoordinates_ = null;
- /**
- * @protected
- * @type {ol.CanvasFillStrokeState}
- */
- this.state = /** @type {ol.CanvasFillStrokeState} */ ({});
- /**
- * @private
- * @type {number}
- */
- this.viewRotation_ = 0;
- /**
- * @private
- * @type {!ol.Transform}
- */
- this.tmpLocalTransform_ = ol.transform.create();
- /**
- * @private
- * @type {!ol.Transform}
- */
- this.resetTransform_ = ol.transform.create();
- };
- ol.inherits(ol.render.canvas.Replay, ol.render.VectorContext);
- /**
- * @param {CanvasRenderingContext2D} context Context.
- * @param {ol.Coordinate} p1 1st point of the background box.
- * @param {ol.Coordinate} p2 2nd point of the background box.
- * @param {ol.Coordinate} p3 3rd point of the background box.
- * @param {ol.Coordinate} p4 4th point of the background box.
- * @param {Array.<*>} fillInstruction Fill instruction.
- * @param {Array.<*>} strokeInstruction Stroke instruction.
- */
- ol.render.canvas.Replay.prototype.replayTextBackground_ = function(context, p1, p2, p3, p4,
- fillInstruction, strokeInstruction) {
- context.beginPath();
- context.moveTo.apply(context, p1);
- context.lineTo.apply(context, p2);
- context.lineTo.apply(context, p3);
- context.lineTo.apply(context, p4);
- context.lineTo.apply(context, p1);
- if (fillInstruction) {
- this.fillOrigin_ = /** @type {Array.<number>} */ (fillInstruction[2]);
- this.fill_(context);
- }
- if (strokeInstruction) {
- this.setStrokeStyle_(context, /** @type {Array.<*>} */ (strokeInstruction));
- context.stroke();
- }
- };
- /**
- * @param {CanvasRenderingContext2D} context Context.
- * @param {number} x X.
- * @param {number} y Y.
- * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} image Image.
- * @param {number} anchorX Anchor X.
- * @param {number} anchorY Anchor Y.
- * @param {ol.DeclutterGroup} declutterGroup Declutter group.
- * @param {number} height Height.
- * @param {number} opacity Opacity.
- * @param {number} originX Origin X.
- * @param {number} originY Origin Y.
- * @param {number} rotation Rotation.
- * @param {number} scale Scale.
- * @param {boolean} snapToPixel Snap to pixel.
- * @param {number} width Width.
- * @param {Array.<number>} padding Padding.
- * @param {Array.<*>} fillInstruction Fill instruction.
- * @param {Array.<*>} strokeInstruction Stroke instruction.
- */
- ol.render.canvas.Replay.prototype.replayImage_ = function(context, x, y, image,
- anchorX, anchorY, declutterGroup, height, opacity, originX, originY,
- rotation, scale, snapToPixel, width, padding, fillInstruction, strokeInstruction) {
- var fillStroke = fillInstruction || strokeInstruction;
- var localTransform = this.tmpLocalTransform_;
- anchorX *= scale;
- anchorY *= scale;
- x -= anchorX;
- y -= anchorY;
- if (snapToPixel) {
- x = Math.round(x);
- y = Math.round(y);
- }
- var w = (width + originX > image.width) ? image.width - originX : width;
- var h = (height + originY > image.height) ? image.height - originY : height;
- var box = this.tmpExtent_;
- var boxW = padding[3] + w * scale + padding[1];
- var boxH = padding[0] + h * scale + padding[2];
- var boxX = x - padding[3];
- var boxY = y - padding[0];
- /** @type {ol.Coordinate} */
- var p1;
- /** @type {ol.Coordinate} */
- var p2;
- /** @type {ol.Coordinate} */
- var p3;
- /** @type {ol.Coordinate} */
- var p4;
- if (fillStroke || rotation !== 0) {
- p1 = [boxX, boxY];
- p2 = [boxX + boxW, boxY];
- p3 = [boxX + boxW, boxY + boxH];
- p4 = [boxX, boxY + boxH];
- }
- var transform = null;
- if (rotation !== 0) {
- var centerX = x + anchorX;
- var centerY = y + anchorY;
- transform = ol.transform.compose(localTransform,
- centerX, centerY, 1, 1, rotation, -centerX, -centerY);
- ol.extent.createOrUpdateEmpty(box);
- ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, p1));
- ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, p2));
- ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, p3));
- ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, p4));
- } else {
- ol.extent.createOrUpdate(boxX, boxY, boxX + boxW, boxY + boxH, box);
- }
- var canvas = context.canvas;
- var intersects = box[0] <= canvas.width && box[2] >= 0 && box[1] <= canvas.height && box[3] >= 0;
- if (declutterGroup) {
- if (!intersects && declutterGroup[4] == 1) {
- return;
- }
- ol.extent.extend(declutterGroup, box);
- var declutterArgs = intersects ?
- [context, transform ? transform.slice(0) : null, opacity, image, originX, originY, w, h, x, y, scale] :
- null;
- if (declutterArgs && fillStroke) {
- declutterArgs.push(fillInstruction, strokeInstruction, p1, p2, p3, p4);
- }
- declutterGroup.push(declutterArgs);
- } else if (intersects) {
- if (fillStroke) {
- this.replayTextBackground_(context, p1, p2, p3, p4,
- /** @type {Array.<*>} */ (fillInstruction),
- /** @type {Array.<*>} */ (strokeInstruction));
- }
- ol.render.canvas.drawImage(context, transform, opacity, image, originX, originY, w, h, x, y, scale);
- }
- };
- /**
- * @protected
- * @param {Array.<number>} dashArray Dash array.
- * @return {Array.<number>} Dash array with pixel ratio applied
- */
- ol.render.canvas.Replay.prototype.applyPixelRatio = function(dashArray) {
- var pixelRatio = this.pixelRatio;
- return pixelRatio == 1 ? dashArray : dashArray.map(function(dash) {
- return dash * pixelRatio;
- });
- };
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {number} end End.
- * @param {number} stride Stride.
- * @param {boolean} closed Last input coordinate equals first.
- * @param {boolean} skipFirst Skip first coordinate.
- * @protected
- * @return {number} My end.
- */
- ol.render.canvas.Replay.prototype.appendFlatCoordinates = function(flatCoordinates, offset, end, stride, closed, skipFirst) {
- var myEnd = this.coordinates.length;
- var extent = this.getBufferedMaxExtent();
- if (skipFirst) {
- offset += stride;
- }
- var lastCoord = [flatCoordinates[offset], flatCoordinates[offset + 1]];
- var nextCoord = [NaN, NaN];
- var skipped = true;
- var i, lastRel, nextRel;
- for (i = offset + stride; i < end; i += stride) {
- nextCoord[0] = flatCoordinates[i];
- nextCoord[1] = flatCoordinates[i + 1];
- nextRel = ol.extent.coordinateRelationship(extent, nextCoord);
- if (nextRel !== lastRel) {
- if (skipped) {
- this.coordinates[myEnd++] = lastCoord[0];
- this.coordinates[myEnd++] = lastCoord[1];
- }
- this.coordinates[myEnd++] = nextCoord[0];
- this.coordinates[myEnd++] = nextCoord[1];
- skipped = false;
- } else if (nextRel === ol.extent.Relationship.INTERSECTING) {
- this.coordinates[myEnd++] = nextCoord[0];
- this.coordinates[myEnd++] = nextCoord[1];
- skipped = false;
- } else {
- skipped = true;
- }
- lastCoord[0] = nextCoord[0];
- lastCoord[1] = nextCoord[1];
- lastRel = nextRel;
- }
- // Last coordinate equals first or only one point to append:
- if ((closed && skipped) || i === offset + stride) {
- this.coordinates[myEnd++] = lastCoord[0];
- this.coordinates[myEnd++] = lastCoord[1];
- }
- return myEnd;
- };
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {Array.<number>} ends Ends.
- * @param {number} stride Stride.
- * @param {Array.<number>} replayEnds Replay ends.
- * @return {number} Offset.
- */
- ol.render.canvas.Replay.prototype.drawCustomCoordinates_ = function(flatCoordinates, offset, ends, stride, replayEnds) {
- for (var i = 0, ii = ends.length; i < ii; ++i) {
- var end = ends[i];
- var replayEnd = this.appendFlatCoordinates(flatCoordinates, offset, end, stride, false, false);
- replayEnds.push(replayEnd);
- offset = end;
- }
- return offset;
- };
- /**
- * @inheritDoc.
- */
- ol.render.canvas.Replay.prototype.drawCustom = function(geometry, feature, renderer) {
- this.beginGeometry(geometry, feature);
- var type = geometry.getType();
- var stride = geometry.getStride();
- var replayBegin = this.coordinates.length;
- var flatCoordinates, replayEnd, replayEnds, replayEndss;
- var offset;
- if (type == ol.geom.GeometryType.MULTI_POLYGON) {
- geometry = /** @type {ol.geom.MultiPolygon} */ (geometry);
- flatCoordinates = geometry.getOrientedFlatCoordinates();
- replayEndss = [];
- var endss = geometry.getEndss();
- offset = 0;
- for (var i = 0, ii = endss.length; i < ii; ++i) {
- var myEnds = [];
- offset = this.drawCustomCoordinates_(flatCoordinates, offset, endss[i], stride, myEnds);
- replayEndss.push(myEnds);
- }
- this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
- replayBegin, replayEndss, geometry, renderer, ol.geom.flat.inflate.coordinatesss]);
- } else if (type == ol.geom.GeometryType.POLYGON || type == ol.geom.GeometryType.MULTI_LINE_STRING) {
- replayEnds = [];
- flatCoordinates = (type == ol.geom.GeometryType.POLYGON) ?
- /** @type {ol.geom.Polygon} */ (geometry).getOrientedFlatCoordinates() :
- geometry.getFlatCoordinates();
- offset = this.drawCustomCoordinates_(flatCoordinates, 0,
- /** @type {ol.geom.Polygon|ol.geom.MultiLineString} */ (geometry).getEnds(),
- stride, replayEnds);
- this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
- replayBegin, replayEnds, geometry, renderer, ol.geom.flat.inflate.coordinatess]);
- } else if (type == ol.geom.GeometryType.LINE_STRING || type == ol.geom.GeometryType.MULTI_POINT) {
- flatCoordinates = geometry.getFlatCoordinates();
- replayEnd = this.appendFlatCoordinates(
- flatCoordinates, 0, flatCoordinates.length, stride, false, false);
- this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
- replayBegin, replayEnd, geometry, renderer, ol.geom.flat.inflate.coordinates]);
- } else if (type == ol.geom.GeometryType.POINT) {
- flatCoordinates = geometry.getFlatCoordinates();
- this.coordinates.push(flatCoordinates[0], flatCoordinates[1]);
- replayEnd = this.coordinates.length;
- this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
- replayBegin, replayEnd, geometry, renderer]);
- }
- this.endGeometry(geometry, feature);
- };
- /**
- * @protected
- * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
- */
- ol.render.canvas.Replay.prototype.beginGeometry = function(geometry, feature) {
- this.beginGeometryInstruction1_ =
- [ol.render.canvas.Instruction.BEGIN_GEOMETRY, feature, 0];
- this.instructions.push(this.beginGeometryInstruction1_);
- this.beginGeometryInstruction2_ =
- [ol.render.canvas.Instruction.BEGIN_GEOMETRY, feature, 0];
- this.hitDetectionInstructions.push(this.beginGeometryInstruction2_);
- };
- /**
- * @private
- * @param {CanvasRenderingContext2D} context Context.
- */
- ol.render.canvas.Replay.prototype.fill_ = function(context) {
- if (this.fillOrigin_) {
- var origin = ol.transform.apply(this.renderedTransform_, this.fillOrigin_.slice());
- context.translate(origin[0], origin[1]);
- context.rotate(this.viewRotation_);
- }
- context.fill();
- if (this.fillOrigin_) {
- context.setTransform.apply(context, ol.render.canvas.resetTransform_);
- }
- };
- /**
- * @private
- * @param {CanvasRenderingContext2D} context Context.
- * @param {Array.<*>} instruction Instruction.
- */
- ol.render.canvas.Replay.prototype.setStrokeStyle_ = function(context, instruction) {
- context.strokeStyle = /** @type {ol.ColorLike} */ (instruction[1]);
- context.lineWidth = /** @type {number} */ (instruction[2]);
- context.lineCap = /** @type {string} */ (instruction[3]);
- context.lineJoin = /** @type {string} */ (instruction[4]);
- context.miterLimit = /** @type {number} */ (instruction[5]);
- if (ol.has.CANVAS_LINE_DASH) {
- context.lineDashOffset = /** @type {number} */ (instruction[7]);
- context.setLineDash(/** @type {Array.<number>} */ (instruction[6]));
- }
- };
- /**
- * @param {ol.DeclutterGroup} declutterGroup Declutter group.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
- */
- ol.render.canvas.Replay.prototype.renderDeclutter_ = function(declutterGroup, feature) {
- if (declutterGroup && declutterGroup.length > 5) {
- var groupCount = declutterGroup[4];
- if (groupCount == 1 || groupCount == declutterGroup.length - 5) {
- /** @type {ol.RBushEntry} */
- var box = {
- minX: /** @type {number} */ (declutterGroup[0]),
- minY: /** @type {number} */ (declutterGroup[1]),
- maxX: /** @type {number} */ (declutterGroup[2]),
- maxY: /** @type {number} */ (declutterGroup[3]),
- value: feature
- };
- if (!this.declutterTree.collides(box)) {
- this.declutterTree.insert(box);
- var drawImage = ol.render.canvas.drawImage;
- for (var j = 5, jj = declutterGroup.length; j < jj; ++j) {
- var declutterData = /** @type {Array} */ (declutterGroup[j]);
- if (declutterData) {
- if (declutterData.length > 11) {
- this.replayTextBackground_(declutterData[0],
- declutterData[13], declutterData[14], declutterData[15], declutterData[16],
- declutterData[11], declutterData[12]);
- }
- drawImage.apply(undefined, declutterData);
- }
- }
- }
- declutterGroup.length = 5;
- ol.extent.createOrUpdateEmpty(declutterGroup);
- }
- }
- };
- /**
- * @private
- * @param {CanvasRenderingContext2D} context Context.
- * @param {ol.Transform} transform Transform.
- * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
- * to skip.
- * @param {Array.<*>} instructions Instructions array.
- * @param {function((ol.Feature|ol.render.Feature)): T|undefined}
- * featureCallback Feature callback.
- * @param {ol.Extent=} opt_hitExtent Only check features that intersect this
- * extent.
- * @return {T|undefined} Callback result.
- * @template T
- */
- ol.render.canvas.Replay.prototype.replay_ = function(
- context, transform, skippedFeaturesHash,
- instructions, featureCallback, opt_hitExtent) {
- /** @type {Array.<number>} */
- var pixelCoordinates;
- if (this.pixelCoordinates_ && ol.array.equals(transform, this.renderedTransform_)) {
- pixelCoordinates = this.pixelCoordinates_;
- } else {
- if (!this.pixelCoordinates_) {
- this.pixelCoordinates_ = [];
- }
- pixelCoordinates = ol.geom.flat.transform.transform2D(
- this.coordinates, 0, this.coordinates.length, 2,
- transform, this.pixelCoordinates_);
- ol.transform.setFromArray(this.renderedTransform_, transform);
- }
- var skipFeatures = !ol.obj.isEmpty(skippedFeaturesHash);
- var i = 0; // instruction index
- var ii = instructions.length; // end of instructions
- var d = 0; // data index
- var dd; // end of per-instruction data
- var anchorX, anchorY, prevX, prevY, roundX, roundY, declutterGroup, image;
- var pendingFill = 0;
- var pendingStroke = 0;
- var lastFillInstruction = null;
- var lastStrokeInstruction = null;
- var coordinateCache = this.coordinateCache_;
- var viewRotation = this.viewRotation_;
- var state = /** @type {olx.render.State} */ ({
- context: context,
- pixelRatio: this.pixelRatio,
- resolution: this.resolution,
- rotation: viewRotation
- });
- // When the batch size gets too big, performance decreases. 200 is a good
- // balance between batch size and number of fill/stroke instructions.
- var batchSize =
- this.instructions != instructions || this.overlaps ? 0 : 200;
- while (i < ii) {
- var instruction = instructions[i];
- var type = /** @type {ol.render.canvas.Instruction} */ (instruction[0]);
- var /** @type {ol.Feature|ol.render.Feature} */ feature, x, y;
- switch (type) {
- case ol.render.canvas.Instruction.BEGIN_GEOMETRY:
- feature = /** @type {ol.Feature|ol.render.Feature} */ (instruction[1]);
- if ((skipFeatures &&
- skippedFeaturesHash[ol.getUid(feature).toString()]) ||
- !feature.getGeometry()) {
- i = /** @type {number} */ (instruction[2]);
- } else if (opt_hitExtent !== undefined && !ol.extent.intersects(
- opt_hitExtent, feature.getGeometry().getExtent())) {
- i = /** @type {number} */ (instruction[2]) + 1;
- } else {
- ++i;
- }
- break;
- case ol.render.canvas.Instruction.BEGIN_PATH:
- if (pendingFill > batchSize) {
- this.fill_(context);
- pendingFill = 0;
- }
- if (pendingStroke > batchSize) {
- context.stroke();
- pendingStroke = 0;
- }
- if (!pendingFill && !pendingStroke) {
- context.beginPath();
- prevX = prevY = NaN;
- }
- ++i;
- break;
- case ol.render.canvas.Instruction.CIRCLE:
- d = /** @type {number} */ (instruction[1]);
- var x1 = pixelCoordinates[d];
- var y1 = pixelCoordinates[d + 1];
- var x2 = pixelCoordinates[d + 2];
- var y2 = pixelCoordinates[d + 3];
- var dx = x2 - x1;
- var dy = y2 - y1;
- var r = Math.sqrt(dx * dx + dy * dy);
- context.moveTo(x1 + r, y1);
- context.arc(x1, y1, r, 0, 2 * Math.PI, true);
- ++i;
- break;
- case ol.render.canvas.Instruction.CLOSE_PATH:
- context.closePath();
- ++i;
- break;
- case ol.render.canvas.Instruction.CUSTOM:
- d = /** @type {number} */ (instruction[1]);
- dd = instruction[2];
- var geometry = /** @type {ol.geom.SimpleGeometry} */ (instruction[3]);
- var renderer = instruction[4];
- var fn = instruction.length == 6 ? instruction[5] : undefined;
- state.geometry = geometry;
- state.feature = feature;
- if (!(i in coordinateCache)) {
- coordinateCache[i] = [];
- }
- var coords = coordinateCache[i];
- if (fn) {
- fn(pixelCoordinates, d, dd, 2, coords);
- } else {
- coords[0] = pixelCoordinates[d];
- coords[1] = pixelCoordinates[d + 1];
- coords.length = 2;
- }
- renderer(coords, state);
- ++i;
- break;
- case ol.render.canvas.Instruction.DRAW_IMAGE:
- d = /** @type {number} */ (instruction[1]);
- dd = /** @type {number} */ (instruction[2]);
- image = /** @type {HTMLCanvasElement|HTMLVideoElement|Image} */
- (instruction[3]);
- // Remaining arguments in DRAW_IMAGE are in alphabetical order
- anchorX = /** @type {number} */ (instruction[4]);
- anchorY = /** @type {number} */ (instruction[5]);
- declutterGroup = featureCallback ? null : /** @type {ol.DeclutterGroup} */ (instruction[6]);
- var height = /** @type {number} */ (instruction[7]);
- var opacity = /** @type {number} */ (instruction[8]);
- var originX = /** @type {number} */ (instruction[9]);
- var originY = /** @type {number} */ (instruction[10]);
- var rotateWithView = /** @type {boolean} */ (instruction[11]);
- var rotation = /** @type {number} */ (instruction[12]);
- var scale = /** @type {number} */ (instruction[13]);
- var snapToPixel = /** @type {boolean} */ (instruction[14]);
- var width = /** @type {number} */ (instruction[15]);
- var padding, backgroundFill, backgroundStroke;
- if (instruction.length > 16) {
- padding = /** @type {Array.<number>} */ (instruction[16]);
- backgroundFill = /** @type {boolean} */ (instruction[17]);
- backgroundStroke = /** @type {boolean} */ (instruction[18]);
- } else {
- padding = ol.render.canvas.defaultPadding;
- backgroundFill = backgroundStroke = false;
- }
- if (rotateWithView) {
- rotation += viewRotation;
- }
- for (; d < dd; d += 2) {
- this.replayImage_(context,
- pixelCoordinates[d], pixelCoordinates[d + 1], image, anchorX, anchorY,
- declutterGroup, height, opacity, originX, originY, rotation, scale,
- snapToPixel, width, padding,
- backgroundFill ? /** @type {Array.<*>} */ (lastFillInstruction) : null,
- backgroundStroke ? /** @type {Array.<*>} */ (lastStrokeInstruction) : null);
- }
- this.renderDeclutter_(declutterGroup, feature);
- ++i;
- break;
- case ol.render.canvas.Instruction.DRAW_CHARS:
- var begin = /** @type {number} */ (instruction[1]);
- var end = /** @type {number} */ (instruction[2]);
- var baseline = /** @type {number} */ (instruction[3]);
- declutterGroup = featureCallback ? null : /** @type {ol.DeclutterGroup} */ (instruction[4]);
- var overflow = /** @type {number} */ (instruction[5]);
- var fillKey = /** @type {string} */ (instruction[6]);
- var maxAngle = /** @type {number} */ (instruction[7]);
- var measure = /** @type {function(string):number} */ (instruction[8]);
- var offsetY = /** @type {number} */ (instruction[9]);
- var strokeKey = /** @type {string} */ (instruction[10]);
- var strokeWidth = /** @type {number} */ (instruction[11]);
- var text = /** @type {string} */ (instruction[12]);
- var textKey = /** @type {string} */ (instruction[13]);
- var textScale = /** @type {number} */ (instruction[14]);
- var pathLength = ol.geom.flat.length.lineString(pixelCoordinates, begin, end, 2);
- var textLength = measure(text);
- if (overflow || textLength <= pathLength) {
- var textAlign = /** @type {ol.render.canvas.TextReplay} */ (this).textStates[textKey].textAlign;
- var startM = (pathLength - textLength) * ol.render.replay.TEXT_ALIGN[textAlign];
- var parts = ol.geom.flat.textpath.lineString(
- pixelCoordinates, begin, end, 2, text, measure, startM, maxAngle);
- if (parts) {
- var c, cc, chars, label, part;
- if (strokeKey) {
- for (c = 0, cc = parts.length; c < cc; ++c) {
- part = parts[c]; // x, y, anchorX, rotation, chunk
- chars = /** @type {string} */ (part[4]);
- label = /** @type {ol.render.canvas.TextReplay} */ (this).getImage(chars, textKey, '', strokeKey);
- anchorX = /** @type {number} */ (part[2]) + strokeWidth;
- anchorY = baseline * label.height + (0.5 - baseline) * 2 * strokeWidth - offsetY;
- this.replayImage_(context,
- /** @type {number} */ (part[0]), /** @type {number} */ (part[1]), label,
- anchorX, anchorY, declutterGroup, label.height, 1, 0, 0,
- /** @type {number} */ (part[3]), textScale, false, label.width,
- ol.render.canvas.defaultPadding, null, null);
- }
- }
- if (fillKey) {
- for (c = 0, cc = parts.length; c < cc; ++c) {
- part = parts[c]; // x, y, anchorX, rotation, chunk
- chars = /** @type {string} */ (part[4]);
- label = /** @type {ol.render.canvas.TextReplay} */ (this).getImage(chars, textKey, fillKey, '');
- anchorX = /** @type {number} */ (part[2]);
- anchorY = baseline * label.height - offsetY;
- this.replayImage_(context,
- /** @type {number} */ (part[0]), /** @type {number} */ (part[1]), label,
- anchorX, anchorY, declutterGroup, label.height, 1, 0, 0,
- /** @type {number} */ (part[3]), textScale, false, label.width,
- ol.render.canvas.defaultPadding, null, null);
- }
- }
- }
- }
- this.renderDeclutter_(declutterGroup, feature);
- ++i;
- break;
- case ol.render.canvas.Instruction.END_GEOMETRY:
- if (featureCallback !== undefined) {
- feature = /** @type {ol.Feature|ol.render.Feature} */ (instruction[1]);
- var result = featureCallback(feature);
- if (result) {
- return result;
- }
- }
- ++i;
- break;
- case ol.render.canvas.Instruction.FILL:
- if (batchSize) {
- pendingFill++;
- } else {
- this.fill_(context);
- }
- ++i;
- break;
- case ol.render.canvas.Instruction.MOVE_TO_LINE_TO:
- d = /** @type {number} */ (instruction[1]);
- dd = /** @type {number} */ (instruction[2]);
- x = pixelCoordinates[d];
- y = pixelCoordinates[d + 1];
- roundX = (x + 0.5) | 0;
- roundY = (y + 0.5) | 0;
- if (roundX !== prevX || roundY !== prevY) {
- context.moveTo(x, y);
- prevX = roundX;
- prevY = roundY;
- }
- for (d += 2; d < dd; d += 2) {
- x = pixelCoordinates[d];
- y = pixelCoordinates[d + 1];
- roundX = (x + 0.5) | 0;
- roundY = (y + 0.5) | 0;
- if (d == dd - 2 || roundX !== prevX || roundY !== prevY) {
- context.lineTo(x, y);
- prevX = roundX;
- prevY = roundY;
- }
- }
- ++i;
- break;
- case ol.render.canvas.Instruction.SET_FILL_STYLE:
- lastFillInstruction = instruction;
- this.fillOrigin_ = instruction[2];
- if (pendingFill) {
- this.fill_(context);
- pendingFill = 0;
- if (pendingStroke) {
- context.stroke();
- pendingStroke = 0;
- }
- }
- context.fillStyle = /** @type {ol.ColorLike} */ (instruction[1]);
- ++i;
- break;
- case ol.render.canvas.Instruction.SET_STROKE_STYLE:
- lastStrokeInstruction = instruction;
- if (pendingStroke) {
- context.stroke();
- pendingStroke = 0;
- }
- this.setStrokeStyle_(context, /** @type {Array.<*>} */ (instruction));
- ++i;
- break;
- case ol.render.canvas.Instruction.STROKE:
- if (batchSize) {
- pendingStroke++;
- } else {
- context.stroke();
- }
- ++i;
- break;
- default:
- ++i; // consume the instruction anyway, to avoid an infinite loop
- break;
- }
- }
- if (pendingFill) {
- this.fill_(context);
- }
- if (pendingStroke) {
- context.stroke();
- }
- return undefined;
- };
- /**
- * @param {CanvasRenderingContext2D} context Context.
- * @param {ol.Transform} transform Transform.
- * @param {number} viewRotation View rotation.
- * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
- * to skip.
- */
- ol.render.canvas.Replay.prototype.replay = function(
- context, transform, viewRotation, skippedFeaturesHash) {
- this.viewRotation_ = viewRotation;
- this.replay_(context, transform,
- skippedFeaturesHash, this.instructions, undefined, undefined);
- };
- /**
- * @param {CanvasRenderingContext2D} context Context.
- * @param {ol.Transform} transform Transform.
- * @param {number} viewRotation View rotation.
- * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
- * to skip.
- * @param {function((ol.Feature|ol.render.Feature)): T=} opt_featureCallback
- * Feature callback.
- * @param {ol.Extent=} opt_hitExtent Only check features that intersect this
- * extent.
- * @return {T|undefined} Callback result.
- * @template T
- */
- ol.render.canvas.Replay.prototype.replayHitDetection = function(
- context, transform, viewRotation, skippedFeaturesHash,
- opt_featureCallback, opt_hitExtent) {
- this.viewRotation_ = viewRotation;
- return this.replay_(context, transform, skippedFeaturesHash,
- this.hitDetectionInstructions, opt_featureCallback, opt_hitExtent);
- };
- /**
- * Reverse the hit detection instructions.
- */
- ol.render.canvas.Replay.prototype.reverseHitDetectionInstructions = function() {
- var hitDetectionInstructions = this.hitDetectionInstructions;
- // step 1 - reverse array
- hitDetectionInstructions.reverse();
- // step 2 - reverse instructions within geometry blocks
- var i;
- var n = hitDetectionInstructions.length;
- var instruction;
- var type;
- var begin = -1;
- for (i = 0; i < n; ++i) {
- instruction = hitDetectionInstructions[i];
- type = /** @type {ol.render.canvas.Instruction} */ (instruction[0]);
- if (type == ol.render.canvas.Instruction.END_GEOMETRY) {
- begin = i;
- } else if (type == ol.render.canvas.Instruction.BEGIN_GEOMETRY) {
- instruction[2] = i;
- ol.array.reverseSubArray(this.hitDetectionInstructions, begin, i);
- begin = -1;
- }
- }
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.Replay.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
- var state = this.state;
- if (fillStyle) {
- var fillStyleColor = fillStyle.getColor();
- state.fillStyle = ol.colorlike.asColorLike(fillStyleColor ?
- fillStyleColor : ol.render.canvas.defaultFillStyle);
- } else {
- state.fillStyle = undefined;
- }
- if (strokeStyle) {
- var strokeStyleColor = strokeStyle.getColor();
- state.strokeStyle = ol.colorlike.asColorLike(strokeStyleColor ?
- strokeStyleColor : ol.render.canvas.defaultStrokeStyle);
- var strokeStyleLineCap = strokeStyle.getLineCap();
- state.lineCap = strokeStyleLineCap !== undefined ?
- strokeStyleLineCap : ol.render.canvas.defaultLineCap;
- var strokeStyleLineDash = strokeStyle.getLineDash();
- state.lineDash = strokeStyleLineDash ?
- strokeStyleLineDash.slice() : ol.render.canvas.defaultLineDash;
- var strokeStyleLineDashOffset = strokeStyle.getLineDashOffset();
- state.lineDashOffset = strokeStyleLineDashOffset ?
- strokeStyleLineDashOffset : ol.render.canvas.defaultLineDashOffset;
- var strokeStyleLineJoin = strokeStyle.getLineJoin();
- state.lineJoin = strokeStyleLineJoin !== undefined ?
- strokeStyleLineJoin : ol.render.canvas.defaultLineJoin;
- var strokeStyleWidth = strokeStyle.getWidth();
- state.lineWidth = strokeStyleWidth !== undefined ?
- strokeStyleWidth : ol.render.canvas.defaultLineWidth;
- var strokeStyleMiterLimit = strokeStyle.getMiterLimit();
- state.miterLimit = strokeStyleMiterLimit !== undefined ?
- strokeStyleMiterLimit : ol.render.canvas.defaultMiterLimit;
- if (state.lineWidth > this.maxLineWidth) {
- this.maxLineWidth = state.lineWidth;
- // invalidate the buffered max extent cache
- this.bufferedMaxExtent_ = null;
- }
- } else {
- state.strokeStyle = undefined;
- state.lineCap = undefined;
- state.lineDash = null;
- state.lineDashOffset = undefined;
- state.lineJoin = undefined;
- state.lineWidth = undefined;
- state.miterLimit = undefined;
- }
- };
- /**
- * @param {ol.CanvasFillStrokeState} state State.
- * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
- */
- ol.render.canvas.Replay.prototype.applyFill = function(state, geometry) {
- var fillStyle = state.fillStyle;
- var fillInstruction = [ol.render.canvas.Instruction.SET_FILL_STYLE, fillStyle];
- if (typeof fillStyle !== 'string') {
- var fillExtent = geometry.getExtent();
- fillInstruction.push([fillExtent[0], fillExtent[3]]);
- }
- this.instructions.push(fillInstruction);
- };
- /**
- * @param {ol.CanvasFillStrokeState} state State.
- */
- ol.render.canvas.Replay.prototype.applyStroke = function(state) {
- this.instructions.push([
- ol.render.canvas.Instruction.SET_STROKE_STYLE,
- state.strokeStyle, state.lineWidth * this.pixelRatio, state.lineCap,
- state.lineJoin, state.miterLimit,
- this.applyPixelRatio(state.lineDash), state.lineDashOffset * this.pixelRatio
- ]);
- };
- /**
- * @param {ol.CanvasFillStrokeState} state State.
- * @param {function(this:ol.render.canvas.Replay, ol.CanvasFillStrokeState, (ol.geom.Geometry|ol.render.Feature))} applyFill Apply fill.
- * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
- */
- ol.render.canvas.Replay.prototype.updateFillStyle = function(state, applyFill, geometry) {
- var fillStyle = state.fillStyle;
- if (typeof fillStyle !== 'string' || state.currentFillStyle != fillStyle) {
- applyFill.call(this, state, geometry);
- state.currentFillStyle = fillStyle;
- }
- };
- /**
- * @param {ol.CanvasFillStrokeState} state State.
- * @param {function(this:ol.render.canvas.Replay, ol.CanvasFillStrokeState)} applyStroke Apply stroke.
- */
- ol.render.canvas.Replay.prototype.updateStrokeStyle = function(state, applyStroke) {
- var strokeStyle = state.strokeStyle;
- var lineCap = state.lineCap;
- var lineDash = state.lineDash;
- var lineDashOffset = state.lineDashOffset;
- var lineJoin = state.lineJoin;
- var lineWidth = state.lineWidth;
- var miterLimit = state.miterLimit;
- if (state.currentStrokeStyle != strokeStyle ||
- state.currentLineCap != lineCap ||
- (lineDash != state.currentLineDash && !ol.array.equals(state.currentLineDash, lineDash)) ||
- state.currentLineDashOffset != lineDashOffset ||
- state.currentLineJoin != lineJoin ||
- state.currentLineWidth != lineWidth ||
- state.currentMiterLimit != miterLimit) {
- applyStroke.call(this, state);
- state.currentStrokeStyle = strokeStyle;
- state.currentLineCap = lineCap;
- state.currentLineDash = lineDash;
- state.currentLineDashOffset = lineDashOffset;
- state.currentLineJoin = lineJoin;
- state.currentLineWidth = lineWidth;
- state.currentMiterLimit = miterLimit;
- }
- };
- /**
- * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
- */
- ol.render.canvas.Replay.prototype.endGeometry = function(geometry, feature) {
- this.beginGeometryInstruction1_[2] = this.instructions.length;
- this.beginGeometryInstruction1_ = null;
- this.beginGeometryInstruction2_[2] = this.hitDetectionInstructions.length;
- this.beginGeometryInstruction2_ = null;
- var endGeometryInstruction =
- [ol.render.canvas.Instruction.END_GEOMETRY, feature];
- this.instructions.push(endGeometryInstruction);
- this.hitDetectionInstructions.push(endGeometryInstruction);
- };
- /**
- * FIXME empty description for jsdoc
- */
- ol.render.canvas.Replay.prototype.finish = ol.nullFunction;
- /**
- * Get the buffered rendering extent. Rendering will be clipped to the extent
- * provided to the constructor. To account for symbolizers that may intersect
- * this extent, we calculate a buffered extent (e.g. based on stroke width).
- * @return {ol.Extent} The buffered rendering extent.
- * @protected
- */
- ol.render.canvas.Replay.prototype.getBufferedMaxExtent = function() {
- if (!this.bufferedMaxExtent_) {
- this.bufferedMaxExtent_ = ol.extent.clone(this.maxExtent);
- if (this.maxLineWidth > 0) {
- var width = this.resolution * (this.maxLineWidth + 1) / 2;
- ol.extent.buffer(this.bufferedMaxExtent_, width, this.bufferedMaxExtent_);
- }
- }
- return this.bufferedMaxExtent_;
- };
- /**
- * @constructor
- * @extends {ol.render.canvas.Replay}
- * @param {number} tolerance Tolerance.
- * @param {ol.Extent} maxExtent Maximum extent.
- * @param {number} resolution Resolution.
- * @param {number} pixelRatio Pixel ratio.
- * @param {boolean} overlaps The replay can have overlapping geometries.
- * @param {?} declutterTree Declutter tree.
- * @struct
- */
- ol.render.canvas.ImageReplay = function(
- tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) {
- ol.render.canvas.Replay.call(this,
- tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree);
- /**
- * @private
- * @type {ol.DeclutterGroup}
- */
- this.declutterGroup_ = null;
- /**
- * @private
- * @type {HTMLCanvasElement|HTMLVideoElement|Image}
- */
- this.hitDetectionImage_ = null;
- /**
- * @private
- * @type {HTMLCanvasElement|HTMLVideoElement|Image}
- */
- this.image_ = null;
- /**
- * @private
- * @type {number|undefined}
- */
- this.anchorX_ = undefined;
- /**
- * @private
- * @type {number|undefined}
- */
- this.anchorY_ = undefined;
- /**
- * @private
- * @type {number|undefined}
- */
- this.height_ = undefined;
- /**
- * @private
- * @type {number|undefined}
- */
- this.opacity_ = undefined;
- /**
- * @private
- * @type {number|undefined}
- */
- this.originX_ = undefined;
- /**
- * @private
- * @type {number|undefined}
- */
- this.originY_ = undefined;
- /**
- * @private
- * @type {boolean|undefined}
- */
- this.rotateWithView_ = undefined;
- /**
- * @private
- * @type {number|undefined}
- */
- this.rotation_ = undefined;
- /**
- * @private
- * @type {number|undefined}
- */
- this.scale_ = undefined;
- /**
- * @private
- * @type {boolean|undefined}
- */
- this.snapToPixel_ = undefined;
- /**
- * @private
- * @type {number|undefined}
- */
- this.width_ = undefined;
- };
- ol.inherits(ol.render.canvas.ImageReplay, ol.render.canvas.Replay);
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {number} end End.
- * @param {number} stride Stride.
- * @private
- * @return {number} My end.
- */
- ol.render.canvas.ImageReplay.prototype.drawCoordinates_ = function(flatCoordinates, offset, end, stride) {
- return this.appendFlatCoordinates(
- flatCoordinates, offset, end, stride, false, false);
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.ImageReplay.prototype.drawPoint = function(pointGeometry, feature) {
- if (!this.image_) {
- return;
- }
- this.beginGeometry(pointGeometry, feature);
- var flatCoordinates = pointGeometry.getFlatCoordinates();
- var stride = pointGeometry.getStride();
- var myBegin = this.coordinates.length;
- var myEnd = this.drawCoordinates_(
- flatCoordinates, 0, flatCoordinates.length, stride);
- this.instructions.push([
- ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd, this.image_,
- // Remaining arguments to DRAW_IMAGE are in alphabetical order
- this.anchorX_, this.anchorY_, this.declutterGroup_, this.height_, this.opacity_,
- this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
- this.scale_ * this.pixelRatio, this.snapToPixel_, this.width_
- ]);
- this.hitDetectionInstructions.push([
- ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd,
- this.hitDetectionImage_,
- // Remaining arguments to DRAW_IMAGE are in alphabetical order
- this.anchorX_, this.anchorY_, this.declutterGroup_, this.height_, this.opacity_,
- this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
- this.scale_, this.snapToPixel_, this.width_
- ]);
- this.endGeometry(pointGeometry, feature);
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.ImageReplay.prototype.drawMultiPoint = function(multiPointGeometry, feature) {
- if (!this.image_) {
- return;
- }
- this.beginGeometry(multiPointGeometry, feature);
- var flatCoordinates = multiPointGeometry.getFlatCoordinates();
- var stride = multiPointGeometry.getStride();
- var myBegin = this.coordinates.length;
- var myEnd = this.drawCoordinates_(
- flatCoordinates, 0, flatCoordinates.length, stride);
- this.instructions.push([
- ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd, this.image_,
- // Remaining arguments to DRAW_IMAGE are in alphabetical order
- this.anchorX_, this.anchorY_, this.declutterGroup_, this.height_, this.opacity_,
- this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
- this.scale_ * this.pixelRatio, this.snapToPixel_, this.width_
- ]);
- this.hitDetectionInstructions.push([
- ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd,
- this.hitDetectionImage_,
- // Remaining arguments to DRAW_IMAGE are in alphabetical order
- this.anchorX_, this.anchorY_, this.declutterGroup_, this.height_, this.opacity_,
- this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
- this.scale_, this.snapToPixel_, this.width_
- ]);
- this.endGeometry(multiPointGeometry, feature);
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.ImageReplay.prototype.finish = function() {
- this.reverseHitDetectionInstructions();
- // FIXME this doesn't really protect us against further calls to draw*Geometry
- this.anchorX_ = undefined;
- this.anchorY_ = undefined;
- this.hitDetectionImage_ = null;
- this.image_ = null;
- this.height_ = undefined;
- this.scale_ = undefined;
- this.opacity_ = undefined;
- this.originX_ = undefined;
- this.originY_ = undefined;
- this.rotateWithView_ = undefined;
- this.rotation_ = undefined;
- this.snapToPixel_ = undefined;
- this.width_ = undefined;
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.ImageReplay.prototype.setImageStyle = function(imageStyle, declutterGroup) {
- var anchor = imageStyle.getAnchor();
- var size = imageStyle.getSize();
- var hitDetectionImage = imageStyle.getHitDetectionImage(1);
- var image = imageStyle.getImage(1);
- var origin = imageStyle.getOrigin();
- this.anchorX_ = anchor[0];
- this.anchorY_ = anchor[1];
- this.declutterGroup_ = /** @type {ol.DeclutterGroup} */ (declutterGroup);
- this.hitDetectionImage_ = hitDetectionImage;
- this.image_ = image;
- this.height_ = size[1];
- this.opacity_ = imageStyle.getOpacity();
- this.originX_ = origin[0];
- this.originY_ = origin[1];
- this.rotateWithView_ = imageStyle.getRotateWithView();
- this.rotation_ = imageStyle.getRotation();
- this.scale_ = imageStyle.getScale();
- this.snapToPixel_ = imageStyle.getSnapToPixel();
- this.width_ = size[0];
- };
- /**
- * @constructor
- * @extends {ol.render.canvas.Replay}
- * @param {number} tolerance Tolerance.
- * @param {ol.Extent} maxExtent Maximum extent.
- * @param {number} resolution Resolution.
- * @param {number} pixelRatio Pixel ratio.
- * @param {boolean} overlaps The replay can have overlapping geometries.
- * @param {?} declutterTree Declutter tree.
- * @struct
- */
- ol.render.canvas.LineStringReplay = function(
- tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) {
- ol.render.canvas.Replay.call(this,
- tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree);
- };
- ol.inherits(ol.render.canvas.LineStringReplay, ol.render.canvas.Replay);
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {number} end End.
- * @param {number} stride Stride.
- * @private
- * @return {number} end.
- */
- ol.render.canvas.LineStringReplay.prototype.drawFlatCoordinates_ = function(flatCoordinates, offset, end, stride) {
- var myBegin = this.coordinates.length;
- var myEnd = this.appendFlatCoordinates(
- flatCoordinates, offset, end, stride, false, false);
- var moveToLineToInstruction =
- [ol.render.canvas.Instruction.MOVE_TO_LINE_TO, myBegin, myEnd];
- this.instructions.push(moveToLineToInstruction);
- this.hitDetectionInstructions.push(moveToLineToInstruction);
- return end;
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.LineStringReplay.prototype.drawLineString = function(lineStringGeometry, feature) {
- var state = this.state;
- var strokeStyle = state.strokeStyle;
- var lineWidth = state.lineWidth;
- if (strokeStyle === undefined || lineWidth === undefined) {
- return;
- }
- this.updateStrokeStyle(state, this.applyStroke);
- this.beginGeometry(lineStringGeometry, feature);
- this.hitDetectionInstructions.push([
- ol.render.canvas.Instruction.SET_STROKE_STYLE,
- state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
- state.miterLimit, state.lineDash, state.lineDashOffset
- ], [
- ol.render.canvas.Instruction.BEGIN_PATH
- ]);
- var flatCoordinates = lineStringGeometry.getFlatCoordinates();
- var stride = lineStringGeometry.getStride();
- this.drawFlatCoordinates_(flatCoordinates, 0, flatCoordinates.length, stride);
- this.hitDetectionInstructions.push([ol.render.canvas.Instruction.STROKE]);
- this.endGeometry(lineStringGeometry, feature);
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.LineStringReplay.prototype.drawMultiLineString = function(multiLineStringGeometry, feature) {
- var state = this.state;
- var strokeStyle = state.strokeStyle;
- var lineWidth = state.lineWidth;
- if (strokeStyle === undefined || lineWidth === undefined) {
- return;
- }
- this.updateStrokeStyle(state, this.applyStroke);
- this.beginGeometry(multiLineStringGeometry, feature);
- this.hitDetectionInstructions.push([
- ol.render.canvas.Instruction.SET_STROKE_STYLE,
- state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
- state.miterLimit, state.lineDash, state.lineDashOffset
- ], [
- ol.render.canvas.Instruction.BEGIN_PATH
- ]);
- var ends = multiLineStringGeometry.getEnds();
- var flatCoordinates = multiLineStringGeometry.getFlatCoordinates();
- var stride = multiLineStringGeometry.getStride();
- var offset = 0;
- var i, ii;
- for (i = 0, ii = ends.length; i < ii; ++i) {
- offset = this.drawFlatCoordinates_(
- flatCoordinates, offset, ends[i], stride);
- }
- this.hitDetectionInstructions.push([ol.render.canvas.Instruction.STROKE]);
- this.endGeometry(multiLineStringGeometry, feature);
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.LineStringReplay.prototype.finish = function() {
- var state = this.state;
- if (state.lastStroke != undefined && state.lastStroke != this.coordinates.length) {
- this.instructions.push([ol.render.canvas.Instruction.STROKE]);
- }
- this.reverseHitDetectionInstructions();
- this.state = null;
- };
- /**
- * @inheritDoc.
- */
- ol.render.canvas.LineStringReplay.prototype.applyStroke = function(state) {
- if (state.lastStroke != undefined && state.lastStroke != this.coordinates.length) {
- this.instructions.push([ol.render.canvas.Instruction.STROKE]);
- state.lastStroke = this.coordinates.length;
- }
- state.lastStroke = 0;
- ol.render.canvas.Replay.prototype.applyStroke.call(this, state);
- this.instructions.push([ol.render.canvas.Instruction.BEGIN_PATH]);
- };
- /**
- * @constructor
- * @extends {ol.render.canvas.Replay}
- * @param {number} tolerance Tolerance.
- * @param {ol.Extent} maxExtent Maximum extent.
- * @param {number} resolution Resolution.
- * @param {number} pixelRatio Pixel ratio.
- * @param {boolean} overlaps The replay can have overlapping geometries.
- * @param {?} declutterTree Declutter tree.
- * @struct
- */
- ol.render.canvas.PolygonReplay = function(
- tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) {
- ol.render.canvas.Replay.call(this,
- tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree);
- };
- ol.inherits(ol.render.canvas.PolygonReplay, ol.render.canvas.Replay);
- /**
- * @param {Array.<number>} flatCoordinates Flat coordinates.
- * @param {number} offset Offset.
- * @param {Array.<number>} ends Ends.
- * @param {number} stride Stride.
- * @private
- * @return {number} End.
- */
- ol.render.canvas.PolygonReplay.prototype.drawFlatCoordinatess_ = function(flatCoordinates, offset, ends, stride) {
- var state = this.state;
- var fill = state.fillStyle !== undefined;
- var stroke = state.strokeStyle != undefined;
- var numEnds = ends.length;
- var beginPathInstruction = [ol.render.canvas.Instruction.BEGIN_PATH];
- this.instructions.push(beginPathInstruction);
- this.hitDetectionInstructions.push(beginPathInstruction);
- for (var i = 0; i < numEnds; ++i) {
- var end = ends[i];
- var myBegin = this.coordinates.length;
- var myEnd = this.appendFlatCoordinates(
- flatCoordinates, offset, end, stride, true, !stroke);
- var moveToLineToInstruction =
- [ol.render.canvas.Instruction.MOVE_TO_LINE_TO, myBegin, myEnd];
- this.instructions.push(moveToLineToInstruction);
- this.hitDetectionInstructions.push(moveToLineToInstruction);
- if (stroke) {
- // Performance optimization: only call closePath() when we have a stroke.
- // Otherwise the ring is closed already (see appendFlatCoordinates above).
- var closePathInstruction = [ol.render.canvas.Instruction.CLOSE_PATH];
- this.instructions.push(closePathInstruction);
- this.hitDetectionInstructions.push(closePathInstruction);
- }
- offset = end;
- }
- var fillInstruction = [ol.render.canvas.Instruction.FILL];
- this.hitDetectionInstructions.push(fillInstruction);
- if (fill) {
- this.instructions.push(fillInstruction);
- }
- if (stroke) {
- var strokeInstruction = [ol.render.canvas.Instruction.STROKE];
- this.instructions.push(strokeInstruction);
- this.hitDetectionInstructions.push(strokeInstruction);
- }
- return offset;
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.PolygonReplay.prototype.drawCircle = function(circleGeometry, feature) {
- var state = this.state;
- var fillStyle = state.fillStyle;
- var strokeStyle = state.strokeStyle;
- if (fillStyle === undefined && strokeStyle === undefined) {
- return;
- }
- this.setFillStrokeStyles_(circleGeometry);
- this.beginGeometry(circleGeometry, feature);
- // always fill the circle for hit detection
- this.hitDetectionInstructions.push([
- ol.render.canvas.Instruction.SET_FILL_STYLE,
- ol.color.asString(ol.render.canvas.defaultFillStyle)
- ]);
- if (state.strokeStyle !== undefined) {
- this.hitDetectionInstructions.push([
- ol.render.canvas.Instruction.SET_STROKE_STYLE,
- state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
- state.miterLimit, state.lineDash, state.lineDashOffset
- ]);
- }
- var flatCoordinates = circleGeometry.getFlatCoordinates();
- var stride = circleGeometry.getStride();
- var myBegin = this.coordinates.length;
- this.appendFlatCoordinates(
- flatCoordinates, 0, flatCoordinates.length, stride, false, false);
- var beginPathInstruction = [ol.render.canvas.Instruction.BEGIN_PATH];
- var circleInstruction = [ol.render.canvas.Instruction.CIRCLE, myBegin];
- this.instructions.push(beginPathInstruction, circleInstruction);
- this.hitDetectionInstructions.push(beginPathInstruction, circleInstruction);
- var fillInstruction = [ol.render.canvas.Instruction.FILL];
- this.hitDetectionInstructions.push(fillInstruction);
- if (state.fillStyle !== undefined) {
- this.instructions.push(fillInstruction);
- }
- if (state.strokeStyle !== undefined) {
- var strokeInstruction = [ol.render.canvas.Instruction.STROKE];
- this.instructions.push(strokeInstruction);
- this.hitDetectionInstructions.push(strokeInstruction);
- }
- this.endGeometry(circleGeometry, feature);
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.PolygonReplay.prototype.drawPolygon = function(polygonGeometry, feature) {
- var state = this.state;
- this.setFillStrokeStyles_(polygonGeometry);
- this.beginGeometry(polygonGeometry, feature);
- // always fill the polygon for hit detection
- this.hitDetectionInstructions.push([
- ol.render.canvas.Instruction.SET_FILL_STYLE,
- ol.color.asString(ol.render.canvas.defaultFillStyle)]
- );
- if (state.strokeStyle !== undefined) {
- this.hitDetectionInstructions.push([
- ol.render.canvas.Instruction.SET_STROKE_STYLE,
- state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
- state.miterLimit, state.lineDash, state.lineDashOffset
- ]);
- }
- var ends = polygonGeometry.getEnds();
- var flatCoordinates = polygonGeometry.getOrientedFlatCoordinates();
- var stride = polygonGeometry.getStride();
- this.drawFlatCoordinatess_(flatCoordinates, 0, ends, stride);
- this.endGeometry(polygonGeometry, feature);
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.PolygonReplay.prototype.drawMultiPolygon = function(multiPolygonGeometry, feature) {
- var state = this.state;
- var fillStyle = state.fillStyle;
- var strokeStyle = state.strokeStyle;
- if (fillStyle === undefined && strokeStyle === undefined) {
- return;
- }
- this.setFillStrokeStyles_(multiPolygonGeometry);
- this.beginGeometry(multiPolygonGeometry, feature);
- // always fill the multi-polygon for hit detection
- this.hitDetectionInstructions.push([
- ol.render.canvas.Instruction.SET_FILL_STYLE,
- ol.color.asString(ol.render.canvas.defaultFillStyle)
- ]);
- if (state.strokeStyle !== undefined) {
- this.hitDetectionInstructions.push([
- ol.render.canvas.Instruction.SET_STROKE_STYLE,
- state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
- state.miterLimit, state.lineDash, state.lineDashOffset
- ]);
- }
- var endss = multiPolygonGeometry.getEndss();
- var flatCoordinates = multiPolygonGeometry.getOrientedFlatCoordinates();
- var stride = multiPolygonGeometry.getStride();
- var offset = 0;
- var i, ii;
- for (i = 0, ii = endss.length; i < ii; ++i) {
- offset = this.drawFlatCoordinatess_(
- flatCoordinates, offset, endss[i], stride);
- }
- this.endGeometry(multiPolygonGeometry, feature);
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.PolygonReplay.prototype.finish = function() {
- this.reverseHitDetectionInstructions();
- this.state = null;
- // We want to preserve topology when drawing polygons. Polygons are
- // simplified using quantization and point elimination. However, we might
- // have received a mix of quantized and non-quantized geometries, so ensure
- // that all are quantized by quantizing all coordinates in the batch.
- var tolerance = this.tolerance;
- if (tolerance !== 0) {
- var coordinates = this.coordinates;
- var i, ii;
- for (i = 0, ii = coordinates.length; i < ii; ++i) {
- coordinates[i] = ol.geom.flat.simplify.snap(coordinates[i], tolerance);
- }
- }
- };
- /**
- * @private
- * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
- */
- ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyles_ = function(geometry) {
- var state = this.state;
- var fillStyle = state.fillStyle;
- if (fillStyle !== undefined) {
- this.updateFillStyle(state, this.applyFill, geometry);
- }
- if (state.strokeStyle !== undefined) {
- this.updateStrokeStyle(state, this.applyStroke);
- }
- };
- ol.geom.flat.straightchunk = {};
- ol.geom.flat.straightchunk.lineString = function(maxAngle, flatCoordinates, offset, end, stride) {
- var chunkStart = offset;
- var chunkEnd = offset;
- var chunkM = 0;
- var m = 0;
- var start = offset;
- var acos, i, m12, m23, x1, y1, x12, y12, x23, y23;
- for (i = offset; i < end; i += stride) {
- var x2 = flatCoordinates[i];
- var y2 = flatCoordinates[i + 1];
- if (x1 !== undefined) {
- x23 = x2 - x1;
- y23 = y2 - y1;
- m23 = Math.sqrt(x23 * x23 + y23 * y23);
- if (x12 !== undefined) {
- m += m12;
- acos = Math.acos((x12 * x23 + y12 * y23) / (m12 * m23));
- if (acos > maxAngle) {
- if (m > chunkM) {
- chunkM = m;
- chunkStart = start;
- chunkEnd = i;
- }
- m = 0;
- start = i - stride;
- }
- }
- m12 = m23;
- x12 = x23;
- y12 = y23;
- }
- x1 = x2;
- y1 = y2;
- }
- m += m23;
- return m > chunkM ? [start, i] : [chunkStart, chunkEnd];
- };
- ol.style.TextPlacement = {
- POINT: 'point',
- LINE: 'line'
- };
- ol.render.canvas.TextReplay = function(
- tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) {
- ol.render.canvas.Replay.call(this,
- tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree);
- /**
- * @private
- * @type {ol.DeclutterGroup}
- */
- this.declutterGroup_;
- /**
- * @private
- * @type {Array.<HTMLCanvasElement>}
- */
- this.labels_ = null;
- /**
- * @private
- * @type {string}
- */
- this.text_ = '';
- /**
- * @private
- * @type {number}
- */
- this.textOffsetX_ = 0;
- /**
- * @private
- * @type {number}
- */
- this.textOffsetY_ = 0;
- /**
- * @private
- * @type {boolean|undefined}
- */
- this.textRotateWithView_ = undefined;
- /**
- * @private
- * @type {number}
- */
- this.textRotation_ = 0;
- /**
- * @private
- * @type {?ol.CanvasFillState}
- */
- this.textFillState_ = null;
- /**
- * @type {Object.<string, ol.CanvasFillState>}
- */
- this.fillStates = {};
- /**
- * @private
- * @type {?ol.CanvasStrokeState}
- */
- this.textStrokeState_ = null;
- /**
- * @type {Object.<string, ol.CanvasStrokeState>}
- */
- this.strokeStates = {};
- /**
- * @private
- * @type {ol.CanvasTextState}
- */
- this.textState_ = /** @type {ol.CanvasTextState} */ ({});
- /**
- * @type {Object.<string, ol.CanvasTextState>}
- */
- this.textStates = {};
- /**
- * @private
- * @type {string}
- */
- this.textKey_ = '';
- /**
- * @private
- * @type {string}
- */
- this.fillKey_ = '';
- /**
- * @private
- * @type {string}
- */
- this.strokeKey_ = '';
- /**
- * @private
- * @type {Object.<string, Object.<string, number>>}
- */
- this.widths_ = {};
- var labelCache = ol.render.canvas.labelCache;
- labelCache.prune();
- };
- ol.inherits(ol.render.canvas.TextReplay, ol.render.canvas.Replay);
- /**
- * @param {string} font Font to use for measuring.
- * @param {Array.<string>} lines Lines to measure.
- * @param {Array.<number>} widths Array will be populated with the widths of
- * each line.
- * @return {number} Width of the whole text.
- */
- ol.render.canvas.TextReplay.measureTextWidths = function(font, lines, widths) {
- var numLines = lines.length;
- var width = 0;
- var currentWidth, i;
- for (i = 0; i < numLines; ++i) {
- currentWidth = ol.render.canvas.measureTextWidth(font, lines[i]);
- width = Math.max(width, currentWidth);
- widths.push(currentWidth);
- }
- return width;
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.TextReplay.prototype.drawText = function(geometry, feature) {
- var fillState = this.textFillState_;
- var strokeState = this.textStrokeState_;
- var textState = this.textState_;
- if (this.text_ === '' || !textState || (!fillState && !strokeState)) {
- return;
- }
- var begin = this.coordinates.length;
- var geometryType = geometry.getType();
- var flatCoordinates = null;
- var end = 2;
- var stride = 2;
- var i, ii;
- if (textState.placement === ol.style.TextPlacement.LINE) {
- if (!ol.extent.intersects(this.getBufferedMaxExtent(), geometry.getExtent())) {
- return;
- }
- var ends;
- flatCoordinates = geometry.getFlatCoordinates();
- stride = geometry.getStride();
- if (geometryType == ol.geom.GeometryType.LINE_STRING) {
- ends = [flatCoordinates.length];
- } else if (geometryType == ol.geom.GeometryType.MULTI_LINE_STRING) {
- ends = geometry.getEnds();
- } else if (geometryType == ol.geom.GeometryType.POLYGON) {
- ends = geometry.getEnds().slice(0, 1);
- } else if (geometryType == ol.geom.GeometryType.MULTI_POLYGON) {
- var endss = geometry.getEndss();
- ends = [];
- for (i = 0, ii = endss.length; i < ii; ++i) {
- ends.push(endss[i][0]);
- }
- }
- this.beginGeometry(geometry, feature);
- var textAlign = textState.textAlign;
- var flatOffset = 0;
- var flatEnd;
- for (var o = 0, oo = ends.length; o < oo; ++o) {
- if (textAlign == undefined) {
- var range = ol.geom.flat.straightchunk.lineString(
- textState.maxAngle, flatCoordinates, flatOffset, ends[o], stride);
- flatOffset = range[0];
- flatEnd = range[1];
- } else {
- flatEnd = ends[o];
- }
- for (i = flatOffset; i < flatEnd; i += stride) {
- this.coordinates.push(flatCoordinates[i], flatCoordinates[i + 1]);
- }
- end = this.coordinates.length;
- flatOffset = ends[o];
- this.drawChars_(begin, end, this.declutterGroup_);
- begin = end;
- }
- this.endGeometry(geometry, feature);
- } else {
- var label = this.getImage(this.text_, this.textKey_, this.fillKey_, this.strokeKey_);
- var width = label.width / this.pixelRatio;
- switch (geometryType) {
- case ol.geom.GeometryType.POINT:
- case ol.geom.GeometryType.MULTI_POINT:
- flatCoordinates = geometry.getFlatCoordinates();
- end = flatCoordinates.length;
- break;
- case ol.geom.GeometryType.LINE_STRING:
- flatCoordinates = /** @type {ol.geom.LineString} */ (geometry).getFlatMidpoint();
- break;
- case ol.geom.GeometryType.CIRCLE:
- flatCoordinates = /** @type {ol.geom.Circle} */ (geometry).getCenter();
- break;
- case ol.geom.GeometryType.MULTI_LINE_STRING:
- flatCoordinates = /** @type {ol.geom.MultiLineString} */ (geometry).getFlatMidpoints();
- end = flatCoordinates.length;
- break;
- case ol.geom.GeometryType.POLYGON:
- flatCoordinates = /** @type {ol.geom.Polygon} */ (geometry).getFlatInteriorPoint();
- if (!textState.overflow && flatCoordinates[2] / this.resolution < width) {
- return;
- }
- stride = 3;
- break;
- case ol.geom.GeometryType.MULTI_POLYGON:
- var interiorPoints = /** @type {ol.geom.MultiPolygon} */ (geometry).getFlatInteriorPoints();
- flatCoordinates = [];
- for (i = 0, ii = interiorPoints.length; i < ii; i += 3) {
- if (textState.overflow || interiorPoints[i + 2] / this.resolution >= width) {
- flatCoordinates.push(interiorPoints[i], interiorPoints[i + 1]);
- }
- }
- end = flatCoordinates.length;
- if (end == 0) {
- return;
- }
- break;
- }
- end = this.appendFlatCoordinates(flatCoordinates, 0, end, stride, false, false);
- this.beginGeometry(geometry, feature);
- if (textState.backgroundFill || textState.backgroundStroke) {
- this.setFillStrokeStyle(textState.backgroundFill, textState.backgroundStroke);
- this.updateFillStyle(this.state, this.applyFill, geometry);
- this.updateStrokeStyle(this.state, this.applyStroke);
- }
- this.drawTextImage_(label, begin, end);
- this.endGeometry(geometry, feature);
- }
- };
- /**
- * @param {string} text Text.
- * @param {string} textKey Text style key.
- * @param {string} fillKey Fill style key.
- * @param {string} strokeKey Stroke style key.
- * @return {HTMLCanvasElement} Image.
- */
- ol.render.canvas.TextReplay.prototype.getImage = function(text, textKey, fillKey, strokeKey) {
- var label;
- var key = strokeKey + textKey + text + fillKey + this.pixelRatio;
- var labelCache = ol.render.canvas.labelCache;
- if (!labelCache.containsKey(key)) {
- var strokeState = strokeKey ? this.strokeStates[strokeKey] || this.textStrokeState_ : null;
- var fillState = fillKey ? this.fillStates[fillKey] || this.textFillState_ : null;
- var textState = this.textStates[textKey] || this.textState_;
- var pixelRatio = this.pixelRatio;
- var scale = textState.scale * pixelRatio;
- var align = ol.render.replay.TEXT_ALIGN[textState.textAlign || ol.render.canvas.defaultTextAlign];
- var strokeWidth = strokeKey && strokeState.lineWidth ? strokeState.lineWidth : 0;
- var lines = text.split('\n');
- var numLines = lines.length;
- var widths = [];
- var width = ol.render.canvas.TextReplay.measureTextWidths(textState.font, lines, widths);
- var lineHeight = ol.render.canvas.measureTextHeight(textState.font);
- var height = lineHeight * numLines;
- var renderWidth = (width + strokeWidth);
- var context = ol.dom.createCanvasContext2D(
- Math.ceil(renderWidth * scale),
- Math.ceil((height + strokeWidth) * scale));
- label = context.canvas;
- labelCache.set(key, label);
- if (scale != 1) {
- context.scale(scale, scale);
- }
- context.font = textState.font;
- if (strokeKey) {
- context.strokeStyle = strokeState.strokeStyle;
- context.lineWidth = strokeWidth * (ol.has.SAFARI ? scale : 1);
- context.lineCap = strokeState.lineCap;
- context.lineJoin = strokeState.lineJoin;
- context.miterLimit = strokeState.miterLimit;
- if (ol.has.CANVAS_LINE_DASH && strokeState.lineDash.length) {
- context.setLineDash(strokeState.lineDash);
- context.lineDashOffset = strokeState.lineDashOffset;
- }
- }
- if (fillKey) {
- context.fillStyle = fillState.fillStyle;
- }
- context.textBaseline = 'middle';
- context.textAlign = 'center';
- var leftRight = (0.5 - align);
- var x = align * label.width / scale + leftRight * strokeWidth;
- var i;
- if (strokeKey) {
- for (i = 0; i < numLines; ++i) {
- context.strokeText(lines[i], x + leftRight * widths[i], 0.5 * (strokeWidth + lineHeight) + i * lineHeight);
- }
- }
- if (fillKey) {
- for (i = 0; i < numLines; ++i) {
- context.fillText(lines[i], x + leftRight * widths[i], 0.5 * (strokeWidth + lineHeight) + i * lineHeight);
- }
- }
- }
- return labelCache.get(key);
- };
- /**
- * @private
- * @param {HTMLCanvasElement} label Label.
- * @param {number} begin Begin.
- * @param {number} end End.
- */
- ol.render.canvas.TextReplay.prototype.drawTextImage_ = function(label, begin, end) {
- var textState = this.textState_;
- var strokeState = this.textStrokeState_;
- var pixelRatio = this.pixelRatio;
- var align = ol.render.replay.TEXT_ALIGN[textState.textAlign || ol.render.canvas.defaultTextAlign];
- var baseline = ol.render.replay.TEXT_ALIGN[textState.textBaseline];
- var strokeWidth = strokeState && strokeState.lineWidth ? strokeState.lineWidth : 0;
- var anchorX = align * label.width / pixelRatio + 2 * (0.5 - align) * strokeWidth;
- var anchorY = baseline * label.height / pixelRatio + 2 * (0.5 - baseline) * strokeWidth;
- this.instructions.push([ol.render.canvas.Instruction.DRAW_IMAGE, begin, end,
- label, (anchorX - this.textOffsetX_) * pixelRatio, (anchorY - this.textOffsetY_) * pixelRatio,
- this.declutterGroup_, label.height, 1, 0, 0, this.textRotateWithView_, this.textRotation_,
- 1, true, label.width,
- textState.padding == ol.render.canvas.defaultPadding ?
- ol.render.canvas.defaultPadding : textState.padding.map(function(p) {
- return p * pixelRatio;
- }),
- !!textState.backgroundFill, !!textState.backgroundStroke
- ]);
- this.hitDetectionInstructions.push([ol.render.canvas.Instruction.DRAW_IMAGE, begin, end,
- label, (anchorX - this.textOffsetX_) * pixelRatio, (anchorY - this.textOffsetY_) * pixelRatio,
- this.declutterGroup_, label.height, 1, 0, 0, this.textRotateWithView_, this.textRotation_,
- 1 / pixelRatio, true, label.width, textState.padding,
- !!textState.backgroundFill, !!textState.backgroundStroke
- ]);
- };
- /**
- * @private
- * @param {number} begin Begin.
- * @param {number} end End.
- * @param {ol.DeclutterGroup} declutterGroup Declutter group.
- */
- ol.render.canvas.TextReplay.prototype.drawChars_ = function(begin, end, declutterGroup) {
- var strokeState = this.textStrokeState_;
- var textState = this.textState_;
- var fillState = this.textFillState_;
- var strokeKey = this.strokeKey_;
- if (strokeState) {
- if (!(strokeKey in this.strokeStates)) {
- this.strokeStates[strokeKey] = /** @type {ol.CanvasStrokeState} */ ({
- strokeStyle: strokeState.strokeStyle,
- lineCap: strokeState.lineCap,
- lineDashOffset: strokeState.lineDashOffset,
- lineWidth: strokeState.lineWidth,
- lineJoin: strokeState.lineJoin,
- miterLimit: strokeState.miterLimit,
- lineDash: strokeState.lineDash
- });
- }
- }
- var textKey = this.textKey_;
- if (!(this.textKey_ in this.textStates)) {
- this.textStates[this.textKey_] = /** @type {ol.CanvasTextState} */ ({
- font: textState.font,
- textAlign: textState.textAlign || ol.render.canvas.defaultTextAlign,
- scale: textState.scale
- });
- }
- var fillKey = this.fillKey_;
- if (fillState) {
- if (!(fillKey in this.fillStates)) {
- this.fillStates[fillKey] = /** @type {ol.CanvasFillState} */ ({
- fillStyle: fillState.fillStyle
- });
- }
- }
- var pixelRatio = this.pixelRatio;
- var baseline = ol.render.replay.TEXT_ALIGN[textState.textBaseline];
- var offsetY = this.textOffsetY_ * pixelRatio;
- var text = this.text_;
- var font = textState.font;
- var textScale = textState.scale;
- var strokeWidth = strokeState ? strokeState.lineWidth * textScale / 2 : 0;
- var widths = this.widths_[font];
- if (!widths) {
- this.widths_[font] = widths = {};
- }
- this.instructions.push([ol.render.canvas.Instruction.DRAW_CHARS,
- begin, end, baseline, declutterGroup,
- textState.overflow, fillKey, textState.maxAngle,
- function(text) {
- var width = widths[text];
- if (!width) {
- width = widths[text] = ol.render.canvas.measureTextWidth(font, text);
- }
- return width * textScale * pixelRatio;
- },
- offsetY, strokeKey, strokeWidth * pixelRatio, text, textKey, 1
- ]);
- this.hitDetectionInstructions.push([ol.render.canvas.Instruction.DRAW_CHARS,
- begin, end, baseline, declutterGroup,
- textState.overflow, fillKey, textState.maxAngle,
- function(text) {
- var width = widths[text];
- if (!width) {
- width = widths[text] = ol.render.canvas.measureTextWidth(font, text);
- }
- return width * textScale;
- },
- offsetY, strokeKey, strokeWidth, text, textKey, 1 / pixelRatio
- ]);
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.TextReplay.prototype.setTextStyle = function(textStyle, declutterGroup) {
- var textState, fillState, strokeState;
- if (!textStyle) {
- this.text_ = '';
- } else {
- this.declutterGroup_ = /** @type {ol.DeclutterGroup} */ (declutterGroup);
- var textFillStyle = textStyle.getFill();
- if (!textFillStyle) {
- fillState = this.textFillState_ = null;
- } else {
- fillState = this.textFillState_;
- if (!fillState) {
- fillState = this.textFillState_ = /** @type {ol.CanvasFillState} */ ({});
- }
- fillState.fillStyle = ol.colorlike.asColorLike(
- textFillStyle.getColor() || ol.render.canvas.defaultFillStyle);
- }
- var textStrokeStyle = textStyle.getStroke();
- if (!textStrokeStyle) {
- strokeState = this.textStrokeState_ = null;
- } else {
- strokeState = this.textStrokeState_;
- if (!strokeState) {
- strokeState = this.textStrokeState_ = /** @type {ol.CanvasStrokeState} */ ({});
- }
- var lineDash = textStrokeStyle.getLineDash();
- var lineDashOffset = textStrokeStyle.getLineDashOffset();
- var lineWidth = textStrokeStyle.getWidth();
- var miterLimit = textStrokeStyle.getMiterLimit();
- strokeState.lineCap = textStrokeStyle.getLineCap() || ol.render.canvas.defaultLineCap;
- strokeState.lineDash = lineDash ? lineDash.slice() : ol.render.canvas.defaultLineDash;
- strokeState.lineDashOffset =
- lineDashOffset === undefined ? ol.render.canvas.defaultLineDashOffset : lineDashOffset;
- strokeState.lineJoin = textStrokeStyle.getLineJoin() || ol.render.canvas.defaultLineJoin;
- strokeState.lineWidth =
- lineWidth === undefined ? ol.render.canvas.defaultLineWidth : lineWidth;
- strokeState.miterLimit =
- miterLimit === undefined ? ol.render.canvas.defaultMiterLimit : miterLimit;
- strokeState.strokeStyle = ol.colorlike.asColorLike(
- textStrokeStyle.getColor() || ol.render.canvas.defaultStrokeStyle);
- }
- textState = this.textState_;
- var font = textStyle.getFont() || ol.render.canvas.defaultFont;
- //ol.render.canvas.checkFont(font); // FIXME sunyl
- var textScale = textStyle.getScale();
- textState.overflow = textStyle.getOverflow();
- textState.font = font;
- textState.maxAngle = textStyle.getMaxAngle();
- textState.placement = textStyle.getPlacement();
- textState.textAlign = textStyle.getTextAlign();
- textState.textBaseline = textStyle.getTextBaseline() || ol.render.canvas.defaultTextBaseline;
- textState.backgroundFill = textStyle.getBackgroundFill();
- textState.backgroundStroke = textStyle.getBackgroundStroke();
- textState.padding = textStyle.getPadding() || ol.render.canvas.defaultPadding;
- textState.scale = textScale === undefined ? 1 : textScale;
- var textOffsetX = textStyle.getOffsetX();
- var textOffsetY = textStyle.getOffsetY();
- var textRotateWithView = textStyle.getRotateWithView();
- var textRotation = textStyle.getRotation();
- this.text_ = textStyle.getText() || '';
- this.textOffsetX_ = textOffsetX === undefined ? 0 : textOffsetX;
- this.textOffsetY_ = textOffsetY === undefined ? 0 : textOffsetY;
- this.textRotateWithView_ = textRotateWithView === undefined ? false : textRotateWithView;
- this.textRotation_ = textRotation === undefined ? 0 : textRotation;
- this.strokeKey_ = strokeState ?
- (typeof strokeState.strokeStyle == 'string' ? strokeState.strokeStyle : ol.getUid(strokeState.strokeStyle)) +
- strokeState.lineCap + strokeState.lineDashOffset + '|' + strokeState.lineWidth +
- strokeState.lineJoin + strokeState.miterLimit + '[' + strokeState.lineDash.join() + ']' :
- '';
- this.textKey_ = textState.font + textState.scale + (textState.textAlign || '?');
- this.fillKey_ = fillState ?
- (typeof fillState.fillStyle == 'string' ? fillState.fillStyle : ('|' + ol.getUid(fillState.fillStyle))) :
- '';
- }
- };
- /**
- * @constructor
- * @extends {ol.render.ReplayGroup}
- * @param {number} tolerance Tolerance.
- * @param {ol.Extent} maxExtent Max extent.
- * @param {number} resolution Resolution.
- * @param {number} pixelRatio Pixel ratio.
- * @param {boolean} overlaps The replay group can have overlapping geometries.
- * @param {?} declutterTree Declutter tree
- * for declutter processing in postrender.
- * @param {number=} opt_renderBuffer Optional rendering buffer.
- * @struct
- */
- ol.render.canvas.ReplayGroup = function(
- tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree, opt_renderBuffer) {
- ol.render.ReplayGroup.call(this);
- /**
- * Declutter tree.
- * @private
- */
- this.declutterTree_ = declutterTree;
- /**
- * @type {ol.DeclutterGroup}
- * @private
- */
- this.declutterGroup_ = null;
- /**
- * @private
- * @type {number}
- */
- this.tolerance_ = tolerance;
- /**
- * @private
- * @type {ol.Extent}
- */
- this.maxExtent_ = maxExtent;
- /**
- * @private
- * @type {boolean}
- */
- this.overlaps_ = overlaps;
- /**
- * @private
- * @type {number}
- */
- this.pixelRatio_ = pixelRatio;
- /**
- * @private
- * @type {number}
- */
- this.resolution_ = resolution;
- /**
- * @private
- * @type {number|undefined}
- */
- this.renderBuffer_ = opt_renderBuffer;
- /**
- * @private
- * @type {!Object.<string,
- * Object.<ol.render.ReplayType, ol.render.canvas.Replay>>}
- */
- this.replaysByZIndex_ = {};
- /**
- * @private
- * @type {CanvasRenderingContext2D}
- */
- // FIXME
- this.hitDetectionContext_ = null;
- /**
- * @private
- * @type {ol.Transform}
- */
- this.hitDetectionTransform_ = ol.transform.create();
- };
- ol.inherits(ol.render.canvas.ReplayGroup, ol.render.ReplayGroup);
- /**
- * This cache is used for storing calculated pixel circles for increasing performance.
- * It is a static property to allow each Replaygroup to access it.
- * @type {Object.<number, Array.<Array.<(boolean|undefined)>>>}
- * @private
- */
- ol.render.canvas.ReplayGroup.circleArrayCache_ = {
- 0: [[true]]
- };
- /**
- * This method fills a row in the array from the given coordinate to the
- * middle with `true`.
- * @param {Array.<Array.<(boolean|undefined)>>} array The array that will be altered.
- * @param {number} x X coordinate.
- * @param {number} y Y coordinate.
- * @private
- */
- ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_ = function(array, x, y) {
- var i;
- var radius = Math.floor(array.length / 2);
- if (x >= radius) {
- for (i = radius; i < x; i++) {
- array[i][y] = true;
- }
- } else if (x < radius) {
- for (i = x + 1; i < radius; i++) {
- array[i][y] = true;
- }
- }
- };
- /**
- * This methods creates a circle inside a fitting array. Points inside the
- * circle are marked by true, points on the outside are undefined.
- * It uses the midpoint circle algorithm.
- * A cache is used to increase performance.
- * @param {number} radius Radius.
- * @returns {Array.<Array.<(boolean|undefined)>>} An array with marked circle points.
- * @private
- */
- ol.render.canvas.ReplayGroup.getCircleArray_ = function(radius) {
- if (ol.render.canvas.ReplayGroup.circleArrayCache_[radius] !== undefined) {
- return ol.render.canvas.ReplayGroup.circleArrayCache_[radius];
- }
- var arraySize = radius * 2 + 1;
- var arr = new Array(arraySize);
- for (var i = 0; i < arraySize; i++) {
- arr[i] = new Array(arraySize);
- }
- var x = radius;
- var y = 0;
- var error = 0;
- while (x >= y) {
- ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + x, radius + y);
- ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + y, radius + x);
- ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - y, radius + x);
- ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - x, radius + y);
- ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - x, radius - y);
- ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - y, radius - x);
- ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + y, radius - x);
- ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + x, radius - y);
- y++;
- error += 1 + 2 * y;
- if (2 * (error - x) + 1 > 0) {
- x -= 1;
- error += 1 - 2 * x;
- }
- }
- ol.render.canvas.ReplayGroup.circleArrayCache_[radius] = arr;
- return arr;
- };
- /**
- * @param {!Object.<string, Array.<*>>} declutterReplays Declutter replays.
- * @param {CanvasRenderingContext2D} context Context.
- * @param {number} rotation Rotation.
- */
- ol.render.canvas.ReplayGroup.replayDeclutter = function(declutterReplays, context, rotation) {
- var zs = Object.keys(declutterReplays).map(Number).sort(ol.array.numberSafeCompareFunction);
- var skippedFeatureUids = {};
- for (var z = 0, zz = zs.length; z < zz; ++z) {
- var replayData = declutterReplays[zs[z].toString()];
- for (var i = 0, ii = replayData.length; i < ii;) {
- var replay = replayData[i++];
- var transform = replayData[i++];
- replay.replay(context, transform, rotation, skippedFeatureUids);
- }
- }
- };
- /**
- * @param {boolean} group Group with previous replay.
- * @return {ol.DeclutterGroup} Declutter instruction group.
- */
- ol.render.canvas.ReplayGroup.prototype.addDeclutter = function(group) {
- var declutter = null;
- if (this.declutterTree_) {
- if (group) {
- declutter = this.declutterGroup_;
- /** @type {number} */ (declutter[4])++;
- } else {
- declutter = this.declutterGroup_ = ol.extent.createEmpty();
- declutter.push(1);
- }
- }
- return declutter;
- };
- /**
- * @param {CanvasRenderingContext2D} context Context.
- * @param {ol.Transform} transform Transform.
- */
- ol.render.canvas.ReplayGroup.prototype.clip = function(context, transform) {
- var flatClipCoords = this.getClipCoords(transform);
- context.beginPath();
- context.moveTo(flatClipCoords[0], flatClipCoords[1]);
- context.lineTo(flatClipCoords[2], flatClipCoords[3]);
- context.lineTo(flatClipCoords[4], flatClipCoords[5]);
- context.lineTo(flatClipCoords[6], flatClipCoords[7]);
- context.clip();
- };
- /**
- * @param {Array.<ol.render.ReplayType>} replays Replays.
- * @return {boolean} Has replays of the provided types.
- */
- ol.render.canvas.ReplayGroup.prototype.hasReplays = function(replays) {
- for (var zIndex in this.replaysByZIndex_) {
- var candidates = this.replaysByZIndex_[zIndex];
- for (var i = 0, ii = replays.length; i < ii; ++i) {
- if (replays[i] in candidates) {
- return true;
- }
- }
- }
- return false;
- };
- /**
- * FIXME empty description for jsdoc
- */
- ol.render.canvas.ReplayGroup.prototype.finish = function() {
- var zKey;
- for (zKey in this.replaysByZIndex_) {
- var replays = this.replaysByZIndex_[zKey];
- var replayKey;
- for (replayKey in replays) {
- replays[replayKey].finish();
- }
- }
- };
- /**
- * @param {ol.Coordinate} coordinate Coordinate.
- * @param {number} resolution Resolution.
- * @param {number} rotation Rotation.
- * @param {number} hitTolerance Hit tolerance in pixels.
- * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
- * to skip.
- * @param {function((ol.Feature|ol.render.Feature)): T} callback Feature
- * callback.
- * @param {Object.<string, ol.DeclutterGroup>} declutterReplays Declutter
- * replays.
- * @return {T|undefined} Callback result.
- * @template T
- */
- ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
- coordinate, resolution, rotation, hitTolerance, skippedFeaturesHash, callback, declutterReplays) {
- hitTolerance = Math.round(hitTolerance);
- var contextSize = hitTolerance * 2 + 1;
- var transform = ol.transform.compose(this.hitDetectionTransform_,
- hitTolerance + 0.5, hitTolerance + 0.5,
- 1 / resolution, -1 / resolution,
- -rotation,
- -coordinate[0], -coordinate[1]);
- var context = this.hitDetectionContext_;
- if (context.canvas.width !== contextSize || context.canvas.height !== contextSize) {
- context.canvas.width = contextSize;
- context.canvas.height = contextSize;
- } else {
- context.clearRect(0, 0, contextSize, contextSize);
- }
- /**
- * @type {ol.Extent}
- */
- var hitExtent;
- if (this.renderBuffer_ !== undefined) {
- hitExtent = ol.extent.createEmpty();
- ol.extent.extendCoordinate(hitExtent, coordinate);
- ol.extent.buffer(hitExtent, resolution * (this.renderBuffer_ + hitTolerance), hitExtent);
- }
- var mask = ol.render.canvas.ReplayGroup.getCircleArray_(hitTolerance);
- var declutteredFeatures;
- if (this.declutterTree_) {
- declutteredFeatures = this.declutterTree_.all().map(function(entry) {
- return entry.value;
- });
- }
- var replayType;
- /**
- * @param {ol.Feature|ol.render.Feature} feature Feature.
- * @return {?} Callback result.
- */
- function featureCallback(feature) {
- var imageData = context.getImageData(0, 0, contextSize, contextSize).data;
- for (var i = 0; i < contextSize; i++) {
- for (var j = 0; j < contextSize; j++) {
- if (mask[i][j]) {
- if (imageData[(j * contextSize + i) * 4 + 3] > 0) {
- var result;
- if (!(declutteredFeatures && (replayType == ol.render.ReplayType.IMAGE || replayType == ol.render.ReplayType.TEXT)) ||
- declutteredFeatures.indexOf(feature) !== -1) {
- result = callback(feature);
- }
- if (result) {
- return result;
- } else {
- context.clearRect(0, 0, contextSize, contextSize);
- return undefined;
- }
- }
- }
- }
- }
- }
- /** @type {Array.<number>} */
- var zs = Object.keys(this.replaysByZIndex_).map(Number);
- zs.sort(ol.array.numberSafeCompareFunction);
- var i, j, replays, replay, result;
- for (i = zs.length - 1; i >= 0; --i) {
- var zIndexKey = zs[i].toString();
- replays = this.replaysByZIndex_[zIndexKey];
- for (j = ol.render.replay.ORDER.length - 1; j >= 0; --j) {
- replayType = ol.render.replay.ORDER[j];
- replay = replays[replayType];
- if (replay !== undefined) {
- if (declutterReplays &&
- (replayType == ol.render.ReplayType.IMAGE || replayType == ol.render.ReplayType.TEXT)) {
- var declutter = declutterReplays[zIndexKey];
- if (!declutter) {
- declutterReplays[zIndexKey] = [replay, transform.slice(0)];
- } else {
- declutter.push(replay, transform.slice(0));
- }
- } else {
- result = replay.replayHitDetection(context, transform, rotation,
- skippedFeaturesHash, featureCallback, hitExtent);
- if (result) {
- return result;
- }
- }
- }
- }
- }
- return undefined;
- };
- /**
- * @param {ol.Transform} transform Transform.
- * @return {Array.<number>} Clip coordinates.
- */
- ol.render.canvas.ReplayGroup.prototype.getClipCoords = function(transform) {
- var maxExtent = this.maxExtent_;
- var minX = maxExtent[0];
- var minY = maxExtent[1];
- var maxX = maxExtent[2];
- var maxY = maxExtent[3];
- var flatClipCoords = [minX, minY, minX, maxY, maxX, maxY, maxX, minY];
- ol.geom.flat.transform.transform2D(
- flatClipCoords, 0, 8, 2, transform, flatClipCoords);
- return flatClipCoords;
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.ReplayGroup.prototype.getReplay = function(zIndex, replayType) {
- var zIndexKey = zIndex !== undefined ? zIndex.toString() : '0';
- var replays = this.replaysByZIndex_[zIndexKey];
- if (replays === undefined) {
- replays = {};
- this.replaysByZIndex_[zIndexKey] = replays;
- }
- var replay = replays[replayType];
- if (replay === undefined) {
- var Constructor = ol.render.canvas.ReplayGroup.BATCH_CONSTRUCTORS_[replayType];
- replay = new Constructor(this.tolerance_, this.maxExtent_,
- this.resolution_, this.pixelRatio_, this.overlaps_, this.declutterTree_);
- replays[replayType] = replay;
- }
- return replay;
- };
- /**
- * @return {Object.<string, Object.<ol.render.ReplayType, ol.render.canvas.Replay>>} Replays.
- */
- ol.render.canvas.ReplayGroup.prototype.getReplays = function() {
- return this.replaysByZIndex_;
- };
- /**
- * @inheritDoc
- */
- ol.render.canvas.ReplayGroup.prototype.isEmpty = function() {
- return ol.obj.isEmpty(this.replaysByZIndex_);
- };
- /**
- * @param {CanvasRenderingContext2D} context Context.
- * @param {ol.Transform} transform Transform.
- * @param {number} viewRotation View rotation.
- * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
- * to skip.
- * @param {Array.<ol.render.ReplayType>=} opt_replayTypes Ordered replay types
- * to replay. Default is {@link ol.render.replay.ORDER}
- * @param {Object.<string, ol.DeclutterGroup>=} opt_declutterReplays Declutter
- * replays.
- */
- ol.render.canvas.ReplayGroup.prototype.replay = function(context,
- transform, viewRotation, skippedFeaturesHash, opt_replayTypes, opt_declutterReplays) {
- /** @type {Array.<number>} */
- var zs = Object.keys(this.replaysByZIndex_).map(Number);
- zs.sort(ol.array.numberSafeCompareFunction);
- // setup clipping so that the parts of over-simplified geometries are not
- // visible outside the current extent when panning
- context.save();
- this.clip(context, transform);
- var replayTypes = opt_replayTypes ? opt_replayTypes : ol.render.replay.ORDER;
- var i, ii, j, jj, replays, replay;
- for (i = 0, ii = zs.length; i < ii; ++i) {
- var zIndexKey = zs[i].toString();
- replays = this.replaysByZIndex_[zIndexKey];
- for (j = 0, jj = replayTypes.length; j < jj; ++j) {
- var replayType = replayTypes[j];
- replay = replays[replayType];
- if (replay !== undefined) {
- if (opt_declutterReplays &&
- (replayType == ol.render.ReplayType.IMAGE || replayType == ol.render.ReplayType.TEXT)) {
- var declutter = opt_declutterReplays[zIndexKey];
- if (!declutter) {
- opt_declutterReplays[zIndexKey] = [replay, transform.slice(0)];
- } else {
- declutter.push(replay, transform.slice(0));
- }
- } else {
- replay.replay(context, transform, viewRotation, skippedFeaturesHash);
- }
- }
- }
- }
- context.restore();
- };
- /**
- * @const
- * @private
- * @type {Object.<ol.render.ReplayType,
- * function(new: ol.render.canvas.Replay, number, ol.Extent,
- * number, number, boolean, Array.<ol.DeclutterGroup>)>}
- */
- ol.render.canvas.ReplayGroup.BATCH_CONSTRUCTORS_ = {
- 'Circle': ol.render.canvas.PolygonReplay,
- 'Default': ol.render.canvas.Replay,
- 'Image': ol.render.canvas.ImageReplay,
- 'LineString': ol.render.canvas.LineStringReplay,
- 'Polygon': ol.render.canvas.PolygonReplay,
- 'Text': ol.render.canvas.TextReplay
- };
- ol.renderer = {};
- ol.renderer.vector = {};
- /**
- * @param {ol.Feature|ol.render.Feature} feature1 Feature 1.
- * @param {ol.Feature|ol.render.Feature} feature2 Feature 2.
- * @return {number} Order.
- */
- ol.renderer.vector.defaultOrder = function(feature1, feature2) {
- return ol.getUid(feature1) - ol.getUid(feature2);
- };
- /**
- * @param {number} resolution Resolution.
- * @param {number} pixelRatio Pixel ratio.
- * @return {number} Squared pixel tolerance.
- */
- ol.renderer.vector.getSquaredTolerance = function(resolution, pixelRatio) {
- var tolerance = ol.renderer.vector.getTolerance(resolution, pixelRatio);
- return tolerance * tolerance;
- };
- /**
- * @param {number} resolution Resolution.
- * @param {number} pixelRatio Pixel ratio.
- * @return {number} Pixel tolerance.
- */
- ol.renderer.vector.getTolerance = function(resolution, pixelRatio) {
- return ol.SIMPLIFY_TOLERANCE * resolution / pixelRatio;
- };
- /**
- * @param {ol.render.ReplayGroup} replayGroup Replay group.
- * @param {ol.geom.Circle} geometry Geometry.
- * @param {ol.style.Style} style Style.
- * @param {ol.Feature} feature Feature.
- * @private
- */
- ol.renderer.vector.renderCircleGeometry_ = function(replayGroup, geometry, style, feature) {
- var fillStyle = style.getFill();
- var strokeStyle = style.getStroke();
- if (fillStyle || strokeStyle) {
- var circleReplay = replayGroup.getReplay(
- style.getZIndex(), ol.render.ReplayType.CIRCLE);
- circleReplay.setFillStrokeStyle(fillStyle, strokeStyle);
- circleReplay.drawCircle(geometry, feature);
- }
- var textStyle = style.getText();
- if (textStyle) {
- var textReplay = replayGroup.getReplay(
- style.getZIndex(), ol.render.ReplayType.TEXT);
- textReplay.setTextStyle(textStyle, replayGroup.addDeclutter(false));
- textReplay.drawText(geometry, feature);
- }
- };
- /**
- * @param {ol.render.ReplayGroup} replayGroup Replay group.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
- * @param {ol.style.Style} style Style.
- * @param {number} squaredTolerance Squared tolerance.
- * @param {function(this: T, ol.events.Event)} listener Listener function.
- * @param {T} thisArg Value to use as `this` when executing `listener`.
- * @return {boolean} `true` if style is loading.
- * @template T
- */
- ol.renderer.vector.renderFeature = function(
- replayGroup, feature, style, squaredTolerance, listener, thisArg) {
- var loading = false;
- var imageStyle, imageState;
- imageStyle = style.getImage();
- if (imageStyle) {
- imageState = imageStyle.getImageState();
- if (imageState == ol.ImageState.LOADED ||
- imageState == ol.ImageState.ERROR) {
- imageStyle.unlistenImageChange(listener, thisArg);
- } else {
- if (imageState == ol.ImageState.IDLE) {
- imageStyle.load();
- }
- imageState = imageStyle.getImageState();
- imageStyle.listenImageChange(listener, thisArg);
- loading = true;
- }
- }
- ol.renderer.vector.renderFeature_(replayGroup, feature, style,
- squaredTolerance);
- return loading;
- };
- /**
- * @param {ol.render.ReplayGroup} replayGroup Replay group.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
- * @param {ol.style.Style} style Style.
- * @param {number} squaredTolerance Squared tolerance.
- * @private
- */
- ol.renderer.vector.renderFeature_ = function(
- replayGroup, feature, style, squaredTolerance) {
- var geometry = style.getGeometryFunction()(feature);
- if (!geometry) {
- return;
- }
- var simplifiedGeometry = geometry.getSimplifiedGeometry(squaredTolerance);
- var renderer = style.getRenderer();
- if (renderer) {
- ol.renderer.vector.renderGeometry_(replayGroup, simplifiedGeometry, style, feature);
- } else {
- var geometryRenderer =
- ol.renderer.vector.GEOMETRY_RENDERERS_[simplifiedGeometry.getType()];
- geometryRenderer(replayGroup, simplifiedGeometry, style, feature);
- }
- };
- /**
- * @param {ol.render.ReplayGroup} replayGroup Replay group.
- * @param {ol.geom.Geometry} geometry Geometry.
- * @param {ol.style.Style} style Style.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
- * @private
- */
- ol.renderer.vector.renderGeometry_ = function(replayGroup, geometry, style, feature) {
- if (geometry.getType() == ol.geom.GeometryType.GEOMETRY_COLLECTION) {
- var geometries = /** @type {ol.geom.GeometryCollection} */ (geometry).getGeometries();
- for (var i = 0, ii = geometries.length; i < ii; ++i) {
- ol.renderer.vector.renderGeometry_(replayGroup, geometries[i], style, feature);
- }
- return;
- }
- var replay = replayGroup.getReplay(style.getZIndex(), ol.render.ReplayType.DEFAULT);
- replay.drawCustom(/** @type {ol.geom.SimpleGeometry} */ (geometry), feature, style.getRenderer());
- };
- /**
- * @param {ol.render.ReplayGroup} replayGroup Replay group.
- * @param {ol.geom.GeometryCollection} geometry Geometry.
- * @param {ol.style.Style} style Style.
- * @param {ol.Feature} feature Feature.
- * @private
- */
- ol.renderer.vector.renderGeometryCollectionGeometry_ = function(replayGroup, geometry, style, feature) {
- var geometries = geometry.getGeometriesArray();
- var i, ii;
- for (i = 0, ii = geometries.length; i < ii; ++i) {
- var geometryRenderer =
- ol.renderer.vector.GEOMETRY_RENDERERS_[geometries[i].getType()];
- geometryRenderer(replayGroup, geometries[i], style, feature);
- }
- };
- /**
- * @param {ol.render.ReplayGroup} replayGroup Replay group.
- * @param {ol.geom.LineString|ol.render.Feature} geometry Geometry.
- * @param {ol.style.Style} style Style.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
- * @private
- */
- ol.renderer.vector.renderLineStringGeometry_ = function(replayGroup, geometry, style, feature) {
- var strokeStyle = style.getStroke();
- if (strokeStyle) {
- var lineStringReplay = replayGroup.getReplay(
- style.getZIndex(), ol.render.ReplayType.LINE_STRING);
- lineStringReplay.setFillStrokeStyle(null, strokeStyle);
- lineStringReplay.drawLineString(geometry, feature);
- }
- var textStyle = style.getText();
- if (textStyle) {
- var textReplay = replayGroup.getReplay(
- style.getZIndex(), ol.render.ReplayType.TEXT);
- textReplay.setTextStyle(textStyle, replayGroup.addDeclutter(false));
- textReplay.drawText(geometry, feature);
- }
- };
- /**
- * @param {ol.render.ReplayGroup} replayGroup Replay group.
- * @param {ol.geom.MultiLineString|ol.render.Feature} geometry Geometry.
- * @param {ol.style.Style} style Style.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
- * @private
- */
- ol.renderer.vector.renderMultiLineStringGeometry_ = function(replayGroup, geometry, style, feature) {
- var strokeStyle = style.getStroke();
- if (strokeStyle) {
- var lineStringReplay = replayGroup.getReplay(
- style.getZIndex(), ol.render.ReplayType.LINE_STRING);
- lineStringReplay.setFillStrokeStyle(null, strokeStyle);
- lineStringReplay.drawMultiLineString(geometry, feature);
- }
- var textStyle = style.getText();
- if (textStyle) {
- var textReplay = replayGroup.getReplay(
- style.getZIndex(), ol.render.ReplayType.TEXT);
- textReplay.setTextStyle(textStyle, replayGroup.addDeclutter(false));
- textReplay.drawText(geometry, feature);
- }
- };
- /**
- * @param {ol.render.ReplayGroup} replayGroup Replay group.
- * @param {ol.geom.MultiPolygon} geometry Geometry.
- * @param {ol.style.Style} style Style.
- * @param {ol.Feature} feature Feature.
- * @private
- */
- ol.renderer.vector.renderMultiPolygonGeometry_ = function(replayGroup, geometry, style, feature) {
- var fillStyle = style.getFill();
- var strokeStyle = style.getStroke();
- if (strokeStyle || fillStyle) {
- var polygonReplay = replayGroup.getReplay(
- style.getZIndex(), ol.render.ReplayType.POLYGON);
- polygonReplay.setFillStrokeStyle(fillStyle, strokeStyle);
- polygonReplay.drawMultiPolygon(geometry, feature);
- }
- var textStyle = style.getText();
- if (textStyle) {
- var textReplay = replayGroup.getReplay(
- style.getZIndex(), ol.render.ReplayType.TEXT);
- textReplay.setTextStyle(textStyle, replayGroup.addDeclutter(false));
- textReplay.drawText(geometry, feature);
- }
- };
- /**
- * @param {ol.render.ReplayGroup} replayGroup Replay group.
- * @param {ol.geom.Point|ol.render.Feature} geometry Geometry.
- * @param {ol.style.Style} style Style.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
- * @private
- */
- ol.renderer.vector.renderPointGeometry_ = function(replayGroup, geometry, style, feature) {
- var imageStyle = style.getImage();
- if (imageStyle) {
- if (imageStyle.getImageState() != ol.ImageState.LOADED) {
- return;
- }
- var imageReplay = replayGroup.getReplay(
- style.getZIndex(), ol.render.ReplayType.IMAGE);
- imageReplay.setImageStyle(imageStyle, replayGroup.addDeclutter(false));
- imageReplay.drawPoint(geometry, feature);
- }
- var textStyle = style.getText();
- if (textStyle) {
- var textReplay = replayGroup.getReplay(
- style.getZIndex(), ol.render.ReplayType.TEXT);
- textReplay.setTextStyle(textStyle, replayGroup.addDeclutter(!!imageStyle));
- textReplay.drawText(geometry, feature);
- }
- };
- /**
- * @param {ol.render.ReplayGroup} replayGroup Replay group.
- * @param {ol.geom.MultiPoint|ol.render.Feature} geometry Geometry.
- * @param {ol.style.Style} style Style.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
- * @private
- */
- ol.renderer.vector.renderMultiPointGeometry_ = function(replayGroup, geometry, style, feature) {
- var imageStyle = style.getImage();
- if (imageStyle) {
- if (imageStyle.getImageState() != ol.ImageState.LOADED) {
- return;
- }
- var imageReplay = replayGroup.getReplay(
- style.getZIndex(), ol.render.ReplayType.IMAGE);
- imageReplay.setImageStyle(imageStyle, replayGroup.addDeclutter(false));
- imageReplay.drawMultiPoint(geometry, feature);
- }
- var textStyle = style.getText();
- if (textStyle) {
- var textReplay = replayGroup.getReplay(
- style.getZIndex(), ol.render.ReplayType.TEXT);
- textReplay.setTextStyle(textStyle, replayGroup.addDeclutter(!!imageStyle));
- textReplay.drawText(geometry, feature);
- }
- };
- /**
- * @param {ol.render.ReplayGroup} replayGroup Replay group.
- * @param {ol.geom.Polygon|ol.render.Feature} geometry Geometry.
- * @param {ol.style.Style} style Style.
- * @param {ol.Feature|ol.render.Feature} feature Feature.
- * @private
- */
- ol.renderer.vector.renderPolygonGeometry_ = function(replayGroup, geometry, style, feature) {
- var fillStyle = style.getFill();
- var strokeStyle = style.getStroke();
- if (fillStyle || strokeStyle) {
- var polygonReplay = replayGroup.getReplay(
- style.getZIndex(), ol.render.ReplayType.POLYGON);
- polygonReplay.setFillStrokeStyle(fillStyle, strokeStyle);
- polygonReplay.drawPolygon(geometry, feature);
- }
- var textStyle = style.getText();
- if (textStyle) {
- var textReplay = replayGroup.getReplay(
- style.getZIndex(), ol.render.ReplayType.TEXT);
- textReplay.setTextStyle(textStyle, replayGroup.addDeclutter(false));
- textReplay.drawText(geometry, feature);
- }
- };
- /**
- * @const
- * @private
- * @type {Object.<ol.geom.GeometryType,
- * function(ol.render.ReplayGroup, ol.geom.Geometry,
- * ol.style.Style, Object)>}
- */
- ol.renderer.vector.GEOMETRY_RENDERERS_ = {
- 'Point': ol.renderer.vector.renderPointGeometry_,
- 'LineString': ol.renderer.vector.renderLineStringGeometry_,
- 'Polygon': ol.renderer.vector.renderPolygonGeometry_,
- 'MultiPoint': ol.renderer.vector.renderMultiPointGeometry_,
- 'MultiLineString': ol.renderer.vector.renderMultiLineStringGeometry_,
- 'MultiPolygon': ol.renderer.vector.renderMultiPolygonGeometry_,
- 'GeometryCollection': ol.renderer.vector.renderGeometryCollectionGeometry_,
- 'Circle': ol.renderer.vector.renderCircleGeometry_
- };
- var spriteImageCanvas = {};
- var mvtStyleClass = new MvtStyle(ol, true);
- var mvtRenderer2D = new MvtRenderer2D({
- mvtStyle: mvtStyleClass,
- openlayer: ol,
- useOffscreen: true
- });
- function MVTWorker(parameters, transferableObjects) {
- var canvas = new OffscreenCanvas(parameters.canvasWidth, parameters.canvasWidth);
- var idCanvas = new OffscreenCanvas(parameters.canvasWidth, parameters.canvasWidth);
- var pbfData = parameters.pbfData;
- var layers = parameters.layers;
- var transform = parameters.transform;
- var squaredTolerance = parameters.squaredTolerance;
- var spriteImageDatas = parameters.spriteImageDatas;
- var keepProperties = parameters.keepProperties;
- var tileLevel = parameters.tileLevel;
- var needSourceLayerNames = parameters.needSourceLayerNames;
- var selectEnabled = parameters.selectEnabled;
- var featureProperties = {};
- try {
- var mvtParser = new ol.format.MVT({
- featureClass: ol.Feature
- });
- var features = mvtParser.readFeatures(pbfData, {
- needSourceLayerNames: needSourceLayerNames
- });
- var renderResult = mvtRenderer2D.renderFeatures({
- colorCanvas: canvas,
- idCanvas: idCanvas,
- transform: transform,
- layers: layers,
- features: features,
- tileLevel: tileLevel,
- spriteImageCanvas: spriteImageCanvas,
- spriteImageDatas: spriteImageDatas,
- squaredTolerance: squaredTolerance,
- selectEnabled: selectEnabled,
- showBillboard: false
- });
- if (keepProperties) {
- var featuresToRender = renderResult.idFeatures;
- var featuresToRenderLength = featuresToRender.length;
- for (var i = 0; i < featuresToRenderLength; i++) {
- var feature = featuresToRender[i];
- var featureID = getFeatureID$1(feature);
- var propertiesWithoutGeometry = feature.getProperties();
- if (when.defined(propertiesWithoutGeometry.geometry)) {
- delete propertiesWithoutGeometry.geometry;
- }
- featureProperties[featureID] = propertiesWithoutGeometry;
- }
- }
- }
- catch (err) {
- }
- var imageBitmap = canvas.transferToImageBitmap();
- var idImageBitmap = selectEnabled ? idCanvas.transferToImageBitmap() : null;
- transferableObjects.push(imageBitmap);
- return {
- buffer: imageBitmap,
- idBuffer: idImageBitmap,
- properties: featureProperties
- };
- }
- function getFeatureID$1(feature) {
- var id = feature.getId();
- // 只在颜色中记录256*256*256这么大范围的ID,超过这个范围的ID舍去
- var discard = Math.floor(id / 16777216);
- id = id - discard * 16777216;
- return id;
- }
- var MVTWorker$1 = createTaskProcessorWorker(MVTWorker);
- return MVTWorker$1;
- });
|