MVTWorker.js 490 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334
  1. /**
  2. * Cesium - https://github.com/AnalyticalGraphicsInc/cesium
  3. *
  4. * Copyright 2011-2017 Cesium Contributors
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * Columbus View (Pat. Pend.)
  19. *
  20. * Portions licensed separately.
  21. * See https://github.com/AnalyticalGraphicsInc/cesium/blob/master/LICENSE.md for full licensing details.
  22. */
  23. define(['./when-8d13db60', './Check-70bec281', './Math-61ede240', './FeatureDetection-7bd32c34', './createTaskProcessorWorker', './Color-69f1845f', './pbf-9fe59c76'], function (when, Check, _Math, FeatureDetection, createTaskProcessorWorker, Color, pbf) { 'use strict';
  24. // 用来根据Mapbox style标准构建过滤器和定义过滤方法
  25. function MvtFilter() {
  26. }
  27. /**
  28. * 根据根据Mapbox style的过滤器对象构造过滤条件
  29. * @param filter 输入过滤器
  30. * @returns 返回过滤条件数组
  31. */
  32. MvtFilter.parseLayerFilter = function(filter) {
  33. if (!when.defined(filter) || !(filter instanceof Array)) {
  34. return null;
  35. }
  36. var filterArray = [];
  37. var condition;
  38. if (isOperator(filter[0])) {
  39. condition = parseSingleFilterArray(filter);
  40. if(when.defined(condition)){
  41. filterArray.push(condition);
  42. }
  43. }
  44. else{
  45. for (var fi = 0; fi < filter.length; fi++) {
  46. if (!(filter[fi] instanceof Array)) {
  47. continue;
  48. }
  49. if (filter[fi].length !== 3) {
  50. for (var fj = 0; fj < filter[fi].length; fj++) {
  51. if (filter[fi][fj] instanceof Array && filter[fi][fj].length === 3) {
  52. condition = parseSingleFilterArray(filter[fi][fj]);
  53. if(when.defined(condition)){
  54. filterArray.push(condition);
  55. }
  56. }
  57. }
  58. } else {
  59. condition = parseSingleFilterArray(filter[fi]);
  60. if(when.defined(condition)){
  61. filterArray.push(condition);
  62. }
  63. }
  64. }
  65. }
  66. return filterArray;
  67. };
  68. /**
  69. * 根据对象的属性进行过滤条件测试
  70. * @param filterArray 过滤条件数组
  71. * @param properties 对象属性
  72. * @returns 通过过滤条件返回true
  73. */
  74. MvtFilter.filterTest = function(properties, filterArray) {
  75. for(var filterIdx = 0, filterCount = filterArray.length; filterIdx < filterCount; filterIdx++){
  76. var filter = filterArray[filterIdx];
  77. if(!compareFunctions[filter.filterOperator](properties, filter.filterFieldName, filter.filterCompareValue)){
  78. return false;
  79. }
  80. }
  81. return true;
  82. };
  83. function parseSingleFilterArray(filterArray){
  84. var filterCompareValue = null;
  85. var filterFieldName = null;
  86. var filterOperator = null;
  87. if (isOperator(filterArray[0])) {
  88. filterOperator = filterArray[0];
  89. }
  90. else{
  91. return null;
  92. }
  93. if(filterArray.length > 1){
  94. filterFieldName = filterArray[1];
  95. // TODO: 系统字段暂不处理
  96. if(filterFieldName[0] === "$" ){
  97. return null;
  98. }
  99. }
  100. if(filterArray.length > 2){
  101. filterCompareValue = filterArray[2];
  102. }
  103. return {
  104. filterOperator : filterOperator,
  105. filterFieldName : filterFieldName,
  106. filterCompareValue : filterCompareValue
  107. };
  108. }
  109. function isOperator(key) {
  110. return ["==", "===", ">=", "<=", ">", "<", "!=", "has"].indexOf(key) !== -1;
  111. }
  112. function equalFunction(properties, fieldName, testValue){
  113. return properties[fieldName] == testValue;
  114. }
  115. function greaterFunction(properties, fieldName, testValue){
  116. return properties[fieldName] > testValue;
  117. }
  118. function lessFunction(properties, fieldName, testValue){
  119. return properties[fieldName] < testValue;
  120. }
  121. function greaterEqualFunction(properties, fieldName, testValue){
  122. return properties[fieldName] >= testValue;
  123. }
  124. function lessEqualFunction(properties, fieldName, testValue){
  125. return properties[fieldName] <= testValue;
  126. }
  127. function notEqualFunction(properties, fieldName, testValue){
  128. return properties[fieldName] != testValue;
  129. }
  130. function hasFunction(properties, fieldName){
  131. return when.defined(properties[fieldName]);
  132. }
  133. var compareFunctions = {
  134. "==" : equalFunction,
  135. "===" : equalFunction,
  136. ">" : greaterFunction,
  137. "<" : lessFunction,
  138. ">=" : greaterEqualFunction,
  139. "<=" : lessEqualFunction,
  140. "!=" : notEqualFunction,
  141. "has" : hasFunction
  142. };
  143. function MvtStyle(openlayer, useOffscreen) {
  144. if(!openlayer){
  145. throw new Check.DeveloperError('need include ol-debug.js');
  146. }
  147. this._useOffscreen = useOffscreen;
  148. this._openlayer = openlayer;
  149. }
  150. Object.defineProperties(MvtStyle.prototype, {
  151. proxy: {
  152. get: function() {}
  153. }
  154. });
  155. MvtStyle.prototype.getStyle = function() {
  156. var openlayer = this._openlayer;
  157. var fill = new openlayer.style.Fill({
  158. color: ""
  159. });
  160. fill.setColor("#ffffff");
  161. var stroke = new openlayer.style.Stroke({
  162. color: "",
  163. width: 1
  164. });
  165. stroke.setWidth(1);
  166. stroke.setColor("#000000");
  167. var fillAndOutlineStyle = new openlayer.style.Style({
  168. fill: fill,
  169. stroke: stroke
  170. });
  171. return fillAndOutlineStyle;
  172. };
  173. function parseMapboxColorString(colorString){
  174. var tempS = colorString.substring(colorString.indexOf("(") + 1, colorString.indexOf(")"));
  175. tempS = tempS.split(",");
  176. var resultColor = [];
  177. resultColor.push(parseFloat(tempS[0]));
  178. resultColor.push(parseFloat(tempS[1]));
  179. resultColor.push(parseFloat(tempS[2]));
  180. resultColor.push(parseFloat(tempS[3]));
  181. return resultColor;
  182. }
  183. function colorWithOpacity(color, opacity) {
  184. if (color && opacity !== undefined) {
  185. var colorData = {
  186. color: [
  187. color[0] * 255 / color[3],
  188. color[1] * 255 / color[3],
  189. color[2] * 255 / color[3],
  190. color[3]
  191. ],
  192. opacity: color[3]
  193. };
  194. color = colorData.color;
  195. color[3] = colorData.opacity * opacity;
  196. if (color[3] === 0) {
  197. color = undefined;
  198. }
  199. }
  200. return color;
  201. }
  202. MvtStyle.prototype.getStyleByMapboxStyle = function(mapboxStyle) {
  203. var openlayer = this._openlayer;
  204. var type = mapboxStyle.type;
  205. var paint = mapboxStyle.paint;
  206. var layout = mapboxStyle.layout;
  207. if(!when.defined(type) || !when.defined(paint)){
  208. return this.getStyle();
  209. }
  210. if(type == "fill"){
  211. var fillStyle = new openlayer.style.Style({
  212. });
  213. var fill = new openlayer.style.Fill({
  214. color: "[255,255,255,1]"
  215. });
  216. fillStyle.setFill(fill);
  217. var fillOpcatiy = paint["fill-opacity"];
  218. if (when.defined(paint["fill-color"])) {
  219. var fillColor = parseMapboxColorString(paint["fill-color"]);
  220. if(when.defined(fillOpcatiy)){
  221. fillColor[3] *= fillOpcatiy;
  222. }
  223. fill.setColor(fillColor);
  224. }
  225. if (when.defined(paint["fill-outline-color"])) {
  226. var fillOutlineStroke = new openlayer.style.Stroke({
  227. color: "",
  228. width: 1
  229. });
  230. fillOutlineStroke.setColor(paint["fill-outline-color"]);
  231. fillStyle.setStroke(fillOutlineStroke);
  232. }
  233. if (when.defined(paint["fill-pattern"])) {
  234. fillStyle.fillPatternName = paint["fill-pattern"];
  235. }
  236. return fillStyle;
  237. }
  238. else if(type == "line"){
  239. var lineStyle = new openlayer.style.Style({
  240. });
  241. var lineStroke = new openlayer.style.Stroke({
  242. color: "#000000",
  243. width: 1
  244. });
  245. lineStyle.setStroke(lineStroke);
  246. var lineOpcatiy = paint["line-opacity"];
  247. if (when.defined(paint["line-color"])) {
  248. var lineColor = parseMapboxColorString(paint["line-color"]);
  249. if(when.defined(lineOpcatiy)){
  250. lineColor[3] *= lineOpcatiy;
  251. }
  252. }
  253. if (when.defined(paint["line-width"])) {
  254. var lineWidth = paint["line-width"];
  255. lineStroke.setWidth(lineWidth);
  256. }
  257. if (when.defined(paint["line-dasharray"])) {
  258. var lineDasharray = paint["line-dasharray"];
  259. lineStroke.setLineDash(lineDasharray);
  260. }
  261. if(when.defined(layout)){
  262. if (when.defined(layout["line-cap"])) {
  263. var lineCap = layout["line-cap"];
  264. lineStroke.setLineCap(lineCap);
  265. }
  266. if (when.defined(layout["line-join"])) {
  267. var lineJoin = layout["line-join"];
  268. lineStroke.setLineJoin(lineJoin);
  269. }
  270. if (when.defined(layout["line-miter-limit"])) {
  271. var lineMiterLimit = layout["line-miter-limit"];
  272. lineStroke.setMiterLimit(lineMiterLimit);
  273. }
  274. }
  275. lineStroke.setColor(lineColor);
  276. return lineStyle;
  277. }
  278. else if(type == "symbol"){
  279. var iconStyle = new openlayer.style.Style({
  280. });
  281. if(when.defined(layout) && when.defined(layout["icon-image"])){
  282. iconStyle.hasIconImage = true;
  283. }
  284. if(when.defined(layout) && when.defined(layout["text-field"])){
  285. iconStyle.hasTextStyle = true;
  286. }
  287. return iconStyle;
  288. }
  289. else if(type == "circle"){
  290. var circleRadius = paint["circle-radius"];
  291. var circleColor = paint["circle-color"];
  292. var circleStrokeColor = paint["circle-stroke-color"];
  293. var circleOpacity = paint["circle-opacity"];
  294. var circleStrokeOpacity = paint["circle-stroke-opacity"];
  295. var circleStrokeWidth = paint["circle-stroke-width"];
  296. var iconImg = new openlayer.style.Circle({
  297. radius: circleRadius,
  298. stroke: circleStrokeWidth === 0 ? undefined : new openlayer.style.Stroke({
  299. width: circleStrokeWidth,
  300. color: colorWithOpacity(circleStrokeColor, circleStrokeOpacity)
  301. }),
  302. fill: new openlayer.style.Fill({
  303. color: colorWithOpacity(circleColor, circleOpacity)
  304. })
  305. });
  306. var circleStyle = new openlayer.style.Style({
  307. });
  308. circleStyle.setImage(iconImg);
  309. return circleStyle;
  310. }
  311. else{
  312. return this.getStyle();
  313. }
  314. };
  315. var scratchIDColor = new Color.Color();
  316. function convertIDtoColor(id, layerID){
  317. var colorB = Math.floor(id / 65536);
  318. var d = id - colorB * 65536;
  319. var colorG = Math.floor(d / 256);
  320. var colorR = d - colorG * 256;
  321. var alpha = 1;
  322. scratchIDColor.red = colorR / 256;
  323. scratchIDColor.green = colorG / 256;
  324. scratchIDColor.blue = colorB / 256;
  325. scratchIDColor.alpha = alpha;
  326. return scratchIDColor;
  327. }
  328. MvtStyle.prototype.getIDColorStyle = function(geometryType, id, layerID, lineWidth, radius, lineWidthExpand) {
  329. var openlayer = this._openlayer;
  330. var idColor = convertIDtoColor(id);
  331. var cssColor = idColor.toCssColorString();
  332. if(geometryType == 'LineString' || geometryType == 'LinearRing' || geometryType == 'MultiLineString'){
  333. var expandWidth = 4;
  334. if (when.defined(lineWidth)) {
  335. expandWidth = lineWidth * 2 + lineWidthExpand;
  336. }
  337. var scratchIDStroke = new openlayer.style.Stroke({
  338. color: "",
  339. width: expandWidth
  340. });
  341. scratchIDStroke.setColor(cssColor);
  342. return new openlayer.style.Style({
  343. stroke: scratchIDStroke
  344. });
  345. }
  346. else if(geometryType == 'Point' || geometryType == 'MultiPoint'){
  347. var iconImg = new openlayer.style.Circle({
  348. radius: (radius - 0.5),
  349. fill: new openlayer.style.Fill({
  350. color: cssColor
  351. })
  352. });
  353. var circleStyle = new openlayer.style.Style({
  354. });
  355. circleStyle.setImage(iconImg);
  356. return circleStyle;
  357. }
  358. else{
  359. var scratchIDFill = new openlayer.style.Fill({
  360. color: ""
  361. });
  362. scratchIDFill.setColor(cssColor);
  363. var resultStyle = new openlayer.style.Style({
  364. fill: scratchIDFill
  365. });
  366. if(when.defined(lineWidth)){
  367. var scratchIDStroke = new openlayer.style.Stroke({
  368. color: "",
  369. width: when.defined(lineWidth) ? lineWidth * 2 : 4
  370. });
  371. scratchIDStroke.setColor(cssColor);
  372. resultStyle.setStroke(scratchIDStroke);
  373. }
  374. return resultStyle;
  375. }
  376. };
  377. var templateRegEx = /^([^]*)\{(.*)\}([^]*)$/;
  378. function fromTemplate(text, properties) {
  379. var parts;
  380. do {
  381. parts = text.match(templateRegEx);
  382. if (parts) {
  383. const value = properties[parts[2]] || '';
  384. text = parts[1] + value + parts[3];
  385. }
  386. } while (parts);
  387. return text;
  388. }
  389. MvtStyle.prototype.getTextStyle = function(oldStyle, feature, mapboxStyleLayer) {
  390. var openlayer = this._openlayer;
  391. var paint = mapboxStyleLayer.paint;
  392. var layout = mapboxStyleLayer.layout;
  393. var textField = layout['text-field'];
  394. var label = fromTemplate(textField, feature.getProperties());
  395. if(!when.defined(label)){
  396. return;
  397. }
  398. var style = new openlayer.style.Style();
  399. var text = new openlayer.style.Text();
  400. style.setText(text);
  401. var textSize = layout['text-size'];
  402. var font = when.defaultValue(layout['text-font'], ['Open Sans Regular', 'Arial Unicode MS Regular']);
  403. var textTransform = layout['text-transform'];
  404. if (textTransform == 'uppercase') {
  405. label = label.toUpperCase();
  406. } else if (textTransform == 'lowercase') {
  407. label = label.toLowerCase();
  408. }
  409. var textMaxWidth = when.defaultValue(layout['text-max-width'], 10);
  410. //var wrappedLabel = wrapText(label, font, textMaxWidth);
  411. var wrappedLabel = label;
  412. text.setText(wrappedLabel);
  413. text.setFont(font);
  414. text.setRotation(0);
  415. var textAnchor = when.defaultValue(layout['text-anchor'], 'center');
  416. var placement = when.defaultValue(layout['symbol-placement'], 'point');
  417. text.setPlacement(placement);
  418. if (placement == 'point') {
  419. var textAlign = 'center';
  420. if (textAnchor.indexOf('left') !== -1) {
  421. textAlign = 'left';
  422. } else if (textAnchor.indexOf('right') !== -1) {
  423. textAlign = 'right';
  424. }
  425. text.setTextAlign(textAlign);
  426. } else {
  427. text.setTextAlign();
  428. }
  429. var textBaseline = 'middle';
  430. if (textAnchor.indexOf('bottom') == 0) {
  431. textBaseline = 'bottom';
  432. } else if (textAnchor.indexOf('top') == 0) {
  433. textBaseline = 'top';
  434. }
  435. text.setTextBaseline(textBaseline);
  436. var textOffset = when.defaultValue(layout['text-offset'], [0.0, 0.0]);
  437. var textTranslate = when.defaultValue(layout['text-translate'], [0.0, 0.0]);
  438. text.setOffsetX(textOffset[0] * textSize + textTranslate[0]);
  439. text.setOffsetY(textOffset[1] * textSize + textTranslate[1]);
  440. var opacity = paint['text-opacity'];
  441. var textColorFill = new openlayer.style.Fill();
  442. var textColor = paint["text-color"];
  443. if(when.defined(textColor)){
  444. textColor = parseMapboxColorString(textColor);
  445. textColorFill.setColor(textColor);
  446. }
  447. text.setFill(textColorFill);
  448. var textHaloColor = paint["text-halo-color"];
  449. if (when.defined(textHaloColor)) {
  450. var textHalo = new openlayer.style.Stroke();
  451. textHaloColor = parseMapboxColorString(textHaloColor);
  452. textHalo.setColor(textHaloColor);
  453. textHalo.setWidth(paint['text-halo-width']);
  454. text.setStroke(textHalo);
  455. } else {
  456. text.setStroke(undefined);
  457. }
  458. style.setZIndex(oldStyle.getZIndex());
  459. style.hasIconImage = oldStyle.hasIconImage;
  460. style.textSize = textSize;
  461. return style;
  462. };
  463. function covertIconAnchor(iconAnchor) {
  464. var anchorOffset = [0.5, 0.5];
  465. if (['top-left', 'top-right', 'bottom-left', 'bottom-right'].includes(iconAnchor)) {
  466. anchorOffset = [0, 0];
  467. }
  468. if (iconAnchor === 'left') {
  469. iconAnchor = 'top-left';
  470. anchorOffset = [0, 0.5];
  471. }
  472. if (iconAnchor === 'right') {
  473. iconAnchor = 'top-left';
  474. anchorOffset = [1, 0.5];
  475. }
  476. if (iconAnchor === 'bottom') {
  477. iconAnchor = 'top-left';
  478. anchorOffset = [0.5, 1];
  479. }
  480. if (iconAnchor === 'top') {
  481. iconAnchor = 'top-left';
  482. anchorOffset = [0.5, 0];
  483. }
  484. return {
  485. anchorOffset: anchorOffset,
  486. iconAnchor: iconAnchor
  487. };
  488. }
  489. var iconImageCache = {};
  490. MvtStyle.prototype.setIconImageForStyle = function(spriteImageDatas, style, mapboxStyleLayer){
  491. var openlayer = this._openlayer;
  492. var paint = mapboxStyleLayer.paint;
  493. var layout = mapboxStyleLayer.layout;
  494. var iconSize = when.defaultValue(layout["icon-size"], 1);
  495. var iconColor = paint['icon-color'];
  496. var iconTranslate = when.defaultValue(paint['icon-translate'], [0.0, 0.0]);
  497. var iconTranslateAnchor = when.defaultValue(paint['icon-translate-anchor'], 'map');
  498. var iconAnchor = when.defaultValue(layout['icon-anchor'], 'center');
  499. var anchorOffsetAndIconAnchor = covertIconAnchor(iconAnchor);
  500. var anchorOffset = anchorOffsetAndIconAnchor.anchorOffset;
  501. var iconOffset = when.defaultValue(layout['iconoffset'], [0.0, 0.0]);
  502. var iconOpacity = when.defaultValue(layout['icon-opacity'], 1.0);
  503. var spriteImageName = layout["icon-image"];
  504. if(!when.defined(spriteImageDatas[spriteImageName])){
  505. console.log('miss icon-image ' + spriteImageName);
  506. return;
  507. }
  508. var icon_cache_key = spriteImageName + '.' + iconSize + '.' + iconTranslate + '.' + iconTranslateAnchor + '.' + iconAnchor + '.' + iconOffset;
  509. if (when.defined(iconColor)) {
  510. icon_cache_key += '.' + iconColor;
  511. }
  512. var iconImg = iconImageCache[icon_cache_key];
  513. if(!when.defined(iconImg)){
  514. var spriteImage = spriteImageDatas[spriteImageName];
  515. var canvas;
  516. if(this._useOffscreen){
  517. canvas = new OffscreenCanvas(spriteImage.width, spriteImage.height);
  518. }
  519. else{
  520. canvas = document.createElement('canvas');
  521. canvas.width = spriteImage.width;
  522. canvas.height = spriteImage.height;
  523. }
  524. var ctx = canvas.getContext('2d');
  525. ctx.putImageData(spriteImage, 0, 0);
  526. var translateOffset = [iconTranslate[0] / spriteImage.width, iconTranslate[1] / spriteImage.height];
  527. iconImg = new openlayer.style.Icon({
  528. img: canvas,
  529. anchorOrigin: anchorOffsetAndIconAnchor.iconAnchor,
  530. anchor: [iconOffset[0] + anchorOffset[0] + translateOffset[0], iconOffset[1] + anchorOffset[1] - translateOffset[1]],
  531. imgSize: [canvas.width, canvas.height],
  532. scale: iconSize
  533. });
  534. iconImg.setOpacity(iconOpacity);
  535. iconImageCache[icon_cache_key] = iconImg;
  536. }
  537. style.setImage(iconImg);
  538. //style.setText(undefined);
  539. };
  540. var VALUE_EXTENT = 4096;
  541. var replays = ["Default", "Polygon", "LineString", "Image", "Symbol", "Text"];
  542. function MvtRenderer2D(options) {
  543. this._mvtStyleClass = options.mvtStyle;
  544. this._openlayer = options.openlayer;
  545. }
  546. Object.defineProperties(MvtRenderer2D.prototype, {
  547. });
  548. MvtRenderer2D.prototype.renderFeatures = function(options) {
  549. var canvas = options.colorCanvas;
  550. var idCanvas = options.idCanvas;
  551. var transform = options.transform;
  552. var layers = options.layers;
  553. var features = options.features;
  554. var tileLevel = options.tileLevel;
  555. var spriteImageCanvas = options.spriteImageCanvas;
  556. var spriteImageDatas = options.spriteImageDatas;
  557. var squaredTolerance = options.squaredTolerance;
  558. var showBillboard = options.showBillboard;
  559. var renderID = options.renderID;
  560. var renderColor = options.renderColor;
  561. var lineWidthExpand = options.lineWidthExpand;
  562. var ol = this._openlayer;
  563. var ctx = canvas.getContext('2d');
  564. var idFeatures = [];
  565. var iconImageObjects = [];
  566. var textObjects = [];
  567. var style = null;
  568. var declutterTree = ol.ext.rbush(9);
  569. var replayGroup = new ol.render.canvas.ReplayGroup(0, [0, 0, VALUE_EXTENT, VALUE_EXTENT], 8, 2, true, declutterTree);
  570. var featureLength = features.length;
  571. for (var r = 0; r < featureLength; r++) {
  572. var feature = features[r];
  573. var sourceLayer = feature.getProperties().layer;
  574. feature.index = sourceLayer + feature.getId();
  575. var featureHasStyle = false;
  576. var layerGroupById = layers[sourceLayer];
  577. var zIndex = 0;
  578. for (var layerId in layerGroupById) {
  579. var layerById = layerGroupById[layerId];
  580. var maxzoom = layerById.mapboxStyleLayer.maxzoom;
  581. var minzoom = layerById.mapboxStyleLayer.minzoom;
  582. if(tileLevel < minzoom || tileLevel > maxzoom){
  583. continue;
  584. }
  585. var filterArray = layerById.filterArray;
  586. if (!when.defined(filterArray)) {
  587. style = this._mvtStyleClass.getStyleByMapboxStyle(layerById.mapboxStyleLayer);
  588. }
  589. else {
  590. var properties = feature.getProperties();
  591. if (MvtFilter.filterTest(properties, filterArray)) {
  592. style = this._mvtStyleClass.getStyleByMapboxStyle(layerById.mapboxStyleLayer);
  593. }
  594. else {
  595. continue;
  596. }
  597. }
  598. if (!when.defined(style)) {
  599. continue;
  600. }
  601. this.createFillPatternForStyle(style, spriteImageCanvas, spriteImageDatas, ctx);
  602. if (when.defined(style.hasTextStyle)) {
  603. var textStyle = this._mvtStyleClass.getTextStyle(style, feature, layerById.mapboxStyleLayer);
  604. textStyle.setZIndex(zIndex);
  605. if(showBillboard){
  606. textObjects.push({
  607. feature : feature,
  608. style : textStyle
  609. });
  610. }
  611. else{
  612. if(renderColor){
  613. ol.renderer.vector.renderFeature_(replayGroup, feature, textStyle, -1);
  614. }
  615. }
  616. }
  617. if (when.defined(style.hasIconImage) && !when.defined(style.getImage())) {
  618. if(showBillboard){
  619. iconImageObjects.push({
  620. feature : feature,
  621. style : layerById.mapboxStyleLayer
  622. });
  623. continue;
  624. }
  625. else{
  626. this._mvtStyleClass.setIconImageForStyle(spriteImageDatas, style, layerById.mapboxStyleLayer);
  627. }
  628. }
  629. style.setZIndex(zIndex);
  630. this.setPickStyleInFeature(feature, style);
  631. zIndex++;
  632. if(renderColor){
  633. ol.renderer.vector.renderFeature_(replayGroup, feature, style, -1);
  634. }
  635. featureHasStyle = true;
  636. }
  637. if (featureHasStyle) {
  638. idFeatures.push(feature);
  639. }
  640. }
  641. if(renderColor){
  642. replayGroup.finish();
  643. var declutterReplays = {};
  644. replayGroup.replay(ctx, transform, 0, {}, replays, declutterReplays);
  645. if (declutterReplays) {
  646. ol.render.canvas.ReplayGroup.replayDeclutter(declutterReplays, ctx, 0.0);
  647. }
  648. }
  649. replayGroup = null;
  650. if(renderID){
  651. this.renderIDtoTexture(transform, idCanvas, idFeatures, 0, squaredTolerance, lineWidthExpand);
  652. }
  653. return {
  654. idFeatures : idFeatures,
  655. iconImageObjects : iconImageObjects,
  656. textObjects : textObjects
  657. }
  658. };
  659. MvtRenderer2D.prototype.renderIDtoTexture = function(transform, canvas, features, layerID, tileTolerance, lineWidthExpand) {
  660. var ol = this._openlayer;
  661. var ctx = canvas.getContext('2d');
  662. var declutterTree = ol.ext.rbush(9);
  663. var replayGroup = new ol.render.canvas.ReplayGroup(0, [0, 0, VALUE_EXTENT, VALUE_EXTENT], 8, 2, true, declutterTree);
  664. var featureLength = features.length;
  665. for (var r = 0; r < featureLength; r++) {
  666. var feature = features[r];
  667. var id = getFeatureID(feature);
  668. var idStyle = this._mvtStyleClass.getIDColorStyle(feature.getGeometry().getType(), id, layerID, feature.lineWidth, feature.radius, lineWidthExpand);
  669. idStyle.setZIndex(feature.zIndex);
  670. ol.renderer.vector.renderFeature_(replayGroup, feature, idStyle, -1);
  671. }
  672. replayGroup.finish();
  673. var declutterReplays = {};
  674. replayGroup.replay(ctx, transform, 0, {}, replays, declutterReplays);
  675. if (declutterReplays) {
  676. ol.render.canvas.ReplayGroup.replayDeclutter(declutterReplays, ctx, 0.0);
  677. }
  678. replayGroup = null;
  679. };
  680. MvtRenderer2D.prototype.createFillPatternForStyle = function(style, spriteImageCanvas, subSpriteImage, ctx){
  681. if(!when.defined(style.fillPatternName)){
  682. return;
  683. }
  684. var patternName = style.fillPatternName;
  685. var patternCanvas = null;
  686. if (when.defined(spriteImageCanvas[patternName])) {
  687. patternCanvas = spriteImageCanvas[patternName];
  688. }
  689. else {
  690. var imageData = subSpriteImage[patternName];
  691. if (!when.defined(imageData)) {
  692. console.log('miss sprite ' + patternName);
  693. return;
  694. }
  695. patternCanvas = document.createElement('canvas');
  696. patternCanvas.width = imageData.width;
  697. patternCanvas.height = imageData.height;
  698. var spriteCtx = patternCanvas.getContext('2d');
  699. spriteCtx.putImageData(imageData, 0, 0);
  700. spriteImageCanvas[patternName] = patternCanvas;
  701. }
  702. style.fill_.color_ = ctx.createPattern(patternCanvas, 'repeat');
  703. };
  704. MvtRenderer2D.prototype.setPickStyleInFeature = function(feature, style){
  705. var ol = this._openlayer;
  706. feature.zIndex = style.getZIndex();
  707. if(when.defined(style.getStroke())){
  708. var styleLineWidth = style.getStroke().getWidth();
  709. if(when.defined(feature.lineWidth)){
  710. feature.lineWidth = Math.max(feature.lineWidth, styleLineWidth);
  711. }
  712. else{
  713. feature.lineWidth = styleLineWidth;
  714. }
  715. }
  716. if(when.defined(style.getImage())){
  717. var imageStyle = style.getImage();
  718. var radius = 1.0;
  719. if(imageStyle instanceof ol.style.Icon ){
  720. var imageSize = imageStyle.getImageSize();
  721. radius = Math.max(imageSize[0], imageSize[1]) / 2.0;
  722. radius -= 1.0;
  723. }
  724. else if(imageStyle instanceof ol.style.Circle ){
  725. radius = imageStyle.getRadius();
  726. }
  727. if(when.defined(feature.radius)){
  728. feature.radius = Math.max(feature.radius, radius);
  729. }
  730. else{
  731. feature.radius = radius;
  732. }
  733. }
  734. };
  735. function getFeatureID(feature) {
  736. var id = feature.getId();
  737. // 只在颜色中记录256*256*256这么大范围的ID,超过这个范围的ID舍去
  738. var discard = Math.floor(id / 16777216);
  739. id = id - discard * 16777216;
  740. return id;
  741. }
  742. function ol() {
  743. }
  744. ol.array = {};
  745. /**
  746. * 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.
  747. * https://github.com/darkskyapp/binary-search
  748. *
  749. * @param {Array.<*>} haystack Items to search through.
  750. * @param {*} needle The item to look for.
  751. * @param {Function=} opt_comparator Comparator function.
  752. * @return {number} The index of the item if found, -1 if not.
  753. */
  754. ol.array.binarySearch = function(haystack, needle, opt_comparator) {
  755. var mid, cmp;
  756. var comparator = opt_comparator || ol.array.numberSafeCompareFunction;
  757. var low = 0;
  758. var high = haystack.length;
  759. var found = false;
  760. while (low < high) {
  761. /* Note that "(low + high) >>> 1" may overflow, and results in a typecast
  762. * to double (which gives the wrong results). */
  763. mid = low + (high - low >> 1);
  764. cmp = +comparator(haystack[mid], needle);
  765. if (cmp < 0.0) { /* Too low. */
  766. low = mid + 1;
  767. } else { /* Key found or too high */
  768. high = mid;
  769. found = !cmp;
  770. }
  771. }
  772. /* Key not found. */
  773. return found ? low : ~low;
  774. };
  775. /**
  776. * Compare function for array sort that is safe for numbers.
  777. * @param {*} a The first object to be compared.
  778. * @param {*} b The second object to be compared.
  779. * @return {number} A negative number, zero, or a positive number as the first
  780. * argument is less than, equal to, or greater than the second.
  781. */
  782. ol.array.numberSafeCompareFunction = function(a, b) {
  783. return a > b ? 1 : a < b ? -1 : 0;
  784. };
  785. /**
  786. * Whether the array contains the given object.
  787. * @param {Array.<*>} arr The array to test for the presence of the element.
  788. * @param {*} obj The object for which to test.
  789. * @return {boolean} The object is in the array.
  790. */
  791. ol.array.includes = function(arr, obj) {
  792. return arr.indexOf(obj) >= 0;
  793. };
  794. /**
  795. * @param {Array.<number>} arr Array.
  796. * @param {number} target Target.
  797. * @param {number} direction 0 means return the nearest, > 0
  798. * means return the largest nearest, < 0 means return the
  799. * smallest nearest.
  800. * @return {number} Index.
  801. */
  802. ol.array.linearFindNearest = function(arr, target, direction) {
  803. var n = arr.length;
  804. if (arr[0] <= target) {
  805. return 0;
  806. } else if (target <= arr[n - 1]) {
  807. return n - 1;
  808. } else {
  809. var i;
  810. if (direction > 0) {
  811. for (i = 1; i < n; ++i) {
  812. if (arr[i] < target) {
  813. return i - 1;
  814. }
  815. }
  816. } else if (direction < 0) {
  817. for (i = 1; i < n; ++i) {
  818. if (arr[i] <= target) {
  819. return i;
  820. }
  821. }
  822. } else {
  823. for (i = 1; i < n; ++i) {
  824. if (arr[i] == target) {
  825. return i;
  826. } else if (arr[i] < target) {
  827. if (arr[i - 1] - target < target - arr[i]) {
  828. return i - 1;
  829. } else {
  830. return i;
  831. }
  832. }
  833. }
  834. }
  835. return n - 1;
  836. }
  837. };
  838. /**
  839. * @param {Array.<*>} arr Array.
  840. * @param {number} begin Begin index.
  841. * @param {number} end End index.
  842. */
  843. ol.array.reverseSubArray = function(arr, begin, end) {
  844. while (begin < end) {
  845. var tmp = arr[begin];
  846. arr[begin] = arr[end];
  847. arr[end] = tmp;
  848. ++begin;
  849. --end;
  850. }
  851. };
  852. /**
  853. * @param {Array.<VALUE>} arr The array to modify.
  854. * @param {Array.<VALUE>|VALUE} data The elements or arrays of elements
  855. * to add to arr.
  856. * @template VALUE
  857. */
  858. ol.array.extend = function(arr, data) {
  859. var i;
  860. var extension = Array.isArray(data) ? data : [data];
  861. var length = extension.length;
  862. for (i = 0; i < length; i++) {
  863. arr[arr.length] = extension[i];
  864. }
  865. };
  866. /**
  867. * @param {Array.<VALUE>} arr The array to modify.
  868. * @param {VALUE} obj The element to remove.
  869. * @template VALUE
  870. * @return {boolean} If the element was removed.
  871. */
  872. ol.array.remove = function(arr, obj) {
  873. var i = arr.indexOf(obj);
  874. var found = i > -1;
  875. if (found) {
  876. arr.splice(i, 1);
  877. }
  878. return found;
  879. };
  880. /**
  881. * @param {Array.<VALUE>} arr The array to search in.
  882. * @param {function(VALUE, number, ?) : boolean} func The function to compare.
  883. * @template VALUE
  884. * @return {VALUE} The element found.
  885. */
  886. ol.array.find = function(arr, func) {
  887. var length = arr.length >>> 0;
  888. var value;
  889. for (var i = 0; i < length; i++) {
  890. value = arr[i];
  891. if (func(value, i, arr)) {
  892. return value;
  893. }
  894. }
  895. return null;
  896. };
  897. /**
  898. * @param {Array|Uint8ClampedArray} arr1 The first array to compare.
  899. * @param {Array|Uint8ClampedArray} arr2 The second array to compare.
  900. * @return {boolean} Whether the two arrays are equal.
  901. */
  902. ol.array.equals = function(arr1, arr2) {
  903. var len1 = arr1.length;
  904. if (len1 !== arr2.length) {
  905. return false;
  906. }
  907. for (var i = 0; i < len1; i++) {
  908. if (arr1[i] !== arr2[i]) {
  909. return false;
  910. }
  911. }
  912. return true;
  913. };
  914. /**
  915. * @param {Array.<*>} arr The array to sort (modifies original).
  916. * @param {Function} compareFnc Comparison function.
  917. */
  918. ol.array.stableSort = function(arr, compareFnc) {
  919. var length = arr.length;
  920. var tmp = Array(arr.length);
  921. var i;
  922. for (i = 0; i < length; i++) {
  923. tmp[i] = {index: i, value: arr[i]};
  924. }
  925. tmp.sort(function(a, b) {
  926. return compareFnc(a.value, b.value) || a.index - b.index;
  927. });
  928. for (i = 0; i < arr.length; i++) {
  929. arr[i] = tmp[i].value;
  930. }
  931. };
  932. /**
  933. * @param {Array.<*>} arr The array to search in.
  934. * @param {Function} func Comparison function.
  935. * @return {number} Return index.
  936. */
  937. ol.array.findIndex = function(arr, func) {
  938. var index;
  939. var found = !arr.every(function(el, idx) {
  940. index = idx;
  941. return !func(el, idx, arr);
  942. });
  943. return found ? index : -1;
  944. };
  945. /**
  946. * @param {Array.<*>} arr The array to test.
  947. * @param {Function=} opt_func Comparison function.
  948. * @param {boolean=} opt_strict Strictly sorted (default false).
  949. * @return {boolean} Return index.
  950. */
  951. ol.array.isSorted = function(arr, opt_func, opt_strict) {
  952. var compare = opt_func || ol.array.numberSafeCompareFunction;
  953. return arr.every(function(currentVal, index) {
  954. if (index === 0) {
  955. return true;
  956. }
  957. var res = compare(arr[index - 1], currentVal);
  958. return !(res > 0 || opt_strict && res === 0);
  959. });
  960. };
  961. ol.ASSUME_TOUCH = false;
  962. ol.DEFAULT_MAX_ZOOM = 42;
  963. ol.DEFAULT_MIN_ZOOM = 0;
  964. ol.DEFAULT_RASTER_REPROJECTION_ERROR_THRESHOLD = 0.5;
  965. ol.DEFAULT_TILE_SIZE = 256;
  966. ol.DEFAULT_WMS_VERSION = '1.3.0';
  967. ol.ENABLE_CANVAS = true;
  968. ol.ENABLE_PROJ4JS = true;
  969. ol.ENABLE_RASTER_REPROJECTION = true;
  970. ol.ENABLE_WEBGL = true;
  971. ol.DEBUG_WEBGL = true;
  972. ol.INITIAL_ATLAS_SIZE = 256;
  973. ol.MAX_ATLAS_SIZE = -1;
  974. ol.MOUSEWHEELZOOM_MAXDELTA = 1;
  975. ol.OVERVIEWMAP_MAX_RATIO = 0.75;
  976. ol.OVERVIEWMAP_MIN_RATIO = 0.1;
  977. ol.RASTER_REPROJECTION_MAX_SOURCE_TILES = 100;
  978. ol.RASTER_REPROJECTION_MAX_SUBDIVISION = 10;
  979. ol.RASTER_REPROJECTION_MAX_TRIANGLE_WIDTH = 0.25;
  980. ol.SIMPLIFY_TOLERANCE = 0.5;
  981. ol.WEBGL_TEXTURE_CACHE_HIGH_WATER_MARK = 1024;
  982. ol.VERSION = '';
  983. ol.inherits = function(childCtor, parentCtor) {
  984. childCtor.prototype = Object.create(parentCtor.prototype);
  985. childCtor.prototype.constructor = childCtor;
  986. };
  987. ol.nullFunction = function() {};
  988. ol.getUid = function(obj) {
  989. return obj.ol_uid ||
  990. (obj.ol_uid = ++ol.uidCounter_);
  991. };
  992. ol.asserts = {};
  993. ol.asserts.assert = function(assertion, errorCode) {
  994. };
  995. ol.has = {};
  996. var ua = typeof navigator !== 'undefined' ?
  997. navigator.userAgent.toLowerCase() : '';
  998. ol.has.FIREFOX = ua.indexOf('firefox') !== -1;
  999. ol.has.SAFARI = ua.indexOf('safari') !== -1 && ua.indexOf('chrom') == -1;
  1000. ol.has.WEBKIT = ua.indexOf('webkit') !== -1 && ua.indexOf('edge') == -1;
  1001. ol.has.MAC = ua.indexOf('macintosh') !== -1;
  1002. ol.has.DEVICE_PIXEL_RATIO = 1;
  1003. ol.has.CANVAS_LINE_DASH = true;
  1004. ol.structs = {};
  1005. /**
  1006. * @enum {string}
  1007. */
  1008. ol.CollectionEventType = {
  1009. ADD: 'add',
  1010. REMOVE: 'remove'
  1011. };
  1012. /**
  1013. * @enum {string}
  1014. */
  1015. ol.ObjectEventType = {
  1016. PROPERTYCHANGE: 'propertychange'
  1017. };
  1018. ol.events = {};
  1019. /**
  1020. * @param {ol.EventsKey} listenerObj Listener object.
  1021. * @return {ol.EventsListenerFunctionType} Bound listener.
  1022. */
  1023. ol.events.bindListener_ = function(listenerObj) {
  1024. var boundListener = function(evt) {
  1025. var listener = listenerObj.listener;
  1026. var bindTo = listenerObj.bindTo || listenerObj.target;
  1027. if (listenerObj.callOnce) {
  1028. ol.events.unlistenByKey(listenerObj);
  1029. }
  1030. return listener.call(bindTo, evt);
  1031. };
  1032. listenerObj.boundListener = boundListener;
  1033. return boundListener;
  1034. };
  1035. ol.events.findListener_ = function(listeners, listener, opt_this,
  1036. opt_setDeleteIndex) {
  1037. var listenerObj;
  1038. for (var i = 0, ii = listeners.length; i < ii; ++i) {
  1039. listenerObj = listeners[i];
  1040. if (listenerObj.listener === listener &&
  1041. listenerObj.bindTo === opt_this) {
  1042. if (opt_setDeleteIndex) {
  1043. listenerObj.deleteIndex = i;
  1044. }
  1045. return listenerObj;
  1046. }
  1047. }
  1048. return undefined;
  1049. };
  1050. /**
  1051. * @param {ol.EventTargetLike} target Target.
  1052. * @param {string} type Type.
  1053. * @return {Array.<ol.EventsKey>|undefined} Listeners.
  1054. */
  1055. ol.events.getListeners = function(target, type) {
  1056. var listenerMap = target.ol_lm;
  1057. return listenerMap ? listenerMap[type] : undefined;
  1058. };
  1059. /**
  1060. * Get the lookup of listeners. If one does not exist on the target, it is
  1061. * created.
  1062. * @param {ol.EventTargetLike} target Target.
  1063. * @return {!Object.<string, Array.<ol.EventsKey>>} Map of
  1064. * listeners by event type.
  1065. * @private
  1066. */
  1067. ol.events.getListenerMap_ = function(target) {
  1068. var listenerMap = target.ol_lm;
  1069. if (!listenerMap) {
  1070. listenerMap = target.ol_lm = {};
  1071. }
  1072. return listenerMap;
  1073. };
  1074. /**
  1075. * Clean up all listener objects of the given type. All properties on the
  1076. * listener objects will be removed, and if no listeners remain in the listener
  1077. * map, it will be removed from the target.
  1078. * @param {ol.EventTargetLike} target Target.
  1079. * @param {string} type Type.
  1080. * @private
  1081. */
  1082. ol.events.removeListeners_ = function(target, type) {
  1083. var listeners = ol.events.getListeners(target, type);
  1084. if (listeners) {
  1085. for (var i = 0, ii = listeners.length; i < ii; ++i) {
  1086. target.removeEventListener(type, listeners[i].boundListener);
  1087. ol.obj.clear(listeners[i]);
  1088. }
  1089. listeners.length = 0;
  1090. var listenerMap = target.ol_lm;
  1091. if (listenerMap) {
  1092. delete listenerMap[type];
  1093. if (Object.keys(listenerMap).length === 0) {
  1094. delete target.ol_lm;
  1095. }
  1096. }
  1097. }
  1098. };
  1099. ol.events.listen = function(target, type, listener, opt_this, opt_once) {
  1100. var listenerMap = ol.events.getListenerMap_(target);
  1101. var listeners = listenerMap[type];
  1102. if (!listeners) {
  1103. listeners = listenerMap[type] = [];
  1104. }
  1105. var listenerObj = ol.events.findListener_(listeners, listener, opt_this,
  1106. false);
  1107. if (listenerObj) {
  1108. if (!opt_once) {
  1109. // Turn one-off listener into a permanent one.
  1110. listenerObj.callOnce = false;
  1111. }
  1112. } else {
  1113. listenerObj = /** @type {ol.EventsKey} */ ({
  1114. bindTo: opt_this,
  1115. callOnce: !!opt_once,
  1116. listener: listener,
  1117. target: target,
  1118. type: type
  1119. });
  1120. target.addEventListener(type, ol.events.bindListener_(listenerObj));
  1121. listeners.push(listenerObj);
  1122. }
  1123. return listenerObj;
  1124. };
  1125. ol.events.listenOnce = function(target, type, listener, opt_this) {
  1126. return ol.events.listen(target, type, listener, opt_this, true);
  1127. };
  1128. ol.events.unlisten = function(target, type, listener, opt_this) {
  1129. var listeners = ol.events.getListeners(target, type);
  1130. if (listeners) {
  1131. var listenerObj = ol.events.findListener_(listeners, listener, opt_this,
  1132. true);
  1133. if (listenerObj) {
  1134. ol.events.unlistenByKey(listenerObj);
  1135. }
  1136. }
  1137. };
  1138. ol.events.unlistenByKey = function(key) {
  1139. if (key && key.target) {
  1140. key.target.removeEventListener(key.type, key.boundListener);
  1141. var listeners = ol.events.getListeners(key.target, key.type);
  1142. if (listeners) {
  1143. var i = 'deleteIndex' in key ? key.deleteIndex : listeners.indexOf(key);
  1144. if (i !== -1) {
  1145. listeners.splice(i, 1);
  1146. }
  1147. if (listeners.length === 0) {
  1148. ol.events.removeListeners_(key.target, key.type);
  1149. }
  1150. }
  1151. ol.obj.clear(key);
  1152. }
  1153. };
  1154. ol.events.unlistenAll = function(target) {
  1155. var listenerMap = ol.events.getListenerMap_(target);
  1156. for (var type in listenerMap) {
  1157. ol.events.removeListeners_(target, type);
  1158. }
  1159. };
  1160. /**
  1161. * Objects that need to clean up after themselves.
  1162. * @constructor
  1163. */
  1164. ol.Disposable = function() {};
  1165. ol.Disposable.prototype.disposed_ = false;
  1166. ol.Disposable.prototype.dispose = function() {
  1167. if (!this.disposed_) {
  1168. this.disposed_ = true;
  1169. this.disposeInternal();
  1170. }
  1171. };
  1172. ol.Disposable.prototype.disposeInternal = ol.nullFunction;
  1173. ol.events.Event = {};
  1174. ol.events.Event = function(type) {
  1175. this.propagationStopped;
  1176. this.type = type;
  1177. this.target = null;
  1178. };
  1179. ol.events.Event.prototype.preventDefault =
  1180. /**
  1181. * Stop event propagation.
  1182. * @function
  1183. * @override
  1184. * @api
  1185. */
  1186. ol.events.Event.prototype.stopPropagation = function() {
  1187. this.propagationStopped = true;
  1188. };
  1189. /**
  1190. * @param {Event|ol.events.Event} evt Event
  1191. */
  1192. ol.events.Event.stopPropagation = function(evt) {
  1193. evt.stopPropagation();
  1194. };
  1195. /**
  1196. * @param {Event|ol.events.Event} evt Event
  1197. */
  1198. ol.events.Event.preventDefault = function(evt) {
  1199. evt.preventDefault();
  1200. };
  1201. ol.events.EventTarget = {};
  1202. ol.events.EventTarget = function() {
  1203. ol.Disposable.call(this);
  1204. this.pendingRemovals_ = {};
  1205. this.dispatching_ = {};
  1206. this.listeners_ = {};
  1207. };
  1208. ol.inherits(ol.events.EventTarget, ol.Disposable);
  1209. /**
  1210. * @param {string} type Type.
  1211. * @param {ol.EventsListenerFunctionType} listener Listener.
  1212. */
  1213. ol.events.EventTarget.prototype.addEventListener = function(type, listener) {
  1214. var listeners = this.listeners_[type];
  1215. if (!listeners) {
  1216. listeners = this.listeners_[type] = [];
  1217. }
  1218. if (listeners.indexOf(listener) === -1) {
  1219. listeners.push(listener);
  1220. }
  1221. };
  1222. ol.events.EventTarget.prototype.dispatchEvent = function(event) {
  1223. var evt = typeof event === 'string' ? new ol.events.Event(event) : event;
  1224. var type = evt.type;
  1225. evt.target = this;
  1226. var listeners = this.listeners_[type];
  1227. var propagate;
  1228. if (listeners) {
  1229. if (!(type in this.dispatching_)) {
  1230. this.dispatching_[type] = 0;
  1231. this.pendingRemovals_[type] = 0;
  1232. }
  1233. ++this.dispatching_[type];
  1234. for (var i = 0, ii = listeners.length; i < ii; ++i) {
  1235. if (listeners[i].call(this, evt) === false || evt.propagationStopped) {
  1236. propagate = false;
  1237. break;
  1238. }
  1239. }
  1240. --this.dispatching_[type];
  1241. if (this.dispatching_[type] === 0) {
  1242. var pendingRemovals = this.pendingRemovals_[type];
  1243. delete this.pendingRemovals_[type];
  1244. while (pendingRemovals--) {
  1245. this.removeEventListener(type, ol.nullFunction);
  1246. }
  1247. delete this.dispatching_[type];
  1248. }
  1249. return propagate;
  1250. }
  1251. };
  1252. /**
  1253. * @inheritDoc
  1254. */
  1255. ol.events.EventTarget.prototype.disposeInternal = function() {
  1256. ol.events.unlistenAll(this);
  1257. };
  1258. /**
  1259. * Get the listeners for a specified event type. Listeners are returned in the
  1260. * order that they will be called in.
  1261. *
  1262. * @param {string} type Type.
  1263. * @return {Array.<ol.EventsListenerFunctionType>} Listeners.
  1264. */
  1265. ol.events.EventTarget.prototype.getListeners = function(type) {
  1266. return this.listeners_[type];
  1267. };
  1268. /**
  1269. * @param {string=} opt_type Type. If not provided,
  1270. * `true` will be returned if this EventTarget has any listeners.
  1271. * @return {boolean} Has listeners.
  1272. */
  1273. ol.events.EventTarget.prototype.hasListener = function(opt_type) {
  1274. return opt_type ?
  1275. opt_type in this.listeners_ :
  1276. Object.keys(this.listeners_).length > 0;
  1277. };
  1278. /**
  1279. * @param {string} type Type.
  1280. * @param {ol.EventsListenerFunctionType} listener Listener.
  1281. */
  1282. ol.events.EventTarget.prototype.removeEventListener = function(type, listener) {
  1283. var listeners = this.listeners_[type];
  1284. if (listeners) {
  1285. var index = listeners.indexOf(listener);
  1286. if (type in this.pendingRemovals_) {
  1287. // make listener a no-op, and remove later in #dispatchEvent()
  1288. listeners[index] = ol.nullFunction;
  1289. ++this.pendingRemovals_[type];
  1290. } else {
  1291. listeners.splice(index, 1);
  1292. if (listeners.length === 0) {
  1293. delete this.listeners_[type];
  1294. }
  1295. }
  1296. }
  1297. };
  1298. /**
  1299. * @enum {string}
  1300. * @const
  1301. */
  1302. ol.events.EventType = {
  1303. CHANGE: 'change',
  1304. CLEAR: 'clear',
  1305. CLICK: 'click',
  1306. DBLCLICK: 'dblclick',
  1307. DRAGENTER: 'dragenter',
  1308. DRAGOVER: 'dragover',
  1309. DROP: 'drop',
  1310. ERROR: 'error',
  1311. KEYDOWN: 'keydown',
  1312. KEYPRESS: 'keypress',
  1313. LOAD: 'load',
  1314. MOUSEDOWN: 'mousedown',
  1315. MOUSEMOVE: 'mousemove',
  1316. MOUSEOUT: 'mouseout',
  1317. MOUSEUP: 'mouseup',
  1318. MOUSEWHEEL: 'mousewheel',
  1319. MSPOINTERDOWN: 'MSPointerDown',
  1320. RESIZE: 'resize',
  1321. TOUCHSTART: 'touchstart',
  1322. TOUCHMOVE: 'touchmove',
  1323. TOUCHEND: 'touchend',
  1324. WHEEL: 'wheel'
  1325. };
  1326. ol.Observable = function() {
  1327. this.revision_ = 0;
  1328. };
  1329. ol.inherits(ol.Observable, ol.events.EventTarget);
  1330. ol.Observable.unByKey = function(key) {
  1331. if (Array.isArray(key)) {
  1332. for (var i = 0, ii = key.length; i < ii; ++i) {
  1333. ol.events.unlistenByKey(key[i]);
  1334. }
  1335. } else {
  1336. ol.events.unlistenByKey(/** @type {ol.EventsKey} */ (key));
  1337. }
  1338. };
  1339. /**
  1340. * Increases the revision counter and dispatches a 'change' event.
  1341. * @api
  1342. */
  1343. ol.Observable.prototype.changed = function() {
  1344. ++this.revision_;
  1345. //this.dispatchEvent(ol.events.EventType.CHANGE);
  1346. };
  1347. /**
  1348. * Dispatches an event and calls all listeners listening for events
  1349. * of this type. The event parameter can either be a string or an
  1350. * Object with a `type` property.
  1351. *
  1352. * @param {{type: string,
  1353. * target: (EventTarget|ol.events.EventTarget|undefined)}|ol.events.Event|
  1354. * string} event Event object.
  1355. * @function
  1356. * @api
  1357. */
  1358. ol.Observable.prototype.dispatchEvent;
  1359. /**
  1360. * Get the version number for this object. Each time the object is modified,
  1361. * its version number will be incremented.
  1362. * @return {number} Revision.
  1363. * @api
  1364. */
  1365. ol.Observable.prototype.getRevision = function() {
  1366. return this.revision_;
  1367. };
  1368. /**
  1369. * Listen for a certain type of event.
  1370. * @param {string|Array.<string>} type The event type or array of event types.
  1371. * @param {function(?): ?} listener The listener function.
  1372. * @param {Object=} opt_this The object to use as `this` in `listener`.
  1373. * @return {ol.EventsKey|Array.<ol.EventsKey>} Unique key for the listener. If
  1374. * called with an array of event types as the first argument, the return
  1375. * will be an array of keys.
  1376. * @api
  1377. */
  1378. ol.Observable.prototype.on = function(type, listener, opt_this) {
  1379. if (Array.isArray(type)) {
  1380. var len = type.length;
  1381. var keys = new Array(len);
  1382. for (var i = 0; i < len; ++i) {
  1383. keys[i] = ol.events.listen(this, type[i], listener, opt_this);
  1384. }
  1385. return keys;
  1386. } else {
  1387. return ol.events.listen(
  1388. this, /** @type {string} */ (type), listener, opt_this);
  1389. }
  1390. };
  1391. /**
  1392. * Listen once for a certain type of event.
  1393. * @param {string|Array.<string>} type The event type or array of event types.
  1394. * @param {function(?): ?} listener The listener function.
  1395. * @param {Object=} opt_this The object to use as `this` in `listener`.
  1396. * @return {ol.EventsKey|Array.<ol.EventsKey>} Unique key for the listener. If
  1397. * called with an array of event types as the first argument, the return
  1398. * will be an array of keys.
  1399. * @api
  1400. */
  1401. ol.Observable.prototype.once = function(type, listener, opt_this) {
  1402. if (Array.isArray(type)) {
  1403. var len = type.length;
  1404. var keys = new Array(len);
  1405. for (var i = 0; i < len; ++i) {
  1406. keys[i] = ol.events.listenOnce(this, type[i], listener, opt_this);
  1407. }
  1408. return keys;
  1409. } else {
  1410. return ol.events.listenOnce(
  1411. this, /** @type {string} */ (type), listener, opt_this);
  1412. }
  1413. };
  1414. /**
  1415. * Unlisten for a certain type of event.
  1416. * @param {string|Array.<string>} type The event type or array of event types.
  1417. * @param {function(?): ?} listener The listener function.
  1418. * @param {Object=} opt_this The object which was used as `this` by the
  1419. * `listener`.
  1420. * @api
  1421. */
  1422. ol.Observable.prototype.un = function(type, listener, opt_this) {
  1423. if (Array.isArray(type)) {
  1424. for (var i = 0, ii = type.length; i < ii; ++i) {
  1425. ol.events.unlisten(this, type[i], listener, opt_this);
  1426. }
  1427. return;
  1428. } else {
  1429. ol.events.unlisten(this, /** @type {string} */ (type), listener, opt_this);
  1430. }
  1431. };
  1432. ol.uidCounter_ = 0;
  1433. ol.Object = function(opt_values) {
  1434. ol.Observable.call(this);
  1435. // Call ol.getUid to ensure that the order of objects' ids is the same as
  1436. // the order in which they were created. This also helps to ensure that
  1437. // object properties are always added in the same order, which helps many
  1438. // JavaScript engines generate faster code.
  1439. ol.getUid(this);
  1440. /**
  1441. * @private
  1442. * @type {!Object.<string, *>}
  1443. */
  1444. this.values_ = {};
  1445. if (opt_values !== undefined) {
  1446. this.setProperties(opt_values);
  1447. }
  1448. };
  1449. ol.inherits(ol.Object, ol.Observable);
  1450. /**
  1451. * @private
  1452. * @type {Object.<string, string>}
  1453. */
  1454. ol.Object.changeEventTypeCache_ = {};
  1455. /**
  1456. * @param {string} key Key name.
  1457. * @return {string} Change name.
  1458. */
  1459. ol.Object.getChangeEventType = function(key) {
  1460. return ol.Object.changeEventTypeCache_.hasOwnProperty(key) ?
  1461. ol.Object.changeEventTypeCache_[key] :
  1462. (ol.Object.changeEventTypeCache_[key] = 'change:' + key);
  1463. };
  1464. /**
  1465. * Gets a value.
  1466. * @param {string} key Key name.
  1467. * @return {*} Value.
  1468. * @api
  1469. */
  1470. ol.Object.prototype.get = function(key) {
  1471. var value;
  1472. if (this.values_.hasOwnProperty(key)) {
  1473. value = this.values_[key];
  1474. }
  1475. return value;
  1476. };
  1477. /**
  1478. * Get a list of object property names.
  1479. * @return {Array.<string>} List of property names.
  1480. * @api
  1481. */
  1482. ol.Object.prototype.getKeys = function() {
  1483. return Object.keys(this.values_);
  1484. };
  1485. /**
  1486. * Get an object of all property names and values.
  1487. * @return {Object.<string, *>} Object.
  1488. * @api
  1489. */
  1490. ol.Object.prototype.getProperties = function() {
  1491. return ol.obj.assign({}, this.values_);
  1492. };
  1493. /**
  1494. * @param {string} key Key name.
  1495. * @param {*} oldValue Old value.
  1496. */
  1497. ol.Object.prototype.notify = function(key, oldValue) {
  1498. // FIX ME
  1499. return;
  1500. };
  1501. /**
  1502. * Sets a value.
  1503. * @param {string} key Key name.
  1504. * @param {*} value Value.
  1505. * @param {boolean=} opt_silent Update without triggering an event.
  1506. * @api
  1507. */
  1508. ol.Object.prototype.set = function(key, value, opt_silent) {
  1509. if (opt_silent) {
  1510. this.values_[key] = value;
  1511. } else {
  1512. var oldValue = this.values_[key];
  1513. this.values_[key] = value;
  1514. if (oldValue !== value) {
  1515. this.notify(key, oldValue);
  1516. }
  1517. }
  1518. };
  1519. /**
  1520. * Sets a collection of key-value pairs. Note that this changes any existing
  1521. * properties and adds new ones (it does not remove any existing properties).
  1522. * @param {Object.<string, *>} values Values.
  1523. * @param {boolean=} opt_silent Update without triggering an event.
  1524. * @api
  1525. */
  1526. ol.Object.prototype.setProperties = function(values, opt_silent) {
  1527. var key;
  1528. for (key in values) {
  1529. this.set(key, values[key], opt_silent);
  1530. }
  1531. };
  1532. /**
  1533. * Unsets a property.
  1534. * @param {string} key Key name.
  1535. * @param {boolean=} opt_silent Unset without triggering an event.
  1536. * @api
  1537. */
  1538. ol.Object.prototype.unset = function(key, opt_silent) {
  1539. if (key in this.values_) {
  1540. var oldValue = this.values_[key];
  1541. delete this.values_[key];
  1542. if (!opt_silent) {
  1543. this.notify(key, oldValue);
  1544. }
  1545. }
  1546. };
  1547. ol.Object.Event = function(type, key, oldValue) {
  1548. ol.events.Event.call(this, type);
  1549. this.key = key;
  1550. this.oldValue = oldValue;
  1551. };
  1552. ol.inherits(ol.Object.Event, ol.events.Event);
  1553. ol.functions = {};
  1554. /**
  1555. * Always returns true.
  1556. * @returns {boolean} true.
  1557. */
  1558. ol.functions.TRUE = function() {
  1559. return true;
  1560. };
  1561. /**
  1562. * Always returns false.
  1563. * @returns {boolean} false.
  1564. */
  1565. ol.functions.FALSE = function() {
  1566. return false;
  1567. };
  1568. ol.math = {};
  1569. ol.math.clamp = function(value, min, max) {
  1570. return Math.min(Math.max(value, min), max);
  1571. };
  1572. ol.math.cosh = (function() {
  1573. // Wrapped in a iife, to save the overhead of checking for the native
  1574. // implementation on every invocation.
  1575. var cosh;
  1576. if ('cosh' in Math) {
  1577. // The environment supports the native Math.cosh function, use it…
  1578. cosh = Math.cosh;
  1579. } else {
  1580. // … else, use the reference implementation of MDN:
  1581. cosh = function(x) {
  1582. var y = Math.exp(x);
  1583. return (y + 1 / y) / 2;
  1584. };
  1585. }
  1586. return cosh;
  1587. }());
  1588. /**
  1589. * @param {number} x X.
  1590. * @return {number} The smallest power of two greater than or equal to x.
  1591. */
  1592. ol.math.roundUpToPowerOfTwo = function(x) {
  1593. ol.asserts.assert(0 < x, 29); // `x` must be greater than `0`
  1594. return Math.pow(2, Math.ceil(Math.log(x) / Math.LN2));
  1595. };
  1596. ol.math.squaredSegmentDistance = function(x, y, x1, y1, x2, y2) {
  1597. var dx = x2 - x1;
  1598. var dy = y2 - y1;
  1599. if (dx !== 0 || dy !== 0) {
  1600. var t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy);
  1601. if (t > 1) {
  1602. x1 = x2;
  1603. y1 = y2;
  1604. } else if (t > 0) {
  1605. x1 += dx * t;
  1606. y1 += dy * t;
  1607. }
  1608. }
  1609. return ol.math.squaredDistance(x, y, x1, y1);
  1610. };
  1611. ol.math.squaredDistance = function(x1, y1, x2, y2) {
  1612. var dx = x2 - x1;
  1613. var dy = y2 - y1;
  1614. return dx * dx + dy * dy;
  1615. };
  1616. ol.math.solveLinearSystem = function(mat) {
  1617. var n = mat.length;
  1618. for (var i = 0; i < n; i++) {
  1619. // Find max in the i-th column (ignoring i - 1 first rows)
  1620. var maxRow = i;
  1621. var maxEl = Math.abs(mat[i][i]);
  1622. for (var r = i + 1; r < n; r++) {
  1623. var absValue = Math.abs(mat[r][i]);
  1624. if (absValue > maxEl) {
  1625. maxEl = absValue;
  1626. maxRow = r;
  1627. }
  1628. }
  1629. if (maxEl === 0) {
  1630. return null; // matrix is singular
  1631. }
  1632. // Swap max row with i-th (current) row
  1633. var tmp = mat[maxRow];
  1634. mat[maxRow] = mat[i];
  1635. mat[i] = tmp;
  1636. // Subtract the i-th row to make all the remaining rows 0 in the i-th column
  1637. for (var j = i + 1; j < n; j++) {
  1638. var coef = -mat[j][i] / mat[i][i];
  1639. for (var k = i; k < n + 1; k++) {
  1640. if (i == k) {
  1641. mat[j][k] = 0;
  1642. } else {
  1643. mat[j][k] += coef * mat[i][k];
  1644. }
  1645. }
  1646. }
  1647. }
  1648. // Solve Ax=b for upper triangular matrix A (mat)
  1649. var x = new Array(n);
  1650. for (var l = n - 1; l >= 0; l--) {
  1651. x[l] = mat[l][n] / mat[l][l];
  1652. for (var m = l - 1; m >= 0; m--) {
  1653. mat[m][n] -= mat[m][l] * x[l];
  1654. }
  1655. }
  1656. return x;
  1657. };
  1658. ol.math.toDegrees = function(angleInRadians) {
  1659. return angleInRadians * 180 / Math.PI;
  1660. };
  1661. ol.math.toRadians = function(angleInDegrees) {
  1662. return angleInDegrees * Math.PI / 180;
  1663. };
  1664. ol.math.modulo = function(a, b) {
  1665. var r = a % b;
  1666. return r * b < 0 ? r + b : r;
  1667. };
  1668. ol.math.lerp = function(a, b, x) {
  1669. return a + x * (b - a);
  1670. };
  1671. ol.ImageState = {
  1672. IDLE: 0,
  1673. LOADING: 1,
  1674. LOADED: 2,
  1675. ERROR: 3
  1676. };
  1677. ol.color = {};
  1678. ol.color.HEX_COLOR_RE_ = /^#(?:[0-9a-f]{3,4}){1,2}$/i;
  1679. ol.color.NAMED_COLOR_RE_ = /^([a-z]*)$/i;
  1680. ol.color.asArray = function(color) {
  1681. if (Array.isArray(color)) {
  1682. return color;
  1683. } else {
  1684. return ol.color.fromString(/** @type {string} */ (color));
  1685. }
  1686. };
  1687. ol.color.asString = function(color) {
  1688. if (typeof color === 'string') {
  1689. return color;
  1690. } else {
  1691. return ol.color.toString(color);
  1692. }
  1693. };
  1694. ol.color.fromNamed = function(color) {
  1695. var el = document.createElement('div');
  1696. el.style.color = color;
  1697. document.body.appendChild(el);
  1698. var rgb = getComputedStyle(el).color;
  1699. document.body.removeChild(el);
  1700. return rgb;
  1701. };
  1702. ol.color.fromString = (
  1703. function() {
  1704. // We maintain a small cache of parsed strings. To provide cheap LRU-like
  1705. // semantics, whenever the cache grows too large we simply delete an
  1706. // arbitrary 25% of the entries.
  1707. /**
  1708. * @const
  1709. * @type {number}
  1710. */
  1711. var MAX_CACHE_SIZE = 1024;
  1712. /**
  1713. * @type {Object.<string, ol.Color>}
  1714. */
  1715. var cache = {};
  1716. /**
  1717. * @type {number}
  1718. */
  1719. var cacheSize = 0;
  1720. return (
  1721. /**
  1722. * @param {string} s String.
  1723. * @return {ol.Color} Color.
  1724. */
  1725. function(s) {
  1726. var color;
  1727. if (cache.hasOwnProperty(s)) {
  1728. color = cache[s];
  1729. } else {
  1730. if (cacheSize >= MAX_CACHE_SIZE) {
  1731. var i = 0;
  1732. var key;
  1733. for (key in cache) {
  1734. if ((i++ & 3) === 0) {
  1735. delete cache[key];
  1736. --cacheSize;
  1737. }
  1738. }
  1739. }
  1740. color = ol.color.fromStringInternal_(s);
  1741. cache[s] = color;
  1742. ++cacheSize;
  1743. }
  1744. return color;
  1745. });
  1746. })();
  1747. ol.color.fromStringInternal_ = function(s) {
  1748. var r, g, b, a, color, parts;
  1749. if (ol.color.NAMED_COLOR_RE_.exec(s)) {
  1750. s = ol.color.fromNamed(s);
  1751. }
  1752. if (ol.color.HEX_COLOR_RE_.exec(s)) { // hex
  1753. var n = s.length - 1; // number of hex digits
  1754. var d; // number of digits per channel
  1755. if (n <= 4) {
  1756. d = 1;
  1757. } else {
  1758. d = 2;
  1759. }
  1760. var hasAlpha = n === 4 || n === 8;
  1761. r = parseInt(s.substr(1 + 0 * d, d), 16);
  1762. g = parseInt(s.substr(1 + 1 * d, d), 16);
  1763. b = parseInt(s.substr(1 + 2 * d, d), 16);
  1764. if (hasAlpha) {
  1765. a = parseInt(s.substr(1 + 3 * d, d), 16);
  1766. } else {
  1767. a = 255;
  1768. }
  1769. if (d == 1) {
  1770. r = (r << 4) + r;
  1771. g = (g << 4) + g;
  1772. b = (b << 4) + b;
  1773. if (hasAlpha) {
  1774. a = (a << 4) + a;
  1775. }
  1776. }
  1777. color = [r, g, b, a / 255];
  1778. } else if (s.indexOf('rgba(') == 0) { // rgba()
  1779. parts = s.slice(5, -1).split(',').map(Number);
  1780. color = ol.color.normalize(parts);
  1781. } else if (s.indexOf('rgb(') == 0) { // rgb()
  1782. parts = s.slice(4, -1).split(',').map(Number);
  1783. parts.push(1);
  1784. color = ol.color.normalize(parts);
  1785. } else {
  1786. ol.asserts.assert(false, 14); // Invalid color
  1787. }
  1788. return /** @type {ol.Color} */ (color);
  1789. };
  1790. /**
  1791. * @param {ol.Color} color Color.
  1792. * @param {ol.Color=} opt_color Color.
  1793. * @return {ol.Color} Clamped color.
  1794. */
  1795. ol.color.normalize = function(color, opt_color) {
  1796. var result = opt_color || [];
  1797. result[0] = ol.math.clamp((color[0] + 0.5) | 0, 0, 255);
  1798. result[1] = ol.math.clamp((color[1] + 0.5) | 0, 0, 255);
  1799. result[2] = ol.math.clamp((color[2] + 0.5) | 0, 0, 255);
  1800. result[3] = ol.math.clamp(color[3], 0, 1);
  1801. return result;
  1802. };
  1803. /**
  1804. * @param {ol.Color} color Color.
  1805. * @return {string} String.
  1806. */
  1807. ol.color.toString = function(color) {
  1808. var r = color[0];
  1809. if (r != (r | 0)) {
  1810. r = (r + 0.5) | 0;
  1811. }
  1812. var g = color[1];
  1813. if (g != (g | 0)) {
  1814. g = (g + 0.5) | 0;
  1815. }
  1816. var b = color[2];
  1817. if (b != (b | 0)) {
  1818. b = (b + 0.5) | 0;
  1819. }
  1820. var a = color[3] === undefined ? 1 : color[3];
  1821. return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
  1822. };
  1823. ol.colorlike = {};
  1824. ol.colorlike.asColorLike = function(color) {
  1825. if (ol.colorlike.isColorLike(color)) {
  1826. return /** @type {string|CanvasPattern|CanvasGradient} */ (color);
  1827. } else {
  1828. return ol.color.asString(/** @type {ol.Color} */ (color));
  1829. }
  1830. };
  1831. ol.colorlike.isColorLike = function(color) {
  1832. return (
  1833. typeof color === 'string' ||
  1834. color instanceof CanvasPattern ||
  1835. color instanceof CanvasGradient
  1836. );
  1837. };
  1838. ol.css = {};
  1839. ol.css.CLASS_HIDDEN = 'ol-hidden';
  1840. ol.css.CLASS_SELECTABLE = 'ol-selectable';
  1841. ol.css.CLASS_UNSELECTABLE = 'ol-unselectable';
  1842. ol.css.CLASS_UNSUPPORTED = 'ol-unsupported';
  1843. ol.css.CLASS_CONTROL = 'ol-control';
  1844. ol.css.getFontFamilies = (function() {
  1845. var style;
  1846. var cache = {};
  1847. return function(font) {
  1848. if (!style) {
  1849. style = document.createElement('div').style;
  1850. }
  1851. if (!(font in cache)) {
  1852. style.font = font;
  1853. var family = style.fontFamily;
  1854. style.font = '';
  1855. if (!family) {
  1856. return null;
  1857. }
  1858. cache[font] = family.split(/,\s?/);
  1859. }
  1860. return cache[font];
  1861. };
  1862. })();
  1863. ol.dom = {};
  1864. /**
  1865. * Create an html canvas element and returns its 2d context.
  1866. * @param {number=} opt_width Canvas width.
  1867. * @param {number=} opt_height Canvas height.
  1868. * @return {CanvasRenderingContext2D} The context.
  1869. */
  1870. ol.dom.createCanvasContext2D = function(opt_width, opt_height) {
  1871. //var canvas = document.createElement('CANVAS');
  1872. var canvas;
  1873. if (opt_width && opt_height) {
  1874. canvas = new OffscreenCanvas(opt_width, opt_height);
  1875. }
  1876. else{
  1877. canvas = new OffscreenCanvas(1, 1);
  1878. }
  1879. return canvas.getContext('2d');
  1880. };
  1881. /**
  1882. * Get the current computed width for the given element including margin,
  1883. * padding and border.
  1884. * Equivalent to jQuery's `$(el).outerWidth(true)`.
  1885. * @param {!Element} element Element.
  1886. * @return {number} The width.
  1887. */
  1888. ol.dom.outerWidth = function(element) {
  1889. var width = element.offsetWidth;
  1890. var style = getComputedStyle(element);
  1891. width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10);
  1892. return width;
  1893. };
  1894. /**
  1895. * Get the current computed height for the given element including margin,
  1896. * padding and border.
  1897. * Equivalent to jQuery's `$(el).outerHeight(true)`.
  1898. * @param {!Element} element Element.
  1899. * @return {number} The height.
  1900. */
  1901. ol.dom.outerHeight = function(element) {
  1902. var height = element.offsetHeight;
  1903. var style = getComputedStyle(element);
  1904. height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10);
  1905. return height;
  1906. };
  1907. /**
  1908. * @param {Node} newNode Node to replace old node
  1909. * @param {Node} oldNode The node to be replaced
  1910. */
  1911. ol.dom.replaceNode = function(newNode, oldNode) {
  1912. var parent = oldNode.parentNode;
  1913. if (parent) {
  1914. parent.replaceChild(newNode, oldNode);
  1915. }
  1916. };
  1917. /**
  1918. * @param {Node} node The node to remove.
  1919. * @returns {Node} The node that was removed or null.
  1920. */
  1921. ol.dom.removeNode = function(node) {
  1922. return node && node.parentNode ? node.parentNode.removeChild(node) : null;
  1923. };
  1924. /**
  1925. * @param {Node} node The node to remove the children from.
  1926. */
  1927. ol.dom.removeChildren = function(node) {
  1928. while (node.lastChild) {
  1929. node.removeChild(node.lastChild);
  1930. }
  1931. };
  1932. ol.extent = {};
  1933. ol.extent.Corner = {
  1934. BOTTOM_LEFT: 'bottom-left',
  1935. BOTTOM_RIGHT: 'bottom-right',
  1936. TOP_LEFT: 'top-left',
  1937. TOP_RIGHT: 'top-right'
  1938. };
  1939. /**
  1940. * Relationship to an extent.
  1941. * @enum {number}
  1942. */
  1943. ol.extent.Relationship = {
  1944. UNKNOWN: 0,
  1945. INTERSECTING: 1,
  1946. ABOVE: 2,
  1947. RIGHT: 4,
  1948. BELOW: 8,
  1949. LEFT: 16
  1950. };
  1951. /**
  1952. * Build an extent that includes all given coordinates.
  1953. *
  1954. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  1955. * @return {ol.Extent} Bounding extent.
  1956. * @api
  1957. */
  1958. ol.extent.boundingExtent = function(coordinates) {
  1959. var extent = ol.extent.createEmpty();
  1960. for (var i = 0, ii = coordinates.length; i < ii; ++i) {
  1961. ol.extent.extendCoordinate(extent, coordinates[i]);
  1962. }
  1963. return extent;
  1964. };
  1965. ol.extent.boundingExtentXYs_ = function(xs, ys, opt_extent) {
  1966. var minX = Math.min.apply(null, xs);
  1967. var minY = Math.min.apply(null, ys);
  1968. var maxX = Math.max.apply(null, xs);
  1969. var maxY = Math.max.apply(null, ys);
  1970. return ol.extent.createOrUpdate(minX, minY, maxX, maxY, opt_extent);
  1971. };
  1972. ol.extent.buffer = function(extent, value, opt_extent) {
  1973. if (opt_extent) {
  1974. opt_extent[0] = extent[0] - value;
  1975. opt_extent[1] = extent[1] - value;
  1976. opt_extent[2] = extent[2] + value;
  1977. opt_extent[3] = extent[3] + value;
  1978. return opt_extent;
  1979. } else {
  1980. return [
  1981. extent[0] - value,
  1982. extent[1] - value,
  1983. extent[2] + value,
  1984. extent[3] + value
  1985. ];
  1986. }
  1987. };
  1988. ol.extent.clone = function(extent, opt_extent) {
  1989. if (opt_extent) {
  1990. opt_extent[0] = extent[0];
  1991. opt_extent[1] = extent[1];
  1992. opt_extent[2] = extent[2];
  1993. opt_extent[3] = extent[3];
  1994. return opt_extent;
  1995. } else {
  1996. return extent.slice();
  1997. }
  1998. };
  1999. ol.extent.closestSquaredDistanceXY = function(extent, x, y) {
  2000. var dx, dy;
  2001. if (x < extent[0]) {
  2002. dx = extent[0] - x;
  2003. } else if (extent[2] < x) {
  2004. dx = x - extent[2];
  2005. } else {
  2006. dx = 0;
  2007. }
  2008. if (y < extent[1]) {
  2009. dy = extent[1] - y;
  2010. } else if (extent[3] < y) {
  2011. dy = y - extent[3];
  2012. } else {
  2013. dy = 0;
  2014. }
  2015. return dx * dx + dy * dy;
  2016. };
  2017. /**
  2018. * Check if the passed coordinate is contained or on the edge of the extent.
  2019. *
  2020. * @param {ol.Extent} extent Extent.
  2021. * @param {ol.Coordinate} coordinate Coordinate.
  2022. * @return {boolean} The coordinate is contained in the extent.
  2023. * @api
  2024. */
  2025. ol.extent.containsCoordinate = function(extent, coordinate) {
  2026. return ol.extent.containsXY(extent, coordinate[0], coordinate[1]);
  2027. };
  2028. /**
  2029. * Check if one extent contains another.
  2030. *
  2031. * An extent is deemed contained if it lies completely within the other extent,
  2032. * including if they share one or more edges.
  2033. *
  2034. * @param {ol.Extent} extent1 Extent 1.
  2035. * @param {ol.Extent} extent2 Extent 2.
  2036. * @return {boolean} The second extent is contained by or on the edge of the
  2037. * first.
  2038. * @api
  2039. */
  2040. ol.extent.containsExtent = function(extent1, extent2) {
  2041. return extent1[0] <= extent2[0] && extent2[2] <= extent1[2] &&
  2042. extent1[1] <= extent2[1] && extent2[3] <= extent1[3];
  2043. };
  2044. /**
  2045. * Check if the passed coordinate is contained or on the edge of the extent.
  2046. *
  2047. * @param {ol.Extent} extent Extent.
  2048. * @param {number} x X coordinate.
  2049. * @param {number} y Y coordinate.
  2050. * @return {boolean} The x, y values are contained in the extent.
  2051. * @api
  2052. */
  2053. ol.extent.containsXY = function(extent, x, y) {
  2054. return extent[0] <= x && x <= extent[2] && extent[1] <= y && y <= extent[3];
  2055. };
  2056. /**
  2057. * Get the relationship between a coordinate and extent.
  2058. * @param {ol.Extent} extent The extent.
  2059. * @param {ol.Coordinate} coordinate The coordinate.
  2060. * @return {number} The relationship (bitwise compare with
  2061. * ol.extent.Relationship).
  2062. */
  2063. ol.extent.coordinateRelationship = function(extent, coordinate) {
  2064. var minX = extent[0];
  2065. var minY = extent[1];
  2066. var maxX = extent[2];
  2067. var maxY = extent[3];
  2068. var x = coordinate[0];
  2069. var y = coordinate[1];
  2070. var relationship = ol.extent.Relationship.UNKNOWN;
  2071. if (x < minX) {
  2072. relationship = relationship | ol.extent.Relationship.LEFT;
  2073. } else if (x > maxX) {
  2074. relationship = relationship | ol.extent.Relationship.RIGHT;
  2075. }
  2076. if (y < minY) {
  2077. relationship = relationship | ol.extent.Relationship.BELOW;
  2078. } else if (y > maxY) {
  2079. relationship = relationship | ol.extent.Relationship.ABOVE;
  2080. }
  2081. if (relationship === ol.extent.Relationship.UNKNOWN) {
  2082. relationship = ol.extent.Relationship.INTERSECTING;
  2083. }
  2084. return relationship;
  2085. };
  2086. /**
  2087. * Create an empty extent.
  2088. * @return {ol.Extent} Empty extent.
  2089. * @api
  2090. */
  2091. ol.extent.createEmpty = function() {
  2092. return [Infinity, Infinity, -Infinity, -Infinity];
  2093. };
  2094. /**
  2095. * Create a new extent or update the provided extent.
  2096. * @param {number} minX Minimum X.
  2097. * @param {number} minY Minimum Y.
  2098. * @param {number} maxX Maximum X.
  2099. * @param {number} maxY Maximum Y.
  2100. * @param {ol.Extent=} opt_extent Destination extent.
  2101. * @return {ol.Extent} Extent.
  2102. */
  2103. ol.extent.createOrUpdate = function(minX, minY, maxX, maxY, opt_extent) {
  2104. if (opt_extent) {
  2105. opt_extent[0] = minX;
  2106. opt_extent[1] = minY;
  2107. opt_extent[2] = maxX;
  2108. opt_extent[3] = maxY;
  2109. return opt_extent;
  2110. } else {
  2111. return [minX, minY, maxX, maxY];
  2112. }
  2113. };
  2114. /**
  2115. * Create a new empty extent or make the provided one empty.
  2116. * @param {ol.Extent=} opt_extent Extent.
  2117. * @return {ol.Extent} Extent.
  2118. */
  2119. ol.extent.createOrUpdateEmpty = function(opt_extent) {
  2120. return ol.extent.createOrUpdate(
  2121. Infinity, Infinity, -Infinity, -Infinity, opt_extent);
  2122. };
  2123. /**
  2124. * @param {ol.Coordinate} coordinate Coordinate.
  2125. * @param {ol.Extent=} opt_extent Extent.
  2126. * @return {ol.Extent} Extent.
  2127. */
  2128. ol.extent.createOrUpdateFromCoordinate = function(coordinate, opt_extent) {
  2129. var x = coordinate[0];
  2130. var y = coordinate[1];
  2131. return ol.extent.createOrUpdate(x, y, x, y, opt_extent);
  2132. };
  2133. /**
  2134. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  2135. * @param {ol.Extent=} opt_extent Extent.
  2136. * @return {ol.Extent} Extent.
  2137. */
  2138. ol.extent.createOrUpdateFromCoordinates = function(coordinates, opt_extent) {
  2139. var extent = ol.extent.createOrUpdateEmpty(opt_extent);
  2140. return ol.extent.extendCoordinates(extent, coordinates);
  2141. };
  2142. /**
  2143. * @param {Array.<number>} flatCoordinates Flat coordinates.
  2144. * @param {number} offset Offset.
  2145. * @param {number} end End.
  2146. * @param {number} stride Stride.
  2147. * @param {ol.Extent=} opt_extent Extent.
  2148. * @return {ol.Extent} Extent.
  2149. */
  2150. ol.extent.createOrUpdateFromFlatCoordinates = function(flatCoordinates, offset, end, stride, opt_extent) {
  2151. var extent = ol.extent.createOrUpdateEmpty(opt_extent);
  2152. return ol.extent.extendFlatCoordinates(
  2153. extent, flatCoordinates, offset, end, stride);
  2154. };
  2155. /**
  2156. * @param {Array.<Array.<ol.Coordinate>>} rings Rings.
  2157. * @param {ol.Extent=} opt_extent Extent.
  2158. * @return {ol.Extent} Extent.
  2159. */
  2160. ol.extent.createOrUpdateFromRings = function(rings, opt_extent) {
  2161. var extent = ol.extent.createOrUpdateEmpty(opt_extent);
  2162. return ol.extent.extendRings(extent, rings);
  2163. };
  2164. /**
  2165. * Determine if two extents are equivalent.
  2166. * @param {ol.Extent} extent1 Extent 1.
  2167. * @param {ol.Extent} extent2 Extent 2.
  2168. * @return {boolean} The two extents are equivalent.
  2169. * @api
  2170. */
  2171. ol.extent.equals = function(extent1, extent2) {
  2172. return extent1[0] == extent2[0] && extent1[2] == extent2[2] &&
  2173. extent1[1] == extent2[1] && extent1[3] == extent2[3];
  2174. };
  2175. /**
  2176. * Modify an extent to include another extent.
  2177. * @param {ol.Extent} extent1 The extent to be modified.
  2178. * @param {ol.Extent} extent2 The extent that will be included in the first.
  2179. * @return {ol.Extent} A reference to the first (extended) extent.
  2180. * @api
  2181. */
  2182. ol.extent.extend = function(extent1, extent2) {
  2183. if (extent2[0] < extent1[0]) {
  2184. extent1[0] = extent2[0];
  2185. }
  2186. if (extent2[2] > extent1[2]) {
  2187. extent1[2] = extent2[2];
  2188. }
  2189. if (extent2[1] < extent1[1]) {
  2190. extent1[1] = extent2[1];
  2191. }
  2192. if (extent2[3] > extent1[3]) {
  2193. extent1[3] = extent2[3];
  2194. }
  2195. return extent1;
  2196. };
  2197. /**
  2198. * @param {ol.Extent} extent Extent.
  2199. * @param {ol.Coordinate} coordinate Coordinate.
  2200. */
  2201. ol.extent.extendCoordinate = function(extent, coordinate) {
  2202. if (coordinate[0] < extent[0]) {
  2203. extent[0] = coordinate[0];
  2204. }
  2205. if (coordinate[0] > extent[2]) {
  2206. extent[2] = coordinate[0];
  2207. }
  2208. if (coordinate[1] < extent[1]) {
  2209. extent[1] = coordinate[1];
  2210. }
  2211. if (coordinate[1] > extent[3]) {
  2212. extent[3] = coordinate[1];
  2213. }
  2214. };
  2215. /**
  2216. * @param {ol.Extent} extent Extent.
  2217. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  2218. * @return {ol.Extent} Extent.
  2219. */
  2220. ol.extent.extendCoordinates = function(extent, coordinates) {
  2221. var i, ii;
  2222. for (i = 0, ii = coordinates.length; i < ii; ++i) {
  2223. ol.extent.extendCoordinate(extent, coordinates[i]);
  2224. }
  2225. return extent;
  2226. };
  2227. /**
  2228. * @param {ol.Extent} extent Extent.
  2229. * @param {Array.<number>} flatCoordinates Flat coordinates.
  2230. * @param {number} offset Offset.
  2231. * @param {number} end End.
  2232. * @param {number} stride Stride.
  2233. * @return {ol.Extent} Extent.
  2234. */
  2235. ol.extent.extendFlatCoordinates = function(extent, flatCoordinates, offset, end, stride) {
  2236. for (; offset < end; offset += stride) {
  2237. ol.extent.extendXY(
  2238. extent, flatCoordinates[offset], flatCoordinates[offset + 1]);
  2239. }
  2240. return extent;
  2241. };
  2242. /**
  2243. * @param {ol.Extent} extent Extent.
  2244. * @param {Array.<Array.<ol.Coordinate>>} rings Rings.
  2245. * @return {ol.Extent} Extent.
  2246. */
  2247. ol.extent.extendRings = function(extent, rings) {
  2248. var i, ii;
  2249. for (i = 0, ii = rings.length; i < ii; ++i) {
  2250. ol.extent.extendCoordinates(extent, rings[i]);
  2251. }
  2252. return extent;
  2253. };
  2254. /**
  2255. * @param {ol.Extent} extent Extent.
  2256. * @param {number} x X.
  2257. * @param {number} y Y.
  2258. */
  2259. ol.extent.extendXY = function(extent, x, y) {
  2260. extent[0] = Math.min(extent[0], x);
  2261. extent[1] = Math.min(extent[1], y);
  2262. extent[2] = Math.max(extent[2], x);
  2263. extent[3] = Math.max(extent[3], y);
  2264. };
  2265. /**
  2266. * This function calls `callback` for each corner of the extent. If the
  2267. * callback returns a truthy value the function returns that value
  2268. * immediately. Otherwise the function returns `false`.
  2269. * @param {ol.Extent} extent Extent.
  2270. * @param {function(this:T, ol.Coordinate): S} callback Callback.
  2271. * @param {T=} opt_this Value to use as `this` when executing `callback`.
  2272. * @return {S|boolean} Value.
  2273. * @template S, T
  2274. */
  2275. ol.extent.forEachCorner = function(extent, callback, opt_this) {
  2276. var val;
  2277. val = callback.call(opt_this, ol.extent.getBottomLeft(extent));
  2278. if (val) {
  2279. return val;
  2280. }
  2281. val = callback.call(opt_this, ol.extent.getBottomRight(extent));
  2282. if (val) {
  2283. return val;
  2284. }
  2285. val = callback.call(opt_this, ol.extent.getTopRight(extent));
  2286. if (val) {
  2287. return val;
  2288. }
  2289. val = callback.call(opt_this, ol.extent.getTopLeft(extent));
  2290. if (val) {
  2291. return val;
  2292. }
  2293. return false;
  2294. };
  2295. /**
  2296. * Get the size of an extent.
  2297. * @param {ol.Extent} extent Extent.
  2298. * @return {number} Area.
  2299. * @api
  2300. */
  2301. ol.extent.getArea = function(extent) {
  2302. var area = 0;
  2303. if (!ol.extent.isEmpty(extent)) {
  2304. area = ol.extent.getWidth(extent) * ol.extent.getHeight(extent);
  2305. }
  2306. return area;
  2307. };
  2308. /**
  2309. * Get the bottom left coordinate of an extent.
  2310. * @param {ol.Extent} extent Extent.
  2311. * @return {ol.Coordinate} Bottom left coordinate.
  2312. * @api
  2313. */
  2314. ol.extent.getBottomLeft = function(extent) {
  2315. return [extent[0], extent[1]];
  2316. };
  2317. /**
  2318. * Get the bottom right coordinate of an extent.
  2319. * @param {ol.Extent} extent Extent.
  2320. * @return {ol.Coordinate} Bottom right coordinate.
  2321. * @api
  2322. */
  2323. ol.extent.getBottomRight = function(extent) {
  2324. return [extent[2], extent[1]];
  2325. };
  2326. /**
  2327. * Get the center coordinate of an extent.
  2328. * @param {ol.Extent} extent Extent.
  2329. * @return {ol.Coordinate} Center.
  2330. * @api
  2331. */
  2332. ol.extent.getCenter = function(extent) {
  2333. return [(extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2];
  2334. };
  2335. /**
  2336. * Get a corner coordinate of an extent.
  2337. * @param {ol.Extent} extent Extent.
  2338. * @param {ol.extent.Corner} corner Corner.
  2339. * @return {ol.Coordinate} Corner coordinate.
  2340. */
  2341. ol.extent.getCorner = function(extent, corner) {
  2342. var coordinate;
  2343. if (corner === ol.extent.Corner.BOTTOM_LEFT) {
  2344. coordinate = ol.extent.getBottomLeft(extent);
  2345. } else if (corner === ol.extent.Corner.BOTTOM_RIGHT) {
  2346. coordinate = ol.extent.getBottomRight(extent);
  2347. } else if (corner === ol.extent.Corner.TOP_LEFT) {
  2348. coordinate = ol.extent.getTopLeft(extent);
  2349. } else if (corner === ol.extent.Corner.TOP_RIGHT) {
  2350. coordinate = ol.extent.getTopRight(extent);
  2351. } else {
  2352. ol.asserts.assert(false, 13); // Invalid corner
  2353. }
  2354. return /** @type {!ol.Coordinate} */ (coordinate);
  2355. };
  2356. /**
  2357. * @param {ol.Extent} extent1 Extent 1.
  2358. * @param {ol.Extent} extent2 Extent 2.
  2359. * @return {number} Enlarged area.
  2360. */
  2361. ol.extent.getEnlargedArea = function(extent1, extent2) {
  2362. var minX = Math.min(extent1[0], extent2[0]);
  2363. var minY = Math.min(extent1[1], extent2[1]);
  2364. var maxX = Math.max(extent1[2], extent2[2]);
  2365. var maxY = Math.max(extent1[3], extent2[3]);
  2366. return (maxX - minX) * (maxY - minY);
  2367. };
  2368. /**
  2369. * @param {ol.Coordinate} center Center.
  2370. * @param {number} resolution Resolution.
  2371. * @param {number} rotation Rotation.
  2372. * @param {ol.Size} size Size.
  2373. * @param {ol.Extent=} opt_extent Destination extent.
  2374. * @return {ol.Extent} Extent.
  2375. */
  2376. ol.extent.getForViewAndSize = function(center, resolution, rotation, size, opt_extent) {
  2377. var dx = resolution * size[0] / 2;
  2378. var dy = resolution * size[1] / 2;
  2379. var cosRotation = Math.cos(rotation);
  2380. var sinRotation = Math.sin(rotation);
  2381. var xCos = dx * cosRotation;
  2382. var xSin = dx * sinRotation;
  2383. var yCos = dy * cosRotation;
  2384. var ySin = dy * sinRotation;
  2385. var x = center[0];
  2386. var y = center[1];
  2387. var x0 = x - xCos + ySin;
  2388. var x1 = x - xCos - ySin;
  2389. var x2 = x + xCos - ySin;
  2390. var x3 = x + xCos + ySin;
  2391. var y0 = y - xSin - yCos;
  2392. var y1 = y - xSin + yCos;
  2393. var y2 = y + xSin + yCos;
  2394. var y3 = y + xSin - yCos;
  2395. return ol.extent.createOrUpdate(
  2396. Math.min(x0, x1, x2, x3), Math.min(y0, y1, y2, y3),
  2397. Math.max(x0, x1, x2, x3), Math.max(y0, y1, y2, y3),
  2398. opt_extent);
  2399. };
  2400. /**
  2401. * Get the height of an extent.
  2402. * @param {ol.Extent} extent Extent.
  2403. * @return {number} Height.
  2404. * @api
  2405. */
  2406. ol.extent.getHeight = function(extent) {
  2407. return extent[3] - extent[1];
  2408. };
  2409. /**
  2410. * @param {ol.Extent} extent1 Extent 1.
  2411. * @param {ol.Extent} extent2 Extent 2.
  2412. * @return {number} Intersection area.
  2413. */
  2414. ol.extent.getIntersectionArea = function(extent1, extent2) {
  2415. var intersection = ol.extent.getIntersection(extent1, extent2);
  2416. return ol.extent.getArea(intersection);
  2417. };
  2418. /**
  2419. * Get the intersection of two extents.
  2420. * @param {ol.Extent} extent1 Extent 1.
  2421. * @param {ol.Extent} extent2 Extent 2.
  2422. * @param {ol.Extent=} opt_extent Optional extent to populate with intersection.
  2423. * @return {ol.Extent} Intersecting extent.
  2424. * @api
  2425. */
  2426. ol.extent.getIntersection = function(extent1, extent2, opt_extent) {
  2427. var intersection = opt_extent ? opt_extent : ol.extent.createEmpty();
  2428. if (ol.extent.intersects(extent1, extent2)) {
  2429. if (extent1[0] > extent2[0]) {
  2430. intersection[0] = extent1[0];
  2431. } else {
  2432. intersection[0] = extent2[0];
  2433. }
  2434. if (extent1[1] > extent2[1]) {
  2435. intersection[1] = extent1[1];
  2436. } else {
  2437. intersection[1] = extent2[1];
  2438. }
  2439. if (extent1[2] < extent2[2]) {
  2440. intersection[2] = extent1[2];
  2441. } else {
  2442. intersection[2] = extent2[2];
  2443. }
  2444. if (extent1[3] < extent2[3]) {
  2445. intersection[3] = extent1[3];
  2446. } else {
  2447. intersection[3] = extent2[3];
  2448. }
  2449. }
  2450. return intersection;
  2451. };
  2452. /**
  2453. * @param {ol.Extent} extent Extent.
  2454. * @return {number} Margin.
  2455. */
  2456. ol.extent.getMargin = function(extent) {
  2457. return ol.extent.getWidth(extent) + ol.extent.getHeight(extent);
  2458. };
  2459. /**
  2460. * Get the size (width, height) of an extent.
  2461. * @param {ol.Extent} extent The extent.
  2462. * @return {ol.Size} The extent size.
  2463. * @api
  2464. */
  2465. ol.extent.getSize = function(extent) {
  2466. return [extent[2] - extent[0], extent[3] - extent[1]];
  2467. };
  2468. /**
  2469. * Get the top left coordinate of an extent.
  2470. * @param {ol.Extent} extent Extent.
  2471. * @return {ol.Coordinate} Top left coordinate.
  2472. * @api
  2473. */
  2474. ol.extent.getTopLeft = function(extent) {
  2475. return [extent[0], extent[3]];
  2476. };
  2477. /**
  2478. * Get the top right coordinate of an extent.
  2479. * @param {ol.Extent} extent Extent.
  2480. * @return {ol.Coordinate} Top right coordinate.
  2481. * @api
  2482. */
  2483. ol.extent.getTopRight = function(extent) {
  2484. return [extent[2], extent[3]];
  2485. };
  2486. /**
  2487. * Get the width of an extent.
  2488. * @param {ol.Extent} extent Extent.
  2489. * @return {number} Width.
  2490. * @api
  2491. */
  2492. ol.extent.getWidth = function(extent) {
  2493. return extent[2] - extent[0];
  2494. };
  2495. /**
  2496. * Determine if one extent intersects another.
  2497. * @param {ol.Extent} extent1 Extent 1.
  2498. * @param {ol.Extent} extent2 Extent.
  2499. * @return {boolean} The two extents intersect.
  2500. * @api
  2501. */
  2502. ol.extent.intersects = function(extent1, extent2) {
  2503. return extent1[0] <= extent2[2] &&
  2504. extent1[2] >= extent2[0] &&
  2505. extent1[1] <= extent2[3] &&
  2506. extent1[3] >= extent2[1];
  2507. };
  2508. /**
  2509. * Determine if an extent is empty.
  2510. * @param {ol.Extent} extent Extent.
  2511. * @return {boolean} Is empty.
  2512. * @api
  2513. */
  2514. ol.extent.isEmpty = function(extent) {
  2515. return extent[2] < extent[0] || extent[3] < extent[1];
  2516. };
  2517. /**
  2518. * @param {ol.Extent} extent Extent.
  2519. * @param {ol.Extent=} opt_extent Extent.
  2520. * @return {ol.Extent} Extent.
  2521. */
  2522. ol.extent.returnOrUpdate = function(extent, opt_extent) {
  2523. if (opt_extent) {
  2524. opt_extent[0] = extent[0];
  2525. opt_extent[1] = extent[1];
  2526. opt_extent[2] = extent[2];
  2527. opt_extent[3] = extent[3];
  2528. return opt_extent;
  2529. } else {
  2530. return extent;
  2531. }
  2532. };
  2533. /**
  2534. * @param {ol.Extent} extent Extent.
  2535. * @param {number} value Value.
  2536. */
  2537. ol.extent.scaleFromCenter = function(extent, value) {
  2538. var deltaX = ((extent[2] - extent[0]) / 2) * (value - 1);
  2539. var deltaY = ((extent[3] - extent[1]) / 2) * (value - 1);
  2540. extent[0] -= deltaX;
  2541. extent[2] += deltaX;
  2542. extent[1] -= deltaY;
  2543. extent[3] += deltaY;
  2544. };
  2545. /**
  2546. * Determine if the segment between two coordinates intersects (crosses,
  2547. * touches, or is contained by) the provided extent.
  2548. * @param {ol.Extent} extent The extent.
  2549. * @param {ol.Coordinate} start Segment start coordinate.
  2550. * @param {ol.Coordinate} end Segment end coordinate.
  2551. * @return {boolean} The segment intersects the extent.
  2552. */
  2553. ol.extent.intersectsSegment = function(extent, start, end) {
  2554. var intersects = false;
  2555. var startRel = ol.extent.coordinateRelationship(extent, start);
  2556. var endRel = ol.extent.coordinateRelationship(extent, end);
  2557. if (startRel === ol.extent.Relationship.INTERSECTING ||
  2558. endRel === ol.extent.Relationship.INTERSECTING) {
  2559. intersects = true;
  2560. } else {
  2561. var minX = extent[0];
  2562. var minY = extent[1];
  2563. var maxX = extent[2];
  2564. var maxY = extent[3];
  2565. var startX = start[0];
  2566. var startY = start[1];
  2567. var endX = end[0];
  2568. var endY = end[1];
  2569. var slope = (endY - startY) / (endX - startX);
  2570. var x, y;
  2571. if (!!(endRel & ol.extent.Relationship.ABOVE) &&
  2572. !(startRel & ol.extent.Relationship.ABOVE)) {
  2573. // potentially intersects top
  2574. x = endX - ((endY - maxY) / slope);
  2575. intersects = x >= minX && x <= maxX;
  2576. }
  2577. if (!intersects && !!(endRel & ol.extent.Relationship.RIGHT) &&
  2578. !(startRel & ol.extent.Relationship.RIGHT)) {
  2579. // potentially intersects right
  2580. y = endY - ((endX - maxX) * slope);
  2581. intersects = y >= minY && y <= maxY;
  2582. }
  2583. if (!intersects && !!(endRel & ol.extent.Relationship.BELOW) &&
  2584. !(startRel & ol.extent.Relationship.BELOW)) {
  2585. // potentially intersects bottom
  2586. x = endX - ((endY - minY) / slope);
  2587. intersects = x >= minX && x <= maxX;
  2588. }
  2589. if (!intersects && !!(endRel & ol.extent.Relationship.LEFT) &&
  2590. !(startRel & ol.extent.Relationship.LEFT)) {
  2591. // potentially intersects left
  2592. y = endY - ((endX - minX) * slope);
  2593. intersects = y >= minY && y <= maxY;
  2594. }
  2595. }
  2596. return intersects;
  2597. };
  2598. /**
  2599. * Apply a transform function to the extent.
  2600. * @param {ol.Extent} extent Extent.
  2601. * @param {ol.TransformFunction} transformFn Transform function. Called with
  2602. * [minX, minY, maxX, maxY] extent coordinates.
  2603. * @param {ol.Extent=} opt_extent Destination extent.
  2604. * @return {ol.Extent} Extent.
  2605. * @api
  2606. */
  2607. ol.extent.applyTransform = function(extent, transformFn, opt_extent) {
  2608. var coordinates = [
  2609. extent[0], extent[1],
  2610. extent[0], extent[3],
  2611. extent[2], extent[1],
  2612. extent[2], extent[3]
  2613. ];
  2614. transformFn(coordinates, coordinates, 2);
  2615. var xs = [coordinates[0], coordinates[2], coordinates[4], coordinates[6]];
  2616. var ys = [coordinates[1], coordinates[3], coordinates[5], coordinates[7]];
  2617. return ol.extent.boundingExtentXYs_(xs, ys, opt_extent);
  2618. };
  2619. ol.obj = {};
  2620. /**
  2621. * Polyfill for Object.assign(). Assigns enumerable and own properties from
  2622. * one or more source objects to a target object.
  2623. *
  2624. * @see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
  2625. * @param {!Object} target The target object.
  2626. * @param {...Object} var_sources The source object(s).
  2627. * @return {!Object} The modified target object.
  2628. */
  2629. ol.obj.assign = (typeof Object.assign === 'function') ? Object.assign : function(target, var_sources) {
  2630. if (target === undefined || target === null) {
  2631. throw new TypeError('Cannot convert undefined or null to object');
  2632. }
  2633. var output = Object(target);
  2634. for (var i = 1, ii = arguments.length; i < ii; ++i) {
  2635. var source = arguments[i];
  2636. if (source !== undefined && source !== null) {
  2637. for (var key in source) {
  2638. if (source.hasOwnProperty(key)) {
  2639. output[key] = source[key];
  2640. }
  2641. }
  2642. }
  2643. }
  2644. return output;
  2645. };
  2646. /**
  2647. * Removes all properties from an object.
  2648. * @param {Object} object The object to clear.
  2649. */
  2650. ol.obj.clear = function(object) {
  2651. for (var property in object) {
  2652. delete object[property];
  2653. }
  2654. };
  2655. /**
  2656. * Get an array of property values from an object.
  2657. * @param {Object<K,V>} object The object from which to get the values.
  2658. * @return {!Array<V>} The property values.
  2659. * @template K,V
  2660. */
  2661. ol.obj.getValues = function(object) {
  2662. var values = [];
  2663. for (var property in object) {
  2664. values.push(object[property]);
  2665. }
  2666. return values;
  2667. };
  2668. /**
  2669. * Determine if an object has any properties.
  2670. * @param {Object} object The object to check.
  2671. * @return {boolean} The object is empty.
  2672. */
  2673. ol.obj.isEmpty = function(object) {
  2674. var property;
  2675. for (property in object) {
  2676. return false;
  2677. }
  2678. return !property;
  2679. };
  2680. ol.transform = {};
  2681. /**
  2682. * @private
  2683. * @type {ol.Transform}
  2684. */
  2685. ol.transform.tmp_ = new Array(6);
  2686. /**
  2687. * Create an identity transform.
  2688. * @return {!ol.Transform} Identity transform.
  2689. */
  2690. ol.transform.create = function() {
  2691. return [1, 0, 0, 1, 0, 0];
  2692. };
  2693. /**
  2694. * Resets the given transform to an identity transform.
  2695. * @param {!ol.Transform} transform Transform.
  2696. * @return {!ol.Transform} Transform.
  2697. */
  2698. ol.transform.reset = function(transform) {
  2699. return ol.transform.set(transform, 1, 0, 0, 1, 0, 0);
  2700. };
  2701. /**
  2702. * Multiply the underlying matrices of two transforms and return the result in
  2703. * the first transform.
  2704. * @param {!ol.Transform} transform1 Transform parameters of matrix 1.
  2705. * @param {!ol.Transform} transform2 Transform parameters of matrix 2.
  2706. * @return {!ol.Transform} transform1 multiplied with transform2.
  2707. */
  2708. ol.transform.multiply = function(transform1, transform2) {
  2709. var a1 = transform1[0];
  2710. var b1 = transform1[1];
  2711. var c1 = transform1[2];
  2712. var d1 = transform1[3];
  2713. var e1 = transform1[4];
  2714. var f1 = transform1[5];
  2715. var a2 = transform2[0];
  2716. var b2 = transform2[1];
  2717. var c2 = transform2[2];
  2718. var d2 = transform2[3];
  2719. var e2 = transform2[4];
  2720. var f2 = transform2[5];
  2721. transform1[0] = a1 * a2 + c1 * b2;
  2722. transform1[1] = b1 * a2 + d1 * b2;
  2723. transform1[2] = a1 * c2 + c1 * d2;
  2724. transform1[3] = b1 * c2 + d1 * d2;
  2725. transform1[4] = a1 * e2 + c1 * f2 + e1;
  2726. transform1[5] = b1 * e2 + d1 * f2 + f1;
  2727. return transform1;
  2728. };
  2729. /**
  2730. * Set the transform components a-f on a given transform.
  2731. * @param {!ol.Transform} transform Transform.
  2732. * @param {number} a The a component of the transform.
  2733. * @param {number} b The b component of the transform.
  2734. * @param {number} c The c component of the transform.
  2735. * @param {number} d The d component of the transform.
  2736. * @param {number} e The e component of the transform.
  2737. * @param {number} f The f component of the transform.
  2738. * @return {!ol.Transform} Matrix with transform applied.
  2739. */
  2740. ol.transform.set = function(transform, a, b, c, d, e, f) {
  2741. transform[0] = a;
  2742. transform[1] = b;
  2743. transform[2] = c;
  2744. transform[3] = d;
  2745. transform[4] = e;
  2746. transform[5] = f;
  2747. return transform;
  2748. };
  2749. /**
  2750. * Set transform on one matrix from another matrix.
  2751. * @param {!ol.Transform} transform1 Matrix to set transform to.
  2752. * @param {!ol.Transform} transform2 Matrix to set transform from.
  2753. * @return {!ol.Transform} transform1 with transform from transform2 applied.
  2754. */
  2755. ol.transform.setFromArray = function(transform1, transform2) {
  2756. transform1[0] = transform2[0];
  2757. transform1[1] = transform2[1];
  2758. transform1[2] = transform2[2];
  2759. transform1[3] = transform2[3];
  2760. transform1[4] = transform2[4];
  2761. transform1[5] = transform2[5];
  2762. return transform1;
  2763. };
  2764. /**
  2765. * Transforms the given coordinate with the given transform returning the
  2766. * resulting, transformed coordinate. The coordinate will be modified in-place.
  2767. *
  2768. * @param {ol.Transform} transform The transformation.
  2769. * @param {ol.Coordinate|ol.Pixel} coordinate The coordinate to transform.
  2770. * @return {ol.Coordinate|ol.Pixel} return coordinate so that operations can be
  2771. * chained together.
  2772. */
  2773. ol.transform.apply = function(transform, coordinate) {
  2774. var x = coordinate[0], y = coordinate[1];
  2775. coordinate[0] = transform[0] * x + transform[2] * y + transform[4];
  2776. coordinate[1] = transform[1] * x + transform[3] * y + transform[5];
  2777. return coordinate;
  2778. };
  2779. /**
  2780. * Applies rotation to the given transform.
  2781. * @param {!ol.Transform} transform Transform.
  2782. * @param {number} angle Angle in radians.
  2783. * @return {!ol.Transform} The rotated transform.
  2784. */
  2785. ol.transform.rotate = function(transform, angle) {
  2786. var cos = Math.cos(angle);
  2787. var sin = Math.sin(angle);
  2788. return ol.transform.multiply(transform,
  2789. ol.transform.set(ol.transform.tmp_, cos, sin, -sin, cos, 0, 0));
  2790. };
  2791. /**
  2792. * Applies scale to a given transform.
  2793. * @param {!ol.Transform} transform Transform.
  2794. * @param {number} x Scale factor x.
  2795. * @param {number} y Scale factor y.
  2796. * @return {!ol.Transform} The scaled transform.
  2797. */
  2798. ol.transform.scale = function(transform, x, y) {
  2799. return ol.transform.multiply(transform,
  2800. ol.transform.set(ol.transform.tmp_, x, 0, 0, y, 0, 0));
  2801. };
  2802. /**
  2803. * Applies translation to the given transform.
  2804. * @param {!ol.Transform} transform Transform.
  2805. * @param {number} dx Translation x.
  2806. * @param {number} dy Translation y.
  2807. * @return {!ol.Transform} The translated transform.
  2808. */
  2809. ol.transform.translate = function(transform, dx, dy) {
  2810. return ol.transform.multiply(transform,
  2811. ol.transform.set(ol.transform.tmp_, 1, 0, 0, 1, dx, dy));
  2812. };
  2813. /**
  2814. * Creates a composite transform given an initial translation, scale, rotation, and
  2815. * final translation (in that order only, not commutative).
  2816. * @param {!ol.Transform} transform The transform (will be modified in place).
  2817. * @param {number} dx1 Initial translation x.
  2818. * @param {number} dy1 Initial translation y.
  2819. * @param {number} sx Scale factor x.
  2820. * @param {number} sy Scale factor y.
  2821. * @param {number} angle Rotation (in counter-clockwise radians).
  2822. * @param {number} dx2 Final translation x.
  2823. * @param {number} dy2 Final translation y.
  2824. * @return {!ol.Transform} The composite transform.
  2825. */
  2826. ol.transform.compose = function(transform, dx1, dy1, sx, sy, angle, dx2, dy2) {
  2827. var sin = Math.sin(angle);
  2828. var cos = Math.cos(angle);
  2829. transform[0] = sx * cos;
  2830. transform[1] = sy * sin;
  2831. transform[2] = -sx * sin;
  2832. transform[3] = sy * cos;
  2833. transform[4] = dx2 * sx * cos - dy2 * sx * sin + dx1;
  2834. transform[5] = dx2 * sy * sin + dy2 * sy * cos + dy1;
  2835. return transform;
  2836. };
  2837. /**
  2838. * Invert the given transform.
  2839. * @param {!ol.Transform} transform Transform.
  2840. * @return {!ol.Transform} Inverse of the transform.
  2841. */
  2842. ol.transform.invert = function(transform) {
  2843. var det = ol.transform.determinant(transform);
  2844. //ol.asserts.assert(det !== 0, 32); // Transformation matrix cannot be inverted
  2845. var a = transform[0];
  2846. var b = transform[1];
  2847. var c = transform[2];
  2848. var d = transform[3];
  2849. var e = transform[4];
  2850. var f = transform[5];
  2851. transform[0] = d / det;
  2852. transform[1] = -b / det;
  2853. transform[2] = -c / det;
  2854. transform[3] = a / det;
  2855. transform[4] = (c * f - d * e) / det;
  2856. transform[5] = -(a * f - b * e) / det;
  2857. return transform;
  2858. };
  2859. /**
  2860. * Returns the determinant of the given matrix.
  2861. * @param {!ol.Transform} mat Matrix.
  2862. * @return {number} Determinant.
  2863. */
  2864. ol.transform.determinant = function(mat) {
  2865. return mat[0] * mat[3] - mat[1] * mat[2];
  2866. };
  2867. ol.geom = {};
  2868. ol.geom.flat = {};
  2869. ol.geom.flat.center = {};
  2870. ol.geom.flat.reverse = {};
  2871. ol.geom.flat.orient = {};
  2872. ol.geom.flat.transform = {};
  2873. ol.geom.flat.transform.transform2D = function(flatCoordinates, offset, end, stride, transform, opt_dest) {
  2874. var dest = opt_dest ? opt_dest : [];
  2875. var i = 0;
  2876. var j;
  2877. for (j = offset; j < end; j += stride) {
  2878. var x = flatCoordinates[j];
  2879. var y = flatCoordinates[j + 1];
  2880. dest[i++] = transform[0] * x + transform[2] * y + transform[4];
  2881. dest[i++] = transform[1] * x + transform[3] * y + transform[5];
  2882. }
  2883. if (opt_dest && dest.length != i) {
  2884. dest.length = i;
  2885. }
  2886. return dest;
  2887. };
  2888. /**
  2889. * @param {Array.<number>} flatCoordinates Flat coordinates.
  2890. * @param {number} offset Offset.
  2891. * @param {number} end End.
  2892. * @param {number} stride Stride.
  2893. * @param {number} angle Angle.
  2894. * @param {Array.<number>} anchor Rotation anchor point.
  2895. * @param {Array.<number>=} opt_dest Destination.
  2896. * @return {Array.<number>} Transformed coordinates.
  2897. */
  2898. ol.geom.flat.transform.rotate = function(flatCoordinates, offset, end, stride, angle, anchor, opt_dest) {
  2899. var dest = opt_dest ? opt_dest : [];
  2900. var cos = Math.cos(angle);
  2901. var sin = Math.sin(angle);
  2902. var anchorX = anchor[0];
  2903. var anchorY = anchor[1];
  2904. var i = 0;
  2905. for (var j = offset; j < end; j += stride) {
  2906. var deltaX = flatCoordinates[j] - anchorX;
  2907. var deltaY = flatCoordinates[j + 1] - anchorY;
  2908. dest[i++] = anchorX + deltaX * cos - deltaY * sin;
  2909. dest[i++] = anchorY + deltaX * sin + deltaY * cos;
  2910. for (var k = j + 2; k < j + stride; ++k) {
  2911. dest[i++] = flatCoordinates[k];
  2912. }
  2913. }
  2914. if (opt_dest && dest.length != i) {
  2915. dest.length = i;
  2916. }
  2917. return dest;
  2918. };
  2919. /**
  2920. * Scale the coordinates.
  2921. * @param {Array.<number>} flatCoordinates Flat coordinates.
  2922. * @param {number} offset Offset.
  2923. * @param {number} end End.
  2924. * @param {number} stride Stride.
  2925. * @param {number} sx Scale factor in the x-direction.
  2926. * @param {number} sy Scale factor in the y-direction.
  2927. * @param {Array.<number>} anchor Scale anchor point.
  2928. * @param {Array.<number>=} opt_dest Destination.
  2929. * @return {Array.<number>} Transformed coordinates.
  2930. */
  2931. ol.geom.flat.transform.scale = function(flatCoordinates, offset, end, stride, sx, sy, anchor, opt_dest) {
  2932. var dest = opt_dest ? opt_dest : [];
  2933. var anchorX = anchor[0];
  2934. var anchorY = anchor[1];
  2935. var i = 0;
  2936. for (var j = offset; j < end; j += stride) {
  2937. var deltaX = flatCoordinates[j] - anchorX;
  2938. var deltaY = flatCoordinates[j + 1] - anchorY;
  2939. dest[i++] = anchorX + sx * deltaX;
  2940. dest[i++] = anchorY + sy * deltaY;
  2941. for (var k = j + 2; k < j + stride; ++k) {
  2942. dest[i++] = flatCoordinates[k];
  2943. }
  2944. }
  2945. if (opt_dest && dest.length != i) {
  2946. dest.length = i;
  2947. }
  2948. return dest;
  2949. };
  2950. /**
  2951. * The coordinate layout for geometries, indicating whether a 3rd or 4th z ('Z')
  2952. * or measure ('M') coordinate is available. Supported values are `'XY'`,
  2953. * `'XYZ'`, `'XYM'`, `'XYZM'`.
  2954. * @enum {string}
  2955. */
  2956. ol.geom.GeometryLayout = {
  2957. XY: 'XY',
  2958. XYZ: 'XYZ',
  2959. XYM: 'XYM',
  2960. XYZM: 'XYZM'
  2961. };
  2962. /**
  2963. * @param {Array.<number>} flatCoordinates Flat coordinates.
  2964. * @param {number} offset Offset.
  2965. * @param {number} end End.
  2966. * @param {number} stride Stride.
  2967. */
  2968. ol.geom.flat.reverse.coordinates = function(flatCoordinates, offset, end, stride) {
  2969. while (offset < end - stride) {
  2970. var i;
  2971. for (i = 0; i < stride; ++i) {
  2972. var tmp = flatCoordinates[offset + i];
  2973. flatCoordinates[offset + i] = flatCoordinates[end - stride + i];
  2974. flatCoordinates[end - stride + i] = tmp;
  2975. }
  2976. offset += stride;
  2977. end -= stride;
  2978. }
  2979. };
  2980. /**
  2981. * @param {Array.<number>} flatCoordinates Flat coordinates.
  2982. * @param {number} offset Offset.
  2983. * @param {number} end End.
  2984. * @param {number} stride Stride.
  2985. * @return {boolean} Is clockwise.
  2986. */
  2987. ol.geom.flat.orient.linearRingIsClockwise = function(flatCoordinates, offset, end, stride) {
  2988. // http://tinyurl.com/clockwise-method
  2989. // https://github.com/OSGeo/gdal/blob/trunk/gdal/ogr/ogrlinearring.cpp
  2990. var edge = 0;
  2991. var x1 = flatCoordinates[end - stride];
  2992. var y1 = flatCoordinates[end - stride + 1];
  2993. for (; offset < end; offset += stride) {
  2994. var x2 = flatCoordinates[offset];
  2995. var y2 = flatCoordinates[offset + 1];
  2996. edge += (x2 - x1) * (y2 + y1);
  2997. x1 = x2;
  2998. y1 = y2;
  2999. }
  3000. return edge > 0;
  3001. };
  3002. /**
  3003. * Determines if linear rings are oriented. By default, left-hand orientation
  3004. * is tested (first ring must be clockwise, remaining rings counter-clockwise).
  3005. * To test for right-hand orientation, use the `opt_right` argument.
  3006. *
  3007. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3008. * @param {number} offset Offset.
  3009. * @param {Array.<number>} ends Array of end indexes.
  3010. * @param {number} stride Stride.
  3011. * @param {boolean=} opt_right Test for right-hand orientation
  3012. * (counter-clockwise exterior ring and clockwise interior rings).
  3013. * @return {boolean} Rings are correctly oriented.
  3014. */
  3015. ol.geom.flat.orient.linearRingsAreOriented = function(flatCoordinates, offset, ends, stride, opt_right) {
  3016. var right = opt_right !== undefined ? opt_right : false;
  3017. var i, ii;
  3018. for (i = 0, ii = ends.length; i < ii; ++i) {
  3019. var end = ends[i];
  3020. var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(
  3021. flatCoordinates, offset, end, stride);
  3022. if (i === 0) {
  3023. if ((right && isClockwise) || (!right && !isClockwise)) {
  3024. return false;
  3025. }
  3026. } else {
  3027. if ((right && !isClockwise) || (!right && isClockwise)) {
  3028. return false;
  3029. }
  3030. }
  3031. offset = end;
  3032. }
  3033. return true;
  3034. };
  3035. /**
  3036. * Determines if linear rings are oriented. By default, left-hand orientation
  3037. * is tested (first ring must be clockwise, remaining rings counter-clockwise).
  3038. * To test for right-hand orientation, use the `opt_right` argument.
  3039. *
  3040. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3041. * @param {number} offset Offset.
  3042. * @param {Array.<Array.<number>>} endss Array of array of end indexes.
  3043. * @param {number} stride Stride.
  3044. * @param {boolean=} opt_right Test for right-hand orientation
  3045. * (counter-clockwise exterior ring and clockwise interior rings).
  3046. * @return {boolean} Rings are correctly oriented.
  3047. */
  3048. ol.geom.flat.orient.linearRingssAreOriented = function(flatCoordinates, offset, endss, stride, opt_right) {
  3049. var i, ii;
  3050. for (i = 0, ii = endss.length; i < ii; ++i) {
  3051. if (!ol.geom.flat.orient.linearRingsAreOriented(
  3052. flatCoordinates, offset, endss[i], stride, opt_right)) {
  3053. return false;
  3054. }
  3055. }
  3056. return true;
  3057. };
  3058. /**
  3059. * Orient coordinates in a flat array of linear rings. By default, rings
  3060. * are oriented following the left-hand rule (clockwise for exterior and
  3061. * counter-clockwise for interior rings). To orient according to the
  3062. * right-hand rule, use the `opt_right` argument.
  3063. *
  3064. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3065. * @param {number} offset Offset.
  3066. * @param {Array.<number>} ends Ends.
  3067. * @param {number} stride Stride.
  3068. * @param {boolean=} opt_right Follow the right-hand rule for orientation.
  3069. * @return {number} End.
  3070. */
  3071. ol.geom.flat.orient.orientLinearRings = function(flatCoordinates, offset, ends, stride, opt_right) {
  3072. var right = opt_right !== undefined ? opt_right : false;
  3073. var i, ii;
  3074. for (i = 0, ii = ends.length; i < ii; ++i) {
  3075. var end = ends[i];
  3076. var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(
  3077. flatCoordinates, offset, end, stride);
  3078. var reverse = i === 0 ?
  3079. (right && isClockwise) || (!right && !isClockwise) :
  3080. (right && !isClockwise) || (!right && isClockwise);
  3081. if (reverse) {
  3082. ol.geom.flat.reverse.coordinates(flatCoordinates, offset, end, stride);
  3083. }
  3084. offset = end;
  3085. }
  3086. return offset;
  3087. };
  3088. /**
  3089. * Orient coordinates in a flat array of linear rings. By default, rings
  3090. * are oriented following the left-hand rule (clockwise for exterior and
  3091. * counter-clockwise for interior rings). To orient according to the
  3092. * right-hand rule, use the `opt_right` argument.
  3093. *
  3094. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3095. * @param {number} offset Offset.
  3096. * @param {Array.<Array.<number>>} endss Array of array of end indexes.
  3097. * @param {number} stride Stride.
  3098. * @param {boolean=} opt_right Follow the right-hand rule for orientation.
  3099. * @return {number} End.
  3100. */
  3101. ol.geom.flat.orient.orientLinearRingss = function(flatCoordinates, offset, endss, stride, opt_right) {
  3102. var i, ii;
  3103. for (i = 0, ii = endss.length; i < ii; ++i) {
  3104. offset = ol.geom.flat.orient.orientLinearRings(
  3105. flatCoordinates, offset, endss[i], stride, opt_right);
  3106. }
  3107. return offset;
  3108. };
  3109. ol.geom.flat.simplify = {};
  3110. /**
  3111. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3112. * @param {number} offset Offset.
  3113. * @param {number} end End.
  3114. * @param {number} stride Stride.
  3115. * @param {number} squaredTolerance Squared tolerance.
  3116. * @param {boolean} highQuality Highest quality.
  3117. * @param {Array.<number>=} opt_simplifiedFlatCoordinates Simplified flat
  3118. * coordinates.
  3119. * @return {Array.<number>} Simplified line string.
  3120. */
  3121. ol.geom.flat.simplify.lineString = function(flatCoordinates, offset, end,
  3122. stride, squaredTolerance, highQuality, opt_simplifiedFlatCoordinates) {
  3123. var simplifiedFlatCoordinates = opt_simplifiedFlatCoordinates !== undefined ?
  3124. opt_simplifiedFlatCoordinates : [];
  3125. if (!highQuality) {
  3126. end = ol.geom.flat.simplify.radialDistance(flatCoordinates, offset, end,
  3127. stride, squaredTolerance,
  3128. simplifiedFlatCoordinates, 0);
  3129. flatCoordinates = simplifiedFlatCoordinates;
  3130. offset = 0;
  3131. stride = 2;
  3132. }
  3133. simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeucker(
  3134. flatCoordinates, offset, end, stride, squaredTolerance,
  3135. simplifiedFlatCoordinates, 0);
  3136. return simplifiedFlatCoordinates;
  3137. };
  3138. /**
  3139. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3140. * @param {number} offset Offset.
  3141. * @param {number} end End.
  3142. * @param {number} stride Stride.
  3143. * @param {number} squaredTolerance Squared tolerance.
  3144. * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
  3145. * coordinates.
  3146. * @param {number} simplifiedOffset Simplified offset.
  3147. * @return {number} Simplified offset.
  3148. */
  3149. ol.geom.flat.simplify.douglasPeucker = function(flatCoordinates, offset, end,
  3150. stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset) {
  3151. var n = (end - offset) / stride;
  3152. if (n < 3) {
  3153. for (; offset < end; offset += stride) {
  3154. simplifiedFlatCoordinates[simplifiedOffset++] =
  3155. flatCoordinates[offset];
  3156. simplifiedFlatCoordinates[simplifiedOffset++] =
  3157. flatCoordinates[offset + 1];
  3158. }
  3159. return simplifiedOffset;
  3160. }
  3161. /** @type {Array.<number>} */
  3162. var markers = new Array(n);
  3163. markers[0] = 1;
  3164. markers[n - 1] = 1;
  3165. /** @type {Array.<number>} */
  3166. var stack = [offset, end - stride];
  3167. var index = 0;
  3168. var i;
  3169. while (stack.length > 0) {
  3170. var last = stack.pop();
  3171. var first = stack.pop();
  3172. var maxSquaredDistance = 0;
  3173. var x1 = flatCoordinates[first];
  3174. var y1 = flatCoordinates[first + 1];
  3175. var x2 = flatCoordinates[last];
  3176. var y2 = flatCoordinates[last + 1];
  3177. for (i = first + stride; i < last; i += stride) {
  3178. var x = flatCoordinates[i];
  3179. var y = flatCoordinates[i + 1];
  3180. var squaredDistance = ol.math.squaredSegmentDistance(
  3181. x, y, x1, y1, x2, y2);
  3182. if (squaredDistance > maxSquaredDistance) {
  3183. index = i;
  3184. maxSquaredDistance = squaredDistance;
  3185. }
  3186. }
  3187. if (maxSquaredDistance > squaredTolerance) {
  3188. markers[(index - offset) / stride] = 1;
  3189. if (first + stride < index) {
  3190. stack.push(first, index);
  3191. }
  3192. if (index + stride < last) {
  3193. stack.push(index, last);
  3194. }
  3195. }
  3196. }
  3197. for (i = 0; i < n; ++i) {
  3198. if (markers[i]) {
  3199. simplifiedFlatCoordinates[simplifiedOffset++] =
  3200. flatCoordinates[offset + i * stride];
  3201. simplifiedFlatCoordinates[simplifiedOffset++] =
  3202. flatCoordinates[offset + i * stride + 1];
  3203. }
  3204. }
  3205. return simplifiedOffset;
  3206. };
  3207. /**
  3208. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3209. * @param {number} offset Offset.
  3210. * @param {Array.<number>} ends Ends.
  3211. * @param {number} stride Stride.
  3212. * @param {number} squaredTolerance Squared tolerance.
  3213. * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
  3214. * coordinates.
  3215. * @param {number} simplifiedOffset Simplified offset.
  3216. * @param {Array.<number>} simplifiedEnds Simplified ends.
  3217. * @return {number} Simplified offset.
  3218. */
  3219. ol.geom.flat.simplify.douglasPeuckers = function(flatCoordinates, offset,
  3220. ends, stride, squaredTolerance, simplifiedFlatCoordinates,
  3221. simplifiedOffset, simplifiedEnds) {
  3222. var i, ii;
  3223. for (i = 0, ii = ends.length; i < ii; ++i) {
  3224. var end = ends[i];
  3225. simplifiedOffset = ol.geom.flat.simplify.douglasPeucker(
  3226. flatCoordinates, offset, end, stride, squaredTolerance,
  3227. simplifiedFlatCoordinates, simplifiedOffset);
  3228. simplifiedEnds.push(simplifiedOffset);
  3229. offset = end;
  3230. }
  3231. return simplifiedOffset;
  3232. };
  3233. /**
  3234. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3235. * @param {number} offset Offset.
  3236. * @param {Array.<Array.<number>>} endss Endss.
  3237. * @param {number} stride Stride.
  3238. * @param {number} squaredTolerance Squared tolerance.
  3239. * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
  3240. * coordinates.
  3241. * @param {number} simplifiedOffset Simplified offset.
  3242. * @param {Array.<Array.<number>>} simplifiedEndss Simplified endss.
  3243. * @return {number} Simplified offset.
  3244. */
  3245. ol.geom.flat.simplify.douglasPeuckerss = function(
  3246. flatCoordinates, offset, endss, stride, squaredTolerance,
  3247. simplifiedFlatCoordinates, simplifiedOffset, simplifiedEndss) {
  3248. var i, ii;
  3249. for (i = 0, ii = endss.length; i < ii; ++i) {
  3250. var ends = endss[i];
  3251. var simplifiedEnds = [];
  3252. simplifiedOffset = ol.geom.flat.simplify.douglasPeuckers(
  3253. flatCoordinates, offset, ends, stride, squaredTolerance,
  3254. simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds);
  3255. simplifiedEndss.push(simplifiedEnds);
  3256. offset = ends[ends.length - 1];
  3257. }
  3258. return simplifiedOffset;
  3259. };
  3260. /**
  3261. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3262. * @param {number} offset Offset.
  3263. * @param {number} end End.
  3264. * @param {number} stride Stride.
  3265. * @param {number} squaredTolerance Squared tolerance.
  3266. * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
  3267. * coordinates.
  3268. * @param {number} simplifiedOffset Simplified offset.
  3269. * @return {number} Simplified offset.
  3270. */
  3271. ol.geom.flat.simplify.radialDistance = function(flatCoordinates, offset, end,
  3272. stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset) {
  3273. if (end <= offset + stride) {
  3274. // zero or one point, no simplification possible, so copy and return
  3275. for (; offset < end; offset += stride) {
  3276. simplifiedFlatCoordinates[simplifiedOffset++] = flatCoordinates[offset];
  3277. simplifiedFlatCoordinates[simplifiedOffset++] =
  3278. flatCoordinates[offset + 1];
  3279. }
  3280. return simplifiedOffset;
  3281. }
  3282. var x1 = flatCoordinates[offset];
  3283. var y1 = flatCoordinates[offset + 1];
  3284. // copy first point
  3285. simplifiedFlatCoordinates[simplifiedOffset++] = x1;
  3286. simplifiedFlatCoordinates[simplifiedOffset++] = y1;
  3287. var x2 = x1;
  3288. var y2 = y1;
  3289. for (offset += stride; offset < end; offset += stride) {
  3290. x2 = flatCoordinates[offset];
  3291. y2 = flatCoordinates[offset + 1];
  3292. if (ol.math.squaredDistance(x1, y1, x2, y2) > squaredTolerance) {
  3293. // copy point at offset
  3294. simplifiedFlatCoordinates[simplifiedOffset++] = x2;
  3295. simplifiedFlatCoordinates[simplifiedOffset++] = y2;
  3296. x1 = x2;
  3297. y1 = y2;
  3298. }
  3299. }
  3300. if (x2 != x1 || y2 != y1) {
  3301. // copy last point
  3302. simplifiedFlatCoordinates[simplifiedOffset++] = x2;
  3303. simplifiedFlatCoordinates[simplifiedOffset++] = y2;
  3304. }
  3305. return simplifiedOffset;
  3306. };
  3307. /**
  3308. * @param {number} value Value.
  3309. * @param {number} tolerance Tolerance.
  3310. * @return {number} Rounded value.
  3311. */
  3312. ol.geom.flat.simplify.snap = function(value, tolerance) {
  3313. return tolerance * Math.round(value / tolerance);
  3314. };
  3315. /**
  3316. * Simplifies a line string using an algorithm designed by Tim Schaub.
  3317. * Coordinates are snapped to the nearest value in a virtual grid and
  3318. * consecutive duplicate coordinates are discarded. This effectively preserves
  3319. * topology as the simplification of any subsection of a line string is
  3320. * independent of the rest of the line string. This means that, for examples,
  3321. * the common edge between two polygons will be simplified to the same line
  3322. * string independently in both polygons. This implementation uses a single
  3323. * pass over the coordinates and eliminates intermediate collinear points.
  3324. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3325. * @param {number} offset Offset.
  3326. * @param {number} end End.
  3327. * @param {number} stride Stride.
  3328. * @param {number} tolerance Tolerance.
  3329. * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
  3330. * coordinates.
  3331. * @param {number} simplifiedOffset Simplified offset.
  3332. * @return {number} Simplified offset.
  3333. */
  3334. ol.geom.flat.simplify.quantize = function(flatCoordinates, offset, end, stride,
  3335. tolerance, simplifiedFlatCoordinates, simplifiedOffset) {
  3336. // do nothing if the line is empty
  3337. if (offset == end) {
  3338. return simplifiedOffset;
  3339. }
  3340. // snap the first coordinate (P1)
  3341. var x1 = ol.geom.flat.simplify.snap(flatCoordinates[offset], tolerance);
  3342. var y1 = ol.geom.flat.simplify.snap(flatCoordinates[offset + 1], tolerance);
  3343. offset += stride;
  3344. // add the first coordinate to the output
  3345. simplifiedFlatCoordinates[simplifiedOffset++] = x1;
  3346. simplifiedFlatCoordinates[simplifiedOffset++] = y1;
  3347. // find the next coordinate that does not snap to the same value as the first
  3348. // coordinate (P2)
  3349. var x2, y2;
  3350. do {
  3351. x2 = ol.geom.flat.simplify.snap(flatCoordinates[offset], tolerance);
  3352. y2 = ol.geom.flat.simplify.snap(flatCoordinates[offset + 1], tolerance);
  3353. offset += stride;
  3354. if (offset == end) {
  3355. // all coordinates snap to the same value, the line collapses to a point
  3356. // push the last snapped value anyway to ensure that the output contains
  3357. // at least two points
  3358. // FIXME should we really return at least two points anyway?
  3359. simplifiedFlatCoordinates[simplifiedOffset++] = x2;
  3360. simplifiedFlatCoordinates[simplifiedOffset++] = y2;
  3361. return simplifiedOffset;
  3362. }
  3363. } while (x2 == x1 && y2 == y1);
  3364. while (offset < end) {
  3365. var x3, y3;
  3366. // snap the next coordinate (P3)
  3367. x3 = ol.geom.flat.simplify.snap(flatCoordinates[offset], tolerance);
  3368. y3 = ol.geom.flat.simplify.snap(flatCoordinates[offset + 1], tolerance);
  3369. offset += stride;
  3370. // skip P3 if it is equal to P2
  3371. if (x3 == x2 && y3 == y2) {
  3372. continue;
  3373. }
  3374. // calculate the delta between P1 and P2
  3375. var dx1 = x2 - x1;
  3376. var dy1 = y2 - y1;
  3377. // calculate the delta between P3 and P1
  3378. var dx2 = x3 - x1;
  3379. var dy2 = y3 - y1;
  3380. // if P1, P2, and P3 are colinear and P3 is further from P1 than P2 is from
  3381. // P1 in the same direction then P2 is on the straight line between P1 and
  3382. // P3
  3383. if ((dx1 * dy2 == dy1 * dx2) &&
  3384. ((dx1 < 0 && dx2 < dx1) || dx1 == dx2 || (dx1 > 0 && dx2 > dx1)) &&
  3385. ((dy1 < 0 && dy2 < dy1) || dy1 == dy2 || (dy1 > 0 && dy2 > dy1))) {
  3386. // discard P2 and set P2 = P3
  3387. x2 = x3;
  3388. y2 = y3;
  3389. continue;
  3390. }
  3391. // either P1, P2, and P3 are not colinear, or they are colinear but P3 is
  3392. // between P3 and P1 or on the opposite half of the line to P2. add P2,
  3393. // and continue with P1 = P2 and P2 = P3
  3394. simplifiedFlatCoordinates[simplifiedOffset++] = x2;
  3395. simplifiedFlatCoordinates[simplifiedOffset++] = y2;
  3396. x1 = x2;
  3397. y1 = y2;
  3398. x2 = x3;
  3399. y2 = y3;
  3400. }
  3401. // add the last point (P2)
  3402. simplifiedFlatCoordinates[simplifiedOffset++] = x2;
  3403. simplifiedFlatCoordinates[simplifiedOffset++] = y2;
  3404. return simplifiedOffset;
  3405. };
  3406. /**
  3407. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3408. * @param {number} offset Offset.
  3409. * @param {Array.<number>} ends Ends.
  3410. * @param {number} stride Stride.
  3411. * @param {number} tolerance Tolerance.
  3412. * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
  3413. * coordinates.
  3414. * @param {number} simplifiedOffset Simplified offset.
  3415. * @param {Array.<number>} simplifiedEnds Simplified ends.
  3416. * @return {number} Simplified offset.
  3417. */
  3418. ol.geom.flat.simplify.quantizes = function(
  3419. flatCoordinates, offset, ends, stride,
  3420. tolerance,
  3421. simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds) {
  3422. var i, ii;
  3423. for (i = 0, ii = ends.length; i < ii; ++i) {
  3424. var end = ends[i];
  3425. simplifiedOffset = ol.geom.flat.simplify.quantize(
  3426. flatCoordinates, offset, end, stride,
  3427. tolerance,
  3428. simplifiedFlatCoordinates, simplifiedOffset);
  3429. simplifiedEnds.push(simplifiedOffset);
  3430. offset = end;
  3431. }
  3432. return simplifiedOffset;
  3433. };
  3434. /**
  3435. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3436. * @param {number} offset Offset.
  3437. * @param {Array.<Array.<number>>} endss Endss.
  3438. * @param {number} stride Stride.
  3439. * @param {number} tolerance Tolerance.
  3440. * @param {Array.<number>} simplifiedFlatCoordinates Simplified flat
  3441. * coordinates.
  3442. * @param {number} simplifiedOffset Simplified offset.
  3443. * @param {Array.<Array.<number>>} simplifiedEndss Simplified endss.
  3444. * @return {number} Simplified offset.
  3445. */
  3446. ol.geom.flat.simplify.quantizess = function(
  3447. flatCoordinates, offset, endss, stride,
  3448. tolerance,
  3449. simplifiedFlatCoordinates, simplifiedOffset, simplifiedEndss) {
  3450. var i, ii;
  3451. for (i = 0, ii = endss.length; i < ii; ++i) {
  3452. var ends = endss[i];
  3453. var simplifiedEnds = [];
  3454. simplifiedOffset = ol.geom.flat.simplify.quantizes(
  3455. flatCoordinates, offset, ends, stride,
  3456. tolerance,
  3457. simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds);
  3458. simplifiedEndss.push(simplifiedEnds);
  3459. offset = ends[ends.length - 1];
  3460. }
  3461. return simplifiedOffset;
  3462. };
  3463. ol.geom.GeometryType = {
  3464. POINT: 'Point',
  3465. LINE_STRING: 'LineString',
  3466. LINEAR_RING: 'LinearRing',
  3467. POLYGON: 'Polygon',
  3468. MULTI_POINT: 'MultiPoint',
  3469. MULTI_LINE_STRING: 'MultiLineString',
  3470. MULTI_POLYGON: 'MultiPolygon',
  3471. GEOMETRY_COLLECTION: 'GeometryCollection',
  3472. CIRCLE: 'Circle'
  3473. };
  3474. /**
  3475. * @classdesc
  3476. * Abstract base class; normally only used for creating subclasses and not
  3477. * instantiated in apps.
  3478. * Base class for vector geometries.
  3479. *
  3480. * To get notified of changes to the geometry, register a listener for the
  3481. * generic `change` event on your geometry instance.
  3482. *
  3483. * @constructor
  3484. * @abstract
  3485. * @extends {ol.Object}
  3486. * @api
  3487. */
  3488. ol.geom.Geometry = function() {
  3489. ol.Object.call(this);
  3490. /**
  3491. * @private
  3492. * @type {ol.Extent}
  3493. */
  3494. this.extent_ = ol.extent.createEmpty();
  3495. /**
  3496. * @private
  3497. * @type {number}
  3498. */
  3499. this.extentRevision_ = -1;
  3500. /**
  3501. * @protected
  3502. * @type {Object.<string, ol.geom.Geometry>}
  3503. */
  3504. this.simplifiedGeometryCache = {};
  3505. /**
  3506. * @protected
  3507. * @type {number}
  3508. */
  3509. this.simplifiedGeometryMaxMinSquaredTolerance = 0;
  3510. /**
  3511. * @protected
  3512. * @type {number}
  3513. */
  3514. this.simplifiedGeometryRevision = 0;
  3515. /**
  3516. * @private
  3517. * @type {ol.Transform}
  3518. */
  3519. this.tmpTransform_ = ol.transform.create();
  3520. };
  3521. ol.inherits(ol.geom.Geometry, ol.Object);
  3522. /**
  3523. * Make a complete copy of the geometry.
  3524. * @abstract
  3525. * @return {!ol.geom.Geometry} Clone.
  3526. */
  3527. ol.geom.Geometry.prototype.clone = function() {};
  3528. /**
  3529. * @abstract
  3530. * @param {number} x X.
  3531. * @param {number} y Y.
  3532. * @param {ol.Coordinate} closestPoint Closest point.
  3533. * @param {number} minSquaredDistance Minimum squared distance.
  3534. * @return {number} Minimum squared distance.
  3535. */
  3536. ol.geom.Geometry.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {};
  3537. /**
  3538. * Return the closest point of the geometry to the passed point as
  3539. * {@link ol.Coordinate coordinate}.
  3540. * @param {ol.Coordinate} point Point.
  3541. * @param {ol.Coordinate=} opt_closestPoint Closest point.
  3542. * @return {ol.Coordinate} Closest point.
  3543. * @api
  3544. */
  3545. ol.geom.Geometry.prototype.getClosestPoint = function(point, opt_closestPoint) {
  3546. var closestPoint = opt_closestPoint ? opt_closestPoint : [NaN, NaN];
  3547. this.closestPointXY(point[0], point[1], closestPoint, Infinity);
  3548. return closestPoint;
  3549. };
  3550. /**
  3551. * Returns true if this geometry includes the specified coordinate. If the
  3552. * coordinate is on the boundary of the geometry, returns false.
  3553. * @param {ol.Coordinate} coordinate Coordinate.
  3554. * @return {boolean} Contains coordinate.
  3555. * @api
  3556. */
  3557. ol.geom.Geometry.prototype.intersectsCoordinate = function(coordinate) {
  3558. return this.containsXY(coordinate[0], coordinate[1]);
  3559. };
  3560. /**
  3561. * @abstract
  3562. * @param {ol.Extent} extent Extent.
  3563. * @protected
  3564. * @return {ol.Extent} extent Extent.
  3565. */
  3566. ol.geom.Geometry.prototype.computeExtent = function(extent) {};
  3567. /**
  3568. * @param {number} x X.
  3569. * @param {number} y Y.
  3570. * @return {boolean} Contains (x, y).
  3571. */
  3572. ol.geom.Geometry.prototype.containsXY = ol.functions.FALSE;
  3573. /**
  3574. * Get the extent of the geometry.
  3575. * @param {ol.Extent=} opt_extent Extent.
  3576. * @return {ol.Extent} extent Extent.
  3577. * @api
  3578. */
  3579. ol.geom.Geometry.prototype.getExtent = function(opt_extent) {
  3580. if (this.extentRevision_ != this.getRevision()) {
  3581. this.extent_ = this.computeExtent(this.extent_);
  3582. this.extentRevision_ = this.getRevision();
  3583. }
  3584. return ol.extent.returnOrUpdate(this.extent_, opt_extent);
  3585. };
  3586. /**
  3587. * Rotate the geometry around a given coordinate. This modifies the geometry
  3588. * coordinates in place.
  3589. * @abstract
  3590. * @param {number} angle Rotation angle in radians.
  3591. * @param {ol.Coordinate} anchor The rotation center.
  3592. * @api
  3593. */
  3594. ol.geom.Geometry.prototype.rotate = function(angle, anchor) {};
  3595. /**
  3596. * Scale the geometry (with an optional origin). This modifies the geometry
  3597. * coordinates in place.
  3598. * @abstract
  3599. * @param {number} sx The scaling factor in the x-direction.
  3600. * @param {number=} opt_sy The scaling factor in the y-direction (defaults to
  3601. * sx).
  3602. * @param {ol.Coordinate=} opt_anchor The scale origin (defaults to the center
  3603. * of the geometry extent).
  3604. * @api
  3605. */
  3606. ol.geom.Geometry.prototype.scale = function(sx, opt_sy, opt_anchor) {};
  3607. /**
  3608. * Create a simplified version of this geometry. For linestrings, this uses
  3609. * the the {@link
  3610. * https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
  3611. * Douglas Peucker} algorithm. For polygons, a quantization-based
  3612. * simplification is used to preserve topology.
  3613. * @function
  3614. * @param {number} tolerance The tolerance distance for simplification.
  3615. * @return {ol.geom.Geometry} A new, simplified version of the original
  3616. * geometry.
  3617. * @api
  3618. */
  3619. ol.geom.Geometry.prototype.simplify = function(tolerance) {
  3620. return this.getSimplifiedGeometry(tolerance * tolerance);
  3621. };
  3622. /**
  3623. * Create a simplified version of this geometry using the Douglas Peucker
  3624. * algorithm.
  3625. * @see https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
  3626. * @abstract
  3627. * @param {number} squaredTolerance Squared tolerance.
  3628. * @return {ol.geom.Geometry} Simplified geometry.
  3629. */
  3630. ol.geom.Geometry.prototype.getSimplifiedGeometry = function(squaredTolerance) {};
  3631. /**
  3632. * Get the type of this geometry.
  3633. * @abstract
  3634. * @return {ol.geom.GeometryType} Geometry type.
  3635. */
  3636. ol.geom.Geometry.prototype.getType = function() {};
  3637. /**
  3638. * Apply a transform function to each coordinate of the geometry.
  3639. * The geometry is modified in place.
  3640. * If you do not want the geometry modified in place, first `clone()` it and
  3641. * then use this function on the clone.
  3642. * @abstract
  3643. * @param {ol.TransformFunction} transformFn Transform.
  3644. */
  3645. ol.geom.Geometry.prototype.applyTransform = function(transformFn) {};
  3646. /**
  3647. * Test if the geometry and the passed extent intersect.
  3648. * @abstract
  3649. * @param {ol.Extent} extent Extent.
  3650. * @return {boolean} `true` if the geometry and the extent intersect.
  3651. */
  3652. ol.geom.Geometry.prototype.intersectsExtent = function(extent) {};
  3653. /**
  3654. * Translate the geometry. This modifies the geometry coordinates in place. If
  3655. * instead you want a new geometry, first `clone()` this geometry.
  3656. * @abstract
  3657. * @param {number} deltaX Delta X.
  3658. * @param {number} deltaY Delta Y.
  3659. */
  3660. ol.geom.Geometry.prototype.translate = function(deltaX, deltaY) {};
  3661. /**
  3662. * Transform each coordinate of the geometry from one coordinate reference
  3663. * system to another. The geometry is modified in place.
  3664. * For example, a line will be transformed to a line and a circle to a circle.
  3665. * If you do not want the geometry modified in place, first `clone()` it and
  3666. * then use this function on the clone.
  3667. *
  3668. * @param {ol.ProjectionLike} source The current projection. Can be a
  3669. * string identifier or a {@link ol.proj.Projection} object.
  3670. * @param {ol.ProjectionLike} destination The desired projection. Can be a
  3671. * string identifier or a {@link ol.proj.Projection} object.
  3672. * @return {ol.geom.Geometry} This geometry. Note that original geometry is
  3673. * modified in place.
  3674. * @api
  3675. */
  3676. ol.geom.Geometry.prototype.transform = function(source, destination) {
  3677. var tmpTransform = this.tmpTransform_;
  3678. source = ol.proj.get(source);
  3679. var transformFn = source.getUnits() == ol.proj.Units.TILE_PIXELS ?
  3680. function(inCoordinates, outCoordinates, stride) {
  3681. var pixelExtent = source.getExtent();
  3682. var projectedExtent = source.getWorldExtent();
  3683. var scale = ol.extent.getHeight(projectedExtent) / ol.extent.getHeight(pixelExtent);
  3684. ol.transform.compose(tmpTransform,
  3685. projectedExtent[0], projectedExtent[3],
  3686. scale, -scale, 0,
  3687. 0, 0);
  3688. ol.geom.flat.transform.transform2D(inCoordinates, 0, inCoordinates.length, stride,
  3689. tmpTransform, outCoordinates);
  3690. return ol.proj.getTransform(source, destination)(inCoordinates, outCoordinates, stride);
  3691. } :
  3692. ol.proj.getTransform(source, destination);
  3693. this.applyTransform(transformFn);
  3694. return this;
  3695. };
  3696. /**
  3697. * @classdesc
  3698. * Abstract base class; only used for creating subclasses; do not instantiate
  3699. * in apps, as cannot be rendered.
  3700. *
  3701. * @constructor
  3702. * @abstract
  3703. * @extends {ol.geom.Geometry}
  3704. * @api
  3705. */
  3706. ol.geom.SimpleGeometry = function() {
  3707. ol.geom.Geometry.call(this);
  3708. /**
  3709. * @protected
  3710. * @type {ol.geom.GeometryLayout}
  3711. */
  3712. this.layout = ol.geom.GeometryLayout.XY;
  3713. /**
  3714. * @protected
  3715. * @type {number}
  3716. */
  3717. this.stride = 2;
  3718. /**
  3719. * @protected
  3720. * @type {Array.<number>}
  3721. */
  3722. this.flatCoordinates = null;
  3723. };
  3724. ol.inherits(ol.geom.SimpleGeometry, ol.geom.Geometry);
  3725. /**
  3726. * @param {number} stride Stride.
  3727. * @private
  3728. * @return {ol.geom.GeometryLayout} layout Layout.
  3729. */
  3730. ol.geom.SimpleGeometry.getLayoutForStride_ = function(stride) {
  3731. var layout;
  3732. if (stride == 2) {
  3733. layout = ol.geom.GeometryLayout.XY;
  3734. } else if (stride == 3) {
  3735. layout = ol.geom.GeometryLayout.XYZ;
  3736. } else if (stride == 4) {
  3737. layout = ol.geom.GeometryLayout.XYZM;
  3738. }
  3739. return /** @type {ol.geom.GeometryLayout} */ (layout);
  3740. };
  3741. /**
  3742. * @param {ol.geom.GeometryLayout} layout Layout.
  3743. * @return {number} Stride.
  3744. */
  3745. ol.geom.SimpleGeometry.getStrideForLayout = function(layout) {
  3746. var stride;
  3747. if (layout == ol.geom.GeometryLayout.XY) {
  3748. stride = 2;
  3749. } else if (layout == ol.geom.GeometryLayout.XYZ || layout == ol.geom.GeometryLayout.XYM) {
  3750. stride = 3;
  3751. } else if (layout == ol.geom.GeometryLayout.XYZM) {
  3752. stride = 4;
  3753. }
  3754. return /** @type {number} */ (stride);
  3755. };
  3756. /**
  3757. * @inheritDoc
  3758. */
  3759. ol.geom.SimpleGeometry.prototype.containsXY = ol.functions.FALSE;
  3760. /**
  3761. * @inheritDoc
  3762. */
  3763. ol.geom.SimpleGeometry.prototype.computeExtent = function(extent) {
  3764. return ol.extent.createOrUpdateFromFlatCoordinates(
  3765. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
  3766. extent);
  3767. };
  3768. /**
  3769. * @abstract
  3770. * @return {Array} Coordinates.
  3771. */
  3772. ol.geom.SimpleGeometry.prototype.getCoordinates = function() {};
  3773. /**
  3774. * Return the first coordinate of the geometry.
  3775. * @return {ol.Coordinate} First coordinate.
  3776. * @api
  3777. */
  3778. ol.geom.SimpleGeometry.prototype.getFirstCoordinate = function() {
  3779. return this.flatCoordinates.slice(0, this.stride);
  3780. };
  3781. /**
  3782. * @return {Array.<number>} Flat coordinates.
  3783. */
  3784. ol.geom.SimpleGeometry.prototype.getFlatCoordinates = function() {
  3785. return this.flatCoordinates;
  3786. };
  3787. /**
  3788. * Return the last coordinate of the geometry.
  3789. * @return {ol.Coordinate} Last point.
  3790. * @api
  3791. */
  3792. ol.geom.SimpleGeometry.prototype.getLastCoordinate = function() {
  3793. return this.flatCoordinates.slice(this.flatCoordinates.length - this.stride);
  3794. };
  3795. /**
  3796. * Return the {@link ol.geom.GeometryLayout layout} of the geometry.
  3797. * @return {ol.geom.GeometryLayout} Layout.
  3798. * @api
  3799. */
  3800. ol.geom.SimpleGeometry.prototype.getLayout = function() {
  3801. return this.layout;
  3802. };
  3803. /**
  3804. * @inheritDoc
  3805. */
  3806. ol.geom.SimpleGeometry.prototype.getSimplifiedGeometry = function(squaredTolerance) {
  3807. if (this.simplifiedGeometryRevision != this.getRevision()) {
  3808. ol.obj.clear(this.simplifiedGeometryCache);
  3809. this.simplifiedGeometryMaxMinSquaredTolerance = 0;
  3810. this.simplifiedGeometryRevision = this.getRevision();
  3811. }
  3812. // If squaredTolerance is negative or if we know that simplification will not
  3813. // have any effect then just return this.
  3814. if (squaredTolerance < 0 ||
  3815. (this.simplifiedGeometryMaxMinSquaredTolerance !== 0 &&
  3816. squaredTolerance <= this.simplifiedGeometryMaxMinSquaredTolerance)) {
  3817. return this;
  3818. }
  3819. var key = squaredTolerance.toString();
  3820. if (this.simplifiedGeometryCache.hasOwnProperty(key)) {
  3821. return this.simplifiedGeometryCache[key];
  3822. } else {
  3823. var simplifiedGeometry =
  3824. this.getSimplifiedGeometryInternal(squaredTolerance);
  3825. var simplifiedFlatCoordinates = simplifiedGeometry.getFlatCoordinates();
  3826. if (simplifiedFlatCoordinates.length < this.flatCoordinates.length) {
  3827. this.simplifiedGeometryCache[key] = simplifiedGeometry;
  3828. return simplifiedGeometry;
  3829. } else {
  3830. // Simplification did not actually remove any coordinates. We now know
  3831. // that any calls to getSimplifiedGeometry with a squaredTolerance less
  3832. // than or equal to the current squaredTolerance will also not have any
  3833. // effect. This allows us to short circuit simplification (saving CPU
  3834. // cycles) and prevents the cache of simplified geometries from filling
  3835. // up with useless identical copies of this geometry (saving memory).
  3836. this.simplifiedGeometryMaxMinSquaredTolerance = squaredTolerance;
  3837. return this;
  3838. }
  3839. }
  3840. };
  3841. /**
  3842. * @param {number} squaredTolerance Squared tolerance.
  3843. * @return {ol.geom.SimpleGeometry} Simplified geometry.
  3844. * @protected
  3845. */
  3846. ol.geom.SimpleGeometry.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
  3847. return this;
  3848. };
  3849. /**
  3850. * @return {number} Stride.
  3851. */
  3852. ol.geom.SimpleGeometry.prototype.getStride = function() {
  3853. return this.stride;
  3854. };
  3855. /**
  3856. * @param {ol.geom.GeometryLayout} layout Layout.
  3857. * @param {Array.<number>} flatCoordinates Flat coordinates.
  3858. * @protected
  3859. */
  3860. ol.geom.SimpleGeometry.prototype.setFlatCoordinatesInternal = function(layout, flatCoordinates) {
  3861. this.stride = ol.geom.SimpleGeometry.getStrideForLayout(layout);
  3862. this.layout = layout;
  3863. this.flatCoordinates = flatCoordinates;
  3864. };
  3865. /**
  3866. * @abstract
  3867. * @param {Array} coordinates Coordinates.
  3868. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  3869. */
  3870. ol.geom.SimpleGeometry.prototype.setCoordinates = function(coordinates, opt_layout) {};
  3871. /**
  3872. * @param {ol.geom.GeometryLayout|undefined} layout Layout.
  3873. * @param {Array} coordinates Coordinates.
  3874. * @param {number} nesting Nesting.
  3875. * @protected
  3876. */
  3877. ol.geom.SimpleGeometry.prototype.setLayout = function(layout, coordinates, nesting) {
  3878. /** @type {number} */
  3879. var stride;
  3880. if (layout) {
  3881. stride = ol.geom.SimpleGeometry.getStrideForLayout(layout);
  3882. } else {
  3883. var i;
  3884. for (i = 0; i < nesting; ++i) {
  3885. if (coordinates.length === 0) {
  3886. this.layout = ol.geom.GeometryLayout.XY;
  3887. this.stride = 2;
  3888. return;
  3889. } else {
  3890. coordinates = /** @type {Array} */ (coordinates[0]);
  3891. }
  3892. }
  3893. stride = coordinates.length;
  3894. layout = ol.geom.SimpleGeometry.getLayoutForStride_(stride);
  3895. }
  3896. this.layout = layout;
  3897. this.stride = stride;
  3898. };
  3899. /**
  3900. * @inheritDoc
  3901. * @api
  3902. */
  3903. ol.geom.SimpleGeometry.prototype.applyTransform = function(transformFn) {
  3904. if (this.flatCoordinates) {
  3905. transformFn(this.flatCoordinates, this.flatCoordinates, this.stride);
  3906. this.changed();
  3907. }
  3908. };
  3909. /**
  3910. * @inheritDoc
  3911. * @api
  3912. */
  3913. ol.geom.SimpleGeometry.prototype.rotate = function(angle, anchor) {
  3914. var flatCoordinates = this.getFlatCoordinates();
  3915. if (flatCoordinates) {
  3916. var stride = this.getStride();
  3917. ol.geom.flat.transform.rotate(
  3918. flatCoordinates, 0, flatCoordinates.length,
  3919. stride, angle, anchor, flatCoordinates);
  3920. this.changed();
  3921. }
  3922. };
  3923. /**
  3924. * @inheritDoc
  3925. * @api
  3926. */
  3927. ol.geom.SimpleGeometry.prototype.scale = function(sx, opt_sy, opt_anchor) {
  3928. var sy = opt_sy;
  3929. if (sy === undefined) {
  3930. sy = sx;
  3931. }
  3932. var anchor = opt_anchor;
  3933. if (!anchor) {
  3934. anchor = ol.extent.getCenter(this.getExtent());
  3935. }
  3936. var flatCoordinates = this.getFlatCoordinates();
  3937. if (flatCoordinates) {
  3938. var stride = this.getStride();
  3939. ol.geom.flat.transform.scale(
  3940. flatCoordinates, 0, flatCoordinates.length,
  3941. stride, sx, sy, anchor, flatCoordinates);
  3942. this.changed();
  3943. }
  3944. };
  3945. /**
  3946. * @inheritDoc
  3947. * @api
  3948. */
  3949. ol.geom.SimpleGeometry.prototype.translate = function(deltaX, deltaY) {
  3950. var flatCoordinates = this.getFlatCoordinates();
  3951. if (flatCoordinates) {
  3952. var stride = this.getStride();
  3953. ol.geom.flat.transform.translate(
  3954. flatCoordinates, 0, flatCoordinates.length, stride,
  3955. deltaX, deltaY, flatCoordinates);
  3956. this.changed();
  3957. }
  3958. };
  3959. /**
  3960. * @param {ol.geom.SimpleGeometry} simpleGeometry Simple geometry.
  3961. * @param {ol.Transform} transform Transform.
  3962. * @param {Array.<number>=} opt_dest Destination.
  3963. * @return {Array.<number>} Transformed flat coordinates.
  3964. */
  3965. ol.geom.SimpleGeometry.transform2D = function(simpleGeometry, transform, opt_dest) {
  3966. var flatCoordinates = simpleGeometry.getFlatCoordinates();
  3967. if (!flatCoordinates) {
  3968. return null;
  3969. } else {
  3970. var stride = simpleGeometry.getStride();
  3971. return ol.geom.flat.transform.transform2D(
  3972. flatCoordinates, 0, flatCoordinates.length, stride,
  3973. transform, opt_dest);
  3974. }
  3975. };
  3976. ol.geom.Polygon = function(coordinates, opt_layout) {
  3977. ol.geom.SimpleGeometry.call(this);
  3978. /**
  3979. * @type {Array.<number>}
  3980. * @private
  3981. */
  3982. this.ends_ = [];
  3983. /**
  3984. * @private
  3985. * @type {number}
  3986. */
  3987. this.flatInteriorPointRevision_ = -1;
  3988. /**
  3989. * @private
  3990. * @type {ol.Coordinate}
  3991. */
  3992. this.flatInteriorPoint_ = null;
  3993. /**
  3994. * @private
  3995. * @type {number}
  3996. */
  3997. this.maxDelta_ = -1;
  3998. /**
  3999. * @private
  4000. * @type {number}
  4001. */
  4002. this.maxDeltaRevision_ = -1;
  4003. /**
  4004. * @private
  4005. * @type {number}
  4006. */
  4007. this.orientedRevision_ = -1;
  4008. /**
  4009. * @private
  4010. * @type {Array.<number>}
  4011. */
  4012. this.orientedFlatCoordinates_ = null;
  4013. this.setCoordinates(coordinates, opt_layout);
  4014. };
  4015. ol.inherits(ol.geom.Polygon, ol.geom.SimpleGeometry);
  4016. /**
  4017. * Append the passed linear ring to this polygon.
  4018. * @param {ol.geom.LinearRing} linearRing Linear ring.
  4019. * @api
  4020. */
  4021. ol.geom.Polygon.prototype.appendLinearRing = function(linearRing) {
  4022. if (!this.flatCoordinates) {
  4023. this.flatCoordinates = linearRing.getFlatCoordinates().slice();
  4024. } else {
  4025. ol.array.extend(this.flatCoordinates, linearRing.getFlatCoordinates());
  4026. }
  4027. this.ends_.push(this.flatCoordinates.length);
  4028. this.changed();
  4029. };
  4030. /**
  4031. * Make a complete copy of the geometry.
  4032. * @return {!ol.geom.Polygon} Clone.
  4033. * @override
  4034. * @api
  4035. */
  4036. ol.geom.Polygon.prototype.clone = function() {
  4037. var polygon = new ol.geom.Polygon(null);
  4038. polygon.setFlatCoordinates(
  4039. this.layout, this.flatCoordinates.slice(), this.ends_.slice());
  4040. return polygon;
  4041. };
  4042. /**
  4043. * @inheritDoc
  4044. */
  4045. ol.geom.Polygon.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  4046. if (minSquaredDistance <
  4047. ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
  4048. return minSquaredDistance;
  4049. }
  4050. if (this.maxDeltaRevision_ != this.getRevision()) {
  4051. this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getsMaxSquaredDelta(
  4052. this.flatCoordinates, 0, this.ends_, this.stride, 0));
  4053. this.maxDeltaRevision_ = this.getRevision();
  4054. }
  4055. return ol.geom.flat.closest.getsClosestPoint(
  4056. this.flatCoordinates, 0, this.ends_, this.stride,
  4057. this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);
  4058. };
  4059. /**
  4060. * @inheritDoc
  4061. */
  4062. ol.geom.Polygon.prototype.containsXY = function(x, y) {
  4063. return ol.geom.flat.contains.linearRingsContainsXY(
  4064. this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, x, y);
  4065. };
  4066. /**
  4067. * Return the area of the polygon on projected plane.
  4068. * @return {number} Area (on projected plane).
  4069. * @api
  4070. */
  4071. ol.geom.Polygon.prototype.getArea = function() {
  4072. return ol.geom.flat.area.linearRings(
  4073. this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride);
  4074. };
  4075. /**
  4076. * Get the coordinate array for this geometry. This array has the structure
  4077. * of a GeoJSON coordinate array for polygons.
  4078. *
  4079. * @param {boolean=} opt_right Orient coordinates according to the right-hand
  4080. * rule (counter-clockwise for exterior and clockwise for interior rings).
  4081. * If `false`, coordinates will be oriented according to the left-hand rule
  4082. * (clockwise for exterior and counter-clockwise for interior rings).
  4083. * By default, coordinate orientation will depend on how the geometry was
  4084. * constructed.
  4085. * @return {Array.<Array.<ol.Coordinate>>} Coordinates.
  4086. * @override
  4087. * @api
  4088. */
  4089. ol.geom.Polygon.prototype.getCoordinates = function(opt_right) {
  4090. var flatCoordinates;
  4091. if (opt_right !== undefined) {
  4092. flatCoordinates = this.getOrientedFlatCoordinates().slice();
  4093. ol.geom.flat.orient.orientLinearRings(
  4094. flatCoordinates, 0, this.ends_, this.stride, opt_right);
  4095. } else {
  4096. flatCoordinates = this.flatCoordinates;
  4097. }
  4098. return ol.geom.flat.inflate.coordinatess(
  4099. flatCoordinates, 0, this.ends_, this.stride);
  4100. };
  4101. /**
  4102. * @return {Array.<number>} Ends.
  4103. */
  4104. ol.geom.Polygon.prototype.getEnds = function() {
  4105. return this.ends_;
  4106. };
  4107. /**
  4108. * @return {Array.<number>} Interior point.
  4109. */
  4110. ol.geom.Polygon.prototype.getFlatInteriorPoint = function() {
  4111. if (this.flatInteriorPointRevision_ != this.getRevision()) {
  4112. var flatCenter = ol.extent.getCenter(this.getExtent());
  4113. this.flatInteriorPoint_ = ol.geom.flat.interiorpoint.linearRings(
  4114. this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride,
  4115. flatCenter, 0);
  4116. this.flatInteriorPointRevision_ = this.getRevision();
  4117. }
  4118. return this.flatInteriorPoint_;
  4119. };
  4120. /**
  4121. * Return an interior point of the polygon.
  4122. * @return {ol.geom.Point} Interior point as XYM coordinate, where M is the
  4123. * length of the horizontal intersection that the point belongs to.
  4124. * @api
  4125. */
  4126. ol.geom.Polygon.prototype.getInteriorPoint = function() {
  4127. return new ol.geom.Point(this.getFlatInteriorPoint(), ol.geom.GeometryLayout.XYM);
  4128. };
  4129. /**
  4130. * Return the number of rings of the polygon, this includes the exterior
  4131. * ring and any interior rings.
  4132. *
  4133. * @return {number} Number of rings.
  4134. * @api
  4135. */
  4136. ol.geom.Polygon.prototype.getLinearRingCount = function() {
  4137. return this.ends_.length;
  4138. };
  4139. /**
  4140. * Return the Nth linear ring of the polygon geometry. Return `null` if the
  4141. * given index is out of range.
  4142. * The exterior linear ring is available at index `0` and the interior rings
  4143. * at index `1` and beyond.
  4144. *
  4145. * @param {number} index Index.
  4146. * @return {ol.geom.LinearRing} Linear ring.
  4147. * @api
  4148. */
  4149. ol.geom.Polygon.prototype.getLinearRing = function(index) {
  4150. if (index < 0 || this.ends_.length <= index) {
  4151. return null;
  4152. }
  4153. var linearRing = new ol.geom.LinearRing(null);
  4154. linearRing.setFlatCoordinates(this.layout, this.flatCoordinates.slice(
  4155. index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]));
  4156. return linearRing;
  4157. };
  4158. /**
  4159. * Return the linear rings of the polygon.
  4160. * @return {Array.<ol.geom.LinearRing>} Linear rings.
  4161. * @api
  4162. */
  4163. ol.geom.Polygon.prototype.getLinearRings = function() {
  4164. var layout = this.layout;
  4165. var flatCoordinates = this.flatCoordinates;
  4166. var ends = this.ends_;
  4167. var linearRings = [];
  4168. var offset = 0;
  4169. var i, ii;
  4170. for (i = 0, ii = ends.length; i < ii; ++i) {
  4171. var end = ends[i];
  4172. var linearRing = new ol.geom.LinearRing(null);
  4173. linearRing.setFlatCoordinates(layout, flatCoordinates.slice(offset, end));
  4174. linearRings.push(linearRing);
  4175. offset = end;
  4176. }
  4177. return linearRings;
  4178. };
  4179. /**
  4180. * @return {Array.<number>} Oriented flat coordinates.
  4181. */
  4182. ol.geom.Polygon.prototype.getOrientedFlatCoordinates = function() {
  4183. if (this.orientedRevision_ != this.getRevision()) {
  4184. var flatCoordinates = this.flatCoordinates;
  4185. if (ol.geom.flat.orient.linearRingsAreOriented(
  4186. flatCoordinates, 0, this.ends_, this.stride)) {
  4187. this.orientedFlatCoordinates_ = flatCoordinates;
  4188. } else {
  4189. this.orientedFlatCoordinates_ = flatCoordinates.slice();
  4190. this.orientedFlatCoordinates_.length =
  4191. ol.geom.flat.orient.orientLinearRings(
  4192. this.orientedFlatCoordinates_, 0, this.ends_, this.stride);
  4193. }
  4194. this.orientedRevision_ = this.getRevision();
  4195. }
  4196. return this.orientedFlatCoordinates_;
  4197. };
  4198. /**
  4199. * @inheritDoc
  4200. */
  4201. ol.geom.Polygon.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
  4202. var simplifiedFlatCoordinates = [];
  4203. var simplifiedEnds = [];
  4204. simplifiedFlatCoordinates.length = ol.geom.flat.simplify.quantizes(
  4205. this.flatCoordinates, 0, this.ends_, this.stride,
  4206. Math.sqrt(squaredTolerance),
  4207. simplifiedFlatCoordinates, 0, simplifiedEnds);
  4208. var simplifiedPolygon = new ol.geom.Polygon(null);
  4209. simplifiedPolygon.setFlatCoordinates(
  4210. ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates, simplifiedEnds);
  4211. return simplifiedPolygon;
  4212. };
  4213. /**
  4214. * @inheritDoc
  4215. * @api
  4216. */
  4217. ol.geom.Polygon.prototype.getType = function() {
  4218. return ol.geom.GeometryType.POLYGON;
  4219. };
  4220. /**
  4221. * @inheritDoc
  4222. * @api
  4223. */
  4224. ol.geom.Polygon.prototype.intersectsExtent = function(extent) {
  4225. return ol.geom.flat.intersectsextent.linearRings(
  4226. this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, extent);
  4227. };
  4228. /**
  4229. * Set the coordinates of the polygon.
  4230. * @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
  4231. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  4232. * @override
  4233. * @api
  4234. */
  4235. ol.geom.Polygon.prototype.setCoordinates = function(coordinates, opt_layout) {
  4236. if (!coordinates) {
  4237. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.ends_);
  4238. } else {
  4239. this.setLayout(opt_layout, coordinates, 2);
  4240. if (!this.flatCoordinates) {
  4241. this.flatCoordinates = [];
  4242. }
  4243. var ends = ol.geom.flat.deflate.coordinatess(
  4244. this.flatCoordinates, 0, coordinates, this.stride, this.ends_);
  4245. this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1];
  4246. //this.changed();
  4247. }
  4248. };
  4249. /**
  4250. * @param {ol.geom.GeometryLayout} layout Layout.
  4251. * @param {Array.<number>} flatCoordinates Flat coordinates.
  4252. * @param {Array.<number>} ends Ends.
  4253. */
  4254. ol.geom.Polygon.prototype.setFlatCoordinates = function(layout, flatCoordinates, ends) {
  4255. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  4256. this.ends_ = ends;
  4257. //this.changed();
  4258. };
  4259. /**
  4260. * Create an approximation of a circle on the surface of a sphere.
  4261. * @param {ol.Sphere} sphere The sphere.
  4262. * @param {ol.Coordinate} center Center (`[lon, lat]` in degrees).
  4263. * @param {number} radius The great-circle distance from the center to
  4264. * the polygon vertices.
  4265. * @param {number=} opt_n Optional number of vertices for the resulting
  4266. * polygon. Default is `32`.
  4267. * @return {ol.geom.Polygon} The "circular" polygon.
  4268. * @api
  4269. */
  4270. ol.geom.Polygon.circular = function(sphere, center, radius, opt_n) {
  4271. var n = opt_n ? opt_n : 32;
  4272. /** @type {Array.<number>} */
  4273. var flatCoordinates = [];
  4274. var i;
  4275. for (i = 0; i < n; ++i) {
  4276. ol.array.extend(
  4277. flatCoordinates, sphere.offset(center, radius, 2 * Math.PI * i / n));
  4278. }
  4279. flatCoordinates.push(flatCoordinates[0], flatCoordinates[1]);
  4280. var polygon = new ol.geom.Polygon(null);
  4281. polygon.setFlatCoordinates(
  4282. ol.geom.GeometryLayout.XY, flatCoordinates, [flatCoordinates.length]);
  4283. return polygon;
  4284. };
  4285. /**
  4286. * Create a polygon from an extent. The layout used is `XY`.
  4287. * @param {ol.Extent} extent The extent.
  4288. * @return {ol.geom.Polygon} The polygon.
  4289. * @api
  4290. */
  4291. ol.geom.Polygon.fromExtent = function(extent) {
  4292. var minX = extent[0];
  4293. var minY = extent[1];
  4294. var maxX = extent[2];
  4295. var maxY = extent[3];
  4296. var flatCoordinates =
  4297. [minX, minY, minX, maxY, maxX, maxY, maxX, minY, minX, minY];
  4298. var polygon = new ol.geom.Polygon(null);
  4299. polygon.setFlatCoordinates(
  4300. ol.geom.GeometryLayout.XY, flatCoordinates, [flatCoordinates.length]);
  4301. return polygon;
  4302. };
  4303. /**
  4304. * Create a regular polygon from a circle.
  4305. * @param {ol.geom.Circle} circle Circle geometry.
  4306. * @param {number=} opt_sides Number of sides of the polygon. Default is 32.
  4307. * @param {number=} opt_angle Start angle for the first vertex of the polygon in
  4308. * radians. Default is 0.
  4309. * @return {ol.geom.Polygon} Polygon geometry.
  4310. * @api
  4311. */
  4312. ol.geom.Polygon.fromCircle = function(circle, opt_sides, opt_angle) {
  4313. var sides = opt_sides ? opt_sides : 32;
  4314. var stride = circle.getStride();
  4315. var layout = circle.getLayout();
  4316. var polygon = new ol.geom.Polygon(null, layout);
  4317. var arrayLength = stride * (sides + 1);
  4318. var flatCoordinates = new Array(arrayLength);
  4319. for (var i = 0; i < arrayLength; i++) {
  4320. flatCoordinates[i] = 0;
  4321. }
  4322. var ends = [flatCoordinates.length];
  4323. polygon.setFlatCoordinates(layout, flatCoordinates, ends);
  4324. ol.geom.Polygon.makeRegular(
  4325. polygon, circle.getCenter(), circle.getRadius(), opt_angle);
  4326. return polygon;
  4327. };
  4328. /**
  4329. * Modify the coordinates of a polygon to make it a regular polygon.
  4330. * @param {ol.geom.Polygon} polygon Polygon geometry.
  4331. * @param {ol.Coordinate} center Center of the regular polygon.
  4332. * @param {number} radius Radius of the regular polygon.
  4333. * @param {number=} opt_angle Start angle for the first vertex of the polygon in
  4334. * radians. Default is 0.
  4335. */
  4336. ol.geom.Polygon.makeRegular = function(polygon, center, radius, opt_angle) {
  4337. var flatCoordinates = polygon.getFlatCoordinates();
  4338. var layout = polygon.getLayout();
  4339. var stride = polygon.getStride();
  4340. var ends = polygon.getEnds();
  4341. var sides = flatCoordinates.length / stride - 1;
  4342. var startAngle = opt_angle ? opt_angle : 0;
  4343. var angle, offset;
  4344. for (var i = 0; i <= sides; ++i) {
  4345. offset = i * stride;
  4346. angle = startAngle + (ol.math.modulo(i, sides) * 2 * Math.PI / sides);
  4347. flatCoordinates[offset] = center[0] + (radius * Math.cos(angle));
  4348. flatCoordinates[offset + 1] = center[1] + (radius * Math.sin(angle));
  4349. }
  4350. polygon.setFlatCoordinates(layout, flatCoordinates, ends);
  4351. };
  4352. /**
  4353. * @classdesc
  4354. * Linestring geometry.
  4355. *
  4356. * @constructor
  4357. * @extends {ol.geom.SimpleGeometry}
  4358. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  4359. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  4360. * @api
  4361. */
  4362. ol.geom.LineString = function(coordinates, opt_layout) {
  4363. ol.geom.SimpleGeometry.call(this);
  4364. /**
  4365. * @private
  4366. * @type {ol.Coordinate}
  4367. */
  4368. this.flatMidpoint_ = null;
  4369. /**
  4370. * @private
  4371. * @type {number}
  4372. */
  4373. this.flatMidpointRevision_ = -1;
  4374. /**
  4375. * @private
  4376. * @type {number}
  4377. */
  4378. this.maxDelta_ = -1;
  4379. /**
  4380. * @private
  4381. * @type {number}
  4382. */
  4383. this.maxDeltaRevision_ = -1;
  4384. this.setCoordinates(coordinates, opt_layout);
  4385. };
  4386. ol.inherits(ol.geom.LineString, ol.geom.SimpleGeometry);
  4387. /**
  4388. * Append the passed coordinate to the coordinates of the linestring.
  4389. * @param {ol.Coordinate} coordinate Coordinate.
  4390. * @api
  4391. */
  4392. ol.geom.LineString.prototype.appendCoordinate = function(coordinate) {
  4393. if (!this.flatCoordinates) {
  4394. this.flatCoordinates = coordinate.slice();
  4395. } else {
  4396. ol.array.extend(this.flatCoordinates, coordinate);
  4397. }
  4398. this.changed();
  4399. };
  4400. /**
  4401. * Make a complete copy of the geometry.
  4402. * @return {!ol.geom.LineString} Clone.
  4403. * @override
  4404. * @api
  4405. */
  4406. ol.geom.LineString.prototype.clone = function() {
  4407. var lineString = new ol.geom.LineString(null);
  4408. lineString.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
  4409. return lineString;
  4410. };
  4411. /**
  4412. * @inheritDoc
  4413. */
  4414. ol.geom.LineString.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  4415. if (minSquaredDistance <
  4416. ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
  4417. return minSquaredDistance;
  4418. }
  4419. if (this.maxDeltaRevision_ != this.getRevision()) {
  4420. this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getMaxSquaredDelta(
  4421. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, 0));
  4422. this.maxDeltaRevision_ = this.getRevision();
  4423. }
  4424. return ol.geom.flat.closest.getClosestPoint(
  4425. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
  4426. this.maxDelta_, false, x, y, closestPoint, minSquaredDistance);
  4427. };
  4428. /**
  4429. * Iterate over each segment, calling the provided callback.
  4430. * If the callback returns a truthy value the function returns that
  4431. * value immediately. Otherwise the function returns `false`.
  4432. *
  4433. * @param {function(this: S, ol.Coordinate, ol.Coordinate): T} callback Function
  4434. * called for each segment.
  4435. * @param {S=} opt_this The object to be used as the value of 'this'
  4436. * within callback.
  4437. * @return {T|boolean} Value.
  4438. * @template T,S
  4439. * @api
  4440. */
  4441. ol.geom.LineString.prototype.forEachSegment = function(callback, opt_this) {
  4442. return ol.geom.flat.segments.forEach(this.flatCoordinates, 0,
  4443. this.flatCoordinates.length, this.stride, callback, opt_this);
  4444. };
  4445. /**
  4446. * Returns the coordinate at `m` using linear interpolation, or `null` if no
  4447. * such coordinate exists.
  4448. *
  4449. * `opt_extrapolate` controls extrapolation beyond the range of Ms in the
  4450. * MultiLineString. If `opt_extrapolate` is `true` then Ms less than the first
  4451. * M will return the first coordinate and Ms greater than the last M will
  4452. * return the last coordinate.
  4453. *
  4454. * @param {number} m M.
  4455. * @param {boolean=} opt_extrapolate Extrapolate. Default is `false`.
  4456. * @return {ol.Coordinate} Coordinate.
  4457. * @api
  4458. */
  4459. ol.geom.LineString.prototype.getCoordinateAtM = function(m, opt_extrapolate) {
  4460. if (this.layout != ol.geom.GeometryLayout.XYM &&
  4461. this.layout != ol.geom.GeometryLayout.XYZM) {
  4462. return null;
  4463. }
  4464. var extrapolate = opt_extrapolate !== undefined ? opt_extrapolate : false;
  4465. return ol.geom.flat.interpolate.lineStringCoordinateAtM(this.flatCoordinates, 0,
  4466. this.flatCoordinates.length, this.stride, m, extrapolate);
  4467. };
  4468. /**
  4469. * Return the coordinates of the linestring.
  4470. * @return {Array.<ol.Coordinate>} Coordinates.
  4471. * @override
  4472. * @api
  4473. */
  4474. ol.geom.LineString.prototype.getCoordinates = function() {
  4475. return ol.geom.flat.inflate.coordinates(
  4476. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
  4477. };
  4478. /**
  4479. * Return the coordinate at the provided fraction along the linestring.
  4480. * The `fraction` is a number between 0 and 1, where 0 is the start of the
  4481. * linestring and 1 is the end.
  4482. * @param {number} fraction Fraction.
  4483. * @param {ol.Coordinate=} opt_dest Optional coordinate whose values will
  4484. * be modified. If not provided, a new coordinate will be returned.
  4485. * @return {ol.Coordinate} Coordinate of the interpolated point.
  4486. * @api
  4487. */
  4488. ol.geom.LineString.prototype.getCoordinateAt = function(fraction, opt_dest) {
  4489. return ol.geom.flat.interpolate.lineString(
  4490. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
  4491. fraction, opt_dest);
  4492. };
  4493. /**
  4494. * Return the length of the linestring on projected plane.
  4495. * @return {number} Length (on projected plane).
  4496. * @api
  4497. */
  4498. ol.geom.LineString.prototype.getLength = function() {
  4499. return ol.geom.flat.length.lineString(
  4500. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
  4501. };
  4502. /**
  4503. * @return {Array.<number>} Flat midpoint.
  4504. */
  4505. ol.geom.LineString.prototype.getFlatMidpoint = function() {
  4506. if (this.flatMidpointRevision_ != this.getRevision()) {
  4507. this.flatMidpoint_ = this.getCoordinateAt(0.5, this.flatMidpoint_);
  4508. this.flatMidpointRevision_ = this.getRevision();
  4509. }
  4510. return this.flatMidpoint_;
  4511. };
  4512. /**
  4513. * @inheritDoc
  4514. */
  4515. ol.geom.LineString.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
  4516. var simplifiedFlatCoordinates = [];
  4517. simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeucker(
  4518. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
  4519. squaredTolerance, simplifiedFlatCoordinates, 0);
  4520. var simplifiedLineString = new ol.geom.LineString(null);
  4521. simplifiedLineString.setFlatCoordinates(
  4522. ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates);
  4523. return simplifiedLineString;
  4524. };
  4525. /**
  4526. * @inheritDoc
  4527. * @api
  4528. */
  4529. ol.geom.LineString.prototype.getType = function() {
  4530. return ol.geom.GeometryType.LINE_STRING;
  4531. };
  4532. /**
  4533. * @inheritDoc
  4534. * @api
  4535. */
  4536. ol.geom.LineString.prototype.intersectsExtent = function(extent) {
  4537. return ol.geom.flat.intersectsextent.lineString(
  4538. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
  4539. extent);
  4540. };
  4541. /**
  4542. * Set the coordinates of the linestring.
  4543. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  4544. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  4545. * @override
  4546. * @api
  4547. */
  4548. ol.geom.LineString.prototype.setCoordinates = function(coordinates, opt_layout) {
  4549. if (!coordinates) {
  4550. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
  4551. } else {
  4552. this.setLayout(opt_layout, coordinates, 1);
  4553. if (!this.flatCoordinates) {
  4554. this.flatCoordinates = [];
  4555. }
  4556. this.flatCoordinates.length = ol.geom.flat.deflate.coordinates(
  4557. this.flatCoordinates, 0, coordinates, this.stride);
  4558. this.changed();
  4559. }
  4560. };
  4561. /**
  4562. * @param {ol.geom.GeometryLayout} layout Layout.
  4563. * @param {Array.<number>} flatCoordinates Flat coordinates.
  4564. */
  4565. ol.geom.LineString.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
  4566. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  4567. this.changed();
  4568. };
  4569. ol.geom.Point = function(coordinates, opt_layout) {
  4570. ol.geom.SimpleGeometry.call(this);
  4571. this.setCoordinates(coordinates, opt_layout);
  4572. };
  4573. ol.inherits(ol.geom.Point, ol.geom.SimpleGeometry);
  4574. ol.geom.Point.prototype.clone = function() {
  4575. var point = new ol.geom.Point(null);
  4576. point.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
  4577. return point;
  4578. };
  4579. /**
  4580. * @inheritDoc
  4581. */
  4582. ol.geom.Point.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  4583. var flatCoordinates = this.flatCoordinates;
  4584. var squaredDistance = ol.math.squaredDistance(
  4585. x, y, flatCoordinates[0], flatCoordinates[1]);
  4586. if (squaredDistance < minSquaredDistance) {
  4587. var stride = this.stride;
  4588. var i;
  4589. for (i = 0; i < stride; ++i) {
  4590. closestPoint[i] = flatCoordinates[i];
  4591. }
  4592. closestPoint.length = stride;
  4593. return squaredDistance;
  4594. } else {
  4595. return minSquaredDistance;
  4596. }
  4597. };
  4598. ol.geom.Point.prototype.getCoordinates = function() {
  4599. return !this.flatCoordinates ? [] : this.flatCoordinates.slice();
  4600. };
  4601. ol.geom.Point.prototype.computeExtent = function(extent) {
  4602. return ol.extent.createOrUpdateFromCoordinate(this.flatCoordinates, extent);
  4603. };
  4604. ol.geom.Point.prototype.getType = function() {
  4605. return ol.geom.GeometryType.POINT;
  4606. };
  4607. ol.geom.Point.prototype.intersectsExtent = function(extent) {
  4608. return ol.extent.containsXY(extent,
  4609. this.flatCoordinates[0], this.flatCoordinates[1]);
  4610. };
  4611. ol.geom.Point.prototype.setCoordinates = function(coordinates, opt_layout) {
  4612. if (!coordinates) {
  4613. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
  4614. } else {
  4615. this.setLayout(opt_layout, coordinates, 0);
  4616. if (!this.flatCoordinates) {
  4617. this.flatCoordinates = [];
  4618. }
  4619. this.flatCoordinates.length = ol.geom.flat.deflate.coordinate(
  4620. this.flatCoordinates, 0, coordinates, this.stride);
  4621. this.changed();
  4622. }
  4623. };
  4624. ol.geom.Point.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
  4625. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  4626. this.changed();
  4627. };
  4628. /**
  4629. * @classdesc
  4630. * Multi-linestring geometry.
  4631. *
  4632. * @constructor
  4633. * @extends {ol.geom.SimpleGeometry}
  4634. * @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
  4635. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  4636. * @api
  4637. */
  4638. ol.geom.MultiLineString = function(coordinates, opt_layout) {
  4639. ol.geom.SimpleGeometry.call(this);
  4640. /**
  4641. * @type {Array.<number>}
  4642. * @private
  4643. */
  4644. this.ends_ = [];
  4645. /**
  4646. * @private
  4647. * @type {number}
  4648. */
  4649. this.maxDelta_ = -1;
  4650. /**
  4651. * @private
  4652. * @type {number}
  4653. */
  4654. this.maxDeltaRevision_ = -1;
  4655. this.setCoordinates(coordinates, opt_layout);
  4656. };
  4657. ol.inherits(ol.geom.MultiLineString, ol.geom.SimpleGeometry);
  4658. /**
  4659. * Append the passed linestring to the multilinestring.
  4660. * @param {ol.geom.LineString} lineString LineString.
  4661. * @api
  4662. */
  4663. ol.geom.MultiLineString.prototype.appendLineString = function(lineString) {
  4664. if (!this.flatCoordinates) {
  4665. this.flatCoordinates = lineString.getFlatCoordinates().slice();
  4666. } else {
  4667. ol.array.extend(
  4668. this.flatCoordinates, lineString.getFlatCoordinates().slice());
  4669. }
  4670. this.ends_.push(this.flatCoordinates.length);
  4671. this.changed();
  4672. };
  4673. /**
  4674. * Make a complete copy of the geometry.
  4675. * @return {!ol.geom.MultiLineString} Clone.
  4676. * @override
  4677. * @api
  4678. */
  4679. ol.geom.MultiLineString.prototype.clone = function() {
  4680. var multiLineString = new ol.geom.MultiLineString(null);
  4681. multiLineString.setFlatCoordinates(
  4682. this.layout, this.flatCoordinates.slice(), this.ends_.slice());
  4683. return multiLineString;
  4684. };
  4685. /**
  4686. * @inheritDoc
  4687. */
  4688. ol.geom.MultiLineString.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  4689. if (minSquaredDistance <
  4690. ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
  4691. return minSquaredDistance;
  4692. }
  4693. if (this.maxDeltaRevision_ != this.getRevision()) {
  4694. this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getsMaxSquaredDelta(
  4695. this.flatCoordinates, 0, this.ends_, this.stride, 0));
  4696. this.maxDeltaRevision_ = this.getRevision();
  4697. }
  4698. return ol.geom.flat.closest.getsClosestPoint(
  4699. this.flatCoordinates, 0, this.ends_, this.stride,
  4700. this.maxDelta_, false, x, y, closestPoint, minSquaredDistance);
  4701. };
  4702. /**
  4703. * Returns the coordinate at `m` using linear interpolation, or `null` if no
  4704. * such coordinate exists.
  4705. *
  4706. * `opt_extrapolate` controls extrapolation beyond the range of Ms in the
  4707. * MultiLineString. If `opt_extrapolate` is `true` then Ms less than the first
  4708. * M will return the first coordinate and Ms greater than the last M will
  4709. * return the last coordinate.
  4710. *
  4711. * `opt_interpolate` controls interpolation between consecutive LineStrings
  4712. * within the MultiLineString. If `opt_interpolate` is `true` the coordinates
  4713. * will be linearly interpolated between the last coordinate of one LineString
  4714. * and the first coordinate of the next LineString. If `opt_interpolate` is
  4715. * `false` then the function will return `null` for Ms falling between
  4716. * LineStrings.
  4717. *
  4718. * @param {number} m M.
  4719. * @param {boolean=} opt_extrapolate Extrapolate. Default is `false`.
  4720. * @param {boolean=} opt_interpolate Interpolate. Default is `false`.
  4721. * @return {ol.Coordinate} Coordinate.
  4722. * @api
  4723. */
  4724. ol.geom.MultiLineString.prototype.getCoordinateAtM = function(m, opt_extrapolate, opt_interpolate) {
  4725. if ((this.layout != ol.geom.GeometryLayout.XYM &&
  4726. this.layout != ol.geom.GeometryLayout.XYZM) ||
  4727. this.flatCoordinates.length === 0) {
  4728. return null;
  4729. }
  4730. var extrapolate = opt_extrapolate !== undefined ? opt_extrapolate : false;
  4731. var interpolate = opt_interpolate !== undefined ? opt_interpolate : false;
  4732. return ol.geom.flat.interpolate.lineStringsCoordinateAtM(this.flatCoordinates, 0,
  4733. this.ends_, this.stride, m, extrapolate, interpolate);
  4734. };
  4735. /**
  4736. * Return the coordinates of the multilinestring.
  4737. * @return {Array.<Array.<ol.Coordinate>>} Coordinates.
  4738. * @override
  4739. * @api
  4740. */
  4741. ol.geom.MultiLineString.prototype.getCoordinates = function() {
  4742. return ol.geom.flat.inflate.coordinatess(
  4743. this.flatCoordinates, 0, this.ends_, this.stride);
  4744. };
  4745. /**
  4746. * @return {Array.<number>} Ends.
  4747. */
  4748. ol.geom.MultiLineString.prototype.getEnds = function() {
  4749. return this.ends_;
  4750. };
  4751. /**
  4752. * Return the linestring at the specified index.
  4753. * @param {number} index Index.
  4754. * @return {ol.geom.LineString} LineString.
  4755. * @api
  4756. */
  4757. ol.geom.MultiLineString.prototype.getLineString = function(index) {
  4758. if (index < 0 || this.ends_.length <= index) {
  4759. return null;
  4760. }
  4761. var lineString = new ol.geom.LineString(null);
  4762. lineString.setFlatCoordinates(this.layout, this.flatCoordinates.slice(
  4763. index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]));
  4764. return lineString;
  4765. };
  4766. /**
  4767. * Return the linestrings of this multilinestring.
  4768. * @return {Array.<ol.geom.LineString>} LineStrings.
  4769. * @api
  4770. */
  4771. ol.geom.MultiLineString.prototype.getLineStrings = function() {
  4772. var flatCoordinates = this.flatCoordinates;
  4773. var ends = this.ends_;
  4774. var layout = this.layout;
  4775. /** @type {Array.<ol.geom.LineString>} */
  4776. var lineStrings = [];
  4777. var offset = 0;
  4778. var i, ii;
  4779. for (i = 0, ii = ends.length; i < ii; ++i) {
  4780. var end = ends[i];
  4781. var lineString = new ol.geom.LineString(null);
  4782. lineString.setFlatCoordinates(layout, flatCoordinates.slice(offset, end));
  4783. lineStrings.push(lineString);
  4784. offset = end;
  4785. }
  4786. return lineStrings;
  4787. };
  4788. /**
  4789. * @return {Array.<number>} Flat midpoints.
  4790. */
  4791. ol.geom.MultiLineString.prototype.getFlatMidpoints = function() {
  4792. var midpoints = [];
  4793. var flatCoordinates = this.flatCoordinates;
  4794. var offset = 0;
  4795. var ends = this.ends_;
  4796. var stride = this.stride;
  4797. var i, ii;
  4798. for (i = 0, ii = ends.length; i < ii; ++i) {
  4799. var end = ends[i];
  4800. var midpoint = ol.geom.flat.interpolate.lineString(
  4801. flatCoordinates, offset, end, stride, 0.5);
  4802. ol.array.extend(midpoints, midpoint);
  4803. offset = end;
  4804. }
  4805. return midpoints;
  4806. };
  4807. /**
  4808. * @inheritDoc
  4809. */
  4810. ol.geom.MultiLineString.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
  4811. var simplifiedFlatCoordinates = [];
  4812. var simplifiedEnds = [];
  4813. simplifiedFlatCoordinates.length = ol.geom.flat.simplify.douglasPeuckers(
  4814. this.flatCoordinates, 0, this.ends_, this.stride, squaredTolerance,
  4815. simplifiedFlatCoordinates, 0, simplifiedEnds);
  4816. var simplifiedMultiLineString = new ol.geom.MultiLineString(null);
  4817. simplifiedMultiLineString.setFlatCoordinates(
  4818. ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates, simplifiedEnds);
  4819. return simplifiedMultiLineString;
  4820. };
  4821. /**
  4822. * @inheritDoc
  4823. * @api
  4824. */
  4825. ol.geom.MultiLineString.prototype.getType = function() {
  4826. return ol.geom.GeometryType.MULTI_LINE_STRING;
  4827. };
  4828. /**
  4829. * @inheritDoc
  4830. * @api
  4831. */
  4832. ol.geom.MultiLineString.prototype.intersectsExtent = function(extent) {
  4833. return ol.geom.flat.intersectsextent.lineStrings(
  4834. this.flatCoordinates, 0, this.ends_, this.stride, extent);
  4835. };
  4836. /**
  4837. * Set the coordinates of the multilinestring.
  4838. * @param {Array.<Array.<ol.Coordinate>>} coordinates Coordinates.
  4839. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  4840. * @override
  4841. * @api
  4842. */
  4843. ol.geom.MultiLineString.prototype.setCoordinates = function(coordinates, opt_layout) {
  4844. if (!coordinates) {
  4845. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.ends_);
  4846. } else {
  4847. this.setLayout(opt_layout, coordinates, 2);
  4848. if (!this.flatCoordinates) {
  4849. this.flatCoordinates = [];
  4850. }
  4851. var ends = ol.geom.flat.deflate.coordinatess(
  4852. this.flatCoordinates, 0, coordinates, this.stride, this.ends_);
  4853. this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1];
  4854. this.changed();
  4855. }
  4856. };
  4857. /**
  4858. * @param {ol.geom.GeometryLayout} layout Layout.
  4859. * @param {Array.<number>} flatCoordinates Flat coordinates.
  4860. * @param {Array.<number>} ends Ends.
  4861. */
  4862. ol.geom.MultiLineString.prototype.setFlatCoordinates = function(layout, flatCoordinates, ends) {
  4863. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  4864. this.ends_ = ends;
  4865. this.changed();
  4866. };
  4867. /**
  4868. * @param {Array.<ol.geom.LineString>} lineStrings LineStrings.
  4869. */
  4870. ol.geom.MultiLineString.prototype.setLineStrings = function(lineStrings) {
  4871. var layout = this.getLayout();
  4872. var flatCoordinates = [];
  4873. var ends = [];
  4874. var i, ii;
  4875. for (i = 0, ii = lineStrings.length; i < ii; ++i) {
  4876. var lineString = lineStrings[i];
  4877. if (i === 0) {
  4878. layout = lineString.getLayout();
  4879. }
  4880. ol.array.extend(flatCoordinates, lineString.getFlatCoordinates());
  4881. ends.push(flatCoordinates.length);
  4882. }
  4883. this.setFlatCoordinates(layout, flatCoordinates, ends);
  4884. };
  4885. /**
  4886. * @classdesc
  4887. * Multi-point geometry.
  4888. *
  4889. * @constructor
  4890. * @extends {ol.geom.SimpleGeometry}
  4891. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  4892. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  4893. * @api
  4894. */
  4895. ol.geom.MultiPoint = function(coordinates, opt_layout) {
  4896. ol.geom.SimpleGeometry.call(this);
  4897. this.setCoordinates(coordinates, opt_layout);
  4898. };
  4899. ol.inherits(ol.geom.MultiPoint, ol.geom.SimpleGeometry);
  4900. /**
  4901. * Append the passed point to this multipoint.
  4902. * @param {ol.geom.Point} point Point.
  4903. * @api
  4904. */
  4905. ol.geom.MultiPoint.prototype.appendPoint = function(point) {
  4906. if (!this.flatCoordinates) {
  4907. this.flatCoordinates = point.getFlatCoordinates().slice();
  4908. } else {
  4909. ol.array.extend(this.flatCoordinates, point.getFlatCoordinates());
  4910. }
  4911. this.changed();
  4912. };
  4913. /**
  4914. * Make a complete copy of the geometry.
  4915. * @return {!ol.geom.MultiPoint} Clone.
  4916. * @override
  4917. * @api
  4918. */
  4919. ol.geom.MultiPoint.prototype.clone = function() {
  4920. var multiPoint = new ol.geom.MultiPoint(null);
  4921. multiPoint.setFlatCoordinates(this.layout, this.flatCoordinates.slice());
  4922. return multiPoint;
  4923. };
  4924. /**
  4925. * @inheritDoc
  4926. */
  4927. ol.geom.MultiPoint.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  4928. if (minSquaredDistance <
  4929. ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
  4930. return minSquaredDistance;
  4931. }
  4932. var flatCoordinates = this.flatCoordinates;
  4933. var stride = this.stride;
  4934. var i, ii, j;
  4935. for (i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
  4936. var squaredDistance = ol.math.squaredDistance(
  4937. x, y, flatCoordinates[i], flatCoordinates[i + 1]);
  4938. if (squaredDistance < minSquaredDistance) {
  4939. minSquaredDistance = squaredDistance;
  4940. for (j = 0; j < stride; ++j) {
  4941. closestPoint[j] = flatCoordinates[i + j];
  4942. }
  4943. closestPoint.length = stride;
  4944. }
  4945. }
  4946. return minSquaredDistance;
  4947. };
  4948. /**
  4949. * Return the coordinates of the multipoint.
  4950. * @return {Array.<ol.Coordinate>} Coordinates.
  4951. * @override
  4952. * @api
  4953. */
  4954. ol.geom.MultiPoint.prototype.getCoordinates = function() {
  4955. return ol.geom.flat.inflate.coordinates(
  4956. this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
  4957. };
  4958. /**
  4959. * Return the point at the specified index.
  4960. * @param {number} index Index.
  4961. * @return {ol.geom.Point} Point.
  4962. * @api
  4963. */
  4964. ol.geom.MultiPoint.prototype.getPoint = function(index) {
  4965. var n = !this.flatCoordinates ?
  4966. 0 : this.flatCoordinates.length / this.stride;
  4967. if (index < 0 || n <= index) {
  4968. return null;
  4969. }
  4970. var point = new ol.geom.Point(null);
  4971. point.setFlatCoordinates(this.layout, this.flatCoordinates.slice(
  4972. index * this.stride, (index + 1) * this.stride));
  4973. return point;
  4974. };
  4975. /**
  4976. * Return the points of this multipoint.
  4977. * @return {Array.<ol.geom.Point>} Points.
  4978. * @api
  4979. */
  4980. ol.geom.MultiPoint.prototype.getPoints = function() {
  4981. var flatCoordinates = this.flatCoordinates;
  4982. var layout = this.layout;
  4983. var stride = this.stride;
  4984. /** @type {Array.<ol.geom.Point>} */
  4985. var points = [];
  4986. var i, ii;
  4987. for (i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
  4988. var point = new ol.geom.Point(null);
  4989. point.setFlatCoordinates(layout, flatCoordinates.slice(i, i + stride));
  4990. points.push(point);
  4991. }
  4992. return points;
  4993. };
  4994. /**
  4995. * @inheritDoc
  4996. * @api
  4997. */
  4998. ol.geom.MultiPoint.prototype.getType = function() {
  4999. return ol.geom.GeometryType.MULTI_POINT;
  5000. };
  5001. /**
  5002. * @inheritDoc
  5003. * @api
  5004. */
  5005. ol.geom.MultiPoint.prototype.intersectsExtent = function(extent) {
  5006. var flatCoordinates = this.flatCoordinates;
  5007. var stride = this.stride;
  5008. var i, ii, x, y;
  5009. for (i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
  5010. x = flatCoordinates[i];
  5011. y = flatCoordinates[i + 1];
  5012. if (ol.extent.containsXY(extent, x, y)) {
  5013. return true;
  5014. }
  5015. }
  5016. return false;
  5017. };
  5018. /**
  5019. * Set the coordinates of the multipoint.
  5020. * @param {Array.<ol.Coordinate>} coordinates Coordinates.
  5021. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  5022. * @override
  5023. * @api
  5024. */
  5025. ol.geom.MultiPoint.prototype.setCoordinates = function(coordinates, opt_layout) {
  5026. if (!coordinates) {
  5027. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null);
  5028. } else {
  5029. this.setLayout(opt_layout, coordinates, 1);
  5030. if (!this.flatCoordinates) {
  5031. this.flatCoordinates = [];
  5032. }
  5033. this.flatCoordinates.length = ol.geom.flat.deflate.coordinates(
  5034. this.flatCoordinates, 0, coordinates, this.stride);
  5035. this.changed();
  5036. }
  5037. };
  5038. /**
  5039. * @param {ol.geom.GeometryLayout} layout Layout.
  5040. * @param {Array.<number>} flatCoordinates Flat coordinates.
  5041. */
  5042. ol.geom.MultiPoint.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
  5043. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  5044. this.changed();
  5045. };
  5046. /**
  5047. * @param {Array.<number>} flatCoordinates Flat coordinates.
  5048. * @param {number} offset Offset.
  5049. * @param {Array.<Array.<number>>} endss Endss.
  5050. * @param {number} stride Stride.
  5051. * @return {Array.<number>} Flat centers.
  5052. */
  5053. ol.geom.flat.center.linearRingss = {};
  5054. /**
  5055. * @param {Array.<number>} flatCoordinates Flat coordinates.
  5056. * @param {number} offset Offset.
  5057. * @param {Array.<Array.<number>>} endss Endss.
  5058. * @param {number} stride Stride.
  5059. * @return {Array.<number>} Flat centers.
  5060. */
  5061. ol.geom.flat.center.linearRingss = function(flatCoordinates, offset, endss, stride) {
  5062. var flatCenters = [];
  5063. var i, ii;
  5064. var extent = ol.extent.createEmpty();
  5065. for (i = 0, ii = endss.length; i < ii; ++i) {
  5066. var ends = endss[i];
  5067. extent = ol.extent.createOrUpdateFromFlatCoordinates(
  5068. flatCoordinates, offset, ends[0], stride);
  5069. flatCenters.push((extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2);
  5070. offset = ends[ends.length - 1];
  5071. }
  5072. return flatCenters;
  5073. };
  5074. /**
  5075. * @classdesc
  5076. * Multi-polygon geometry.
  5077. *
  5078. * @constructor
  5079. * @extends {ol.geom.SimpleGeometry}
  5080. * @param {Array.<Array.<Array.<ol.Coordinate>>>} coordinates Coordinates.
  5081. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  5082. * @api
  5083. */
  5084. ol.geom.MultiPolygon = function(coordinates, opt_layout) {
  5085. ol.geom.SimpleGeometry.call(this);
  5086. /**
  5087. * @type {Array.<Array.<number>>}
  5088. * @private
  5089. */
  5090. this.endss_ = [];
  5091. /**
  5092. * @private
  5093. * @type {number}
  5094. */
  5095. this.flatInteriorPointsRevision_ = -1;
  5096. /**
  5097. * @private
  5098. * @type {Array.<number>}
  5099. */
  5100. this.flatInteriorPoints_ = null;
  5101. /**
  5102. * @private
  5103. * @type {number}
  5104. */
  5105. this.maxDelta_ = -1;
  5106. /**
  5107. * @private
  5108. * @type {number}
  5109. */
  5110. this.maxDeltaRevision_ = -1;
  5111. /**
  5112. * @private
  5113. * @type {number}
  5114. */
  5115. this.orientedRevision_ = -1;
  5116. /**
  5117. * @private
  5118. * @type {Array.<number>}
  5119. */
  5120. this.orientedFlatCoordinates_ = null;
  5121. this.setCoordinates(coordinates, opt_layout);
  5122. };
  5123. ol.inherits(ol.geom.MultiPolygon, ol.geom.SimpleGeometry);
  5124. /**
  5125. * Append the passed polygon to this multipolygon.
  5126. * @param {ol.geom.Polygon} polygon Polygon.
  5127. * @api
  5128. */
  5129. ol.geom.MultiPolygon.prototype.appendPolygon = function(polygon) {
  5130. /** @type {Array.<number>} */
  5131. var ends;
  5132. if (!this.flatCoordinates) {
  5133. this.flatCoordinates = polygon.getFlatCoordinates().slice();
  5134. ends = polygon.getEnds().slice();
  5135. this.endss_.push();
  5136. } else {
  5137. var offset = this.flatCoordinates.length;
  5138. ol.array.extend(this.flatCoordinates, polygon.getFlatCoordinates());
  5139. ends = polygon.getEnds().slice();
  5140. var i, ii;
  5141. for (i = 0, ii = ends.length; i < ii; ++i) {
  5142. ends[i] += offset;
  5143. }
  5144. }
  5145. this.endss_.push(ends);
  5146. this.changed();
  5147. };
  5148. /**
  5149. * Make a complete copy of the geometry.
  5150. * @return {!ol.geom.MultiPolygon} Clone.
  5151. * @override
  5152. * @api
  5153. */
  5154. ol.geom.MultiPolygon.prototype.clone = function() {
  5155. var multiPolygon = new ol.geom.MultiPolygon(null);
  5156. var len = this.endss_.length;
  5157. var newEndss = new Array(len);
  5158. for (var i = 0; i < len; ++i) {
  5159. newEndss[i] = this.endss_[i].slice();
  5160. }
  5161. multiPolygon.setFlatCoordinates(
  5162. this.layout, this.flatCoordinates.slice(), newEndss);
  5163. return multiPolygon;
  5164. };
  5165. /**
  5166. * @inheritDoc
  5167. */
  5168. ol.geom.MultiPolygon.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {
  5169. if (minSquaredDistance <
  5170. ol.extent.closestSquaredDistanceXY(this.getExtent(), x, y)) {
  5171. return minSquaredDistance;
  5172. }
  5173. if (this.maxDeltaRevision_ != this.getRevision()) {
  5174. this.maxDelta_ = Math.sqrt(ol.geom.flat.closest.getssMaxSquaredDelta(
  5175. this.flatCoordinates, 0, this.endss_, this.stride, 0));
  5176. this.maxDeltaRevision_ = this.getRevision();
  5177. }
  5178. return ol.geom.flat.closest.getssClosestPoint(
  5179. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride,
  5180. this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);
  5181. };
  5182. /**
  5183. * @inheritDoc
  5184. */
  5185. ol.geom.MultiPolygon.prototype.containsXY = function(x, y) {
  5186. return ol.geom.flat.contains.linearRingssContainsXY(
  5187. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, x, y);
  5188. };
  5189. /**
  5190. * Return the area of the multipolygon on projected plane.
  5191. * @return {number} Area (on projected plane).
  5192. * @api
  5193. */
  5194. ol.geom.MultiPolygon.prototype.getArea = function() {
  5195. return ol.geom.flat.area.linearRingss(
  5196. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride);
  5197. };
  5198. /**
  5199. * Get the coordinate array for this geometry. This array has the structure
  5200. * of a GeoJSON coordinate array for multi-polygons.
  5201. *
  5202. * @param {boolean=} opt_right Orient coordinates according to the right-hand
  5203. * rule (counter-clockwise for exterior and clockwise for interior rings).
  5204. * If `false`, coordinates will be oriented according to the left-hand rule
  5205. * (clockwise for exterior and counter-clockwise for interior rings).
  5206. * By default, coordinate orientation will depend on how the geometry was
  5207. * constructed.
  5208. * @return {Array.<Array.<Array.<ol.Coordinate>>>} Coordinates.
  5209. * @override
  5210. * @api
  5211. */
  5212. ol.geom.MultiPolygon.prototype.getCoordinates = function(opt_right) {
  5213. var flatCoordinates;
  5214. if (opt_right !== undefined) {
  5215. flatCoordinates = this.getOrientedFlatCoordinates().slice();
  5216. ol.geom.flat.orient.orientLinearRingss(
  5217. flatCoordinates, 0, this.endss_, this.stride, opt_right);
  5218. } else {
  5219. flatCoordinates = this.flatCoordinates;
  5220. }
  5221. return ol.geom.flat.inflate.coordinatesss(
  5222. flatCoordinates, 0, this.endss_, this.stride);
  5223. };
  5224. /**
  5225. * @return {Array.<Array.<number>>} Endss.
  5226. */
  5227. ol.geom.MultiPolygon.prototype.getEndss = function() {
  5228. return this.endss_;
  5229. };
  5230. /**
  5231. * @return {Array.<number>} Flat interior points.
  5232. */
  5233. ol.geom.MultiPolygon.prototype.getFlatInteriorPoints = function() {
  5234. if (this.flatInteriorPointsRevision_ != this.getRevision()) {
  5235. var flatCenters = ol.geom.flat.center.linearRingss(
  5236. this.flatCoordinates, 0, this.endss_, this.stride);
  5237. this.flatInteriorPoints_ = ol.geom.flat.interiorpoint.linearRingss(
  5238. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride,
  5239. flatCenters);
  5240. this.flatInteriorPointsRevision_ = this.getRevision();
  5241. }
  5242. return this.flatInteriorPoints_;
  5243. };
  5244. /**
  5245. * Return the interior points as {@link ol.geom.MultiPoint multipoint}.
  5246. * @return {ol.geom.MultiPoint} Interior points as XYM coordinates, where M is
  5247. * the length of the horizontal intersection that the point belongs to.
  5248. * @api
  5249. */
  5250. ol.geom.MultiPolygon.prototype.getInteriorPoints = function() {
  5251. var interiorPoints = new ol.geom.MultiPoint(null);
  5252. interiorPoints.setFlatCoordinates(ol.geom.GeometryLayout.XYM,
  5253. this.getFlatInteriorPoints().slice());
  5254. return interiorPoints;
  5255. };
  5256. /**
  5257. * @return {Array.<number>} Oriented flat coordinates.
  5258. */
  5259. ol.geom.MultiPolygon.prototype.getOrientedFlatCoordinates = function() {
  5260. if (this.orientedRevision_ != this.getRevision()) {
  5261. var flatCoordinates = this.flatCoordinates;
  5262. if (ol.geom.flat.orient.linearRingssAreOriented(
  5263. flatCoordinates, 0, this.endss_, this.stride)) {
  5264. this.orientedFlatCoordinates_ = flatCoordinates;
  5265. } else {
  5266. this.orientedFlatCoordinates_ = flatCoordinates.slice();
  5267. this.orientedFlatCoordinates_.length =
  5268. ol.geom.flat.orient.orientLinearRingss(
  5269. this.orientedFlatCoordinates_, 0, this.endss_, this.stride);
  5270. }
  5271. this.orientedRevision_ = this.getRevision();
  5272. }
  5273. return this.orientedFlatCoordinates_;
  5274. };
  5275. /**
  5276. * @inheritDoc
  5277. */
  5278. ol.geom.MultiPolygon.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
  5279. var simplifiedFlatCoordinates = [];
  5280. var simplifiedEndss = [];
  5281. simplifiedFlatCoordinates.length = ol.geom.flat.simplify.quantizess(
  5282. this.flatCoordinates, 0, this.endss_, this.stride,
  5283. Math.sqrt(squaredTolerance),
  5284. simplifiedFlatCoordinates, 0, simplifiedEndss);
  5285. var simplifiedMultiPolygon = new ol.geom.MultiPolygon(null);
  5286. simplifiedMultiPolygon.setFlatCoordinates(
  5287. ol.geom.GeometryLayout.XY, simplifiedFlatCoordinates, simplifiedEndss);
  5288. return simplifiedMultiPolygon;
  5289. };
  5290. /**
  5291. * Return the polygon at the specified index.
  5292. * @param {number} index Index.
  5293. * @return {ol.geom.Polygon} Polygon.
  5294. * @api
  5295. */
  5296. ol.geom.MultiPolygon.prototype.getPolygon = function(index) {
  5297. if (index < 0 || this.endss_.length <= index) {
  5298. return null;
  5299. }
  5300. var offset;
  5301. if (index === 0) {
  5302. offset = 0;
  5303. } else {
  5304. var prevEnds = this.endss_[index - 1];
  5305. offset = prevEnds[prevEnds.length - 1];
  5306. }
  5307. var ends = this.endss_[index].slice();
  5308. var end = ends[ends.length - 1];
  5309. if (offset !== 0) {
  5310. var i, ii;
  5311. for (i = 0, ii = ends.length; i < ii; ++i) {
  5312. ends[i] -= offset;
  5313. }
  5314. }
  5315. var polygon = new ol.geom.Polygon(null);
  5316. polygon.setFlatCoordinates(
  5317. this.layout, this.flatCoordinates.slice(offset, end), ends);
  5318. return polygon;
  5319. };
  5320. /**
  5321. * Return the polygons of this multipolygon.
  5322. * @return {Array.<ol.geom.Polygon>} Polygons.
  5323. * @api
  5324. */
  5325. ol.geom.MultiPolygon.prototype.getPolygons = function() {
  5326. var layout = this.layout;
  5327. var flatCoordinates = this.flatCoordinates;
  5328. var endss = this.endss_;
  5329. var polygons = [];
  5330. var offset = 0;
  5331. var i, ii, j, jj;
  5332. for (i = 0, ii = endss.length; i < ii; ++i) {
  5333. var ends = endss[i].slice();
  5334. var end = ends[ends.length - 1];
  5335. if (offset !== 0) {
  5336. for (j = 0, jj = ends.length; j < jj; ++j) {
  5337. ends[j] -= offset;
  5338. }
  5339. }
  5340. var polygon = new ol.geom.Polygon(null);
  5341. polygon.setFlatCoordinates(
  5342. layout, flatCoordinates.slice(offset, end), ends);
  5343. polygons.push(polygon);
  5344. offset = end;
  5345. }
  5346. return polygons;
  5347. };
  5348. /**
  5349. * @inheritDoc
  5350. * @api
  5351. */
  5352. ol.geom.MultiPolygon.prototype.getType = function() {
  5353. return ol.geom.GeometryType.MULTI_POLYGON;
  5354. };
  5355. /**
  5356. * @inheritDoc
  5357. * @api
  5358. */
  5359. ol.geom.MultiPolygon.prototype.intersectsExtent = function(extent) {
  5360. return ol.geom.flat.intersectsextent.linearRingss(
  5361. this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, extent);
  5362. };
  5363. /**
  5364. * Set the coordinates of the multipolygon.
  5365. * @param {Array.<Array.<Array.<ol.Coordinate>>>} coordinates Coordinates.
  5366. * @param {ol.geom.GeometryLayout=} opt_layout Layout.
  5367. * @override
  5368. * @api
  5369. */
  5370. ol.geom.MultiPolygon.prototype.setCoordinates = function(coordinates, opt_layout) {
  5371. if (!coordinates) {
  5372. this.setFlatCoordinates(ol.geom.GeometryLayout.XY, null, this.endss_);
  5373. } else {
  5374. this.setLayout(opt_layout, coordinates, 3);
  5375. if (!this.flatCoordinates) {
  5376. this.flatCoordinates = [];
  5377. }
  5378. var endss = ol.geom.flat.deflate.coordinatesss(
  5379. this.flatCoordinates, 0, coordinates, this.stride, this.endss_);
  5380. if (endss.length === 0) {
  5381. this.flatCoordinates.length = 0;
  5382. } else {
  5383. var lastEnds = endss[endss.length - 1];
  5384. this.flatCoordinates.length = lastEnds.length === 0 ?
  5385. 0 : lastEnds[lastEnds.length - 1];
  5386. }
  5387. this.changed();
  5388. }
  5389. };
  5390. /**
  5391. * @param {ol.geom.GeometryLayout} layout Layout.
  5392. * @param {Array.<number>} flatCoordinates Flat coordinates.
  5393. * @param {Array.<Array.<number>>} endss Endss.
  5394. */
  5395. ol.geom.MultiPolygon.prototype.setFlatCoordinates = function(layout, flatCoordinates, endss) {
  5396. this.setFlatCoordinatesInternal(layout, flatCoordinates);
  5397. this.endss_ = endss;
  5398. this.changed();
  5399. };
  5400. /**
  5401. * @param {Array.<ol.geom.Polygon>} polygons Polygons.
  5402. */
  5403. ol.geom.MultiPolygon.prototype.setPolygons = function(polygons) {
  5404. var layout = this.getLayout();
  5405. var flatCoordinates = [];
  5406. var endss = [];
  5407. var i, ii, ends;
  5408. for (i = 0, ii = polygons.length; i < ii; ++i) {
  5409. var polygon = polygons[i];
  5410. if (i === 0) {
  5411. layout = polygon.getLayout();
  5412. }
  5413. var offset = flatCoordinates.length;
  5414. ends = polygon.getEnds();
  5415. var j, jj;
  5416. for (j = 0, jj = ends.length; j < jj; ++j) {
  5417. ends[j] += offset;
  5418. }
  5419. ol.array.extend(flatCoordinates, polygon.getFlatCoordinates());
  5420. endss.push(ends);
  5421. }
  5422. this.setFlatCoordinates(layout, flatCoordinates, endss);
  5423. };
  5424. ol.Feature = function(opt_geometryOrProperties) {
  5425. ol.Object.call(this);
  5426. /**
  5427. * @private
  5428. * @type {number|string|undefined}
  5429. */
  5430. this.id_ = undefined;
  5431. /**
  5432. * @type {string}
  5433. * @private
  5434. */
  5435. this.geometryName_ = 'geometry';
  5436. /**
  5437. * User provided style.
  5438. * @private
  5439. * @type {ol.style.Style|Array.<ol.style.Style>|
  5440. * ol.FeatureStyleFunction}
  5441. */
  5442. this.style_ = null;
  5443. /**
  5444. * @private
  5445. * @type {ol.FeatureStyleFunction|undefined}
  5446. */
  5447. this.styleFunction_ = undefined;
  5448. /**
  5449. * @private
  5450. * @type {?ol.EventsKey}
  5451. */
  5452. this.geometryChangeKey_ = null;
  5453. // ol.events.listen(
  5454. // this, ol.Object.getChangeEventType(this.geometryName_),
  5455. // this.handleGeometryChanged_, this);
  5456. if (opt_geometryOrProperties !== undefined) {
  5457. if (opt_geometryOrProperties instanceof ol.geom.Geometry ||
  5458. !opt_geometryOrProperties) {
  5459. var geometry = opt_geometryOrProperties;
  5460. this.setGeometry(geometry);
  5461. } else {
  5462. /** @type {Object.<string, *>} */
  5463. var properties = opt_geometryOrProperties;
  5464. this.setProperties(properties);
  5465. }
  5466. }
  5467. };
  5468. ol.inherits(ol.Feature, ol.Object);
  5469. /**
  5470. * Clone this feature. If the original feature has a geometry it
  5471. * is also cloned. The feature id is not set in the clone.
  5472. * @return {ol.Feature} The clone.
  5473. * @api
  5474. */
  5475. ol.Feature.prototype.clone = function() {
  5476. var clone = new ol.Feature(this.getProperties());
  5477. clone.setGeometryName(this.getGeometryName());
  5478. var geometry = this.getGeometry();
  5479. if (geometry) {
  5480. clone.setGeometry(geometry.clone());
  5481. }
  5482. var style = this.getStyle();
  5483. if (style) {
  5484. clone.setStyle(style);
  5485. }
  5486. return clone;
  5487. };
  5488. /**
  5489. * Get the feature's default geometry. A feature may have any number of named
  5490. * geometries. The "default" geometry (the one that is rendered by default) is
  5491. * set when calling {@link ol.Feature#setGeometry}.
  5492. * @return {ol.geom.Geometry|undefined} The default geometry for the feature.
  5493. * @api
  5494. * @observable
  5495. */
  5496. ol.Feature.prototype.getGeometry = function() {
  5497. return /** @type {ol.geom.Geometry|undefined} */ (
  5498. this.get(this.geometryName_));
  5499. };
  5500. /**
  5501. * Get the feature identifier. This is a stable identifier for the feature and
  5502. * is either set when reading data from a remote source or set explicitly by
  5503. * calling {@link ol.Feature#setId}.
  5504. * @return {number|string|undefined} Id.
  5505. * @api
  5506. */
  5507. ol.Feature.prototype.getId = function() {
  5508. return this.id_;
  5509. };
  5510. /**
  5511. * Get the name of the feature's default geometry. By default, the default
  5512. * geometry is named `geometry`.
  5513. * @return {string} Get the property name associated with the default geometry
  5514. * for this feature.
  5515. * @api
  5516. */
  5517. ol.Feature.prototype.getGeometryName = function() {
  5518. return this.geometryName_;
  5519. };
  5520. /**
  5521. * Get the feature's style. Will return what was provided to the
  5522. * {@link ol.Feature#setStyle} method.
  5523. * @return {ol.style.Style|Array.<ol.style.Style>|
  5524. * ol.FeatureStyleFunction|ol.StyleFunction} The feature style.
  5525. * @api
  5526. */
  5527. ol.Feature.prototype.getStyle = function() {
  5528. return this.style_;
  5529. };
  5530. /**
  5531. * Get the feature's style function.
  5532. * @return {ol.FeatureStyleFunction|undefined} Return a function
  5533. * representing the current style of this feature.
  5534. * @api
  5535. */
  5536. ol.Feature.prototype.getStyleFunction = function() {
  5537. return this.styleFunction_;
  5538. };
  5539. /**
  5540. * @private
  5541. */
  5542. ol.Feature.prototype.handleGeometryChange_ = function() {
  5543. this.changed();
  5544. };
  5545. /**
  5546. * @private
  5547. */
  5548. ol.Feature.prototype.handleGeometryChanged_ = function() {
  5549. if (this.geometryChangeKey_) {
  5550. ol.events.unlistenByKey(this.geometryChangeKey_);
  5551. this.geometryChangeKey_ = null;
  5552. }
  5553. var geometry = this.getGeometry();
  5554. if (geometry) {
  5555. this.geometryChangeKey_ = ol.events.listen(geometry,
  5556. ol.events.EventType.CHANGE, this.handleGeometryChange_, this);
  5557. }
  5558. this.changed();
  5559. };
  5560. /**
  5561. * Set the default geometry for the feature. This will update the property
  5562. * with the name returned by {@link ol.Feature#getGeometryName}.
  5563. * @param {ol.geom.Geometry|undefined} geometry The new geometry.
  5564. * @api
  5565. * @observable
  5566. */
  5567. ol.Feature.prototype.setGeometry = function(geometry) {
  5568. this.set(this.geometryName_, geometry);
  5569. };
  5570. /**
  5571. * Set the style for the feature. This can be a single style object, an array
  5572. * of styles, or a function that takes a resolution and returns an array of
  5573. * styles. If it is `null` the feature has no style (a `null` style).
  5574. * @param {ol.style.Style|Array.<ol.style.Style>|
  5575. * ol.FeatureStyleFunction|ol.StyleFunction} style Style for this feature.
  5576. * @api
  5577. * @fires ol.events.Event#event:change
  5578. */
  5579. ol.Feature.prototype.setStyle = function(style) {
  5580. this.style_ = style;
  5581. this.styleFunction_ = !style ?
  5582. undefined : ol.Feature.createStyleFunction(style);
  5583. this.changed();
  5584. };
  5585. /**
  5586. * Set the feature id. The feature id is considered stable and may be used when
  5587. * requesting features or comparing identifiers returned from a remote source.
  5588. * The feature id can be used with the {@link ol.source.Vector#getFeatureById}
  5589. * method.
  5590. * @param {number|string|undefined} id The feature id.
  5591. * @api
  5592. * @fires ol.events.Event#event:change
  5593. */
  5594. ol.Feature.prototype.setId = function(id) {
  5595. this.id_ = id;
  5596. this.changed();
  5597. };
  5598. /**
  5599. * Set the property name to be used when getting the feature's default geometry.
  5600. * When calling {@link ol.Feature#getGeometry}, the value of the property with
  5601. * this name will be returned.
  5602. * @param {string} name The property name of the default geometry.
  5603. * @api
  5604. */
  5605. ol.Feature.prototype.setGeometryName = function(name) {
  5606. ol.events.unlisten(
  5607. this, ol.Object.getChangeEventType(this.geometryName_),
  5608. this.handleGeometryChanged_, this);
  5609. this.geometryName_ = name;
  5610. ol.events.listen(
  5611. this, ol.Object.getChangeEventType(this.geometryName_),
  5612. this.handleGeometryChanged_, this);
  5613. this.handleGeometryChanged_();
  5614. };
  5615. /**
  5616. * Convert the provided object into a feature style function. Functions passed
  5617. * through unchanged. Arrays of ol.style.Style or single style objects wrapped
  5618. * in a new feature style function.
  5619. * @param {ol.FeatureStyleFunction|!Array.<ol.style.Style>|!ol.style.Style} obj
  5620. * A feature style function, a single style, or an array of styles.
  5621. * @return {ol.FeatureStyleFunction} A style function.
  5622. */
  5623. ol.Feature.createStyleFunction = function(obj) {
  5624. var styleFunction;
  5625. if (typeof obj === 'function') {
  5626. if (obj.length == 2) {
  5627. styleFunction = function(resolution) {
  5628. return /** @type {ol.StyleFunction} */ (obj)(this, resolution);
  5629. };
  5630. } else {
  5631. styleFunction = obj;
  5632. }
  5633. } else {
  5634. /**
  5635. * @type {Array.<ol.style.Style>}
  5636. */
  5637. var styles;
  5638. if (Array.isArray(obj)) {
  5639. styles = obj;
  5640. } else {
  5641. ol.asserts.assert(obj instanceof ol.style.Style,
  5642. 41); // Expected an `ol.style.Style` or an array of `ol.style.Style`
  5643. styles = [obj];
  5644. }
  5645. styleFunction = function() {
  5646. return styles;
  5647. };
  5648. }
  5649. return styleFunction;
  5650. };
  5651. ol.format = {};
  5652. ol.format.Feature = function() {
  5653. /**
  5654. * @protected
  5655. * @type {ol.proj.Projection}
  5656. */
  5657. this.defaultDataProjection = null;
  5658. /**
  5659. * @protected
  5660. * @type {ol.proj.Projection}
  5661. */
  5662. this.defaultFeatureProjection = null;
  5663. };
  5664. /**
  5665. * Adds the data projection to the read options.
  5666. * @param {Document|Node|Object|string} source Source.
  5667. * @param {olx.format.ReadOptions=} opt_options Options.
  5668. * @return {olx.format.ReadOptions|undefined} Options.
  5669. * @protected
  5670. */
  5671. ol.format.Feature.prototype.getReadOptions = function(source, opt_options) {
  5672. var options;
  5673. if (opt_options) {
  5674. options = {
  5675. dataProjection: opt_options.dataProjection ?
  5676. opt_options.dataProjection : this.readProjection(source),
  5677. featureProjection: opt_options.featureProjection
  5678. };
  5679. }
  5680. return this.adaptOptions(options);
  5681. };
  5682. /**
  5683. * Sets the `defaultDataProjection` on the options, if no `dataProjection`
  5684. * is set.
  5685. * @param {olx.format.WriteOptions|olx.format.ReadOptions|undefined} options
  5686. * Options.
  5687. * @protected
  5688. * @return {olx.format.WriteOptions|olx.format.ReadOptions|undefined}
  5689. * Updated options.
  5690. */
  5691. ol.format.Feature.prototype.adaptOptions = function(options) {
  5692. return ol.obj.assign({
  5693. dataProjection: this.defaultDataProjection,
  5694. featureProjection: this.defaultFeatureProjection
  5695. }, options);
  5696. };
  5697. /**
  5698. * Get the extent from the source of the last {@link readFeatures} call.
  5699. * @return {ol.Extent} Tile extent.
  5700. */
  5701. ol.format.Feature.prototype.getLastExtent = function() {
  5702. return null;
  5703. };
  5704. /**
  5705. * @abstract
  5706. * @return {ol.format.FormatType} Format.
  5707. */
  5708. ol.format.Feature.prototype.getType = function() {};
  5709. /**
  5710. * Read a single feature from a source.
  5711. *
  5712. * @abstract
  5713. * @param {Document|Node|Object|string} source Source.
  5714. * @param {olx.format.ReadOptions=} opt_options Read options.
  5715. * @return {ol.Feature} Feature.
  5716. */
  5717. ol.format.Feature.prototype.readFeature = function(source, opt_options) {};
  5718. /**
  5719. * Read all features from a source.
  5720. *
  5721. * @abstract
  5722. * @param {Document|Node|ArrayBuffer|Object|string} source Source.
  5723. * @param {olx.format.ReadOptions=} opt_options Read options.
  5724. * @return {Array.<ol.Feature>} Features.
  5725. */
  5726. ol.format.Feature.prototype.readFeatures = function(source, opt_options) {};
  5727. /**
  5728. * Read a single geometry from a source.
  5729. *
  5730. * @abstract
  5731. * @param {Document|Node|Object|string} source Source.
  5732. * @param {olx.format.ReadOptions=} opt_options Read options.
  5733. * @return {ol.geom.Geometry} Geometry.
  5734. */
  5735. ol.format.Feature.prototype.readGeometry = function(source, opt_options) {};
  5736. /**
  5737. * Read the projection from a source.
  5738. *
  5739. * @abstract
  5740. * @param {Document|Node|Object|string} source Source.
  5741. * @return {ol.proj.Projection} Projection.
  5742. */
  5743. ol.format.Feature.prototype.readProjection = function(source) {};
  5744. /**
  5745. * Encode a feature in this format.
  5746. *
  5747. * @abstract
  5748. * @param {ol.Feature} feature Feature.
  5749. * @param {olx.format.WriteOptions=} opt_options Write options.
  5750. * @return {string} Result.
  5751. */
  5752. ol.format.Feature.prototype.writeFeature = function(feature, opt_options) {};
  5753. /**
  5754. * Encode an array of features in this format.
  5755. *
  5756. * @abstract
  5757. * @param {Array.<ol.Feature>} features Features.
  5758. * @param {olx.format.WriteOptions=} opt_options Write options.
  5759. * @return {string} Result.
  5760. */
  5761. ol.format.Feature.prototype.writeFeatures = function(features, opt_options) {};
  5762. /**
  5763. * Write a single geometry in this format.
  5764. *
  5765. * @abstract
  5766. * @param {ol.geom.Geometry} geometry Geometry.
  5767. * @param {olx.format.WriteOptions=} opt_options Write options.
  5768. * @return {string} Result.
  5769. */
  5770. ol.format.Feature.prototype.writeGeometry = function(geometry, opt_options) {};
  5771. /**
  5772. * @param {ol.geom.Geometry|ol.Extent} geometry Geometry.
  5773. * @param {boolean} write Set to true for writing, false for reading.
  5774. * @param {(olx.format.WriteOptions|olx.format.ReadOptions)=} opt_options
  5775. * Options.
  5776. * @return {ol.geom.Geometry|ol.Extent} Transformed geometry.
  5777. * @protected
  5778. */
  5779. ol.format.Feature.transformWithOptions = function(
  5780. geometry, write, opt_options) {
  5781. /**
  5782. * @type {ol.geom.Geometry|ol.Extent}
  5783. */
  5784. var transformed;
  5785. {
  5786. transformed = geometry;
  5787. }
  5788. if (write && opt_options && opt_options.decimals !== undefined) {
  5789. var power = Math.pow(10, opt_options.decimals);
  5790. // if decimals option on write, round each coordinate appropriately
  5791. /**
  5792. * @param {Array.<number>} coordinates Coordinates.
  5793. * @return {Array.<number>} Transformed coordinates.
  5794. */
  5795. var transform = function(coordinates) {
  5796. for (var i = 0, ii = coordinates.length; i < ii; ++i) {
  5797. coordinates[i] = Math.round(coordinates[i] * power) / power;
  5798. }
  5799. return coordinates;
  5800. };
  5801. if (transformed === geometry) {
  5802. transformed = transformed.clone();
  5803. }
  5804. transformed.applyTransform(transform);
  5805. }
  5806. return transformed;
  5807. };
  5808. ol.format.MVT = function(opt_options) {
  5809. ol.format.Feature.call(this);
  5810. var options = opt_options ? opt_options : {};
  5811. /**
  5812. * @type {ol.proj.Projection}
  5813. */
  5814. // this.defaultDataProjection = new ol.proj.Projection({
  5815. // code: 'EPSG:3857',
  5816. // units: ol.proj.Units.TILE_PIXELS
  5817. // });
  5818. /**
  5819. * @private
  5820. * @type {function((ol.geom.Geometry|Object.<string,*>)=)|
  5821. * function(ol.geom.GeometryType,Array.<number>,
  5822. * (Array.<number>|Array.<Array.<number>>),Object.<string,*>,number)}
  5823. */
  5824. this.featureClass_ = options.featureClass ?
  5825. options.featureClass : ol.render.Feature;
  5826. /**
  5827. * @private
  5828. * @type {string|undefined}
  5829. */
  5830. this.geometryName_ = options.geometryName;
  5831. /**
  5832. * @private
  5833. * @type {string}
  5834. */
  5835. this.layerName_ = options.layerName ? options.layerName : 'layer';
  5836. /**
  5837. * @private
  5838. * @type {Array.<string>}
  5839. */
  5840. this.layers_ = options.layers ? options.layers : null;
  5841. /**
  5842. * @private
  5843. * @type {ol.Extent}
  5844. */
  5845. this.extent_ = null;
  5846. };
  5847. ol.inherits(ol.format.MVT, ol.format.Feature);
  5848. ol.format.MVT.pbfReaders_ = {
  5849. layers: function (tag, layers, pbf) {
  5850. if (tag === 3) {
  5851. var layer = {
  5852. keys: [],
  5853. values: [],
  5854. features: []
  5855. };
  5856. var end = pbf.readVarint() + pbf.pos;
  5857. pbf.readFields(ol.format.MVT.pbfReaders_.layer, layer, end);
  5858. layer.length = layer.features.length;
  5859. if (layer.length) {
  5860. layers[layer.name] = layer;
  5861. }
  5862. }
  5863. },
  5864. layer: function (tag, layer, pbf) {
  5865. if (tag === 15) {
  5866. layer.version = pbf.readVarint();
  5867. } else if (tag === 1) {
  5868. layer.name = pbf.readString();
  5869. } else if (tag === 5) {
  5870. layer.extent = pbf.readVarint();
  5871. } else if (tag === 2) {
  5872. layer.features.push(pbf.pos);
  5873. } else if (tag === 3) {
  5874. layer.keys.push(pbf.readString());
  5875. } else if (tag === 4) {
  5876. var value = null;
  5877. var end = pbf.readVarint() + pbf.pos;
  5878. while (pbf.pos < end) {
  5879. tag = pbf.readVarint() >> 3;
  5880. value = tag === 1 ? pbf.readString() :
  5881. tag === 2 ? pbf.readFloat() :
  5882. tag === 3 ? pbf.readDouble() :
  5883. tag === 4 ? pbf.readVarint64() :
  5884. tag === 5 ? pbf.readVarint() :
  5885. tag === 6 ? pbf.readSVarint() :
  5886. tag === 7 ? pbf.readBoolean() : null;
  5887. }
  5888. layer.values.push(value);
  5889. }
  5890. },
  5891. feature: function (tag, feature, pbf) {
  5892. if (tag == 1) {
  5893. feature.id = pbf.readVarint();
  5894. } else if (tag == 2) {
  5895. var end = pbf.readVarint() + pbf.pos;
  5896. while (pbf.pos < end) {
  5897. var key = feature.layer.keys[pbf.readVarint()];
  5898. var value = feature.layer.values[pbf.readVarint()];
  5899. feature.properties[key] = value;
  5900. }
  5901. } else if (tag == 3) {
  5902. feature.type = pbf.readVarint();
  5903. } else if (tag == 4) {
  5904. feature.geometry = pbf.pos;
  5905. }
  5906. }
  5907. };
  5908. /**
  5909. * Read a raw feature from the pbf offset stored at index `i` in the raw layer.
  5910. * @suppress {missingProperties}
  5911. * @private
  5912. * @param {ol.ext.PBF} pbf PBF.
  5913. * @param {Object} layer Raw layer.
  5914. * @param {number} i Index of the feature in the raw layer's `features` array.
  5915. * @return {Object} Raw feature.
  5916. */
  5917. ol.format.MVT.readRawFeature_ = function (pbf, layer, i) {
  5918. pbf.pos = layer.features[i];
  5919. var end = pbf.readVarint() + pbf.pos;
  5920. var feature = {
  5921. layer: layer,
  5922. type: 0,
  5923. properties: {}
  5924. };
  5925. pbf.readFields(ol.format.MVT.pbfReaders_.feature, feature, end);
  5926. return feature;
  5927. };
  5928. /**
  5929. * Read the raw geometry from the pbf offset stored in a raw feature's geometry
  5930. * proeprty.
  5931. * @suppress {missingProperties}
  5932. * @private
  5933. * @param {ol.ext.PBF} pbf PBF.
  5934. * @param {Object} feature Raw feature.
  5935. * @param {Array.<number>} flatCoordinates Array to store flat coordinates in.
  5936. * @param {Array.<number>} ends Array to store ends in.
  5937. */
  5938. ol.format.MVT.readRawGeometry_ = function (pbf, feature, flatCoordinates, ends) {
  5939. pbf.pos = feature.geometry;
  5940. var end = pbf.readVarint() + pbf.pos;
  5941. var cmd = 1;
  5942. var length = 0;
  5943. var x = 0;
  5944. var y = 0;
  5945. var coordsLen = 0;
  5946. var currentEnd = 0;
  5947. while (pbf.pos < end) {
  5948. if (!length) {
  5949. var cmdLen = pbf.readVarint();
  5950. cmd = cmdLen & 0x7;
  5951. length = cmdLen >> 3;
  5952. }
  5953. length--;
  5954. if (cmd === 1 || cmd === 2) {
  5955. x += pbf.readSVarint();
  5956. y += pbf.readSVarint();
  5957. if (cmd === 1) { // moveTo
  5958. if (coordsLen > currentEnd) {
  5959. ends.push(coordsLen);
  5960. currentEnd = coordsLen;
  5961. }
  5962. }
  5963. flatCoordinates.push(x, y);
  5964. coordsLen += 2;
  5965. } else if (cmd === 7) {
  5966. if (coordsLen > currentEnd) {
  5967. // close polygon
  5968. flatCoordinates.push(
  5969. flatCoordinates[currentEnd], flatCoordinates[currentEnd + 1]);
  5970. coordsLen += 2;
  5971. }
  5972. } else {
  5973. ol.asserts.assert(false, 59); // Invalid command found in the PBF
  5974. }
  5975. }
  5976. if (coordsLen > currentEnd) {
  5977. ends.push(coordsLen);
  5978. currentEnd = coordsLen;
  5979. }
  5980. };
  5981. /**
  5982. * @suppress {missingProperties}
  5983. * @private
  5984. * @param {number} type The raw feature's geometry type
  5985. * @param {number} numEnds Number of ends of the flat coordinates of the
  5986. * geometry.
  5987. * @return {ol.geom.GeometryType} The geometry type.
  5988. */
  5989. ol.format.MVT.getGeometryType_ = function (type, numEnds) {
  5990. /** @type {ol.geom.GeometryType} */
  5991. var geometryType;
  5992. if (type === 1) {
  5993. geometryType = numEnds === 1 ?
  5994. ol.geom.GeometryType.POINT : ol.geom.GeometryType.MULTI_POINT;
  5995. } else if (type === 2) {
  5996. geometryType = numEnds === 1 ?
  5997. ol.geom.GeometryType.LINE_STRING :
  5998. ol.geom.GeometryType.MULTI_LINE_STRING;
  5999. } else if (type === 3) {
  6000. geometryType = ol.geom.GeometryType.POLYGON;
  6001. // MultiPolygon not relevant for rendering - winding order determines
  6002. // outer rings of polygons.
  6003. }
  6004. return geometryType;
  6005. };
  6006. /**
  6007. * @private
  6008. * @param {ol.ext.PBF} pbf PBF
  6009. * @param {Object} rawFeature Raw Mapbox feature.
  6010. * @param {olx.format.ReadOptions=} opt_options Read options.
  6011. * @return {ol.Feature|ol.render.Feature} Feature.
  6012. */
  6013. ol.format.MVT.prototype.createFeature_ = function (pbf, rawFeature, opt_options) {
  6014. var type = rawFeature.type;
  6015. if (type === 0) {
  6016. return null;
  6017. }
  6018. var feature;
  6019. var id = rawFeature.id;
  6020. var values = rawFeature.properties;
  6021. values[this.layerName_] = rawFeature.layer.name;
  6022. var flatCoordinates = [];
  6023. var ends = [];
  6024. ol.format.MVT.readRawGeometry_(pbf, rawFeature, flatCoordinates, ends);
  6025. var geometryType = ol.format.MVT.getGeometryType_(type, ends.length);
  6026. var geom;
  6027. if (geometryType == ol.geom.GeometryType.POLYGON) {
  6028. var endss = [];
  6029. var offset = 0;
  6030. var prevEndIndex = 0;
  6031. for (var i = 0, ii = ends.length; i < ii; ++i) {
  6032. var end = ends[i];
  6033. if (!ol.geom.flat.orient.linearRingIsClockwise(flatCoordinates, offset, end, 2)) {
  6034. endss.push(ends.slice(prevEndIndex, i + 1));
  6035. prevEndIndex = i + 1;
  6036. }
  6037. offset = end;
  6038. }
  6039. if (endss.length > 1) {
  6040. ends = endss;
  6041. geom = new ol.geom.MultiPolygon(null);
  6042. } else {
  6043. geom = new ol.geom.Polygon(null);
  6044. }
  6045. } else {
  6046. geom = geometryType === ol.geom.GeometryType.POINT ? new ol.geom.Point(null) :
  6047. geometryType === ol.geom.GeometryType.LINE_STRING ? new ol.geom.LineString(null) :
  6048. geometryType === ol.geom.GeometryType.POLYGON ? new ol.geom.Polygon(null) :
  6049. geometryType === ol.geom.GeometryType.MULTI_POINT ? new ol.geom.MultiPoint(null) :
  6050. geometryType === ol.geom.GeometryType.MULTI_LINE_STRING ? new ol.geom.MultiLineString(null) :
  6051. null;
  6052. }
  6053. geom.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates, ends);
  6054. feature = new this.featureClass_();
  6055. if (this.geometryName_) {
  6056. feature.setGeometryName(this.geometryName_);
  6057. }
  6058. var geometry = ol.format.Feature.transformWithOptions(geom, false, this.adaptOptions(opt_options));
  6059. feature.setGeometry(geometry);
  6060. feature.setId(id);
  6061. feature.setProperties(values);
  6062. return feature;
  6063. };
  6064. ol.format.MVT.prototype.readFeatures = function (source, opt_options) {
  6065. var layers = this.layers_;
  6066. var pbf$1 = new pbf.Protobuf(/** @type {ArrayBuffer} */ (source));
  6067. var pbfLayers = pbf$1.readFields(ol.format.MVT.pbfReaders_.layers, {});
  6068. /** @type {Array.<ol.Feature|ol.render.Feature>} */
  6069. var features = [];
  6070. var pbfLayer;
  6071. for (var name in pbfLayers) {
  6072. if (layers && layers.indexOf(name) == -1) {
  6073. continue;
  6074. }
  6075. if (opt_options !== undefined) {
  6076. var needSourceLayerNames = opt_options.needSourceLayerNames;
  6077. if (needSourceLayerNames !== undefined && needSourceLayerNames[name] === undefined) {
  6078. continue;
  6079. }
  6080. }
  6081. pbfLayer = pbfLayers[name];
  6082. var rawFeature;
  6083. for (var i = 0, ii = pbfLayer.length; i < ii; ++i) {
  6084. rawFeature = ol.format.MVT.readRawFeature_(pbf$1, pbfLayer, i);
  6085. features.push(this.createFeature_(pbf$1, rawFeature));
  6086. }
  6087. this.extent_ = pbfLayer ? [0, 0, pbfLayer.extent, pbfLayer.extent] : null;
  6088. }
  6089. return features;
  6090. };
  6091. ol.style = {};
  6092. /**
  6093. * Singleton class. Available through {@link ol.style.iconImageCache}.
  6094. * @constructor
  6095. */
  6096. ol.style.IconImageCache = function() {
  6097. this.cache_ = {};
  6098. this.cacheSize_ = 0;
  6099. this.maxCacheSize_ = 32;
  6100. };
  6101. ol.style.IconImageCache.getKey = function(src, crossOrigin, color) {
  6102. var colorString = color ? ol.color.asString(color) : 'null';
  6103. return crossOrigin + ':' + src + ':' + colorString;
  6104. };
  6105. /**
  6106. * FIXME empty description for jsdoc
  6107. */
  6108. ol.style.IconImageCache.prototype.clear = function() {
  6109. this.cache_ = {};
  6110. this.cacheSize_ = 0;
  6111. };
  6112. /**
  6113. * FIXME empty description for jsdoc
  6114. */
  6115. ol.style.IconImageCache.prototype.expire = function() {
  6116. if (this.cacheSize_ > this.maxCacheSize_) {
  6117. var i = 0;
  6118. var key, iconImage;
  6119. for (key in this.cache_) {
  6120. iconImage = this.cache_[key];
  6121. if ((i++ & 3) === 0 && !iconImage.hasListener()) {
  6122. delete this.cache_[key];
  6123. --this.cacheSize_;
  6124. }
  6125. }
  6126. }
  6127. };
  6128. ol.style.IconImageCache.prototype.get = function(src, crossOrigin, color) {
  6129. var key = ol.style.IconImageCache.getKey(src, crossOrigin, color);
  6130. return key in this.cache_ ? this.cache_[key] : null;
  6131. };
  6132. ol.style.IconImageCache.prototype.set = function(src, crossOrigin, color, iconImage) {
  6133. var key = ol.style.IconImageCache.getKey(src, crossOrigin, color);
  6134. this.cache_[key] = iconImage;
  6135. ++this.cacheSize_;
  6136. };
  6137. ol.style.IconImageCache.prototype.setSize = function(maxCacheSize) {
  6138. this.maxCacheSize_ = maxCacheSize;
  6139. this.expire();
  6140. };
  6141. /**
  6142. * The {@link ol.style.IconImageCache} for {@link ol.style.Icon} images.
  6143. * @api
  6144. */
  6145. ol.style.iconImageCache = new ol.style.IconImageCache();
  6146. ol.style.Image = function(options) {
  6147. /**
  6148. * @private
  6149. * @type {number}
  6150. */
  6151. this.opacity_ = options.opacity;
  6152. /**
  6153. * @private
  6154. * @type {boolean}
  6155. */
  6156. this.rotateWithView_ = options.rotateWithView;
  6157. /**
  6158. * @private
  6159. * @type {number}
  6160. */
  6161. this.rotation_ = options.rotation;
  6162. /**
  6163. * @private
  6164. * @type {number}
  6165. */
  6166. this.scale_ = options.scale;
  6167. /**
  6168. * @private
  6169. * @type {boolean}
  6170. */
  6171. this.snapToPixel_ = options.snapToPixel;
  6172. };
  6173. ol.style.Image.prototype.getOpacity = function() {
  6174. return this.opacity_;
  6175. };
  6176. ol.style.Image.prototype.getRotateWithView = function() {
  6177. return this.rotateWithView_;
  6178. };
  6179. ol.style.Image.prototype.getRotation = function() {
  6180. return this.rotation_;
  6181. };
  6182. ol.style.Image.prototype.getScale = function() {
  6183. return this.scale_;
  6184. };
  6185. ol.style.Image.prototype.getSnapToPixel = function() {
  6186. return this.snapToPixel_;
  6187. };
  6188. ol.style.Image.prototype.getAnchor = function() {};
  6189. ol.style.Image.prototype.getImage = function(pixelRatio) {};
  6190. ol.style.Image.prototype.getHitDetectionImage = function(pixelRatio) {};
  6191. ol.style.Image.prototype.getImageState = function() {};
  6192. ol.style.Image.prototype.getImageSize = function() {};
  6193. ol.style.Image.prototype.getHitDetectionImageSize = function() {};
  6194. ol.style.Image.prototype.getOrigin = function() {};
  6195. ol.style.Image.prototype.getSize = function() {};
  6196. ol.style.Image.prototype.setOpacity = function(opacity) {
  6197. this.opacity_ = opacity;
  6198. };
  6199. ol.style.Image.prototype.setRotateWithView = function(rotateWithView) {
  6200. this.rotateWithView_ = rotateWithView;
  6201. };
  6202. ol.style.Image.prototype.setRotation = function(rotation) {
  6203. this.rotation_ = rotation;
  6204. };
  6205. ol.style.Image.prototype.setScale = function(scale) {
  6206. this.scale_ = scale;
  6207. };
  6208. ol.style.Image.prototype.setSnapToPixel = function(snapToPixel) {
  6209. this.snapToPixel_ = snapToPixel;
  6210. };
  6211. ol.style.Image.prototype.listenImageChange = function(listener, thisArg) {};
  6212. ol.style.Image.prototype.load = function() {};
  6213. ol.style.Image.prototype.unlistenImageChange = function(listener, thisArg) {};
  6214. /**
  6215. * @classdesc
  6216. * Set regular shape style for vector features. The resulting shape will be
  6217. * a regular polygon when `radius` is provided, or a star when `radius1` and
  6218. * `radius2` are provided.
  6219. *
  6220. * @constructor
  6221. * @param {olx.style.RegularShapeOptions} options Options.
  6222. * @extends {ol.style.Image}
  6223. * @api
  6224. */
  6225. ol.style.RegularShape = function(options) {
  6226. /**
  6227. * @private
  6228. * @type {Array.<string>}
  6229. */
  6230. this.checksums_ = null;
  6231. /**
  6232. * @private
  6233. * @type {HTMLCanvasElement}
  6234. */
  6235. this.canvas_ = null;
  6236. /**
  6237. * @private
  6238. * @type {HTMLCanvasElement}
  6239. */
  6240. this.hitDetectionCanvas_ = null;
  6241. /**
  6242. * @private
  6243. * @type {ol.style.Fill}
  6244. */
  6245. this.fill_ = options.fill !== undefined ? options.fill : null;
  6246. /**
  6247. * @private
  6248. * @type {Array.<number>}
  6249. */
  6250. this.origin_ = [0, 0];
  6251. /**
  6252. * @private
  6253. * @type {number}
  6254. */
  6255. this.points_ = options.points;
  6256. /**
  6257. * @protected
  6258. * @type {number}
  6259. */
  6260. this.radius_ = /** @type {number} */ (options.radius !== undefined ?
  6261. options.radius : options.radius1);
  6262. /**
  6263. * @private
  6264. * @type {number|undefined}
  6265. */
  6266. this.radius2_ = options.radius2;
  6267. /**
  6268. * @private
  6269. * @type {number}
  6270. */
  6271. this.angle_ = options.angle !== undefined ? options.angle : 0;
  6272. /**
  6273. * @private
  6274. * @type {ol.style.Stroke}
  6275. */
  6276. this.stroke_ = options.stroke !== undefined ? options.stroke : null;
  6277. /**
  6278. * @private
  6279. * @type {Array.<number>}
  6280. */
  6281. this.anchor_ = null;
  6282. /**
  6283. * @private
  6284. * @type {ol.Size}
  6285. */
  6286. this.size_ = null;
  6287. /**
  6288. * @private
  6289. * @type {ol.Size}
  6290. */
  6291. this.imageSize_ = null;
  6292. /**
  6293. * @private
  6294. * @type {ol.Size}
  6295. */
  6296. this.hitDetectionImageSize_ = null;
  6297. /**
  6298. * @protected
  6299. * @type {ol.style.AtlasManager|undefined}
  6300. */
  6301. this.atlasManager_ = options.atlasManager;
  6302. this.render_(this.atlasManager_);
  6303. /**
  6304. * @type {boolean}
  6305. */
  6306. var snapToPixel = options.snapToPixel !== undefined ?
  6307. options.snapToPixel : true;
  6308. /**
  6309. * @type {boolean}
  6310. */
  6311. var rotateWithView = options.rotateWithView !== undefined ?
  6312. options.rotateWithView : false;
  6313. ol.style.Image.call(this, {
  6314. opacity: 1,
  6315. rotateWithView: rotateWithView,
  6316. rotation: options.rotation !== undefined ? options.rotation : 0,
  6317. scale: 1,
  6318. snapToPixel: snapToPixel
  6319. });
  6320. };
  6321. ol.inherits(ol.style.RegularShape, ol.style.Image);
  6322. ol.style.RegularShape.prototype.clone = function() {
  6323. var style = new ol.style.RegularShape({
  6324. fill: this.getFill() ? this.getFill().clone() : undefined,
  6325. points: this.getPoints(),
  6326. radius: this.getRadius(),
  6327. radius2: this.getRadius2(),
  6328. angle: this.getAngle(),
  6329. snapToPixel: this.getSnapToPixel(),
  6330. stroke: this.getStroke() ? this.getStroke().clone() : undefined,
  6331. rotation: this.getRotation(),
  6332. rotateWithView: this.getRotateWithView(),
  6333. atlasManager: this.atlasManager_
  6334. });
  6335. style.setOpacity(this.getOpacity());
  6336. style.setScale(this.getScale());
  6337. return style;
  6338. };
  6339. /**
  6340. * @inheritDoc
  6341. * @api
  6342. */
  6343. ol.style.RegularShape.prototype.getAnchor = function() {
  6344. return this.anchor_;
  6345. };
  6346. /**
  6347. * Get the angle used in generating the shape.
  6348. * @return {number} Shape's rotation in radians.
  6349. * @api
  6350. */
  6351. ol.style.RegularShape.prototype.getAngle = function() {
  6352. return this.angle_;
  6353. };
  6354. /**
  6355. * Get the fill style for the shape.
  6356. * @return {ol.style.Fill} Fill style.
  6357. * @api
  6358. */
  6359. ol.style.RegularShape.prototype.getFill = function() {
  6360. return this.fill_;
  6361. };
  6362. /**
  6363. * @inheritDoc
  6364. */
  6365. ol.style.RegularShape.prototype.getHitDetectionImage = function(pixelRatio) {
  6366. return this.hitDetectionCanvas_;
  6367. };
  6368. /**
  6369. * @inheritDoc
  6370. * @api
  6371. */
  6372. ol.style.RegularShape.prototype.getImage = function(pixelRatio) {
  6373. return this.canvas_;
  6374. };
  6375. /**
  6376. * @inheritDoc
  6377. */
  6378. ol.style.RegularShape.prototype.getImageSize = function() {
  6379. return this.imageSize_;
  6380. };
  6381. /**
  6382. * @inheritDoc
  6383. */
  6384. ol.style.RegularShape.prototype.getHitDetectionImageSize = function() {
  6385. return this.hitDetectionImageSize_;
  6386. };
  6387. /**
  6388. * @inheritDoc
  6389. */
  6390. ol.style.RegularShape.prototype.getImageState = function() {
  6391. return ol.ImageState.LOADED;
  6392. };
  6393. /**
  6394. * @inheritDoc
  6395. * @api
  6396. */
  6397. ol.style.RegularShape.prototype.getOrigin = function() {
  6398. return this.origin_;
  6399. };
  6400. /**
  6401. * Get the number of points for generating the shape.
  6402. * @return {number} Number of points for stars and regular polygons.
  6403. * @api
  6404. */
  6405. ol.style.RegularShape.prototype.getPoints = function() {
  6406. return this.points_;
  6407. };
  6408. /**
  6409. * Get the (primary) radius for the shape.
  6410. * @return {number} Radius.
  6411. * @api
  6412. */
  6413. ol.style.RegularShape.prototype.getRadius = function() {
  6414. return this.radius_;
  6415. };
  6416. /**
  6417. * Get the secondary radius for the shape.
  6418. * @return {number|undefined} Radius2.
  6419. * @api
  6420. */
  6421. ol.style.RegularShape.prototype.getRadius2 = function() {
  6422. return this.radius2_;
  6423. };
  6424. /**
  6425. * @inheritDoc
  6426. * @api
  6427. */
  6428. ol.style.RegularShape.prototype.getSize = function() {
  6429. return this.size_;
  6430. };
  6431. /**
  6432. * Get the stroke style for the shape.
  6433. * @return {ol.style.Stroke} Stroke style.
  6434. * @api
  6435. */
  6436. ol.style.RegularShape.prototype.getStroke = function() {
  6437. return this.stroke_;
  6438. };
  6439. /**
  6440. * @inheritDoc
  6441. */
  6442. ol.style.RegularShape.prototype.listenImageChange = function(listener, thisArg) {};
  6443. /**
  6444. * @inheritDoc
  6445. */
  6446. ol.style.RegularShape.prototype.load = function() {};
  6447. /**
  6448. * @inheritDoc
  6449. */
  6450. ol.style.RegularShape.prototype.unlistenImageChange = function(listener, thisArg) {};
  6451. /**
  6452. * @protected
  6453. * @param {ol.style.AtlasManager|undefined} atlasManager An atlas manager.
  6454. */
  6455. ol.style.RegularShape.prototype.render_ = function(atlasManager) {
  6456. var imageSize;
  6457. var lineCap = '';
  6458. var lineJoin = '';
  6459. var miterLimit = 0;
  6460. var lineDash = null;
  6461. var lineDashOffset = 0;
  6462. var strokeStyle;
  6463. var strokeWidth = 0;
  6464. if (this.stroke_) {
  6465. strokeStyle = this.stroke_.getColor();
  6466. if (strokeStyle === null) {
  6467. strokeStyle = ol.render.canvas.defaultStrokeStyle;
  6468. }
  6469. strokeStyle = ol.colorlike.asColorLike(strokeStyle);
  6470. strokeWidth = this.stroke_.getWidth();
  6471. if (strokeWidth === undefined) {
  6472. strokeWidth = ol.render.canvas.defaultLineWidth;
  6473. }
  6474. lineDash = this.stroke_.getLineDash();
  6475. lineDashOffset = this.stroke_.getLineDashOffset();
  6476. if (!ol.has.CANVAS_LINE_DASH) {
  6477. lineDash = null;
  6478. lineDashOffset = 0;
  6479. }
  6480. lineJoin = this.stroke_.getLineJoin();
  6481. if (lineJoin === undefined) {
  6482. lineJoin = ol.render.canvas.defaultLineJoin;
  6483. }
  6484. lineCap = this.stroke_.getLineCap();
  6485. if (lineCap === undefined) {
  6486. lineCap = ol.render.canvas.defaultLineCap;
  6487. }
  6488. miterLimit = this.stroke_.getMiterLimit();
  6489. if (miterLimit === undefined) {
  6490. miterLimit = ol.render.canvas.defaultMiterLimit;
  6491. }
  6492. }
  6493. var size = 2 * (this.radius_ + strokeWidth) + 1;
  6494. /** @type {ol.RegularShapeRenderOptions} */
  6495. var renderOptions = {
  6496. strokeStyle: strokeStyle,
  6497. strokeWidth: strokeWidth,
  6498. size: size,
  6499. lineCap: lineCap,
  6500. lineDash: lineDash,
  6501. lineDashOffset: lineDashOffset,
  6502. lineJoin: lineJoin,
  6503. miterLimit: miterLimit
  6504. };
  6505. if (atlasManager === undefined) {
  6506. // no atlas manager is used, create a new canvas
  6507. var context = ol.dom.createCanvasContext2D(size, size);
  6508. this.canvas_ = context.canvas;
  6509. // canvas.width and height are rounded to the closest integer
  6510. size = this.canvas_.width;
  6511. imageSize = size;
  6512. this.draw_(renderOptions, context, 0, 0);
  6513. this.createHitDetectionCanvas_(renderOptions);
  6514. } else {
  6515. // an atlas manager is used, add the symbol to an atlas
  6516. size = Math.round(size);
  6517. var hasCustomHitDetectionImage = !this.fill_;
  6518. var renderHitDetectionCallback;
  6519. if (hasCustomHitDetectionImage) {
  6520. // render the hit-detection image into a separate atlas image
  6521. renderHitDetectionCallback =
  6522. this.drawHitDetectionCanvas_.bind(this, renderOptions);
  6523. }
  6524. var id = this.getChecksum();
  6525. var info = atlasManager.add(
  6526. id, size, size, this.draw_.bind(this, renderOptions),
  6527. renderHitDetectionCallback);
  6528. this.canvas_ = info.image;
  6529. this.origin_ = [info.offsetX, info.offsetY];
  6530. imageSize = info.image.width;
  6531. if (hasCustomHitDetectionImage) {
  6532. this.hitDetectionCanvas_ = info.hitImage;
  6533. this.hitDetectionImageSize_ =
  6534. [info.hitImage.width, info.hitImage.height];
  6535. } else {
  6536. this.hitDetectionCanvas_ = this.canvas_;
  6537. this.hitDetectionImageSize_ = [imageSize, imageSize];
  6538. }
  6539. }
  6540. this.anchor_ = [size / 2, size / 2];
  6541. this.size_ = [size, size];
  6542. this.imageSize_ = [imageSize, imageSize];
  6543. };
  6544. /**
  6545. * @private
  6546. * @param {ol.RegularShapeRenderOptions} renderOptions Render options.
  6547. * @param {CanvasRenderingContext2D} context The rendering context.
  6548. * @param {number} x The origin for the symbol (x).
  6549. * @param {number} y The origin for the symbol (y).
  6550. */
  6551. ol.style.RegularShape.prototype.draw_ = function(renderOptions, context, x, y) {
  6552. var i, angle0, radiusC;
  6553. // reset transform
  6554. context.setTransform(1, 0, 0, 1, 0, 0);
  6555. // then move to (x, y)
  6556. context.translate(x, y);
  6557. context.beginPath();
  6558. var points = this.points_;
  6559. if (points === Infinity) {
  6560. context.arc(
  6561. renderOptions.size / 2, renderOptions.size / 2,
  6562. this.radius_, 0, 2 * Math.PI, true);
  6563. } else {
  6564. var radius2 = (this.radius2_ !== undefined) ? this.radius2_
  6565. : this.radius_;
  6566. if (radius2 !== this.radius_) {
  6567. points = 2 * points;
  6568. }
  6569. for (i = 0; i <= points; i++) {
  6570. angle0 = i * 2 * Math.PI / points - Math.PI / 2 + this.angle_;
  6571. radiusC = i % 2 === 0 ? this.radius_ : radius2;
  6572. context.lineTo(renderOptions.size / 2 + radiusC * Math.cos(angle0),
  6573. renderOptions.size / 2 + radiusC * Math.sin(angle0));
  6574. }
  6575. }
  6576. if (this.fill_) {
  6577. var color = this.fill_.getColor();
  6578. if (color === null) {
  6579. color = ol.render.canvas.defaultFillStyle;
  6580. }
  6581. context.fillStyle = ol.colorlike.asColorLike(color);
  6582. context.fill();
  6583. }
  6584. if (this.stroke_) {
  6585. context.strokeStyle = renderOptions.strokeStyle;
  6586. context.lineWidth = renderOptions.strokeWidth;
  6587. if (renderOptions.lineDash) {
  6588. context.setLineDash(renderOptions.lineDash);
  6589. context.lineDashOffset = renderOptions.lineDashOffset;
  6590. }
  6591. context.lineCap = renderOptions.lineCap;
  6592. context.lineJoin = renderOptions.lineJoin;
  6593. context.miterLimit = renderOptions.miterLimit;
  6594. context.stroke();
  6595. }
  6596. context.closePath();
  6597. };
  6598. /**
  6599. * @private
  6600. * @param {ol.RegularShapeRenderOptions} renderOptions Render options.
  6601. */
  6602. ol.style.RegularShape.prototype.createHitDetectionCanvas_ = function(renderOptions) {
  6603. this.hitDetectionImageSize_ = [renderOptions.size, renderOptions.size];
  6604. if (this.fill_) {
  6605. this.hitDetectionCanvas_ = this.canvas_;
  6606. return;
  6607. }
  6608. // if no fill style is set, create an extra hit-detection image with a
  6609. // default fill style
  6610. var context = ol.dom.createCanvasContext2D(renderOptions.size, renderOptions.size);
  6611. this.hitDetectionCanvas_ = context.canvas;
  6612. this.drawHitDetectionCanvas_(renderOptions, context, 0, 0);
  6613. };
  6614. /**
  6615. * @private
  6616. * @param {ol.RegularShapeRenderOptions} renderOptions Render options.
  6617. * @param {CanvasRenderingContext2D} context The context.
  6618. * @param {number} x The origin for the symbol (x).
  6619. * @param {number} y The origin for the symbol (y).
  6620. */
  6621. ol.style.RegularShape.prototype.drawHitDetectionCanvas_ = function(renderOptions, context, x, y) {
  6622. // reset transform
  6623. context.setTransform(1, 0, 0, 1, 0, 0);
  6624. // then move to (x, y)
  6625. context.translate(x, y);
  6626. context.beginPath();
  6627. var points = this.points_;
  6628. if (points === Infinity) {
  6629. context.arc(
  6630. renderOptions.size / 2, renderOptions.size / 2,
  6631. this.radius_, 0, 2 * Math.PI, true);
  6632. } else {
  6633. var radius2 = (this.radius2_ !== undefined) ? this.radius2_
  6634. : this.radius_;
  6635. if (radius2 !== this.radius_) {
  6636. points = 2 * points;
  6637. }
  6638. var i, radiusC, angle0;
  6639. for (i = 0; i <= points; i++) {
  6640. angle0 = i * 2 * Math.PI / points - Math.PI / 2 + this.angle_;
  6641. radiusC = i % 2 === 0 ? this.radius_ : radius2;
  6642. context.lineTo(renderOptions.size / 2 + radiusC * Math.cos(angle0),
  6643. renderOptions.size / 2 + radiusC * Math.sin(angle0));
  6644. }
  6645. }
  6646. context.fillStyle = ol.render.canvas.defaultFillStyle;
  6647. context.fill();
  6648. if (this.stroke_) {
  6649. context.strokeStyle = renderOptions.strokeStyle;
  6650. context.lineWidth = renderOptions.strokeWidth;
  6651. if (renderOptions.lineDash) {
  6652. context.setLineDash(renderOptions.lineDash);
  6653. context.lineDashOffset = renderOptions.lineDashOffset;
  6654. }
  6655. context.stroke();
  6656. }
  6657. context.closePath();
  6658. };
  6659. /**
  6660. * @return {string} The checksum.
  6661. */
  6662. ol.style.RegularShape.prototype.getChecksum = function() {
  6663. var strokeChecksum = this.stroke_ ?
  6664. this.stroke_.getChecksum() : '-';
  6665. var fillChecksum = this.fill_ ?
  6666. this.fill_.getChecksum() : '-';
  6667. var recalculate = !this.checksums_ ||
  6668. (strokeChecksum != this.checksums_[1] ||
  6669. fillChecksum != this.checksums_[2] ||
  6670. this.radius_ != this.checksums_[3] ||
  6671. this.radius2_ != this.checksums_[4] ||
  6672. this.angle_ != this.checksums_[5] ||
  6673. this.points_ != this.checksums_[6]);
  6674. if (recalculate) {
  6675. var checksum = 'r' + strokeChecksum + fillChecksum +
  6676. (this.radius_ !== undefined ? this.radius_.toString() : '-') +
  6677. (this.radius2_ !== undefined ? this.radius2_.toString() : '-') +
  6678. (this.angle_ !== undefined ? this.angle_.toString() : '-') +
  6679. (this.points_ !== undefined ? this.points_.toString() : '-');
  6680. this.checksums_ = [checksum, strokeChecksum, fillChecksum,
  6681. this.radius_, this.radius2_, this.angle_, this.points_];
  6682. }
  6683. return this.checksums_[0];
  6684. };
  6685. /**
  6686. * @classdesc
  6687. * Set circle style for vector features.
  6688. *
  6689. * @constructor
  6690. * @param {olx.style.CircleOptions=} opt_options Options.
  6691. * @extends {ol.style.RegularShape}
  6692. * @api
  6693. */
  6694. ol.style.Circle = function(opt_options) {
  6695. var options = opt_options || {};
  6696. ol.style.RegularShape.call(this, {
  6697. points: Infinity,
  6698. fill: options.fill,
  6699. radius: options.radius,
  6700. snapToPixel: options.snapToPixel,
  6701. stroke: options.stroke,
  6702. atlasManager: options.atlasManager
  6703. });
  6704. };
  6705. ol.inherits(ol.style.Circle, ol.style.RegularShape);
  6706. /**
  6707. * Clones the style. If an atlasmanager was provided to the original style it will be used in the cloned style, too.
  6708. * @return {ol.style.Circle} The cloned style.
  6709. * @override
  6710. * @api
  6711. */
  6712. ol.style.Circle.prototype.clone = function() {
  6713. var style = new ol.style.Circle({
  6714. fill: this.getFill() ? this.getFill().clone() : undefined,
  6715. stroke: this.getStroke() ? this.getStroke().clone() : undefined,
  6716. radius: this.getRadius(),
  6717. snapToPixel: this.getSnapToPixel(),
  6718. atlasManager: this.atlasManager_
  6719. });
  6720. style.setOpacity(this.getOpacity());
  6721. style.setScale(this.getScale());
  6722. return style;
  6723. };
  6724. /**
  6725. * Set the circle radius.
  6726. *
  6727. * @param {number} radius Circle radius.
  6728. * @api
  6729. */
  6730. ol.style.Circle.prototype.setRadius = function(radius) {
  6731. this.radius_ = radius;
  6732. this.render_(this.atlasManager_);
  6733. };
  6734. /**
  6735. * @classdesc
  6736. * Set fill style for vector features.
  6737. *
  6738. * @constructor
  6739. * @param {olx.style.FillOptions=} opt_options Options.
  6740. * @api
  6741. */
  6742. ol.style.Fill = function(opt_options) {
  6743. var options = opt_options || {};
  6744. /**
  6745. * @private
  6746. * @type {ol.Color|ol.ColorLike}
  6747. */
  6748. this.color_ = options.color !== undefined ? options.color : null;
  6749. /**
  6750. * @private
  6751. * @type {string|undefined}
  6752. */
  6753. this.checksum_ = undefined;
  6754. };
  6755. /**
  6756. * Clones the style. The color is not cloned if it is an {@link ol.ColorLike}.
  6757. * @return {ol.style.Fill} The cloned style.
  6758. * @api
  6759. */
  6760. ol.style.Fill.prototype.clone = function() {
  6761. var color = this.getColor();
  6762. return new ol.style.Fill({
  6763. color: (color && color.slice) ? color.slice() : color || undefined
  6764. });
  6765. };
  6766. /**
  6767. * Get the fill color.
  6768. * @return {ol.Color|ol.ColorLike} Color.
  6769. * @api
  6770. */
  6771. ol.style.Fill.prototype.getColor = function() {
  6772. return this.color_;
  6773. };
  6774. /**
  6775. * Set the color.
  6776. *
  6777. * @param {ol.Color|ol.ColorLike} color Color.
  6778. * @api
  6779. */
  6780. ol.style.Fill.prototype.setColor = function(color) {
  6781. this.color_ = color;
  6782. this.checksum_ = undefined;
  6783. };
  6784. /**
  6785. * @return {string} The checksum.
  6786. */
  6787. ol.style.Fill.prototype.getChecksum = function() {
  6788. if (this.checksum_ === undefined) {
  6789. if (
  6790. this.color_ instanceof CanvasPattern ||
  6791. this.color_ instanceof CanvasGradient
  6792. ) {
  6793. this.checksum_ = ol.getUid(this.color_).toString();
  6794. } else {
  6795. this.checksum_ = 'f' + (this.color_ ?
  6796. ol.color.asString(this.color_) : '-');
  6797. }
  6798. }
  6799. return this.checksum_;
  6800. };
  6801. /**
  6802. * @classdesc
  6803. * Set stroke style for vector features.
  6804. * Note that the defaults given are the Canvas defaults, which will be used if
  6805. * option is not defined. The `get` functions return whatever was entered in
  6806. * the options; they will not return the default.
  6807. *
  6808. * @constructor
  6809. * @param {olx.style.StrokeOptions=} opt_options Options.
  6810. * @api
  6811. */
  6812. ol.style.Stroke = function(opt_options) {
  6813. var options = opt_options || {};
  6814. /**
  6815. * @private
  6816. * @type {ol.Color|ol.ColorLike}
  6817. */
  6818. this.color_ = options.color !== undefined ? options.color : null;
  6819. /**
  6820. * @private
  6821. * @type {string|undefined}
  6822. */
  6823. this.lineCap_ = options.lineCap;
  6824. /**
  6825. * @private
  6826. * @type {Array.<number>}
  6827. */
  6828. this.lineDash_ = options.lineDash !== undefined ? options.lineDash : null;
  6829. /**
  6830. * @private
  6831. * @type {number|undefined}
  6832. */
  6833. this.lineDashOffset_ = options.lineDashOffset;
  6834. /**
  6835. * @private
  6836. * @type {string|undefined}
  6837. */
  6838. this.lineJoin_ = options.lineJoin;
  6839. /**
  6840. * @private
  6841. * @type {number|undefined}
  6842. */
  6843. this.miterLimit_ = options.miterLimit;
  6844. /**
  6845. * @private
  6846. * @type {number|undefined}
  6847. */
  6848. this.width_ = options.width;
  6849. /**
  6850. * @private
  6851. * @type {string|undefined}
  6852. */
  6853. this.checksum_ = undefined;
  6854. };
  6855. /**
  6856. * Clones the style.
  6857. * @return {ol.style.Stroke} The cloned style.
  6858. * @api
  6859. */
  6860. ol.style.Stroke.prototype.clone = function() {
  6861. var color = this.getColor();
  6862. return new ol.style.Stroke({
  6863. color: (color && color.slice) ? color.slice() : color || undefined,
  6864. lineCap: this.getLineCap(),
  6865. lineDash: this.getLineDash() ? this.getLineDash().slice() : undefined,
  6866. lineDashOffset: this.getLineDashOffset(),
  6867. lineJoin: this.getLineJoin(),
  6868. miterLimit: this.getMiterLimit(),
  6869. width: this.getWidth()
  6870. });
  6871. };
  6872. /**
  6873. * Get the stroke color.
  6874. * @return {ol.Color|ol.ColorLike} Color.
  6875. * @api
  6876. */
  6877. ol.style.Stroke.prototype.getColor = function() {
  6878. return this.color_;
  6879. };
  6880. /**
  6881. * Get the line cap type for the stroke.
  6882. * @return {string|undefined} Line cap.
  6883. * @api
  6884. */
  6885. ol.style.Stroke.prototype.getLineCap = function() {
  6886. return this.lineCap_;
  6887. };
  6888. /**
  6889. * Get the line dash style for the stroke.
  6890. * @return {Array.<number>} Line dash.
  6891. * @api
  6892. */
  6893. ol.style.Stroke.prototype.getLineDash = function() {
  6894. return this.lineDash_;
  6895. };
  6896. /**
  6897. * Get the line dash offset for the stroke.
  6898. * @return {number|undefined} Line dash offset.
  6899. * @api
  6900. */
  6901. ol.style.Stroke.prototype.getLineDashOffset = function() {
  6902. return this.lineDashOffset_;
  6903. };
  6904. /**
  6905. * Get the line join type for the stroke.
  6906. * @return {string|undefined} Line join.
  6907. * @api
  6908. */
  6909. ol.style.Stroke.prototype.getLineJoin = function() {
  6910. return this.lineJoin_;
  6911. };
  6912. /**
  6913. * Get the miter limit for the stroke.
  6914. * @return {number|undefined} Miter limit.
  6915. * @api
  6916. */
  6917. ol.style.Stroke.prototype.getMiterLimit = function() {
  6918. return this.miterLimit_;
  6919. };
  6920. /**
  6921. * Get the stroke width.
  6922. * @return {number|undefined} Width.
  6923. * @api
  6924. */
  6925. ol.style.Stroke.prototype.getWidth = function() {
  6926. return this.width_;
  6927. };
  6928. /**
  6929. * Set the color.
  6930. *
  6931. * @param {ol.Color|ol.ColorLike} color Color.
  6932. * @api
  6933. */
  6934. ol.style.Stroke.prototype.setColor = function(color) {
  6935. this.color_ = color;
  6936. this.checksum_ = undefined;
  6937. };
  6938. /**
  6939. * Set the line cap.
  6940. *
  6941. * @param {string|undefined} lineCap Line cap.
  6942. * @api
  6943. */
  6944. ol.style.Stroke.prototype.setLineCap = function(lineCap) {
  6945. this.lineCap_ = lineCap;
  6946. this.checksum_ = undefined;
  6947. };
  6948. /**
  6949. * Set the line dash.
  6950. *
  6951. * Please note that Internet Explorer 10 and lower [do not support][mdn] the
  6952. * `setLineDash` method on the `CanvasRenderingContext2D` and therefore this
  6953. * property will have no visual effect in these browsers.
  6954. *
  6955. * [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility
  6956. *
  6957. * @param {Array.<number>} lineDash Line dash.
  6958. * @api
  6959. */
  6960. ol.style.Stroke.prototype.setLineDash = function(lineDash) {
  6961. this.lineDash_ = lineDash;
  6962. this.checksum_ = undefined;
  6963. };
  6964. /**
  6965. * Set the line dash offset.
  6966. *
  6967. * @param {number|undefined} lineDashOffset Line dash offset.
  6968. * @api
  6969. */
  6970. ol.style.Stroke.prototype.setLineDashOffset = function(lineDashOffset) {
  6971. this.lineDashOffset_ = lineDashOffset;
  6972. this.checksum_ = undefined;
  6973. };
  6974. /**
  6975. * Set the line join.
  6976. *
  6977. * @param {string|undefined} lineJoin Line join.
  6978. * @api
  6979. */
  6980. ol.style.Stroke.prototype.setLineJoin = function(lineJoin) {
  6981. this.lineJoin_ = lineJoin;
  6982. this.checksum_ = undefined;
  6983. };
  6984. /**
  6985. * Set the miter limit.
  6986. *
  6987. * @param {number|undefined} miterLimit Miter limit.
  6988. * @api
  6989. */
  6990. ol.style.Stroke.prototype.setMiterLimit = function(miterLimit) {
  6991. this.miterLimit_ = miterLimit;
  6992. this.checksum_ = undefined;
  6993. };
  6994. /**
  6995. * Set the width.
  6996. *
  6997. * @param {number|undefined} width Width.
  6998. * @api
  6999. */
  7000. ol.style.Stroke.prototype.setWidth = function(width) {
  7001. this.width_ = width;
  7002. this.checksum_ = undefined;
  7003. };
  7004. /**
  7005. * @return {string} The checksum.
  7006. */
  7007. ol.style.Stroke.prototype.getChecksum = function() {
  7008. if (this.checksum_ === undefined) {
  7009. this.checksum_ = 's';
  7010. if (this.color_) {
  7011. if (typeof this.color_ === 'string') {
  7012. this.checksum_ += this.color_;
  7013. } else {
  7014. this.checksum_ += ol.getUid(this.color_).toString();
  7015. }
  7016. } else {
  7017. this.checksum_ += '-';
  7018. }
  7019. this.checksum_ += ',' +
  7020. (this.lineCap_ !== undefined ?
  7021. this.lineCap_.toString() : '-') + ',' +
  7022. (this.lineDash_ ?
  7023. this.lineDash_.toString() : '-') + ',' +
  7024. (this.lineDashOffset_ !== undefined ?
  7025. this.lineDashOffset_ : '-') + ',' +
  7026. (this.lineJoin_ !== undefined ?
  7027. this.lineJoin_ : '-') + ',' +
  7028. (this.miterLimit_ !== undefined ?
  7029. this.miterLimit_.toString() : '-') + ',' +
  7030. (this.width_ !== undefined ?
  7031. this.width_.toString() : '-');
  7032. }
  7033. return this.checksum_;
  7034. };
  7035. /**
  7036. * Icon anchor units. One of 'fraction', 'pixels'.
  7037. * @enum {string}
  7038. */
  7039. ol.style.IconAnchorUnits = {
  7040. FRACTION: 'fraction',
  7041. PIXELS: 'pixels'
  7042. };
  7043. /**
  7044. * @constructor
  7045. * @param {Image|HTMLCanvasElement} image Image.
  7046. * @param {string|undefined} src Src.
  7047. * @param {ol.Size} size Size.
  7048. * @param {?string} crossOrigin Cross origin.
  7049. * @param {ol.ImageState} imageState Image state.
  7050. * @param {ol.Color} color Color.
  7051. * @extends {ol.events.EventTarget}
  7052. */
  7053. ol.style.IconImage = function(image, src, size, crossOrigin, imageState,
  7054. color) {
  7055. ol.events.EventTarget.call(this);
  7056. /**
  7057. * @private
  7058. * @type {Image|HTMLCanvasElement}
  7059. */
  7060. this.hitDetectionImage_ = null;
  7061. /**
  7062. * @private
  7063. * @type {Image|HTMLCanvasElement}
  7064. */
  7065. this.image_ = !image ? new Image() : image;
  7066. if (crossOrigin !== null) {
  7067. this.image_.crossOrigin = crossOrigin;
  7068. }
  7069. /**
  7070. * @private
  7071. * @type {HTMLCanvasElement}
  7072. */
  7073. this.canvas_ = color ?
  7074. /** @type {HTMLCanvasElement} */ (document.createElement('CANVAS')) :
  7075. null;
  7076. /**
  7077. * @private
  7078. * @type {ol.Color}
  7079. */
  7080. this.color_ = color;
  7081. /**
  7082. * @private
  7083. * @type {Array.<ol.EventsKey>}
  7084. */
  7085. this.imageListenerKeys_ = null;
  7086. /**
  7087. * @private
  7088. * @type {ol.ImageState}
  7089. */
  7090. this.imageState_ = imageState;
  7091. /**
  7092. * @private
  7093. * @type {ol.Size}
  7094. */
  7095. this.size_ = size;
  7096. /**
  7097. * @private
  7098. * @type {string|undefined}
  7099. */
  7100. this.src_ = src;
  7101. /**
  7102. * @private
  7103. * @type {boolean}
  7104. */
  7105. this.tainting_ = false;
  7106. if (this.imageState_ == ol.ImageState.LOADED) {
  7107. this.determineTainting_();
  7108. }
  7109. };
  7110. ol.inherits(ol.style.IconImage, ol.events.EventTarget);
  7111. /**
  7112. * @param {Image|HTMLCanvasElement} image Image.
  7113. * @param {string} src Src.
  7114. * @param {ol.Size} size Size.
  7115. * @param {?string} crossOrigin Cross origin.
  7116. * @param {ol.ImageState} imageState Image state.
  7117. * @param {ol.Color} color Color.
  7118. * @return {ol.style.IconImage} Icon image.
  7119. */
  7120. ol.style.IconImage.get = function(image, src, size, crossOrigin, imageState,
  7121. color) {
  7122. var iconImageCache = ol.style.iconImageCache;
  7123. var iconImage = iconImageCache.get(src, crossOrigin, color);
  7124. if (!iconImage) {
  7125. iconImage = new ol.style.IconImage(
  7126. image, src, size, crossOrigin, imageState, color);
  7127. iconImageCache.set(src, crossOrigin, color, iconImage);
  7128. }
  7129. return iconImage;
  7130. };
  7131. /**
  7132. * @private
  7133. */
  7134. ol.style.IconImage.prototype.determineTainting_ = function() {
  7135. var context = ol.dom.createCanvasContext2D(1, 1);
  7136. try {
  7137. context.drawImage(this.image_, 0, 0);
  7138. context.getImageData(0, 0, 1, 1);
  7139. } catch (e) {
  7140. this.tainting_ = true;
  7141. }
  7142. };
  7143. /**
  7144. * @private
  7145. */
  7146. ol.style.IconImage.prototype.dispatchChangeEvent_ = function() {
  7147. this.dispatchEvent(ol.events.EventType.CHANGE);
  7148. };
  7149. /**
  7150. * @private
  7151. */
  7152. ol.style.IconImage.prototype.handleImageError_ = function() {
  7153. this.imageState_ = ol.ImageState.ERROR;
  7154. this.unlistenImage_();
  7155. this.dispatchChangeEvent_();
  7156. };
  7157. /**
  7158. * @private
  7159. */
  7160. ol.style.IconImage.prototype.handleImageLoad_ = function() {
  7161. this.imageState_ = ol.ImageState.LOADED;
  7162. if (this.size_) {
  7163. this.image_.width = this.size_[0];
  7164. this.image_.height = this.size_[1];
  7165. }
  7166. this.size_ = [this.image_.width, this.image_.height];
  7167. this.unlistenImage_();
  7168. this.determineTainting_();
  7169. this.replaceColor_();
  7170. this.dispatchChangeEvent_();
  7171. };
  7172. /**
  7173. * @param {number} pixelRatio Pixel ratio.
  7174. * @return {Image|HTMLCanvasElement} Image or Canvas element.
  7175. */
  7176. ol.style.IconImage.prototype.getImage = function(pixelRatio) {
  7177. return this.canvas_ ? this.canvas_ : this.image_;
  7178. };
  7179. /**
  7180. * @return {ol.ImageState} Image state.
  7181. */
  7182. ol.style.IconImage.prototype.getImageState = function() {
  7183. return this.imageState_;
  7184. };
  7185. /**
  7186. * @param {number} pixelRatio Pixel ratio.
  7187. * @return {Image|HTMLCanvasElement} Image element.
  7188. */
  7189. ol.style.IconImage.prototype.getHitDetectionImage = function(pixelRatio) {
  7190. if (!this.hitDetectionImage_) {
  7191. if (this.tainting_) {
  7192. var width = this.size_[0];
  7193. var height = this.size_[1];
  7194. var context = ol.dom.createCanvasContext2D(width, height);
  7195. context.fillRect(0, 0, width, height);
  7196. this.hitDetectionImage_ = context.canvas;
  7197. } else {
  7198. this.hitDetectionImage_ = this.image_;
  7199. }
  7200. }
  7201. return this.hitDetectionImage_;
  7202. };
  7203. /**
  7204. * @return {ol.Size} Image size.
  7205. */
  7206. ol.style.IconImage.prototype.getSize = function() {
  7207. return this.size_;
  7208. };
  7209. /**
  7210. * @return {string|undefined} Image src.
  7211. */
  7212. ol.style.IconImage.prototype.getSrc = function() {
  7213. return this.src_;
  7214. };
  7215. /**
  7216. * Load not yet loaded URI.
  7217. */
  7218. ol.style.IconImage.prototype.load = function() {
  7219. if (this.imageState_ == ol.ImageState.IDLE) {
  7220. this.imageState_ = ol.ImageState.LOADING;
  7221. this.imageListenerKeys_ = [
  7222. ol.events.listenOnce(this.image_, ol.events.EventType.ERROR,
  7223. this.handleImageError_, this),
  7224. ol.events.listenOnce(this.image_, ol.events.EventType.LOAD,
  7225. this.handleImageLoad_, this)
  7226. ];
  7227. try {
  7228. this.image_.src = this.src_;
  7229. } catch (e) {
  7230. this.handleImageError_();
  7231. }
  7232. }
  7233. };
  7234. /**
  7235. * @private
  7236. */
  7237. ol.style.IconImage.prototype.replaceColor_ = function() {
  7238. if (this.tainting_ || this.color_ === null) {
  7239. return;
  7240. }
  7241. this.canvas_.width = this.image_.width;
  7242. this.canvas_.height = this.image_.height;
  7243. var ctx = this.canvas_.getContext('2d');
  7244. ctx.drawImage(this.image_, 0, 0);
  7245. var imgData = ctx.getImageData(0, 0, this.image_.width, this.image_.height);
  7246. var data = imgData.data;
  7247. var r = this.color_[0] / 255.0;
  7248. var g = this.color_[1] / 255.0;
  7249. var b = this.color_[2] / 255.0;
  7250. for (var i = 0, ii = data.length; i < ii; i += 4) {
  7251. data[i] *= r;
  7252. data[i + 1] *= g;
  7253. data[i + 2] *= b;
  7254. }
  7255. ctx.putImageData(imgData, 0, 0);
  7256. };
  7257. /**
  7258. * Discards event handlers which listen for load completion or errors.
  7259. *
  7260. * @private
  7261. */
  7262. ol.style.IconImage.prototype.unlistenImage_ = function() {
  7263. this.imageListenerKeys_.forEach(ol.events.unlistenByKey);
  7264. this.imageListenerKeys_ = null;
  7265. };
  7266. /**
  7267. * Icon origin. One of 'bottom-left', 'bottom-right', 'top-left', 'top-right'.
  7268. * @enum {string}
  7269. */
  7270. ol.style.IconOrigin = {
  7271. BOTTOM_LEFT: 'bottom-left',
  7272. BOTTOM_RIGHT: 'bottom-right',
  7273. TOP_LEFT: 'top-left',
  7274. TOP_RIGHT: 'top-right'
  7275. };
  7276. /**
  7277. * @classdesc
  7278. * Set icon style for vector features.
  7279. *
  7280. * @constructor
  7281. * @param {olx.style.IconOptions=} opt_options Options.
  7282. * @extends {ol.style.Image}
  7283. * @api
  7284. */
  7285. ol.style.Icon = function(opt_options) {
  7286. var options = opt_options || {};
  7287. /**
  7288. * @private
  7289. * @type {Array.<number>}
  7290. */
  7291. this.anchor_ = options.anchor !== undefined ? options.anchor : [0.5, 0.5];
  7292. /**
  7293. * @private
  7294. * @type {Array.<number>}
  7295. */
  7296. this.normalizedAnchor_ = null;
  7297. /**
  7298. * @private
  7299. * @type {ol.style.IconOrigin}
  7300. */
  7301. this.anchorOrigin_ = options.anchorOrigin !== undefined ?
  7302. options.anchorOrigin : ol.style.IconOrigin.TOP_LEFT;
  7303. /**
  7304. * @private
  7305. * @type {ol.style.IconAnchorUnits}
  7306. */
  7307. this.anchorXUnits_ = options.anchorXUnits !== undefined ?
  7308. options.anchorXUnits : ol.style.IconAnchorUnits.FRACTION;
  7309. /**
  7310. * @private
  7311. * @type {ol.style.IconAnchorUnits}
  7312. */
  7313. this.anchorYUnits_ = options.anchorYUnits !== undefined ?
  7314. options.anchorYUnits : ol.style.IconAnchorUnits.FRACTION;
  7315. /**
  7316. * @private
  7317. * @type {?string}
  7318. */
  7319. this.crossOrigin_ =
  7320. options.crossOrigin !== undefined ? options.crossOrigin : null;
  7321. /**
  7322. * @type {Image|HTMLCanvasElement}
  7323. */
  7324. var image = options.img !== undefined ? options.img : null;
  7325. /**
  7326. * @type {ol.Size}
  7327. */
  7328. var imgSize = options.imgSize !== undefined ? options.imgSize : null;
  7329. /**
  7330. * @type {string|undefined}
  7331. */
  7332. var src = options.src;
  7333. // ol.asserts.assert(!(src !== undefined && image),
  7334. // 4); // `image` and `src` cannot be provided at the same time
  7335. // ol.asserts.assert(!image || (image && imgSize),
  7336. // 5); // `imgSize` must be set when `image` is provided
  7337. if ((src === undefined || src.length === 0) && image) {
  7338. src = image.src || ol.getUid(image).toString();
  7339. }
  7340. // ol.asserts.assert(src !== undefined && src.length > 0,
  7341. // 6); // A defined and non-empty `src` or `image` must be provided
  7342. /**
  7343. * @type {ol.ImageState}
  7344. */
  7345. var imageState = options.src !== undefined ?
  7346. ol.ImageState.IDLE : ol.ImageState.LOADED;
  7347. /**
  7348. * @private
  7349. * @type {ol.Color}
  7350. */
  7351. this.color_ = options.color !== undefined ? ol.color.asArray(options.color) :
  7352. null;
  7353. /**
  7354. * @private
  7355. * @type {ol.style.IconImage}
  7356. */
  7357. this.iconImage_ = ol.style.IconImage.get(
  7358. image, /** @type {string} */ (src), imgSize, this.crossOrigin_, imageState, this.color_);
  7359. /**
  7360. * @private
  7361. * @type {Array.<number>}
  7362. */
  7363. this.offset_ = options.offset !== undefined ? options.offset : [0, 0];
  7364. /**
  7365. * @private
  7366. * @type {ol.style.IconOrigin}
  7367. */
  7368. this.offsetOrigin_ = options.offsetOrigin !== undefined ?
  7369. options.offsetOrigin : ol.style.IconOrigin.TOP_LEFT;
  7370. /**
  7371. * @private
  7372. * @type {Array.<number>}
  7373. */
  7374. this.origin_ = null;
  7375. /**
  7376. * @private
  7377. * @type {ol.Size}
  7378. */
  7379. this.size_ = options.size !== undefined ? options.size : null;
  7380. /**
  7381. * @type {number}
  7382. */
  7383. var opacity = options.opacity !== undefined ? options.opacity : 1;
  7384. /**
  7385. * @type {boolean}
  7386. */
  7387. var rotateWithView = options.rotateWithView !== undefined ?
  7388. options.rotateWithView : false;
  7389. /**
  7390. * @type {number}
  7391. */
  7392. var rotation = options.rotation !== undefined ? options.rotation : 0;
  7393. /**
  7394. * @type {number}
  7395. */
  7396. var scale = options.scale !== undefined ? options.scale : 1;
  7397. /**
  7398. * @type {boolean}
  7399. */
  7400. var snapToPixel = options.snapToPixel !== undefined ?
  7401. options.snapToPixel : true;
  7402. ol.style.Image.call(this, {
  7403. opacity: opacity,
  7404. rotation: rotation,
  7405. scale: scale,
  7406. snapToPixel: snapToPixel,
  7407. rotateWithView: rotateWithView
  7408. });
  7409. };
  7410. ol.inherits(ol.style.Icon, ol.style.Image);
  7411. /**
  7412. * Clones the style. The underlying Image/HTMLCanvasElement is not cloned.
  7413. * @return {ol.style.Icon} The cloned style.
  7414. * @api
  7415. */
  7416. ol.style.Icon.prototype.clone = function() {
  7417. return new ol.style.Icon({
  7418. anchor: this.anchor_.slice(),
  7419. anchorOrigin: this.anchorOrigin_,
  7420. anchorXUnits: this.anchorXUnits_,
  7421. anchorYUnits: this.anchorYUnits_,
  7422. crossOrigin: this.crossOrigin_,
  7423. color: (this.color_ && this.color_.slice) ? this.color_.slice() : this.color_ || undefined,
  7424. src: this.getSrc(),
  7425. offset: this.offset_.slice(),
  7426. offsetOrigin: this.offsetOrigin_,
  7427. size: this.size_ !== null ? this.size_.slice() : undefined,
  7428. opacity: this.getOpacity(),
  7429. scale: this.getScale(),
  7430. snapToPixel: this.getSnapToPixel(),
  7431. rotation: this.getRotation(),
  7432. rotateWithView: this.getRotateWithView()
  7433. });
  7434. };
  7435. /**
  7436. * @inheritDoc
  7437. * @api
  7438. */
  7439. ol.style.Icon.prototype.getAnchor = function() {
  7440. if (this.normalizedAnchor_) {
  7441. return this.normalizedAnchor_;
  7442. }
  7443. var anchor = this.anchor_;
  7444. var size = this.getSize();
  7445. if (this.anchorXUnits_ == ol.style.IconAnchorUnits.FRACTION ||
  7446. this.anchorYUnits_ == ol.style.IconAnchorUnits.FRACTION) {
  7447. if (!size) {
  7448. return null;
  7449. }
  7450. anchor = this.anchor_.slice();
  7451. if (this.anchorXUnits_ == ol.style.IconAnchorUnits.FRACTION) {
  7452. anchor[0] *= size[0];
  7453. }
  7454. if (this.anchorYUnits_ == ol.style.IconAnchorUnits.FRACTION) {
  7455. anchor[1] *= size[1];
  7456. }
  7457. }
  7458. if (this.anchorOrigin_ != ol.style.IconOrigin.TOP_LEFT) {
  7459. if (!size) {
  7460. return null;
  7461. }
  7462. if (anchor === this.anchor_) {
  7463. anchor = this.anchor_.slice();
  7464. }
  7465. if (this.anchorOrigin_ == ol.style.IconOrigin.TOP_RIGHT ||
  7466. this.anchorOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) {
  7467. anchor[0] = -anchor[0] + size[0];
  7468. }
  7469. if (this.anchorOrigin_ == ol.style.IconOrigin.BOTTOM_LEFT ||
  7470. this.anchorOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) {
  7471. anchor[1] = -anchor[1] + size[1];
  7472. }
  7473. }
  7474. this.normalizedAnchor_ = anchor;
  7475. return this.normalizedAnchor_;
  7476. };
  7477. /**
  7478. * Get the icon color.
  7479. * @return {ol.Color} Color.
  7480. * @api
  7481. */
  7482. ol.style.Icon.prototype.getColor = function() {
  7483. return this.color_;
  7484. };
  7485. /**
  7486. * Get the image icon.
  7487. * @param {number} pixelRatio Pixel ratio.
  7488. * @return {Image|HTMLCanvasElement} Image or Canvas element.
  7489. * @override
  7490. * @api
  7491. */
  7492. ol.style.Icon.prototype.getImage = function(pixelRatio) {
  7493. return this.iconImage_.getImage(pixelRatio);
  7494. };
  7495. /**
  7496. * @override
  7497. */
  7498. ol.style.Icon.prototype.getImageSize = function() {
  7499. return this.iconImage_.getSize();
  7500. };
  7501. /**
  7502. * @override
  7503. */
  7504. ol.style.Icon.prototype.getHitDetectionImageSize = function() {
  7505. return this.getImageSize();
  7506. };
  7507. /**
  7508. * @override
  7509. */
  7510. ol.style.Icon.prototype.getImageState = function() {
  7511. return this.iconImage_.getImageState();
  7512. };
  7513. /**
  7514. * @override
  7515. */
  7516. ol.style.Icon.prototype.getHitDetectionImage = function(pixelRatio) {
  7517. return this.iconImage_.getHitDetectionImage(pixelRatio);
  7518. };
  7519. /**
  7520. * @inheritDoc
  7521. * @api
  7522. */
  7523. ol.style.Icon.prototype.getOrigin = function() {
  7524. if (this.origin_) {
  7525. return this.origin_;
  7526. }
  7527. var offset = this.offset_;
  7528. if (this.offsetOrigin_ != ol.style.IconOrigin.TOP_LEFT) {
  7529. var size = this.getSize();
  7530. var iconImageSize = this.iconImage_.getSize();
  7531. if (!size || !iconImageSize) {
  7532. return null;
  7533. }
  7534. offset = offset.slice();
  7535. if (this.offsetOrigin_ == ol.style.IconOrigin.TOP_RIGHT ||
  7536. this.offsetOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) {
  7537. offset[0] = iconImageSize[0] - size[0] - offset[0];
  7538. }
  7539. if (this.offsetOrigin_ == ol.style.IconOrigin.BOTTOM_LEFT ||
  7540. this.offsetOrigin_ == ol.style.IconOrigin.BOTTOM_RIGHT) {
  7541. offset[1] = iconImageSize[1] - size[1] - offset[1];
  7542. }
  7543. }
  7544. this.origin_ = offset;
  7545. return this.origin_;
  7546. };
  7547. /**
  7548. * Get the image URL.
  7549. * @return {string|undefined} Image src.
  7550. * @api
  7551. */
  7552. ol.style.Icon.prototype.getSrc = function() {
  7553. return this.iconImage_.getSrc();
  7554. };
  7555. /**
  7556. * @inheritDoc
  7557. * @api
  7558. */
  7559. ol.style.Icon.prototype.getSize = function() {
  7560. return !this.size_ ? this.iconImage_.getSize() : this.size_;
  7561. };
  7562. /**
  7563. * @override
  7564. */
  7565. ol.style.Icon.prototype.listenImageChange = function(listener, thisArg) {
  7566. return ol.events.listen(this.iconImage_, ol.events.EventType.CHANGE,
  7567. listener, thisArg);
  7568. };
  7569. /**
  7570. * Load not yet loaded URI.
  7571. * When rendering a feature with an icon style, the vector renderer will
  7572. * automatically call this method. However, you might want to call this
  7573. * method yourself for preloading or other purposes.
  7574. * @override
  7575. * @api
  7576. */
  7577. ol.style.Icon.prototype.load = function() {
  7578. this.iconImage_.load();
  7579. };
  7580. /**
  7581. * @override
  7582. */
  7583. ol.style.Icon.prototype.unlistenImageChange = function(listener, thisArg) {
  7584. ol.events.unlisten(this.iconImage_, ol.events.EventType.CHANGE,
  7585. listener, thisArg);
  7586. };
  7587. ol.style.Text = function(opt_options) {
  7588. var options = opt_options || {};
  7589. this.font_ = options.font;
  7590. this.rotation_ = options.rotation;
  7591. this.rotateWithView_ = options.rotateWithView;
  7592. this.scale_ = options.scale;
  7593. this.text_ = options.text;
  7594. this.textAlign_ = options.textAlign;
  7595. this.textBaseline_ = options.textBaseline;
  7596. this.fill_ = options.fill !== undefined ? options.fill :
  7597. new ol.style.Fill({color: ol.style.Text.DEFAULT_FILL_COLOR_});
  7598. this.maxAngle_ = options.maxAngle !== undefined ? options.maxAngle : Math.PI / 4;
  7599. this.placement_ = options.placement !== undefined ? options.placement : ol.style.TextPlacement.POINT;
  7600. //TODO Use options.overflow directly after removing @deprecated exceedLength
  7601. var overflow = options.overflow === undefined ? options.exceedLength : options.overflow;
  7602. this.overflow_ = overflow !== undefined ? overflow : false;
  7603. this.stroke_ = options.stroke !== undefined ? options.stroke : null;
  7604. this.offsetX_ = options.offsetX !== undefined ? options.offsetX : 0;
  7605. this.offsetY_ = options.offsetY !== undefined ? options.offsetY : 0;
  7606. this.backgroundFill_ = options.backgroundFill ? options.backgroundFill : null;
  7607. this.backgroundStroke_ = options.backgroundStroke ? options.backgroundStroke : null;
  7608. this.padding_ = options.padding === undefined ? null : options.padding;
  7609. };
  7610. ol.style.Text.DEFAULT_FILL_COLOR_ = '#333';
  7611. ol.style.Text.prototype.clone = function() {
  7612. return new ol.style.Text({
  7613. font: this.getFont(),
  7614. placement: this.getPlacement(),
  7615. maxAngle: this.getMaxAngle(),
  7616. overflow: this.getOverflow(),
  7617. rotation: this.getRotation(),
  7618. rotateWithView: this.getRotateWithView(),
  7619. scale: this.getScale(),
  7620. text: this.getText(),
  7621. textAlign: this.getTextAlign(),
  7622. textBaseline: this.getTextBaseline(),
  7623. fill: this.getFill() ? this.getFill().clone() : undefined,
  7624. stroke: this.getStroke() ? this.getStroke().clone() : undefined,
  7625. offsetX: this.getOffsetX(),
  7626. offsetY: this.getOffsetY()
  7627. });
  7628. };
  7629. ol.style.Text.prototype.getOverflow = function() {
  7630. return this.overflow_;
  7631. };
  7632. ol.style.Text.prototype.getFont = function() {
  7633. return this.font_;
  7634. };
  7635. ol.style.Text.prototype.getMaxAngle = function() {
  7636. return this.maxAngle_;
  7637. };
  7638. ol.style.Text.prototype.getPlacement = function() {
  7639. return this.placement_;
  7640. };
  7641. ol.style.Text.prototype.getOffsetX = function() {
  7642. return this.offsetX_;
  7643. };
  7644. ol.style.Text.prototype.getOffsetY = function() {
  7645. return this.offsetY_;
  7646. };
  7647. ol.style.Text.prototype.getFill = function() {
  7648. return this.fill_;
  7649. };
  7650. ol.style.Text.prototype.getRotateWithView = function() {
  7651. return this.rotateWithView_;
  7652. };
  7653. ol.style.Text.prototype.getRotation = function() {
  7654. return this.rotation_;
  7655. };
  7656. ol.style.Text.prototype.getScale = function() {
  7657. return this.scale_;
  7658. };
  7659. ol.style.Text.prototype.getStroke = function() {
  7660. return this.stroke_;
  7661. };
  7662. ol.style.Text.prototype.getText = function() {
  7663. return this.text_;
  7664. };
  7665. ol.style.Text.prototype.getTextAlign = function() {
  7666. return this.textAlign_;
  7667. };
  7668. ol.style.Text.prototype.getTextBaseline = function() {
  7669. return this.textBaseline_;
  7670. };
  7671. ol.style.Text.prototype.getBackgroundFill = function() {
  7672. return this.backgroundFill_;
  7673. };
  7674. ol.style.Text.prototype.getBackgroundStroke = function() {
  7675. return this.backgroundStroke_;
  7676. };
  7677. ol.style.Text.prototype.getPadding = function() {
  7678. return this.padding_;
  7679. };
  7680. ol.style.Text.prototype.setOverflow = function(overflow) {
  7681. this.overflow_ = overflow;
  7682. };
  7683. ol.style.Text.prototype.setFont = function(font) {
  7684. this.font_ = font;
  7685. };
  7686. ol.style.Text.prototype.setMaxAngle = function(maxAngle) {
  7687. this.maxAngle_ = maxAngle;
  7688. };
  7689. ol.style.Text.prototype.setOffsetX = function(offsetX) {
  7690. this.offsetX_ = offsetX;
  7691. };
  7692. ol.style.Text.prototype.setOffsetY = function(offsetY) {
  7693. this.offsetY_ = offsetY;
  7694. };
  7695. ol.style.Text.prototype.setPlacement = function(placement) {
  7696. this.placement_ = placement;
  7697. };
  7698. ol.style.Text.prototype.setFill = function(fill) {
  7699. this.fill_ = fill;
  7700. };
  7701. ol.style.Text.prototype.setRotation = function(rotation) {
  7702. this.rotation_ = rotation;
  7703. };
  7704. ol.style.Text.prototype.setScale = function(scale) {
  7705. this.scale_ = scale;
  7706. };
  7707. ol.style.Text.prototype.setStroke = function(stroke) {
  7708. this.stroke_ = stroke;
  7709. };
  7710. ol.style.Text.prototype.setText = function(text) {
  7711. this.text_ = text;
  7712. };
  7713. ol.style.Text.prototype.setTextAlign = function(textAlign) {
  7714. this.textAlign_ = textAlign;
  7715. };
  7716. ol.style.Text.prototype.setTextBaseline = function(textBaseline) {
  7717. this.textBaseline_ = textBaseline;
  7718. };
  7719. ol.style.Text.prototype.setBackgroundFill = function(fill) {
  7720. this.backgroundFill_ = fill;
  7721. };
  7722. ol.style.Text.prototype.setBackgroundStroke = function(stroke) {
  7723. this.backgroundStroke_ = stroke;
  7724. };
  7725. ol.style.Text.prototype.setPadding = function(padding) {
  7726. this.padding_ = padding;
  7727. };
  7728. ol.style.Style = function(opt_options) {
  7729. var options = opt_options || {};
  7730. /**
  7731. * @private
  7732. * @type {string|ol.geom.Geometry|ol.StyleGeometryFunction}
  7733. */
  7734. this.geometry_ = null;
  7735. /**
  7736. * @private
  7737. * @type {!ol.StyleGeometryFunction}
  7738. */
  7739. this.geometryFunction_ = ol.style.Style.defaultGeometryFunction;
  7740. if (options.geometry !== undefined) {
  7741. this.setGeometry(options.geometry);
  7742. }
  7743. /**
  7744. * @private
  7745. * @type {ol.style.Fill}
  7746. */
  7747. this.fill_ = options.fill !== undefined ? options.fill : null;
  7748. /**
  7749. * @private
  7750. * @type {ol.style.Image}
  7751. */
  7752. this.image_ = options.image !== undefined ? options.image : null;
  7753. /**
  7754. * @private
  7755. * @type {ol.StyleRenderFunction|null}
  7756. */
  7757. this.renderer_ = options.renderer !== undefined ? options.renderer : null;
  7758. /**
  7759. * @private
  7760. * @type {ol.style.Stroke}
  7761. */
  7762. this.stroke_ = options.stroke !== undefined ? options.stroke : null;
  7763. /**
  7764. * @private
  7765. * @type {ol.style.Text}
  7766. */
  7767. this.text_ = options.text !== undefined ? options.text : null;
  7768. /**
  7769. * @private
  7770. * @type {number|undefined}
  7771. */
  7772. this.zIndex_ = options.zIndex;
  7773. };
  7774. /**
  7775. * Clones the style.
  7776. * @return {ol.style.Style} The cloned style.
  7777. * @api
  7778. */
  7779. ol.style.Style.prototype.clone = function() {
  7780. var geometry = this.getGeometry();
  7781. if (geometry && geometry.clone) {
  7782. geometry = geometry.clone();
  7783. }
  7784. return new ol.style.Style({
  7785. geometry: geometry,
  7786. fill: this.getFill() ? this.getFill().clone() : undefined,
  7787. image: this.getImage() ? this.getImage().clone() : undefined,
  7788. stroke: this.getStroke() ? this.getStroke().clone() : undefined,
  7789. text: this.getText() ? this.getText().clone() : undefined,
  7790. zIndex: this.getZIndex()
  7791. });
  7792. };
  7793. /**
  7794. * Get the custom renderer function that was configured with
  7795. * {@link #setRenderer} or the `renderer` constructor option.
  7796. * @return {ol.StyleRenderFunction|null} Custom renderer function.
  7797. * @api
  7798. */
  7799. ol.style.Style.prototype.getRenderer = function() {
  7800. return this.renderer_;
  7801. };
  7802. /**
  7803. * Sets a custom renderer function for this style. When set, `fill`, `stroke`
  7804. * and `image` options of the style will be ignored.
  7805. * @param {ol.StyleRenderFunction|null} renderer Custom renderer function.
  7806. * @api
  7807. */
  7808. ol.style.Style.prototype.setRenderer = function(renderer) {
  7809. this.renderer_ = renderer;
  7810. };
  7811. /**
  7812. * Get the geometry to be rendered.
  7813. * @return {string|ol.geom.Geometry|ol.StyleGeometryFunction}
  7814. * Feature property or geometry or function that returns the geometry that will
  7815. * be rendered with this style.
  7816. * @api
  7817. */
  7818. ol.style.Style.prototype.getGeometry = function() {
  7819. return this.geometry_;
  7820. };
  7821. /**
  7822. * Get the function used to generate a geometry for rendering.
  7823. * @return {!ol.StyleGeometryFunction} Function that is called with a feature
  7824. * and returns the geometry to render instead of the feature's geometry.
  7825. * @api
  7826. */
  7827. ol.style.Style.prototype.getGeometryFunction = function() {
  7828. return this.geometryFunction_;
  7829. };
  7830. /**
  7831. * Get the fill style.
  7832. * @return {ol.style.Fill} Fill style.
  7833. * @api
  7834. */
  7835. ol.style.Style.prototype.getFill = function() {
  7836. return this.fill_;
  7837. };
  7838. /**
  7839. * Set the fill style.
  7840. * @param {ol.style.Fill} fill Fill style.
  7841. * @api
  7842. */
  7843. ol.style.Style.prototype.setFill = function(fill) {
  7844. this.fill_ = fill;
  7845. };
  7846. /**
  7847. * Get the image style.
  7848. * @return {ol.style.Image} Image style.
  7849. * @api
  7850. */
  7851. ol.style.Style.prototype.getImage = function() {
  7852. return this.image_;
  7853. };
  7854. /**
  7855. * Set the image style.
  7856. * @param {ol.style.Image} image Image style.
  7857. * @api
  7858. */
  7859. ol.style.Style.prototype.setImage = function(image) {
  7860. this.image_ = image;
  7861. };
  7862. /**
  7863. * Get the stroke style.
  7864. * @return {ol.style.Stroke} Stroke style.
  7865. * @api
  7866. */
  7867. ol.style.Style.prototype.getStroke = function() {
  7868. return this.stroke_;
  7869. };
  7870. /**
  7871. * Set the stroke style.
  7872. * @param {ol.style.Stroke} stroke Stroke style.
  7873. * @api
  7874. */
  7875. ol.style.Style.prototype.setStroke = function(stroke) {
  7876. this.stroke_ = stroke;
  7877. };
  7878. /**
  7879. * Get the text style.
  7880. * @return {ol.style.Text} Text style.
  7881. * @api
  7882. */
  7883. ol.style.Style.prototype.getText = function() {
  7884. return this.text_;
  7885. };
  7886. /**
  7887. * Set the text style.
  7888. * @param {ol.style.Text} text Text style.
  7889. * @api
  7890. */
  7891. ol.style.Style.prototype.setText = function(text) {
  7892. this.text_ = text;
  7893. };
  7894. /**
  7895. * Get the z-index for the style.
  7896. * @return {number|undefined} ZIndex.
  7897. * @api
  7898. */
  7899. ol.style.Style.prototype.getZIndex = function() {
  7900. return this.zIndex_;
  7901. };
  7902. /**
  7903. * Set a geometry that is rendered instead of the feature's geometry.
  7904. *
  7905. * @param {string|ol.geom.Geometry|ol.StyleGeometryFunction} geometry
  7906. * Feature property or geometry or function returning a geometry to render
  7907. * for this style.
  7908. * @api
  7909. */
  7910. ol.style.Style.prototype.setGeometry = function(geometry) {
  7911. if (typeof geometry === 'function') {
  7912. this.geometryFunction_ = geometry;
  7913. } else if (typeof geometry === 'string') {
  7914. this.geometryFunction_ = function(feature) {
  7915. return /** @type {ol.geom.Geometry} */ (feature.get(geometry));
  7916. };
  7917. } else if (!geometry) {
  7918. this.geometryFunction_ = ol.style.Style.defaultGeometryFunction;
  7919. } else if (geometry !== undefined) {
  7920. this.geometryFunction_ = function() {
  7921. return /** @type {ol.geom.Geometry} */ (geometry);
  7922. };
  7923. }
  7924. this.geometry_ = geometry;
  7925. };
  7926. /**
  7927. * Set the z-index.
  7928. *
  7929. * @param {number|undefined} zIndex ZIndex.
  7930. * @api
  7931. */
  7932. ol.style.Style.prototype.setZIndex = function(zIndex) {
  7933. this.zIndex_ = zIndex;
  7934. };
  7935. /**
  7936. * Convert the provided object into a style function. Functions passed through
  7937. * unchanged. Arrays of ol.style.Style or single style objects wrapped in a
  7938. * new style function.
  7939. * @param {ol.StyleFunction|Array.<ol.style.Style>|ol.style.Style} obj
  7940. * A style function, a single style, or an array of styles.
  7941. * @return {ol.StyleFunction} A style function.
  7942. */
  7943. ol.style.Style.createFunction = function(obj) {
  7944. var styleFunction;
  7945. if (typeof obj === 'function') {
  7946. styleFunction = obj;
  7947. } else {
  7948. /**
  7949. * @type {Array.<ol.style.Style>}
  7950. */
  7951. var styles;
  7952. if (Array.isArray(obj)) {
  7953. styles = obj;
  7954. } else {
  7955. ol.asserts.assert(obj instanceof ol.style.Style,
  7956. 41); // Expected an `ol.style.Style` or an array of `ol.style.Style`
  7957. styles = [obj];
  7958. }
  7959. styleFunction = function() {
  7960. return styles;
  7961. };
  7962. }
  7963. return styleFunction;
  7964. };
  7965. /**
  7966. * @type {Array.<ol.style.Style>}
  7967. * @private
  7968. */
  7969. ol.style.Style.default_ = null;
  7970. /**
  7971. * @param {ol.Feature|ol.render.Feature} feature Feature.
  7972. * @param {number} resolution Resolution.
  7973. * @return {Array.<ol.style.Style>} Style.
  7974. */
  7975. ol.style.Style.defaultFunction = function(feature, resolution) {
  7976. // We don't use an immediately-invoked function
  7977. // and a closure so we don't get an error at script evaluation time in
  7978. // browsers that do not support Canvas. (ol.style.Circle does
  7979. // canvas.getContext('2d') at construction time, which will cause an.error
  7980. // in such browsers.)
  7981. if (!ol.style.Style.default_) {
  7982. var fill = new ol.style.Fill({
  7983. color: 'rgba(255,255,255,0.4)'
  7984. });
  7985. var stroke = new ol.style.Stroke({
  7986. color: '#3399CC',
  7987. width: 1.25
  7988. });
  7989. ol.style.Style.default_ = [
  7990. new ol.style.Style({
  7991. image: new ol.style.Circle({
  7992. fill: fill,
  7993. stroke: stroke,
  7994. radius: 5
  7995. }),
  7996. fill: fill,
  7997. stroke: stroke
  7998. })
  7999. ];
  8000. }
  8001. return ol.style.Style.default_;
  8002. };
  8003. /**
  8004. * Default styles for editing features.
  8005. * @return {Object.<ol.geom.GeometryType, Array.<ol.style.Style>>} Styles
  8006. */
  8007. ol.style.Style.createDefaultEditing = function() {
  8008. /** @type {Object.<ol.geom.GeometryType, Array.<ol.style.Style>>} */
  8009. var styles = {};
  8010. var white = [255, 255, 255, 1];
  8011. var blue = [0, 153, 255, 1];
  8012. var width = 3;
  8013. styles[ol.geom.GeometryType.POLYGON] = [
  8014. new ol.style.Style({
  8015. fill: new ol.style.Fill({
  8016. color: [255, 255, 255, 0.5]
  8017. })
  8018. })
  8019. ];
  8020. styles[ol.geom.GeometryType.MULTI_POLYGON] =
  8021. styles[ol.geom.GeometryType.POLYGON];
  8022. styles[ol.geom.GeometryType.LINE_STRING] = [
  8023. new ol.style.Style({
  8024. stroke: new ol.style.Stroke({
  8025. color: white,
  8026. width: width + 2
  8027. })
  8028. }),
  8029. new ol.style.Style({
  8030. stroke: new ol.style.Stroke({
  8031. color: blue,
  8032. width: width
  8033. })
  8034. })
  8035. ];
  8036. styles[ol.geom.GeometryType.MULTI_LINE_STRING] =
  8037. styles[ol.geom.GeometryType.LINE_STRING];
  8038. styles[ol.geom.GeometryType.CIRCLE] =
  8039. styles[ol.geom.GeometryType.POLYGON].concat(
  8040. styles[ol.geom.GeometryType.LINE_STRING]
  8041. );
  8042. styles[ol.geom.GeometryType.POINT] = [
  8043. new ol.style.Style({
  8044. image: new ol.style.Circle({
  8045. radius: width * 2,
  8046. fill: new ol.style.Fill({
  8047. color: blue
  8048. }),
  8049. stroke: new ol.style.Stroke({
  8050. color: white,
  8051. width: width / 2
  8052. })
  8053. }),
  8054. zIndex: Infinity
  8055. })
  8056. ];
  8057. styles[ol.geom.GeometryType.MULTI_POINT] =
  8058. styles[ol.geom.GeometryType.POINT];
  8059. styles[ol.geom.GeometryType.GEOMETRY_COLLECTION] =
  8060. styles[ol.geom.GeometryType.POLYGON].concat(
  8061. styles[ol.geom.GeometryType.LINE_STRING],
  8062. styles[ol.geom.GeometryType.POINT]
  8063. );
  8064. return styles;
  8065. };
  8066. /**
  8067. * Function that is called with a feature and returns its default geometry.
  8068. * @param {ol.Feature|ol.render.Feature} feature Feature to get the geometry
  8069. * for.
  8070. * @return {ol.geom.Geometry|ol.render.Feature|undefined} Geometry to render.
  8071. */
  8072. ol.style.Style.defaultGeometryFunction = function(feature) {
  8073. return feature.getGeometry();
  8074. };
  8075. ol.ext = {};
  8076. ol.ext.rbush = function() {};
  8077. (function() {(function (exports) {
  8078. var quickselect_1 = quickselect;
  8079. var default_1 = quickselect;
  8080. function quickselect(arr, k, left, right, compare) {
  8081. quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare);
  8082. }
  8083. function quickselectStep(arr, k, left, right, compare) {
  8084. while (right > left) {
  8085. if (right - left > 600) {
  8086. var n = right - left + 1;
  8087. var m = k - left + 1;
  8088. var z = Math.log(n);
  8089. var s = 0.5 * Math.exp(2 * z / 3);
  8090. var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
  8091. var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
  8092. var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
  8093. quickselectStep(arr, k, newLeft, newRight, compare);
  8094. }
  8095. var t = arr[k];
  8096. var i = left;
  8097. var j = right;
  8098. swap(arr, left, k);
  8099. if (compare(arr[right], t) > 0) swap(arr, left, right);
  8100. while (i < j) {
  8101. swap(arr, i, j);
  8102. i++;
  8103. j--;
  8104. while (compare(arr[i], t) < 0) i++;
  8105. while (compare(arr[j], t) > 0) j--;
  8106. }
  8107. if (compare(arr[left], t) === 0) swap(arr, left, j);
  8108. else {
  8109. j++;
  8110. swap(arr, j, right);
  8111. }
  8112. if (j <= k) left = j + 1;
  8113. if (k <= j) right = j - 1;
  8114. }
  8115. }
  8116. function swap(arr, i, j) {
  8117. var tmp = arr[i];
  8118. arr[i] = arr[j];
  8119. arr[j] = tmp;
  8120. }
  8121. function defaultCompare(a, b) {
  8122. return a < b ? -1 : a > b ? 1 : 0;
  8123. }
  8124. quickselect_1.default = default_1;
  8125. var rbush_1 = rbush;
  8126. function rbush(maxEntries, format) {
  8127. if (!(this instanceof rbush)) return new rbush(maxEntries, format);
  8128. this._maxEntries = Math.max(4, maxEntries || 9);
  8129. this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
  8130. if (format) {
  8131. this._initFormat(format);
  8132. }
  8133. this.clear();
  8134. }
  8135. rbush.prototype = {
  8136. all: function () {
  8137. return this._all(this.data, []);
  8138. },
  8139. search: function (bbox) {
  8140. var node = this.data,
  8141. result = [],
  8142. toBBox = this.toBBox;
  8143. if (!intersects(bbox, node)) return result;
  8144. var nodesToSearch = [],
  8145. i, len, child, childBBox;
  8146. while (node) {
  8147. for (i = 0, len = node.children.length; i < len; i++) {
  8148. child = node.children[i];
  8149. childBBox = node.leaf ? toBBox(child) : child;
  8150. if (intersects(bbox, childBBox)) {
  8151. if (node.leaf) result.push(child);
  8152. else if (contains(bbox, childBBox)) this._all(child, result);
  8153. else nodesToSearch.push(child);
  8154. }
  8155. }
  8156. node = nodesToSearch.pop();
  8157. }
  8158. return result;
  8159. },
  8160. collides: function (bbox) {
  8161. var node = this.data,
  8162. toBBox = this.toBBox;
  8163. if (!intersects(bbox, node)) return false;
  8164. var nodesToSearch = [],
  8165. i, len, child, childBBox;
  8166. while (node) {
  8167. for (i = 0, len = node.children.length; i < len; i++) {
  8168. child = node.children[i];
  8169. childBBox = node.leaf ? toBBox(child) : child;
  8170. if (intersects(bbox, childBBox)) {
  8171. if (node.leaf || contains(bbox, childBBox)) return true;
  8172. nodesToSearch.push(child);
  8173. }
  8174. }
  8175. node = nodesToSearch.pop();
  8176. }
  8177. return false;
  8178. },
  8179. load: function (data) {
  8180. if (!(data && data.length)) return this;
  8181. if (data.length < this._minEntries) {
  8182. for (var i = 0, len = data.length; i < len; i++) {
  8183. this.insert(data[i]);
  8184. }
  8185. return this;
  8186. }
  8187. var node = this._build(data.slice(), 0, data.length - 1, 0);
  8188. if (!this.data.children.length) {
  8189. this.data = node;
  8190. } else if (this.data.height === node.height) {
  8191. this._splitRoot(this.data, node);
  8192. } else {
  8193. if (this.data.height < node.height) {
  8194. var tmpNode = this.data;
  8195. this.data = node;
  8196. node = tmpNode;
  8197. }
  8198. this._insert(node, this.data.height - node.height - 1, true);
  8199. }
  8200. return this;
  8201. },
  8202. insert: function (item) {
  8203. if (item) this._insert(item, this.data.height - 1);
  8204. return this;
  8205. },
  8206. clear: function () {
  8207. this.data = createNode([]);
  8208. return this;
  8209. },
  8210. remove: function (item, equalsFn) {
  8211. if (!item) return this;
  8212. var node = this.data,
  8213. bbox = this.toBBox(item),
  8214. path = [],
  8215. indexes = [],
  8216. i, parent, index, goingUp;
  8217. while (node || path.length) {
  8218. if (!node) {
  8219. node = path.pop();
  8220. parent = path[path.length - 1];
  8221. i = indexes.pop();
  8222. goingUp = true;
  8223. }
  8224. if (node.leaf) {
  8225. index = findItem(item, node.children, equalsFn);
  8226. if (index !== -1) {
  8227. node.children.splice(index, 1);
  8228. path.push(node);
  8229. this._condense(path);
  8230. return this;
  8231. }
  8232. }
  8233. if (!goingUp && !node.leaf && contains(node, bbox)) {
  8234. path.push(node);
  8235. indexes.push(i);
  8236. i = 0;
  8237. parent = node;
  8238. node = node.children[0];
  8239. } else if (parent) {
  8240. i++;
  8241. node = parent.children[i];
  8242. goingUp = false;
  8243. } else node = null;
  8244. }
  8245. return this;
  8246. },
  8247. toBBox: function (item) { return item; },
  8248. compareMinX: compareNodeMinX,
  8249. compareMinY: compareNodeMinY,
  8250. toJSON: function () { return this.data; },
  8251. fromJSON: function (data) {
  8252. this.data = data;
  8253. return this;
  8254. },
  8255. _all: function (node, result) {
  8256. var nodesToSearch = [];
  8257. while (node) {
  8258. if (node.leaf) result.push.apply(result, node.children);
  8259. else nodesToSearch.push.apply(nodesToSearch, node.children);
  8260. node = nodesToSearch.pop();
  8261. }
  8262. return result;
  8263. },
  8264. _build: function (items, left, right, height) {
  8265. var N = right - left + 1,
  8266. M = this._maxEntries,
  8267. node;
  8268. if (N <= M) {
  8269. node = createNode(items.slice(left, right + 1));
  8270. calcBBox(node, this.toBBox);
  8271. return node;
  8272. }
  8273. if (!height) {
  8274. height = Math.ceil(Math.log(N) / Math.log(M));
  8275. M = Math.ceil(N / Math.pow(M, height - 1));
  8276. }
  8277. node = createNode([]);
  8278. node.leaf = false;
  8279. node.height = height;
  8280. var N2 = Math.ceil(N / M),
  8281. N1 = N2 * Math.ceil(Math.sqrt(M)),
  8282. i, j, right2, right3;
  8283. multiSelect(items, left, right, N1, this.compareMinX);
  8284. for (i = left; i <= right; i += N1) {
  8285. right2 = Math.min(i + N1 - 1, right);
  8286. multiSelect(items, i, right2, N2, this.compareMinY);
  8287. for (j = i; j <= right2; j += N2) {
  8288. right3 = Math.min(j + N2 - 1, right2);
  8289. node.children.push(this._build(items, j, right3, height - 1));
  8290. }
  8291. }
  8292. calcBBox(node, this.toBBox);
  8293. return node;
  8294. },
  8295. _chooseSubtree: function (bbox, node, level, path) {
  8296. var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
  8297. while (true) {
  8298. path.push(node);
  8299. if (node.leaf || path.length - 1 === level) break;
  8300. minArea = minEnlargement = Infinity;
  8301. for (i = 0, len = node.children.length; i < len; i++) {
  8302. child = node.children[i];
  8303. area = bboxArea(child);
  8304. enlargement = enlargedArea(bbox, child) - area;
  8305. if (enlargement < minEnlargement) {
  8306. minEnlargement = enlargement;
  8307. minArea = area < minArea ? area : minArea;
  8308. targetNode = child;
  8309. } else if (enlargement === minEnlargement) {
  8310. if (area < minArea) {
  8311. minArea = area;
  8312. targetNode = child;
  8313. }
  8314. }
  8315. }
  8316. node = targetNode || node.children[0];
  8317. }
  8318. return node;
  8319. },
  8320. _insert: function (item, level, isNode) {
  8321. var toBBox = this.toBBox,
  8322. bbox = isNode ? item : toBBox(item),
  8323. insertPath = [];
  8324. var node = this._chooseSubtree(bbox, this.data, level, insertPath);
  8325. node.children.push(item);
  8326. extend(node, bbox);
  8327. while (level >= 0) {
  8328. if (insertPath[level].children.length > this._maxEntries) {
  8329. this._split(insertPath, level);
  8330. level--;
  8331. } else break;
  8332. }
  8333. this._adjustParentBBoxes(bbox, insertPath, level);
  8334. },
  8335. _split: function (insertPath, level) {
  8336. var node = insertPath[level],
  8337. M = node.children.length,
  8338. m = this._minEntries;
  8339. this._chooseSplitAxis(node, m, M);
  8340. var splitIndex = this._chooseSplitIndex(node, m, M);
  8341. var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
  8342. newNode.height = node.height;
  8343. newNode.leaf = node.leaf;
  8344. calcBBox(node, this.toBBox);
  8345. calcBBox(newNode, this.toBBox);
  8346. if (level) insertPath[level - 1].children.push(newNode);
  8347. else this._splitRoot(node, newNode);
  8348. },
  8349. _splitRoot: function (node, newNode) {
  8350. this.data = createNode([node, newNode]);
  8351. this.data.height = node.height + 1;
  8352. this.data.leaf = false;
  8353. calcBBox(this.data, this.toBBox);
  8354. },
  8355. _chooseSplitIndex: function (node, m, M) {
  8356. var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
  8357. minOverlap = minArea = Infinity;
  8358. for (i = m; i <= M - m; i++) {
  8359. bbox1 = distBBox(node, 0, i, this.toBBox);
  8360. bbox2 = distBBox(node, i, M, this.toBBox);
  8361. overlap = intersectionArea(bbox1, bbox2);
  8362. area = bboxArea(bbox1) + bboxArea(bbox2);
  8363. if (overlap < minOverlap) {
  8364. minOverlap = overlap;
  8365. index = i;
  8366. minArea = area < minArea ? area : minArea;
  8367. } else if (overlap === minOverlap) {
  8368. if (area < minArea) {
  8369. minArea = area;
  8370. index = i;
  8371. }
  8372. }
  8373. }
  8374. return index;
  8375. },
  8376. _chooseSplitAxis: function (node, m, M) {
  8377. var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
  8378. compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
  8379. xMargin = this._allDistMargin(node, m, M, compareMinX),
  8380. yMargin = this._allDistMargin(node, m, M, compareMinY);
  8381. if (xMargin < yMargin) node.children.sort(compareMinX);
  8382. },
  8383. _allDistMargin: function (node, m, M, compare) {
  8384. node.children.sort(compare);
  8385. var toBBox = this.toBBox,
  8386. leftBBox = distBBox(node, 0, m, toBBox),
  8387. rightBBox = distBBox(node, M - m, M, toBBox),
  8388. margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
  8389. i, child;
  8390. for (i = m; i < M - m; i++) {
  8391. child = node.children[i];
  8392. extend(leftBBox, node.leaf ? toBBox(child) : child);
  8393. margin += bboxMargin(leftBBox);
  8394. }
  8395. for (i = M - m - 1; i >= m; i--) {
  8396. child = node.children[i];
  8397. extend(rightBBox, node.leaf ? toBBox(child) : child);
  8398. margin += bboxMargin(rightBBox);
  8399. }
  8400. return margin;
  8401. },
  8402. _adjustParentBBoxes: function (bbox, path, level) {
  8403. for (var i = level; i >= 0; i--) {
  8404. extend(path[i], bbox);
  8405. }
  8406. },
  8407. _condense: function (path) {
  8408. for (var i = path.length - 1, siblings; i >= 0; i--) {
  8409. if (path[i].children.length === 0) {
  8410. if (i > 0) {
  8411. siblings = path[i - 1].children;
  8412. siblings.splice(siblings.indexOf(path[i]), 1);
  8413. } else this.clear();
  8414. } else calcBBox(path[i], this.toBBox);
  8415. }
  8416. },
  8417. _initFormat: function (format) {
  8418. var compareArr = ['return a', ' - b', ';'];
  8419. this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
  8420. this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
  8421. this.toBBox = new Function('a',
  8422. 'return {minX: a' + format[0] +
  8423. ', minY: a' + format[1] +
  8424. ', maxX: a' + format[2] +
  8425. ', maxY: a' + format[3] + '};');
  8426. }
  8427. };
  8428. function findItem(item, items, equalsFn) {
  8429. if (!equalsFn) return items.indexOf(item);
  8430. for (var i = 0; i < items.length; i++) {
  8431. if (equalsFn(item, items[i])) return i;
  8432. }
  8433. return -1;
  8434. }
  8435. function calcBBox(node, toBBox) {
  8436. distBBox(node, 0, node.children.length, toBBox, node);
  8437. }
  8438. function distBBox(node, k, p, toBBox, destNode) {
  8439. if (!destNode) destNode = createNode(null);
  8440. destNode.minX = Infinity;
  8441. destNode.minY = Infinity;
  8442. destNode.maxX = -Infinity;
  8443. destNode.maxY = -Infinity;
  8444. for (var i = k, child; i < p; i++) {
  8445. child = node.children[i];
  8446. extend(destNode, node.leaf ? toBBox(child) : child);
  8447. }
  8448. return destNode;
  8449. }
  8450. function extend(a, b) {
  8451. a.minX = Math.min(a.minX, b.minX);
  8452. a.minY = Math.min(a.minY, b.minY);
  8453. a.maxX = Math.max(a.maxX, b.maxX);
  8454. a.maxY = Math.max(a.maxY, b.maxY);
  8455. return a;
  8456. }
  8457. function compareNodeMinX(a, b) { return a.minX - b.minX; }
  8458. function compareNodeMinY(a, b) { return a.minY - b.minY; }
  8459. function bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }
  8460. function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
  8461. function enlargedArea(a, b) {
  8462. return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
  8463. (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
  8464. }
  8465. function intersectionArea(a, b) {
  8466. var minX = Math.max(a.minX, b.minX),
  8467. minY = Math.max(a.minY, b.minY),
  8468. maxX = Math.min(a.maxX, b.maxX),
  8469. maxY = Math.min(a.maxY, b.maxY);
  8470. return Math.max(0, maxX - minX) *
  8471. Math.max(0, maxY - minY);
  8472. }
  8473. function contains(a, b) {
  8474. return a.minX <= b.minX &&
  8475. a.minY <= b.minY &&
  8476. b.maxX <= a.maxX &&
  8477. b.maxY <= a.maxY;
  8478. }
  8479. function intersects(a, b) {
  8480. return b.minX <= a.maxX &&
  8481. b.minY <= a.maxY &&
  8482. b.maxX >= a.minX &&
  8483. b.maxY >= a.minY;
  8484. }
  8485. function createNode(children) {
  8486. return {
  8487. children: children,
  8488. height: 1,
  8489. leaf: true,
  8490. minX: Infinity,
  8491. minY: Infinity,
  8492. maxX: -Infinity,
  8493. maxY: -Infinity
  8494. };
  8495. }
  8496. function multiSelect(arr, left, right, n, compare) {
  8497. var stack = [left, right],
  8498. mid;
  8499. while (stack.length) {
  8500. right = stack.pop();
  8501. left = stack.pop();
  8502. if (right - left <= n) continue;
  8503. mid = left + Math.ceil((right - left) / n / 2) * n;
  8504. quickselect_1(arr, mid, left, right, compare);
  8505. stack.push(left, mid, mid, right);
  8506. }
  8507. }
  8508. exports['default'] = rbush_1;
  8509. }((this.rbush = this.rbush || {})));}).call(ol.ext);
  8510. ol.ext.rbush = ol.ext.rbush.default;
  8511. ol.render = {};
  8512. /**
  8513. * Context for drawing geometries. A vector context is available on render
  8514. * events and does not need to be constructed directly.
  8515. * @constructor
  8516. * @abstract
  8517. * @struct
  8518. * @api
  8519. */
  8520. ol.render.VectorContext = function() {
  8521. };
  8522. ol.render.VectorContext.prototype.drawCustom = function(geometry, feature, renderer) {};
  8523. ol.render.VectorContext.prototype.drawGeometry = function(geometry) {};
  8524. ol.render.VectorContext.prototype.setStyle = function(style) {};
  8525. ol.render.VectorContext.prototype.drawCircle = function(circleGeometry, feature) {};
  8526. ol.render.VectorContext.prototype.drawFeature = function(feature, style) {};
  8527. ol.render.VectorContext.prototype.drawGeometryCollection = function(geometryCollectionGeometry, feature) {};
  8528. ol.render.VectorContext.prototype.drawLineString = function(lineStringGeometry, feature) {};
  8529. ol.render.VectorContext.prototype.drawMultiLineString = function(multiLineStringGeometry, feature) {};
  8530. ol.render.VectorContext.prototype.drawMultiPoint = function(multiPointGeometry, feature) {};
  8531. ol.render.VectorContext.prototype.drawMultiPolygon = function(multiPolygonGeometry, feature) {};
  8532. ol.render.VectorContext.prototype.drawPoint = function(pointGeometry, feature) {};
  8533. ol.render.VectorContext.prototype.drawPolygon = function(polygonGeometry, feature) {};
  8534. ol.render.VectorContext.prototype.drawText = function(geometry, feature) {};
  8535. ol.render.VectorContext.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {};
  8536. ol.render.VectorContext.prototype.setImageStyle = function(imageStyle, opt_declutterGroup) {};
  8537. ol.render.VectorContext.prototype.setTextStyle = function(textStyle, opt_declutterGroup) {};
  8538. ol.render.ReplayGroup = {};
  8539. ol.render.ReplayGroup = function() {};
  8540. ol.render.ReplayGroup.prototype.getReplay = function(zIndex, replayType) {};
  8541. ol.render.ReplayGroup.prototype.isEmpty = function() {};
  8542. ol.render.ReplayType = {
  8543. CIRCLE: 'Circle',
  8544. DEFAULT: 'Default',
  8545. IMAGE: 'Image',
  8546. LINE_STRING: 'LineString',
  8547. POLYGON: 'Polygon',
  8548. TEXT: 'Text'
  8549. };
  8550. ol.geom.flat.length = {};
  8551. ol.geom.flat.length.lineString = function(flatCoordinates, offset, end, stride) {
  8552. var x1 = flatCoordinates[offset];
  8553. var y1 = flatCoordinates[offset + 1];
  8554. var length = 0;
  8555. var i;
  8556. for (i = offset + stride; i < end; i += stride) {
  8557. var x2 = flatCoordinates[i];
  8558. var y2 = flatCoordinates[i + 1];
  8559. length += Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
  8560. x1 = x2;
  8561. y1 = y2;
  8562. }
  8563. return length;
  8564. };
  8565. ol.geom.flat.length.linearRing = function(flatCoordinates, offset, end, stride) {
  8566. var perimeter =
  8567. ol.geom.flat.length.lineString(flatCoordinates, offset, end, stride);
  8568. var dx = flatCoordinates[end - stride] - flatCoordinates[offset];
  8569. var dy = flatCoordinates[end - stride + 1] - flatCoordinates[offset + 1];
  8570. perimeter += Math.sqrt(dx * dx + dy * dy);
  8571. return perimeter;
  8572. };
  8573. ol.geom.flat.textpath = {};
  8574. ol.geom.flat.textpath.lineString = function(
  8575. flatCoordinates, offset, end, stride, text, measure, startM, maxAngle) {
  8576. var result = [];
  8577. // Keep text upright
  8578. var reverse = flatCoordinates[offset] > flatCoordinates[end - stride];
  8579. var numChars = text.length;
  8580. var x1 = flatCoordinates[offset];
  8581. var y1 = flatCoordinates[offset + 1];
  8582. offset += stride;
  8583. var x2 = flatCoordinates[offset];
  8584. var y2 = flatCoordinates[offset + 1];
  8585. var segmentM = 0;
  8586. var segmentLength = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
  8587. var chunk = '';
  8588. var chunkLength = 0;
  8589. var data, index, previousAngle;
  8590. for (var i = 0; i < numChars; ++i) {
  8591. index = reverse ? numChars - i - 1 : i;
  8592. var char = text.charAt(index);
  8593. chunk = reverse ? char + chunk : chunk + char;
  8594. var charLength = measure(chunk) - chunkLength;
  8595. chunkLength += charLength;
  8596. var charM = startM + charLength / 2;
  8597. while (offset < end - stride && segmentM + segmentLength < charM) {
  8598. x1 = x2;
  8599. y1 = y2;
  8600. offset += stride;
  8601. x2 = flatCoordinates[offset];
  8602. y2 = flatCoordinates[offset + 1];
  8603. segmentM += segmentLength;
  8604. segmentLength = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
  8605. }
  8606. var segmentPos = charM - segmentM;
  8607. var angle = Math.atan2(y2 - y1, x2 - x1);
  8608. if (reverse) {
  8609. angle += angle > 0 ? -Math.PI : Math.PI;
  8610. }
  8611. if (previousAngle !== undefined) {
  8612. var delta = angle - previousAngle;
  8613. delta += (delta > Math.PI) ? -2 * Math.PI : (delta < -Math.PI) ? 2 * Math.PI : 0;
  8614. if (Math.abs(delta) > maxAngle) {
  8615. return null;
  8616. }
  8617. }
  8618. var interpolate = segmentPos / segmentLength;
  8619. var x = ol.math.lerp(x1, x2, interpolate);
  8620. var y = ol.math.lerp(y1, y2, interpolate);
  8621. if (previousAngle == angle) {
  8622. if (reverse) {
  8623. data[0] = x;
  8624. data[1] = y;
  8625. data[2] = charLength / 2;
  8626. }
  8627. data[4] = chunk;
  8628. } else {
  8629. chunk = char;
  8630. chunkLength = charLength;
  8631. data = [x, y, charLength / 2, angle, chunk];
  8632. if (reverse) {
  8633. result.unshift(data);
  8634. } else {
  8635. result.push(data);
  8636. }
  8637. previousAngle = angle;
  8638. }
  8639. startM += charLength;
  8640. }
  8641. return result;
  8642. };
  8643. ol.structs.LRUCache = function(opt_highWaterMark) {
  8644. ol.events.EventTarget.call(this);
  8645. this.highWaterMark = opt_highWaterMark !== undefined ? opt_highWaterMark : 2048;
  8646. this.count_ = 0;
  8647. this.entries_ = {};
  8648. this.oldest_ = null;
  8649. this.newest_ = null;
  8650. };
  8651. ol.inherits(ol.structs.LRUCache, ol.events.EventTarget);
  8652. ol.structs.LRUCache.prototype.canExpireCache = function() {
  8653. return this.getCount() > this.highWaterMark;
  8654. };
  8655. ol.structs.LRUCache.prototype.clear = function() {
  8656. this.count_ = 0;
  8657. this.entries_ = {};
  8658. this.oldest_ = null;
  8659. this.newest_ = null;
  8660. this.dispatchEvent(ol.events.EventType.CLEAR);
  8661. };
  8662. ol.structs.LRUCache.prototype.containsKey = function(key) {
  8663. return this.entries_.hasOwnProperty(key);
  8664. };
  8665. ol.structs.LRUCache.prototype.forEach = function(f, opt_this) {
  8666. var entry = this.oldest_;
  8667. while (entry) {
  8668. f.call(opt_this, entry.value_, entry.key_, this);
  8669. entry = entry.newer;
  8670. }
  8671. };
  8672. ol.structs.LRUCache.prototype.get = function(key) {
  8673. var entry = this.entries_[key];
  8674. ol.asserts.assert(entry !== undefined,
  8675. 15); // Tried to get a value for a key that does not exist in the cache
  8676. if (entry === this.newest_) {
  8677. return entry.value_;
  8678. } else if (entry === this.oldest_) {
  8679. this.oldest_ = /** @type {ol.LRUCacheEntry} */ (this.oldest_.newer);
  8680. this.oldest_.older = null;
  8681. } else {
  8682. entry.newer.older = entry.older;
  8683. entry.older.newer = entry.newer;
  8684. }
  8685. entry.newer = null;
  8686. entry.older = this.newest_;
  8687. this.newest_.newer = entry;
  8688. this.newest_ = entry;
  8689. return entry.value_;
  8690. };
  8691. ol.structs.LRUCache.prototype.remove = function(key) {
  8692. var entry = this.entries_[key];
  8693. ol.asserts.assert(entry !== undefined, 15); // Tried to get a value for a key that does not exist in the cache
  8694. if (entry === this.newest_) {
  8695. this.newest_ = /** @type {ol.LRUCacheEntry} */ (entry.older);
  8696. if (this.newest_) {
  8697. this.newest_.newer = null;
  8698. }
  8699. } else if (entry === this.oldest_) {
  8700. this.oldest_ = /** @type {ol.LRUCacheEntry} */ (entry.newer);
  8701. if (this.oldest_) {
  8702. this.oldest_.older = null;
  8703. }
  8704. } else {
  8705. entry.newer.older = entry.older;
  8706. entry.older.newer = entry.newer;
  8707. }
  8708. delete this.entries_[key];
  8709. --this.count_;
  8710. return entry.value_;
  8711. };
  8712. ol.structs.LRUCache.prototype.getCount = function() {
  8713. return this.count_;
  8714. };
  8715. ol.structs.LRUCache.prototype.getKeys = function() {
  8716. var keys = new Array(this.count_);
  8717. var i = 0;
  8718. var entry;
  8719. for (entry = this.newest_; entry; entry = entry.older) {
  8720. keys[i++] = entry.key_;
  8721. }
  8722. return keys;
  8723. };
  8724. ol.structs.LRUCache.prototype.getValues = function() {
  8725. var values = new Array(this.count_);
  8726. var i = 0;
  8727. var entry;
  8728. for (entry = this.newest_; entry; entry = entry.older) {
  8729. values[i++] = entry.value_;
  8730. }
  8731. return values;
  8732. };
  8733. ol.structs.LRUCache.prototype.peekLast = function() {
  8734. return this.oldest_.value_;
  8735. };
  8736. ol.structs.LRUCache.prototype.peekLastKey = function() {
  8737. return this.oldest_.key_;
  8738. };
  8739. ol.structs.LRUCache.prototype.peekFirstKey = function() {
  8740. return this.newest_.key_;
  8741. };
  8742. ol.structs.LRUCache.prototype.pop = function() {
  8743. var entry = this.oldest_;
  8744. delete this.entries_[entry.key_];
  8745. if (entry.newer) {
  8746. entry.newer.older = null;
  8747. }
  8748. this.oldest_ = /** @type {ol.LRUCacheEntry} */ (entry.newer);
  8749. if (!this.oldest_) {
  8750. this.newest_ = null;
  8751. }
  8752. --this.count_;
  8753. return entry.value_;
  8754. };
  8755. ol.structs.LRUCache.prototype.replace = function(key, value) {
  8756. this.get(key); // update `newest_`
  8757. this.entries_[key].value_ = value;
  8758. };
  8759. ol.structs.LRUCache.prototype.set = function(key, value) {
  8760. ol.asserts.assert(!(key in this.entries_),
  8761. 16); // Tried to set a value for a key that is used already
  8762. var entry = /** @type {ol.LRUCacheEntry} */ ({
  8763. key_: key,
  8764. newer: null,
  8765. older: this.newest_,
  8766. value_: value
  8767. });
  8768. if (!this.newest_) {
  8769. this.oldest_ = entry;
  8770. } else {
  8771. this.newest_.newer = entry;
  8772. }
  8773. this.newest_ = entry;
  8774. this.entries_[key] = entry;
  8775. ++this.count_;
  8776. };
  8777. ol.structs.LRUCache.prototype.prune = function() {
  8778. while (this.canExpireCache()) {
  8779. this.pop();
  8780. }
  8781. };
  8782. ol.render.canvas = {};
  8783. ol.render.canvas.defaultFont = '10px sans-serif';
  8784. ol.render.canvas.defaultFillStyle = [0, 0, 0, 1];
  8785. ol.render.canvas.defaultLineCap = 'round';
  8786. ol.render.canvas.defaultLineDash = [];
  8787. ol.render.canvas.defaultLineDashOffset = 0;
  8788. ol.render.canvas.defaultLineJoin = 'round';
  8789. ol.render.canvas.defaultMiterLimit = 10;
  8790. ol.render.canvas.defaultStrokeStyle = [0, 0, 0, 1];
  8791. ol.render.canvas.defaultTextAlign = 'center';
  8792. ol.render.canvas.defaultTextBaseline = 'middle';
  8793. ol.render.canvas.defaultPadding = [0, 0, 0, 0];
  8794. ol.render.canvas.defaultLineWidth = 1;
  8795. ol.render.canvas.labelCache = new ol.structs.LRUCache();
  8796. ol.render.canvas.checkedFonts_ = {};
  8797. ol.render.canvas.measureContext_ = null;
  8798. ol.render.canvas.textHeights_ = {};
  8799. /**
  8800. * Clears the label cache when a font becomes available.
  8801. * @param {string} fontSpec CSS font spec.
  8802. */
  8803. ol.render.canvas.checkFont = (function() {
  8804. var retries = 60;
  8805. var checked = ol.render.canvas.checkedFonts_;
  8806. var labelCache = ol.render.canvas.labelCache;
  8807. var font = '32px monospace';
  8808. var text = 'wmytzilWMYTZIL@#/&?$%10';
  8809. var interval, referenceWidth;
  8810. function isAvailable(fontFamily) {
  8811. var context = ol.render.canvas.getMeasureContext();
  8812. context.font = font;
  8813. referenceWidth = context.measureText(text).width;
  8814. var available = true;
  8815. if (fontFamily != 'monospace') {
  8816. context.font = '32px ' + fontFamily + ',monospace';
  8817. var width = context.measureText(text).width;
  8818. // If width and referenceWidth are the same, then the 'monospace'
  8819. // fallback was used instead of the font we wanted, so the font is not
  8820. // available.
  8821. available = width != referenceWidth;
  8822. }
  8823. return available;
  8824. }
  8825. function check() {
  8826. var done = true;
  8827. for (var font in checked) {
  8828. if (checked[font] < retries) {
  8829. if (isAvailable(font)) {
  8830. checked[font] = retries;
  8831. ol.obj.clear(ol.render.canvas.textHeights_);
  8832. // Make sure that loaded fonts are picked up by Safari
  8833. ol.render.canvas.measureContext_ = null;
  8834. labelCache.clear();
  8835. } else {
  8836. ++checked[font];
  8837. done = false;
  8838. }
  8839. }
  8840. }
  8841. if (done) {
  8842. window.clearInterval(interval);
  8843. interval = undefined;
  8844. }
  8845. }
  8846. return function(fontSpec) {
  8847. var fontFamilies = ol.css.getFontFamilies(fontSpec);
  8848. if (!fontFamilies) {
  8849. return;
  8850. }
  8851. for (var i = 0, ii = fontFamilies.length; i < ii; ++i) {
  8852. var fontFamily = fontFamilies[i];
  8853. if (!(fontFamily in checked)) {
  8854. checked[fontFamily] = retries;
  8855. if (!isAvailable(fontFamily)) {
  8856. checked[fontFamily] = 0;
  8857. if (interval === undefined) {
  8858. interval = window.setInterval(check, 32);
  8859. }
  8860. }
  8861. }
  8862. }
  8863. };
  8864. })();
  8865. /**
  8866. * @return {CanvasRenderingContext2D} Measure context.
  8867. */
  8868. ol.render.canvas.getMeasureContext = function() {
  8869. var context = ol.render.canvas.measureContext_;
  8870. if (!context) {
  8871. context = ol.render.canvas.measureContext_ = ol.dom.createCanvasContext2D(1, 1);
  8872. }
  8873. return context;
  8874. };
  8875. /**
  8876. * @param {string} font Font to use for measuring.
  8877. * @return {ol.Size} Measurement.
  8878. */
  8879. ol.render.canvas.measureTextHeight = (function() {
  8880. var heights = ol.render.canvas.textHeights_;
  8881. return function(font) {
  8882. var height = heights[font];
  8883. if (height == undefined) {
  8884. // if (!span) {
  8885. // span = document.createElement('span');
  8886. // span.textContent = 'M';
  8887. // span.style.margin = span.style.padding = '0 !important';
  8888. // span.style.position = 'absolute !important';
  8889. // span.style.left = '-99999px !important';
  8890. // }
  8891. // span.style.font = font;
  8892. // document.body.appendChild(span);
  8893. // height = heights[font] = span.offsetHeight;
  8894. // document.body.removeChild(span);
  8895. height = heights[font] = 19; // FIXME sunyl
  8896. }
  8897. return height;
  8898. };
  8899. })();
  8900. /**
  8901. * @param {string} font Font.
  8902. * @param {string} text Text.
  8903. * @return {number} Width.
  8904. */
  8905. ol.render.canvas.measureTextWidth = function(font, text) {
  8906. var measureContext = ol.render.canvas.getMeasureContext();
  8907. if (font != measureContext.font) {
  8908. measureContext.font = font;
  8909. }
  8910. return measureContext.measureText(text).width;
  8911. };
  8912. /**
  8913. * @param {CanvasRenderingContext2D} context Context.
  8914. * @param {number} rotation Rotation.
  8915. * @param {number} offsetX X offset.
  8916. * @param {number} offsetY Y offset.
  8917. */
  8918. ol.render.canvas.rotateAtOffset = function(context, rotation, offsetX, offsetY) {
  8919. if (rotation !== 0) {
  8920. context.translate(offsetX, offsetY);
  8921. context.rotate(rotation);
  8922. context.translate(-offsetX, -offsetY);
  8923. }
  8924. };
  8925. ol.render.canvas.resetTransform_ = ol.transform.create();
  8926. /**
  8927. * @param {CanvasRenderingContext2D} context Context.
  8928. * @param {ol.Transform|null} transform Transform.
  8929. * @param {number} opacity Opacity.
  8930. * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} image Image.
  8931. * @param {number} originX Origin X.
  8932. * @param {number} originY Origin Y.
  8933. * @param {number} w Width.
  8934. * @param {number} h Height.
  8935. * @param {number} x X.
  8936. * @param {number} y Y.
  8937. * @param {number} scale Scale.
  8938. */
  8939. ol.render.canvas.drawImage = function(context,
  8940. transform, opacity, image, originX, originY, w, h, x, y, scale) {
  8941. var alpha;
  8942. if (opacity != 1) {
  8943. alpha = context.globalAlpha;
  8944. context.globalAlpha = alpha * opacity;
  8945. }
  8946. if (transform) {
  8947. context.setTransform.apply(context, transform);
  8948. }
  8949. context.drawImage(image, originX, originY, w, h, x, y, w * scale, h * scale);
  8950. if (alpha) {
  8951. context.globalAlpha = alpha;
  8952. }
  8953. if (transform) {
  8954. context.setTransform.apply(context, ol.render.canvas.resetTransform_);
  8955. }
  8956. };
  8957. /**
  8958. * @enum {number}
  8959. */
  8960. ol.render.canvas.Instruction = {
  8961. BEGIN_GEOMETRY: 0,
  8962. BEGIN_PATH: 1,
  8963. CIRCLE: 2,
  8964. CLOSE_PATH: 3,
  8965. CUSTOM: 4,
  8966. DRAW_CHARS: 5,
  8967. DRAW_IMAGE: 6,
  8968. END_GEOMETRY: 7,
  8969. FILL: 8,
  8970. MOVE_TO_LINE_TO: 9,
  8971. SET_FILL_STYLE: 10,
  8972. SET_STROKE_STYLE: 11,
  8973. STROKE: 12
  8974. };
  8975. ol.render.replay = {};
  8976. ol.render.replay.ORDER = [
  8977. ol.render.ReplayType.POLYGON,
  8978. ol.render.ReplayType.CIRCLE,
  8979. ol.render.ReplayType.LINE_STRING,
  8980. ol.render.ReplayType.IMAGE,
  8981. ol.render.ReplayType.TEXT,
  8982. ol.render.ReplayType.DEFAULT
  8983. ];
  8984. ol.render.replay.TEXT_ALIGN = {};
  8985. ol.render.replay.TEXT_ALIGN['left'] = 0;
  8986. ol.render.replay.TEXT_ALIGN['end'] = 0;
  8987. ol.render.replay.TEXT_ALIGN['center'] = 0.5;
  8988. ol.render.replay.TEXT_ALIGN['right'] = 1;
  8989. ol.render.replay.TEXT_ALIGN['start'] = 1;
  8990. ol.render.replay.TEXT_ALIGN['top'] = 0;
  8991. ol.render.replay.TEXT_ALIGN['middle'] = 0.5;
  8992. ol.render.replay.TEXT_ALIGN['hanging'] = 0.2;
  8993. ol.render.replay.TEXT_ALIGN['alphabetic'] = 0.8;
  8994. ol.render.replay.TEXT_ALIGN['ideographic'] = 0.8;
  8995. ol.render.replay.TEXT_ALIGN['bottom'] = 1;
  8996. ol.render.canvas.Replay = function(tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) {
  8997. ol.render.VectorContext.call(this);
  8998. /**
  8999. * @type {?}
  9000. */
  9001. this.declutterTree = declutterTree;
  9002. /**
  9003. * @private
  9004. * @type {ol.Extent}
  9005. */
  9006. this.tmpExtent_ = ol.extent.createEmpty();
  9007. /**
  9008. * @protected
  9009. * @type {number}
  9010. */
  9011. this.tolerance = tolerance;
  9012. /**
  9013. * @protected
  9014. * @const
  9015. * @type {ol.Extent}
  9016. */
  9017. this.maxExtent = maxExtent;
  9018. /**
  9019. * @protected
  9020. * @type {boolean}
  9021. */
  9022. this.overlaps = overlaps;
  9023. /**
  9024. * @protected
  9025. * @type {number}
  9026. */
  9027. this.pixelRatio = pixelRatio;
  9028. /**
  9029. * @protected
  9030. * @type {number}
  9031. */
  9032. this.maxLineWidth = 0;
  9033. /**
  9034. * @protected
  9035. * @const
  9036. * @type {number}
  9037. */
  9038. this.resolution = resolution;
  9039. /**
  9040. * @private
  9041. * @type {ol.Coordinate}
  9042. */
  9043. this.fillOrigin_;
  9044. /**
  9045. * @private
  9046. * @type {Array.<*>}
  9047. */
  9048. this.beginGeometryInstruction1_ = null;
  9049. /**
  9050. * @private
  9051. * @type {Array.<*>}
  9052. */
  9053. this.beginGeometryInstruction2_ = null;
  9054. /**
  9055. * @private
  9056. * @type {ol.Extent}
  9057. */
  9058. this.bufferedMaxExtent_ = null;
  9059. /**
  9060. * @protected
  9061. * @type {Array.<*>}
  9062. */
  9063. this.instructions = [];
  9064. /**
  9065. * @protected
  9066. * @type {Array.<number>}
  9067. */
  9068. this.coordinates = [];
  9069. /**
  9070. * @private
  9071. * @type {Object.<number,ol.Coordinate|Array.<ol.Coordinate>|Array.<Array.<ol.Coordinate>>>}
  9072. */
  9073. this.coordinateCache_ = {};
  9074. /**
  9075. * @private
  9076. * @type {!ol.Transform}
  9077. */
  9078. this.renderedTransform_ = ol.transform.create();
  9079. /**
  9080. * @protected
  9081. * @type {Array.<*>}
  9082. */
  9083. this.hitDetectionInstructions = [];
  9084. /**
  9085. * @private
  9086. * @type {Array.<number>}
  9087. */
  9088. this.pixelCoordinates_ = null;
  9089. /**
  9090. * @protected
  9091. * @type {ol.CanvasFillStrokeState}
  9092. */
  9093. this.state = /** @type {ol.CanvasFillStrokeState} */ ({});
  9094. /**
  9095. * @private
  9096. * @type {number}
  9097. */
  9098. this.viewRotation_ = 0;
  9099. /**
  9100. * @private
  9101. * @type {!ol.Transform}
  9102. */
  9103. this.tmpLocalTransform_ = ol.transform.create();
  9104. /**
  9105. * @private
  9106. * @type {!ol.Transform}
  9107. */
  9108. this.resetTransform_ = ol.transform.create();
  9109. };
  9110. ol.inherits(ol.render.canvas.Replay, ol.render.VectorContext);
  9111. /**
  9112. * @param {CanvasRenderingContext2D} context Context.
  9113. * @param {ol.Coordinate} p1 1st point of the background box.
  9114. * @param {ol.Coordinate} p2 2nd point of the background box.
  9115. * @param {ol.Coordinate} p3 3rd point of the background box.
  9116. * @param {ol.Coordinate} p4 4th point of the background box.
  9117. * @param {Array.<*>} fillInstruction Fill instruction.
  9118. * @param {Array.<*>} strokeInstruction Stroke instruction.
  9119. */
  9120. ol.render.canvas.Replay.prototype.replayTextBackground_ = function(context, p1, p2, p3, p4,
  9121. fillInstruction, strokeInstruction) {
  9122. context.beginPath();
  9123. context.moveTo.apply(context, p1);
  9124. context.lineTo.apply(context, p2);
  9125. context.lineTo.apply(context, p3);
  9126. context.lineTo.apply(context, p4);
  9127. context.lineTo.apply(context, p1);
  9128. if (fillInstruction) {
  9129. this.fillOrigin_ = /** @type {Array.<number>} */ (fillInstruction[2]);
  9130. this.fill_(context);
  9131. }
  9132. if (strokeInstruction) {
  9133. this.setStrokeStyle_(context, /** @type {Array.<*>} */ (strokeInstruction));
  9134. context.stroke();
  9135. }
  9136. };
  9137. /**
  9138. * @param {CanvasRenderingContext2D} context Context.
  9139. * @param {number} x X.
  9140. * @param {number} y Y.
  9141. * @param {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} image Image.
  9142. * @param {number} anchorX Anchor X.
  9143. * @param {number} anchorY Anchor Y.
  9144. * @param {ol.DeclutterGroup} declutterGroup Declutter group.
  9145. * @param {number} height Height.
  9146. * @param {number} opacity Opacity.
  9147. * @param {number} originX Origin X.
  9148. * @param {number} originY Origin Y.
  9149. * @param {number} rotation Rotation.
  9150. * @param {number} scale Scale.
  9151. * @param {boolean} snapToPixel Snap to pixel.
  9152. * @param {number} width Width.
  9153. * @param {Array.<number>} padding Padding.
  9154. * @param {Array.<*>} fillInstruction Fill instruction.
  9155. * @param {Array.<*>} strokeInstruction Stroke instruction.
  9156. */
  9157. ol.render.canvas.Replay.prototype.replayImage_ = function(context, x, y, image,
  9158. anchorX, anchorY, declutterGroup, height, opacity, originX, originY,
  9159. rotation, scale, snapToPixel, width, padding, fillInstruction, strokeInstruction) {
  9160. var fillStroke = fillInstruction || strokeInstruction;
  9161. var localTransform = this.tmpLocalTransform_;
  9162. anchorX *= scale;
  9163. anchorY *= scale;
  9164. x -= anchorX;
  9165. y -= anchorY;
  9166. if (snapToPixel) {
  9167. x = Math.round(x);
  9168. y = Math.round(y);
  9169. }
  9170. var w = (width + originX > image.width) ? image.width - originX : width;
  9171. var h = (height + originY > image.height) ? image.height - originY : height;
  9172. var box = this.tmpExtent_;
  9173. var boxW = padding[3] + w * scale + padding[1];
  9174. var boxH = padding[0] + h * scale + padding[2];
  9175. var boxX = x - padding[3];
  9176. var boxY = y - padding[0];
  9177. /** @type {ol.Coordinate} */
  9178. var p1;
  9179. /** @type {ol.Coordinate} */
  9180. var p2;
  9181. /** @type {ol.Coordinate} */
  9182. var p3;
  9183. /** @type {ol.Coordinate} */
  9184. var p4;
  9185. if (fillStroke || rotation !== 0) {
  9186. p1 = [boxX, boxY];
  9187. p2 = [boxX + boxW, boxY];
  9188. p3 = [boxX + boxW, boxY + boxH];
  9189. p4 = [boxX, boxY + boxH];
  9190. }
  9191. var transform = null;
  9192. if (rotation !== 0) {
  9193. var centerX = x + anchorX;
  9194. var centerY = y + anchorY;
  9195. transform = ol.transform.compose(localTransform,
  9196. centerX, centerY, 1, 1, rotation, -centerX, -centerY);
  9197. ol.extent.createOrUpdateEmpty(box);
  9198. ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, p1));
  9199. ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, p2));
  9200. ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, p3));
  9201. ol.extent.extendCoordinate(box, ol.transform.apply(localTransform, p4));
  9202. } else {
  9203. ol.extent.createOrUpdate(boxX, boxY, boxX + boxW, boxY + boxH, box);
  9204. }
  9205. var canvas = context.canvas;
  9206. var intersects = box[0] <= canvas.width && box[2] >= 0 && box[1] <= canvas.height && box[3] >= 0;
  9207. if (declutterGroup) {
  9208. if (!intersects && declutterGroup[4] == 1) {
  9209. return;
  9210. }
  9211. ol.extent.extend(declutterGroup, box);
  9212. var declutterArgs = intersects ?
  9213. [context, transform ? transform.slice(0) : null, opacity, image, originX, originY, w, h, x, y, scale] :
  9214. null;
  9215. if (declutterArgs && fillStroke) {
  9216. declutterArgs.push(fillInstruction, strokeInstruction, p1, p2, p3, p4);
  9217. }
  9218. declutterGroup.push(declutterArgs);
  9219. } else if (intersects) {
  9220. if (fillStroke) {
  9221. this.replayTextBackground_(context, p1, p2, p3, p4,
  9222. /** @type {Array.<*>} */ (fillInstruction),
  9223. /** @type {Array.<*>} */ (strokeInstruction));
  9224. }
  9225. ol.render.canvas.drawImage(context, transform, opacity, image, originX, originY, w, h, x, y, scale);
  9226. }
  9227. };
  9228. /**
  9229. * @protected
  9230. * @param {Array.<number>} dashArray Dash array.
  9231. * @return {Array.<number>} Dash array with pixel ratio applied
  9232. */
  9233. ol.render.canvas.Replay.prototype.applyPixelRatio = function(dashArray) {
  9234. var pixelRatio = this.pixelRatio;
  9235. return pixelRatio == 1 ? dashArray : dashArray.map(function(dash) {
  9236. return dash * pixelRatio;
  9237. });
  9238. };
  9239. /**
  9240. * @param {Array.<number>} flatCoordinates Flat coordinates.
  9241. * @param {number} offset Offset.
  9242. * @param {number} end End.
  9243. * @param {number} stride Stride.
  9244. * @param {boolean} closed Last input coordinate equals first.
  9245. * @param {boolean} skipFirst Skip first coordinate.
  9246. * @protected
  9247. * @return {number} My end.
  9248. */
  9249. ol.render.canvas.Replay.prototype.appendFlatCoordinates = function(flatCoordinates, offset, end, stride, closed, skipFirst) {
  9250. var myEnd = this.coordinates.length;
  9251. var extent = this.getBufferedMaxExtent();
  9252. if (skipFirst) {
  9253. offset += stride;
  9254. }
  9255. var lastCoord = [flatCoordinates[offset], flatCoordinates[offset + 1]];
  9256. var nextCoord = [NaN, NaN];
  9257. var skipped = true;
  9258. var i, lastRel, nextRel;
  9259. for (i = offset + stride; i < end; i += stride) {
  9260. nextCoord[0] = flatCoordinates[i];
  9261. nextCoord[1] = flatCoordinates[i + 1];
  9262. nextRel = ol.extent.coordinateRelationship(extent, nextCoord);
  9263. if (nextRel !== lastRel) {
  9264. if (skipped) {
  9265. this.coordinates[myEnd++] = lastCoord[0];
  9266. this.coordinates[myEnd++] = lastCoord[1];
  9267. }
  9268. this.coordinates[myEnd++] = nextCoord[0];
  9269. this.coordinates[myEnd++] = nextCoord[1];
  9270. skipped = false;
  9271. } else if (nextRel === ol.extent.Relationship.INTERSECTING) {
  9272. this.coordinates[myEnd++] = nextCoord[0];
  9273. this.coordinates[myEnd++] = nextCoord[1];
  9274. skipped = false;
  9275. } else {
  9276. skipped = true;
  9277. }
  9278. lastCoord[0] = nextCoord[0];
  9279. lastCoord[1] = nextCoord[1];
  9280. lastRel = nextRel;
  9281. }
  9282. // Last coordinate equals first or only one point to append:
  9283. if ((closed && skipped) || i === offset + stride) {
  9284. this.coordinates[myEnd++] = lastCoord[0];
  9285. this.coordinates[myEnd++] = lastCoord[1];
  9286. }
  9287. return myEnd;
  9288. };
  9289. /**
  9290. * @param {Array.<number>} flatCoordinates Flat coordinates.
  9291. * @param {number} offset Offset.
  9292. * @param {Array.<number>} ends Ends.
  9293. * @param {number} stride Stride.
  9294. * @param {Array.<number>} replayEnds Replay ends.
  9295. * @return {number} Offset.
  9296. */
  9297. ol.render.canvas.Replay.prototype.drawCustomCoordinates_ = function(flatCoordinates, offset, ends, stride, replayEnds) {
  9298. for (var i = 0, ii = ends.length; i < ii; ++i) {
  9299. var end = ends[i];
  9300. var replayEnd = this.appendFlatCoordinates(flatCoordinates, offset, end, stride, false, false);
  9301. replayEnds.push(replayEnd);
  9302. offset = end;
  9303. }
  9304. return offset;
  9305. };
  9306. /**
  9307. * @inheritDoc.
  9308. */
  9309. ol.render.canvas.Replay.prototype.drawCustom = function(geometry, feature, renderer) {
  9310. this.beginGeometry(geometry, feature);
  9311. var type = geometry.getType();
  9312. var stride = geometry.getStride();
  9313. var replayBegin = this.coordinates.length;
  9314. var flatCoordinates, replayEnd, replayEnds, replayEndss;
  9315. var offset;
  9316. if (type == ol.geom.GeometryType.MULTI_POLYGON) {
  9317. geometry = /** @type {ol.geom.MultiPolygon} */ (geometry);
  9318. flatCoordinates = geometry.getOrientedFlatCoordinates();
  9319. replayEndss = [];
  9320. var endss = geometry.getEndss();
  9321. offset = 0;
  9322. for (var i = 0, ii = endss.length; i < ii; ++i) {
  9323. var myEnds = [];
  9324. offset = this.drawCustomCoordinates_(flatCoordinates, offset, endss[i], stride, myEnds);
  9325. replayEndss.push(myEnds);
  9326. }
  9327. this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
  9328. replayBegin, replayEndss, geometry, renderer, ol.geom.flat.inflate.coordinatesss]);
  9329. } else if (type == ol.geom.GeometryType.POLYGON || type == ol.geom.GeometryType.MULTI_LINE_STRING) {
  9330. replayEnds = [];
  9331. flatCoordinates = (type == ol.geom.GeometryType.POLYGON) ?
  9332. /** @type {ol.geom.Polygon} */ (geometry).getOrientedFlatCoordinates() :
  9333. geometry.getFlatCoordinates();
  9334. offset = this.drawCustomCoordinates_(flatCoordinates, 0,
  9335. /** @type {ol.geom.Polygon|ol.geom.MultiLineString} */ (geometry).getEnds(),
  9336. stride, replayEnds);
  9337. this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
  9338. replayBegin, replayEnds, geometry, renderer, ol.geom.flat.inflate.coordinatess]);
  9339. } else if (type == ol.geom.GeometryType.LINE_STRING || type == ol.geom.GeometryType.MULTI_POINT) {
  9340. flatCoordinates = geometry.getFlatCoordinates();
  9341. replayEnd = this.appendFlatCoordinates(
  9342. flatCoordinates, 0, flatCoordinates.length, stride, false, false);
  9343. this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
  9344. replayBegin, replayEnd, geometry, renderer, ol.geom.flat.inflate.coordinates]);
  9345. } else if (type == ol.geom.GeometryType.POINT) {
  9346. flatCoordinates = geometry.getFlatCoordinates();
  9347. this.coordinates.push(flatCoordinates[0], flatCoordinates[1]);
  9348. replayEnd = this.coordinates.length;
  9349. this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
  9350. replayBegin, replayEnd, geometry, renderer]);
  9351. }
  9352. this.endGeometry(geometry, feature);
  9353. };
  9354. /**
  9355. * @protected
  9356. * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
  9357. * @param {ol.Feature|ol.render.Feature} feature Feature.
  9358. */
  9359. ol.render.canvas.Replay.prototype.beginGeometry = function(geometry, feature) {
  9360. this.beginGeometryInstruction1_ =
  9361. [ol.render.canvas.Instruction.BEGIN_GEOMETRY, feature, 0];
  9362. this.instructions.push(this.beginGeometryInstruction1_);
  9363. this.beginGeometryInstruction2_ =
  9364. [ol.render.canvas.Instruction.BEGIN_GEOMETRY, feature, 0];
  9365. this.hitDetectionInstructions.push(this.beginGeometryInstruction2_);
  9366. };
  9367. /**
  9368. * @private
  9369. * @param {CanvasRenderingContext2D} context Context.
  9370. */
  9371. ol.render.canvas.Replay.prototype.fill_ = function(context) {
  9372. if (this.fillOrigin_) {
  9373. var origin = ol.transform.apply(this.renderedTransform_, this.fillOrigin_.slice());
  9374. context.translate(origin[0], origin[1]);
  9375. context.rotate(this.viewRotation_);
  9376. }
  9377. context.fill();
  9378. if (this.fillOrigin_) {
  9379. context.setTransform.apply(context, ol.render.canvas.resetTransform_);
  9380. }
  9381. };
  9382. /**
  9383. * @private
  9384. * @param {CanvasRenderingContext2D} context Context.
  9385. * @param {Array.<*>} instruction Instruction.
  9386. */
  9387. ol.render.canvas.Replay.prototype.setStrokeStyle_ = function(context, instruction) {
  9388. context.strokeStyle = /** @type {ol.ColorLike} */ (instruction[1]);
  9389. context.lineWidth = /** @type {number} */ (instruction[2]);
  9390. context.lineCap = /** @type {string} */ (instruction[3]);
  9391. context.lineJoin = /** @type {string} */ (instruction[4]);
  9392. context.miterLimit = /** @type {number} */ (instruction[5]);
  9393. if (ol.has.CANVAS_LINE_DASH) {
  9394. context.lineDashOffset = /** @type {number} */ (instruction[7]);
  9395. context.setLineDash(/** @type {Array.<number>} */ (instruction[6]));
  9396. }
  9397. };
  9398. /**
  9399. * @param {ol.DeclutterGroup} declutterGroup Declutter group.
  9400. * @param {ol.Feature|ol.render.Feature} feature Feature.
  9401. */
  9402. ol.render.canvas.Replay.prototype.renderDeclutter_ = function(declutterGroup, feature) {
  9403. if (declutterGroup && declutterGroup.length > 5) {
  9404. var groupCount = declutterGroup[4];
  9405. if (groupCount == 1 || groupCount == declutterGroup.length - 5) {
  9406. /** @type {ol.RBushEntry} */
  9407. var box = {
  9408. minX: /** @type {number} */ (declutterGroup[0]),
  9409. minY: /** @type {number} */ (declutterGroup[1]),
  9410. maxX: /** @type {number} */ (declutterGroup[2]),
  9411. maxY: /** @type {number} */ (declutterGroup[3]),
  9412. value: feature
  9413. };
  9414. if (!this.declutterTree.collides(box)) {
  9415. this.declutterTree.insert(box);
  9416. var drawImage = ol.render.canvas.drawImage;
  9417. for (var j = 5, jj = declutterGroup.length; j < jj; ++j) {
  9418. var declutterData = /** @type {Array} */ (declutterGroup[j]);
  9419. if (declutterData) {
  9420. if (declutterData.length > 11) {
  9421. this.replayTextBackground_(declutterData[0],
  9422. declutterData[13], declutterData[14], declutterData[15], declutterData[16],
  9423. declutterData[11], declutterData[12]);
  9424. }
  9425. drawImage.apply(undefined, declutterData);
  9426. }
  9427. }
  9428. }
  9429. declutterGroup.length = 5;
  9430. ol.extent.createOrUpdateEmpty(declutterGroup);
  9431. }
  9432. }
  9433. };
  9434. /**
  9435. * @private
  9436. * @param {CanvasRenderingContext2D} context Context.
  9437. * @param {ol.Transform} transform Transform.
  9438. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  9439. * to skip.
  9440. * @param {Array.<*>} instructions Instructions array.
  9441. * @param {function((ol.Feature|ol.render.Feature)): T|undefined}
  9442. * featureCallback Feature callback.
  9443. * @param {ol.Extent=} opt_hitExtent Only check features that intersect this
  9444. * extent.
  9445. * @return {T|undefined} Callback result.
  9446. * @template T
  9447. */
  9448. ol.render.canvas.Replay.prototype.replay_ = function(
  9449. context, transform, skippedFeaturesHash,
  9450. instructions, featureCallback, opt_hitExtent) {
  9451. /** @type {Array.<number>} */
  9452. var pixelCoordinates;
  9453. if (this.pixelCoordinates_ && ol.array.equals(transform, this.renderedTransform_)) {
  9454. pixelCoordinates = this.pixelCoordinates_;
  9455. } else {
  9456. if (!this.pixelCoordinates_) {
  9457. this.pixelCoordinates_ = [];
  9458. }
  9459. pixelCoordinates = ol.geom.flat.transform.transform2D(
  9460. this.coordinates, 0, this.coordinates.length, 2,
  9461. transform, this.pixelCoordinates_);
  9462. ol.transform.setFromArray(this.renderedTransform_, transform);
  9463. }
  9464. var skipFeatures = !ol.obj.isEmpty(skippedFeaturesHash);
  9465. var i = 0; // instruction index
  9466. var ii = instructions.length; // end of instructions
  9467. var d = 0; // data index
  9468. var dd; // end of per-instruction data
  9469. var anchorX, anchorY, prevX, prevY, roundX, roundY, declutterGroup, image;
  9470. var pendingFill = 0;
  9471. var pendingStroke = 0;
  9472. var lastFillInstruction = null;
  9473. var lastStrokeInstruction = null;
  9474. var coordinateCache = this.coordinateCache_;
  9475. var viewRotation = this.viewRotation_;
  9476. var state = /** @type {olx.render.State} */ ({
  9477. context: context,
  9478. pixelRatio: this.pixelRatio,
  9479. resolution: this.resolution,
  9480. rotation: viewRotation
  9481. });
  9482. // When the batch size gets too big, performance decreases. 200 is a good
  9483. // balance between batch size and number of fill/stroke instructions.
  9484. var batchSize =
  9485. this.instructions != instructions || this.overlaps ? 0 : 200;
  9486. while (i < ii) {
  9487. var instruction = instructions[i];
  9488. var type = /** @type {ol.render.canvas.Instruction} */ (instruction[0]);
  9489. var /** @type {ol.Feature|ol.render.Feature} */ feature, x, y;
  9490. switch (type) {
  9491. case ol.render.canvas.Instruction.BEGIN_GEOMETRY:
  9492. feature = /** @type {ol.Feature|ol.render.Feature} */ (instruction[1]);
  9493. if ((skipFeatures &&
  9494. skippedFeaturesHash[ol.getUid(feature).toString()]) ||
  9495. !feature.getGeometry()) {
  9496. i = /** @type {number} */ (instruction[2]);
  9497. } else if (opt_hitExtent !== undefined && !ol.extent.intersects(
  9498. opt_hitExtent, feature.getGeometry().getExtent())) {
  9499. i = /** @type {number} */ (instruction[2]) + 1;
  9500. } else {
  9501. ++i;
  9502. }
  9503. break;
  9504. case ol.render.canvas.Instruction.BEGIN_PATH:
  9505. if (pendingFill > batchSize) {
  9506. this.fill_(context);
  9507. pendingFill = 0;
  9508. }
  9509. if (pendingStroke > batchSize) {
  9510. context.stroke();
  9511. pendingStroke = 0;
  9512. }
  9513. if (!pendingFill && !pendingStroke) {
  9514. context.beginPath();
  9515. prevX = prevY = NaN;
  9516. }
  9517. ++i;
  9518. break;
  9519. case ol.render.canvas.Instruction.CIRCLE:
  9520. d = /** @type {number} */ (instruction[1]);
  9521. var x1 = pixelCoordinates[d];
  9522. var y1 = pixelCoordinates[d + 1];
  9523. var x2 = pixelCoordinates[d + 2];
  9524. var y2 = pixelCoordinates[d + 3];
  9525. var dx = x2 - x1;
  9526. var dy = y2 - y1;
  9527. var r = Math.sqrt(dx * dx + dy * dy);
  9528. context.moveTo(x1 + r, y1);
  9529. context.arc(x1, y1, r, 0, 2 * Math.PI, true);
  9530. ++i;
  9531. break;
  9532. case ol.render.canvas.Instruction.CLOSE_PATH:
  9533. context.closePath();
  9534. ++i;
  9535. break;
  9536. case ol.render.canvas.Instruction.CUSTOM:
  9537. d = /** @type {number} */ (instruction[1]);
  9538. dd = instruction[2];
  9539. var geometry = /** @type {ol.geom.SimpleGeometry} */ (instruction[3]);
  9540. var renderer = instruction[4];
  9541. var fn = instruction.length == 6 ? instruction[5] : undefined;
  9542. state.geometry = geometry;
  9543. state.feature = feature;
  9544. if (!(i in coordinateCache)) {
  9545. coordinateCache[i] = [];
  9546. }
  9547. var coords = coordinateCache[i];
  9548. if (fn) {
  9549. fn(pixelCoordinates, d, dd, 2, coords);
  9550. } else {
  9551. coords[0] = pixelCoordinates[d];
  9552. coords[1] = pixelCoordinates[d + 1];
  9553. coords.length = 2;
  9554. }
  9555. renderer(coords, state);
  9556. ++i;
  9557. break;
  9558. case ol.render.canvas.Instruction.DRAW_IMAGE:
  9559. d = /** @type {number} */ (instruction[1]);
  9560. dd = /** @type {number} */ (instruction[2]);
  9561. image = /** @type {HTMLCanvasElement|HTMLVideoElement|Image} */
  9562. (instruction[3]);
  9563. // Remaining arguments in DRAW_IMAGE are in alphabetical order
  9564. anchorX = /** @type {number} */ (instruction[4]);
  9565. anchorY = /** @type {number} */ (instruction[5]);
  9566. declutterGroup = featureCallback ? null : /** @type {ol.DeclutterGroup} */ (instruction[6]);
  9567. var height = /** @type {number} */ (instruction[7]);
  9568. var opacity = /** @type {number} */ (instruction[8]);
  9569. var originX = /** @type {number} */ (instruction[9]);
  9570. var originY = /** @type {number} */ (instruction[10]);
  9571. var rotateWithView = /** @type {boolean} */ (instruction[11]);
  9572. var rotation = /** @type {number} */ (instruction[12]);
  9573. var scale = /** @type {number} */ (instruction[13]);
  9574. var snapToPixel = /** @type {boolean} */ (instruction[14]);
  9575. var width = /** @type {number} */ (instruction[15]);
  9576. var padding, backgroundFill, backgroundStroke;
  9577. if (instruction.length > 16) {
  9578. padding = /** @type {Array.<number>} */ (instruction[16]);
  9579. backgroundFill = /** @type {boolean} */ (instruction[17]);
  9580. backgroundStroke = /** @type {boolean} */ (instruction[18]);
  9581. } else {
  9582. padding = ol.render.canvas.defaultPadding;
  9583. backgroundFill = backgroundStroke = false;
  9584. }
  9585. if (rotateWithView) {
  9586. rotation += viewRotation;
  9587. }
  9588. for (; d < dd; d += 2) {
  9589. this.replayImage_(context,
  9590. pixelCoordinates[d], pixelCoordinates[d + 1], image, anchorX, anchorY,
  9591. declutterGroup, height, opacity, originX, originY, rotation, scale,
  9592. snapToPixel, width, padding,
  9593. backgroundFill ? /** @type {Array.<*>} */ (lastFillInstruction) : null,
  9594. backgroundStroke ? /** @type {Array.<*>} */ (lastStrokeInstruction) : null);
  9595. }
  9596. this.renderDeclutter_(declutterGroup, feature);
  9597. ++i;
  9598. break;
  9599. case ol.render.canvas.Instruction.DRAW_CHARS:
  9600. var begin = /** @type {number} */ (instruction[1]);
  9601. var end = /** @type {number} */ (instruction[2]);
  9602. var baseline = /** @type {number} */ (instruction[3]);
  9603. declutterGroup = featureCallback ? null : /** @type {ol.DeclutterGroup} */ (instruction[4]);
  9604. var overflow = /** @type {number} */ (instruction[5]);
  9605. var fillKey = /** @type {string} */ (instruction[6]);
  9606. var maxAngle = /** @type {number} */ (instruction[7]);
  9607. var measure = /** @type {function(string):number} */ (instruction[8]);
  9608. var offsetY = /** @type {number} */ (instruction[9]);
  9609. var strokeKey = /** @type {string} */ (instruction[10]);
  9610. var strokeWidth = /** @type {number} */ (instruction[11]);
  9611. var text = /** @type {string} */ (instruction[12]);
  9612. var textKey = /** @type {string} */ (instruction[13]);
  9613. var textScale = /** @type {number} */ (instruction[14]);
  9614. var pathLength = ol.geom.flat.length.lineString(pixelCoordinates, begin, end, 2);
  9615. var textLength = measure(text);
  9616. if (overflow || textLength <= pathLength) {
  9617. var textAlign = /** @type {ol.render.canvas.TextReplay} */ (this).textStates[textKey].textAlign;
  9618. var startM = (pathLength - textLength) * ol.render.replay.TEXT_ALIGN[textAlign];
  9619. var parts = ol.geom.flat.textpath.lineString(
  9620. pixelCoordinates, begin, end, 2, text, measure, startM, maxAngle);
  9621. if (parts) {
  9622. var c, cc, chars, label, part;
  9623. if (strokeKey) {
  9624. for (c = 0, cc = parts.length; c < cc; ++c) {
  9625. part = parts[c]; // x, y, anchorX, rotation, chunk
  9626. chars = /** @type {string} */ (part[4]);
  9627. label = /** @type {ol.render.canvas.TextReplay} */ (this).getImage(chars, textKey, '', strokeKey);
  9628. anchorX = /** @type {number} */ (part[2]) + strokeWidth;
  9629. anchorY = baseline * label.height + (0.5 - baseline) * 2 * strokeWidth - offsetY;
  9630. this.replayImage_(context,
  9631. /** @type {number} */ (part[0]), /** @type {number} */ (part[1]), label,
  9632. anchorX, anchorY, declutterGroup, label.height, 1, 0, 0,
  9633. /** @type {number} */ (part[3]), textScale, false, label.width,
  9634. ol.render.canvas.defaultPadding, null, null);
  9635. }
  9636. }
  9637. if (fillKey) {
  9638. for (c = 0, cc = parts.length; c < cc; ++c) {
  9639. part = parts[c]; // x, y, anchorX, rotation, chunk
  9640. chars = /** @type {string} */ (part[4]);
  9641. label = /** @type {ol.render.canvas.TextReplay} */ (this).getImage(chars, textKey, fillKey, '');
  9642. anchorX = /** @type {number} */ (part[2]);
  9643. anchorY = baseline * label.height - offsetY;
  9644. this.replayImage_(context,
  9645. /** @type {number} */ (part[0]), /** @type {number} */ (part[1]), label,
  9646. anchorX, anchorY, declutterGroup, label.height, 1, 0, 0,
  9647. /** @type {number} */ (part[3]), textScale, false, label.width,
  9648. ol.render.canvas.defaultPadding, null, null);
  9649. }
  9650. }
  9651. }
  9652. }
  9653. this.renderDeclutter_(declutterGroup, feature);
  9654. ++i;
  9655. break;
  9656. case ol.render.canvas.Instruction.END_GEOMETRY:
  9657. if (featureCallback !== undefined) {
  9658. feature = /** @type {ol.Feature|ol.render.Feature} */ (instruction[1]);
  9659. var result = featureCallback(feature);
  9660. if (result) {
  9661. return result;
  9662. }
  9663. }
  9664. ++i;
  9665. break;
  9666. case ol.render.canvas.Instruction.FILL:
  9667. if (batchSize) {
  9668. pendingFill++;
  9669. } else {
  9670. this.fill_(context);
  9671. }
  9672. ++i;
  9673. break;
  9674. case ol.render.canvas.Instruction.MOVE_TO_LINE_TO:
  9675. d = /** @type {number} */ (instruction[1]);
  9676. dd = /** @type {number} */ (instruction[2]);
  9677. x = pixelCoordinates[d];
  9678. y = pixelCoordinates[d + 1];
  9679. roundX = (x + 0.5) | 0;
  9680. roundY = (y + 0.5) | 0;
  9681. if (roundX !== prevX || roundY !== prevY) {
  9682. context.moveTo(x, y);
  9683. prevX = roundX;
  9684. prevY = roundY;
  9685. }
  9686. for (d += 2; d < dd; d += 2) {
  9687. x = pixelCoordinates[d];
  9688. y = pixelCoordinates[d + 1];
  9689. roundX = (x + 0.5) | 0;
  9690. roundY = (y + 0.5) | 0;
  9691. if (d == dd - 2 || roundX !== prevX || roundY !== prevY) {
  9692. context.lineTo(x, y);
  9693. prevX = roundX;
  9694. prevY = roundY;
  9695. }
  9696. }
  9697. ++i;
  9698. break;
  9699. case ol.render.canvas.Instruction.SET_FILL_STYLE:
  9700. lastFillInstruction = instruction;
  9701. this.fillOrigin_ = instruction[2];
  9702. if (pendingFill) {
  9703. this.fill_(context);
  9704. pendingFill = 0;
  9705. if (pendingStroke) {
  9706. context.stroke();
  9707. pendingStroke = 0;
  9708. }
  9709. }
  9710. context.fillStyle = /** @type {ol.ColorLike} */ (instruction[1]);
  9711. ++i;
  9712. break;
  9713. case ol.render.canvas.Instruction.SET_STROKE_STYLE:
  9714. lastStrokeInstruction = instruction;
  9715. if (pendingStroke) {
  9716. context.stroke();
  9717. pendingStroke = 0;
  9718. }
  9719. this.setStrokeStyle_(context, /** @type {Array.<*>} */ (instruction));
  9720. ++i;
  9721. break;
  9722. case ol.render.canvas.Instruction.STROKE:
  9723. if (batchSize) {
  9724. pendingStroke++;
  9725. } else {
  9726. context.stroke();
  9727. }
  9728. ++i;
  9729. break;
  9730. default:
  9731. ++i; // consume the instruction anyway, to avoid an infinite loop
  9732. break;
  9733. }
  9734. }
  9735. if (pendingFill) {
  9736. this.fill_(context);
  9737. }
  9738. if (pendingStroke) {
  9739. context.stroke();
  9740. }
  9741. return undefined;
  9742. };
  9743. /**
  9744. * @param {CanvasRenderingContext2D} context Context.
  9745. * @param {ol.Transform} transform Transform.
  9746. * @param {number} viewRotation View rotation.
  9747. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  9748. * to skip.
  9749. */
  9750. ol.render.canvas.Replay.prototype.replay = function(
  9751. context, transform, viewRotation, skippedFeaturesHash) {
  9752. this.viewRotation_ = viewRotation;
  9753. this.replay_(context, transform,
  9754. skippedFeaturesHash, this.instructions, undefined, undefined);
  9755. };
  9756. /**
  9757. * @param {CanvasRenderingContext2D} context Context.
  9758. * @param {ol.Transform} transform Transform.
  9759. * @param {number} viewRotation View rotation.
  9760. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  9761. * to skip.
  9762. * @param {function((ol.Feature|ol.render.Feature)): T=} opt_featureCallback
  9763. * Feature callback.
  9764. * @param {ol.Extent=} opt_hitExtent Only check features that intersect this
  9765. * extent.
  9766. * @return {T|undefined} Callback result.
  9767. * @template T
  9768. */
  9769. ol.render.canvas.Replay.prototype.replayHitDetection = function(
  9770. context, transform, viewRotation, skippedFeaturesHash,
  9771. opt_featureCallback, opt_hitExtent) {
  9772. this.viewRotation_ = viewRotation;
  9773. return this.replay_(context, transform, skippedFeaturesHash,
  9774. this.hitDetectionInstructions, opt_featureCallback, opt_hitExtent);
  9775. };
  9776. /**
  9777. * Reverse the hit detection instructions.
  9778. */
  9779. ol.render.canvas.Replay.prototype.reverseHitDetectionInstructions = function() {
  9780. var hitDetectionInstructions = this.hitDetectionInstructions;
  9781. // step 1 - reverse array
  9782. hitDetectionInstructions.reverse();
  9783. // step 2 - reverse instructions within geometry blocks
  9784. var i;
  9785. var n = hitDetectionInstructions.length;
  9786. var instruction;
  9787. var type;
  9788. var begin = -1;
  9789. for (i = 0; i < n; ++i) {
  9790. instruction = hitDetectionInstructions[i];
  9791. type = /** @type {ol.render.canvas.Instruction} */ (instruction[0]);
  9792. if (type == ol.render.canvas.Instruction.END_GEOMETRY) {
  9793. begin = i;
  9794. } else if (type == ol.render.canvas.Instruction.BEGIN_GEOMETRY) {
  9795. instruction[2] = i;
  9796. ol.array.reverseSubArray(this.hitDetectionInstructions, begin, i);
  9797. begin = -1;
  9798. }
  9799. }
  9800. };
  9801. /**
  9802. * @inheritDoc
  9803. */
  9804. ol.render.canvas.Replay.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
  9805. var state = this.state;
  9806. if (fillStyle) {
  9807. var fillStyleColor = fillStyle.getColor();
  9808. state.fillStyle = ol.colorlike.asColorLike(fillStyleColor ?
  9809. fillStyleColor : ol.render.canvas.defaultFillStyle);
  9810. } else {
  9811. state.fillStyle = undefined;
  9812. }
  9813. if (strokeStyle) {
  9814. var strokeStyleColor = strokeStyle.getColor();
  9815. state.strokeStyle = ol.colorlike.asColorLike(strokeStyleColor ?
  9816. strokeStyleColor : ol.render.canvas.defaultStrokeStyle);
  9817. var strokeStyleLineCap = strokeStyle.getLineCap();
  9818. state.lineCap = strokeStyleLineCap !== undefined ?
  9819. strokeStyleLineCap : ol.render.canvas.defaultLineCap;
  9820. var strokeStyleLineDash = strokeStyle.getLineDash();
  9821. state.lineDash = strokeStyleLineDash ?
  9822. strokeStyleLineDash.slice() : ol.render.canvas.defaultLineDash;
  9823. var strokeStyleLineDashOffset = strokeStyle.getLineDashOffset();
  9824. state.lineDashOffset = strokeStyleLineDashOffset ?
  9825. strokeStyleLineDashOffset : ol.render.canvas.defaultLineDashOffset;
  9826. var strokeStyleLineJoin = strokeStyle.getLineJoin();
  9827. state.lineJoin = strokeStyleLineJoin !== undefined ?
  9828. strokeStyleLineJoin : ol.render.canvas.defaultLineJoin;
  9829. var strokeStyleWidth = strokeStyle.getWidth();
  9830. state.lineWidth = strokeStyleWidth !== undefined ?
  9831. strokeStyleWidth : ol.render.canvas.defaultLineWidth;
  9832. var strokeStyleMiterLimit = strokeStyle.getMiterLimit();
  9833. state.miterLimit = strokeStyleMiterLimit !== undefined ?
  9834. strokeStyleMiterLimit : ol.render.canvas.defaultMiterLimit;
  9835. if (state.lineWidth > this.maxLineWidth) {
  9836. this.maxLineWidth = state.lineWidth;
  9837. // invalidate the buffered max extent cache
  9838. this.bufferedMaxExtent_ = null;
  9839. }
  9840. } else {
  9841. state.strokeStyle = undefined;
  9842. state.lineCap = undefined;
  9843. state.lineDash = null;
  9844. state.lineDashOffset = undefined;
  9845. state.lineJoin = undefined;
  9846. state.lineWidth = undefined;
  9847. state.miterLimit = undefined;
  9848. }
  9849. };
  9850. /**
  9851. * @param {ol.CanvasFillStrokeState} state State.
  9852. * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
  9853. */
  9854. ol.render.canvas.Replay.prototype.applyFill = function(state, geometry) {
  9855. var fillStyle = state.fillStyle;
  9856. var fillInstruction = [ol.render.canvas.Instruction.SET_FILL_STYLE, fillStyle];
  9857. if (typeof fillStyle !== 'string') {
  9858. var fillExtent = geometry.getExtent();
  9859. fillInstruction.push([fillExtent[0], fillExtent[3]]);
  9860. }
  9861. this.instructions.push(fillInstruction);
  9862. };
  9863. /**
  9864. * @param {ol.CanvasFillStrokeState} state State.
  9865. */
  9866. ol.render.canvas.Replay.prototype.applyStroke = function(state) {
  9867. this.instructions.push([
  9868. ol.render.canvas.Instruction.SET_STROKE_STYLE,
  9869. state.strokeStyle, state.lineWidth * this.pixelRatio, state.lineCap,
  9870. state.lineJoin, state.miterLimit,
  9871. this.applyPixelRatio(state.lineDash), state.lineDashOffset * this.pixelRatio
  9872. ]);
  9873. };
  9874. /**
  9875. * @param {ol.CanvasFillStrokeState} state State.
  9876. * @param {function(this:ol.render.canvas.Replay, ol.CanvasFillStrokeState, (ol.geom.Geometry|ol.render.Feature))} applyFill Apply fill.
  9877. * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
  9878. */
  9879. ol.render.canvas.Replay.prototype.updateFillStyle = function(state, applyFill, geometry) {
  9880. var fillStyle = state.fillStyle;
  9881. if (typeof fillStyle !== 'string' || state.currentFillStyle != fillStyle) {
  9882. applyFill.call(this, state, geometry);
  9883. state.currentFillStyle = fillStyle;
  9884. }
  9885. };
  9886. /**
  9887. * @param {ol.CanvasFillStrokeState} state State.
  9888. * @param {function(this:ol.render.canvas.Replay, ol.CanvasFillStrokeState)} applyStroke Apply stroke.
  9889. */
  9890. ol.render.canvas.Replay.prototype.updateStrokeStyle = function(state, applyStroke) {
  9891. var strokeStyle = state.strokeStyle;
  9892. var lineCap = state.lineCap;
  9893. var lineDash = state.lineDash;
  9894. var lineDashOffset = state.lineDashOffset;
  9895. var lineJoin = state.lineJoin;
  9896. var lineWidth = state.lineWidth;
  9897. var miterLimit = state.miterLimit;
  9898. if (state.currentStrokeStyle != strokeStyle ||
  9899. state.currentLineCap != lineCap ||
  9900. (lineDash != state.currentLineDash && !ol.array.equals(state.currentLineDash, lineDash)) ||
  9901. state.currentLineDashOffset != lineDashOffset ||
  9902. state.currentLineJoin != lineJoin ||
  9903. state.currentLineWidth != lineWidth ||
  9904. state.currentMiterLimit != miterLimit) {
  9905. applyStroke.call(this, state);
  9906. state.currentStrokeStyle = strokeStyle;
  9907. state.currentLineCap = lineCap;
  9908. state.currentLineDash = lineDash;
  9909. state.currentLineDashOffset = lineDashOffset;
  9910. state.currentLineJoin = lineJoin;
  9911. state.currentLineWidth = lineWidth;
  9912. state.currentMiterLimit = miterLimit;
  9913. }
  9914. };
  9915. /**
  9916. * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
  9917. * @param {ol.Feature|ol.render.Feature} feature Feature.
  9918. */
  9919. ol.render.canvas.Replay.prototype.endGeometry = function(geometry, feature) {
  9920. this.beginGeometryInstruction1_[2] = this.instructions.length;
  9921. this.beginGeometryInstruction1_ = null;
  9922. this.beginGeometryInstruction2_[2] = this.hitDetectionInstructions.length;
  9923. this.beginGeometryInstruction2_ = null;
  9924. var endGeometryInstruction =
  9925. [ol.render.canvas.Instruction.END_GEOMETRY, feature];
  9926. this.instructions.push(endGeometryInstruction);
  9927. this.hitDetectionInstructions.push(endGeometryInstruction);
  9928. };
  9929. /**
  9930. * FIXME empty description for jsdoc
  9931. */
  9932. ol.render.canvas.Replay.prototype.finish = ol.nullFunction;
  9933. /**
  9934. * Get the buffered rendering extent. Rendering will be clipped to the extent
  9935. * provided to the constructor. To account for symbolizers that may intersect
  9936. * this extent, we calculate a buffered extent (e.g. based on stroke width).
  9937. * @return {ol.Extent} The buffered rendering extent.
  9938. * @protected
  9939. */
  9940. ol.render.canvas.Replay.prototype.getBufferedMaxExtent = function() {
  9941. if (!this.bufferedMaxExtent_) {
  9942. this.bufferedMaxExtent_ = ol.extent.clone(this.maxExtent);
  9943. if (this.maxLineWidth > 0) {
  9944. var width = this.resolution * (this.maxLineWidth + 1) / 2;
  9945. ol.extent.buffer(this.bufferedMaxExtent_, width, this.bufferedMaxExtent_);
  9946. }
  9947. }
  9948. return this.bufferedMaxExtent_;
  9949. };
  9950. /**
  9951. * @constructor
  9952. * @extends {ol.render.canvas.Replay}
  9953. * @param {number} tolerance Tolerance.
  9954. * @param {ol.Extent} maxExtent Maximum extent.
  9955. * @param {number} resolution Resolution.
  9956. * @param {number} pixelRatio Pixel ratio.
  9957. * @param {boolean} overlaps The replay can have overlapping geometries.
  9958. * @param {?} declutterTree Declutter tree.
  9959. * @struct
  9960. */
  9961. ol.render.canvas.ImageReplay = function(
  9962. tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) {
  9963. ol.render.canvas.Replay.call(this,
  9964. tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree);
  9965. /**
  9966. * @private
  9967. * @type {ol.DeclutterGroup}
  9968. */
  9969. this.declutterGroup_ = null;
  9970. /**
  9971. * @private
  9972. * @type {HTMLCanvasElement|HTMLVideoElement|Image}
  9973. */
  9974. this.hitDetectionImage_ = null;
  9975. /**
  9976. * @private
  9977. * @type {HTMLCanvasElement|HTMLVideoElement|Image}
  9978. */
  9979. this.image_ = null;
  9980. /**
  9981. * @private
  9982. * @type {number|undefined}
  9983. */
  9984. this.anchorX_ = undefined;
  9985. /**
  9986. * @private
  9987. * @type {number|undefined}
  9988. */
  9989. this.anchorY_ = undefined;
  9990. /**
  9991. * @private
  9992. * @type {number|undefined}
  9993. */
  9994. this.height_ = undefined;
  9995. /**
  9996. * @private
  9997. * @type {number|undefined}
  9998. */
  9999. this.opacity_ = undefined;
  10000. /**
  10001. * @private
  10002. * @type {number|undefined}
  10003. */
  10004. this.originX_ = undefined;
  10005. /**
  10006. * @private
  10007. * @type {number|undefined}
  10008. */
  10009. this.originY_ = undefined;
  10010. /**
  10011. * @private
  10012. * @type {boolean|undefined}
  10013. */
  10014. this.rotateWithView_ = undefined;
  10015. /**
  10016. * @private
  10017. * @type {number|undefined}
  10018. */
  10019. this.rotation_ = undefined;
  10020. /**
  10021. * @private
  10022. * @type {number|undefined}
  10023. */
  10024. this.scale_ = undefined;
  10025. /**
  10026. * @private
  10027. * @type {boolean|undefined}
  10028. */
  10029. this.snapToPixel_ = undefined;
  10030. /**
  10031. * @private
  10032. * @type {number|undefined}
  10033. */
  10034. this.width_ = undefined;
  10035. };
  10036. ol.inherits(ol.render.canvas.ImageReplay, ol.render.canvas.Replay);
  10037. /**
  10038. * @param {Array.<number>} flatCoordinates Flat coordinates.
  10039. * @param {number} offset Offset.
  10040. * @param {number} end End.
  10041. * @param {number} stride Stride.
  10042. * @private
  10043. * @return {number} My end.
  10044. */
  10045. ol.render.canvas.ImageReplay.prototype.drawCoordinates_ = function(flatCoordinates, offset, end, stride) {
  10046. return this.appendFlatCoordinates(
  10047. flatCoordinates, offset, end, stride, false, false);
  10048. };
  10049. /**
  10050. * @inheritDoc
  10051. */
  10052. ol.render.canvas.ImageReplay.prototype.drawPoint = function(pointGeometry, feature) {
  10053. if (!this.image_) {
  10054. return;
  10055. }
  10056. this.beginGeometry(pointGeometry, feature);
  10057. var flatCoordinates = pointGeometry.getFlatCoordinates();
  10058. var stride = pointGeometry.getStride();
  10059. var myBegin = this.coordinates.length;
  10060. var myEnd = this.drawCoordinates_(
  10061. flatCoordinates, 0, flatCoordinates.length, stride);
  10062. this.instructions.push([
  10063. ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd, this.image_,
  10064. // Remaining arguments to DRAW_IMAGE are in alphabetical order
  10065. this.anchorX_, this.anchorY_, this.declutterGroup_, this.height_, this.opacity_,
  10066. this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
  10067. this.scale_ * this.pixelRatio, this.snapToPixel_, this.width_
  10068. ]);
  10069. this.hitDetectionInstructions.push([
  10070. ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd,
  10071. this.hitDetectionImage_,
  10072. // Remaining arguments to DRAW_IMAGE are in alphabetical order
  10073. this.anchorX_, this.anchorY_, this.declutterGroup_, this.height_, this.opacity_,
  10074. this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
  10075. this.scale_, this.snapToPixel_, this.width_
  10076. ]);
  10077. this.endGeometry(pointGeometry, feature);
  10078. };
  10079. /**
  10080. * @inheritDoc
  10081. */
  10082. ol.render.canvas.ImageReplay.prototype.drawMultiPoint = function(multiPointGeometry, feature) {
  10083. if (!this.image_) {
  10084. return;
  10085. }
  10086. this.beginGeometry(multiPointGeometry, feature);
  10087. var flatCoordinates = multiPointGeometry.getFlatCoordinates();
  10088. var stride = multiPointGeometry.getStride();
  10089. var myBegin = this.coordinates.length;
  10090. var myEnd = this.drawCoordinates_(
  10091. flatCoordinates, 0, flatCoordinates.length, stride);
  10092. this.instructions.push([
  10093. ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd, this.image_,
  10094. // Remaining arguments to DRAW_IMAGE are in alphabetical order
  10095. this.anchorX_, this.anchorY_, this.declutterGroup_, this.height_, this.opacity_,
  10096. this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
  10097. this.scale_ * this.pixelRatio, this.snapToPixel_, this.width_
  10098. ]);
  10099. this.hitDetectionInstructions.push([
  10100. ol.render.canvas.Instruction.DRAW_IMAGE, myBegin, myEnd,
  10101. this.hitDetectionImage_,
  10102. // Remaining arguments to DRAW_IMAGE are in alphabetical order
  10103. this.anchorX_, this.anchorY_, this.declutterGroup_, this.height_, this.opacity_,
  10104. this.originX_, this.originY_, this.rotateWithView_, this.rotation_,
  10105. this.scale_, this.snapToPixel_, this.width_
  10106. ]);
  10107. this.endGeometry(multiPointGeometry, feature);
  10108. };
  10109. /**
  10110. * @inheritDoc
  10111. */
  10112. ol.render.canvas.ImageReplay.prototype.finish = function() {
  10113. this.reverseHitDetectionInstructions();
  10114. // FIXME this doesn't really protect us against further calls to draw*Geometry
  10115. this.anchorX_ = undefined;
  10116. this.anchorY_ = undefined;
  10117. this.hitDetectionImage_ = null;
  10118. this.image_ = null;
  10119. this.height_ = undefined;
  10120. this.scale_ = undefined;
  10121. this.opacity_ = undefined;
  10122. this.originX_ = undefined;
  10123. this.originY_ = undefined;
  10124. this.rotateWithView_ = undefined;
  10125. this.rotation_ = undefined;
  10126. this.snapToPixel_ = undefined;
  10127. this.width_ = undefined;
  10128. };
  10129. /**
  10130. * @inheritDoc
  10131. */
  10132. ol.render.canvas.ImageReplay.prototype.setImageStyle = function(imageStyle, declutterGroup) {
  10133. var anchor = imageStyle.getAnchor();
  10134. var size = imageStyle.getSize();
  10135. var hitDetectionImage = imageStyle.getHitDetectionImage(1);
  10136. var image = imageStyle.getImage(1);
  10137. var origin = imageStyle.getOrigin();
  10138. this.anchorX_ = anchor[0];
  10139. this.anchorY_ = anchor[1];
  10140. this.declutterGroup_ = /** @type {ol.DeclutterGroup} */ (declutterGroup);
  10141. this.hitDetectionImage_ = hitDetectionImage;
  10142. this.image_ = image;
  10143. this.height_ = size[1];
  10144. this.opacity_ = imageStyle.getOpacity();
  10145. this.originX_ = origin[0];
  10146. this.originY_ = origin[1];
  10147. this.rotateWithView_ = imageStyle.getRotateWithView();
  10148. this.rotation_ = imageStyle.getRotation();
  10149. this.scale_ = imageStyle.getScale();
  10150. this.snapToPixel_ = imageStyle.getSnapToPixel();
  10151. this.width_ = size[0];
  10152. };
  10153. /**
  10154. * @constructor
  10155. * @extends {ol.render.canvas.Replay}
  10156. * @param {number} tolerance Tolerance.
  10157. * @param {ol.Extent} maxExtent Maximum extent.
  10158. * @param {number} resolution Resolution.
  10159. * @param {number} pixelRatio Pixel ratio.
  10160. * @param {boolean} overlaps The replay can have overlapping geometries.
  10161. * @param {?} declutterTree Declutter tree.
  10162. * @struct
  10163. */
  10164. ol.render.canvas.LineStringReplay = function(
  10165. tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) {
  10166. ol.render.canvas.Replay.call(this,
  10167. tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree);
  10168. };
  10169. ol.inherits(ol.render.canvas.LineStringReplay, ol.render.canvas.Replay);
  10170. /**
  10171. * @param {Array.<number>} flatCoordinates Flat coordinates.
  10172. * @param {number} offset Offset.
  10173. * @param {number} end End.
  10174. * @param {number} stride Stride.
  10175. * @private
  10176. * @return {number} end.
  10177. */
  10178. ol.render.canvas.LineStringReplay.prototype.drawFlatCoordinates_ = function(flatCoordinates, offset, end, stride) {
  10179. var myBegin = this.coordinates.length;
  10180. var myEnd = this.appendFlatCoordinates(
  10181. flatCoordinates, offset, end, stride, false, false);
  10182. var moveToLineToInstruction =
  10183. [ol.render.canvas.Instruction.MOVE_TO_LINE_TO, myBegin, myEnd];
  10184. this.instructions.push(moveToLineToInstruction);
  10185. this.hitDetectionInstructions.push(moveToLineToInstruction);
  10186. return end;
  10187. };
  10188. /**
  10189. * @inheritDoc
  10190. */
  10191. ol.render.canvas.LineStringReplay.prototype.drawLineString = function(lineStringGeometry, feature) {
  10192. var state = this.state;
  10193. var strokeStyle = state.strokeStyle;
  10194. var lineWidth = state.lineWidth;
  10195. if (strokeStyle === undefined || lineWidth === undefined) {
  10196. return;
  10197. }
  10198. this.updateStrokeStyle(state, this.applyStroke);
  10199. this.beginGeometry(lineStringGeometry, feature);
  10200. this.hitDetectionInstructions.push([
  10201. ol.render.canvas.Instruction.SET_STROKE_STYLE,
  10202. state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
  10203. state.miterLimit, state.lineDash, state.lineDashOffset
  10204. ], [
  10205. ol.render.canvas.Instruction.BEGIN_PATH
  10206. ]);
  10207. var flatCoordinates = lineStringGeometry.getFlatCoordinates();
  10208. var stride = lineStringGeometry.getStride();
  10209. this.drawFlatCoordinates_(flatCoordinates, 0, flatCoordinates.length, stride);
  10210. this.hitDetectionInstructions.push([ol.render.canvas.Instruction.STROKE]);
  10211. this.endGeometry(lineStringGeometry, feature);
  10212. };
  10213. /**
  10214. * @inheritDoc
  10215. */
  10216. ol.render.canvas.LineStringReplay.prototype.drawMultiLineString = function(multiLineStringGeometry, feature) {
  10217. var state = this.state;
  10218. var strokeStyle = state.strokeStyle;
  10219. var lineWidth = state.lineWidth;
  10220. if (strokeStyle === undefined || lineWidth === undefined) {
  10221. return;
  10222. }
  10223. this.updateStrokeStyle(state, this.applyStroke);
  10224. this.beginGeometry(multiLineStringGeometry, feature);
  10225. this.hitDetectionInstructions.push([
  10226. ol.render.canvas.Instruction.SET_STROKE_STYLE,
  10227. state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
  10228. state.miterLimit, state.lineDash, state.lineDashOffset
  10229. ], [
  10230. ol.render.canvas.Instruction.BEGIN_PATH
  10231. ]);
  10232. var ends = multiLineStringGeometry.getEnds();
  10233. var flatCoordinates = multiLineStringGeometry.getFlatCoordinates();
  10234. var stride = multiLineStringGeometry.getStride();
  10235. var offset = 0;
  10236. var i, ii;
  10237. for (i = 0, ii = ends.length; i < ii; ++i) {
  10238. offset = this.drawFlatCoordinates_(
  10239. flatCoordinates, offset, ends[i], stride);
  10240. }
  10241. this.hitDetectionInstructions.push([ol.render.canvas.Instruction.STROKE]);
  10242. this.endGeometry(multiLineStringGeometry, feature);
  10243. };
  10244. /**
  10245. * @inheritDoc
  10246. */
  10247. ol.render.canvas.LineStringReplay.prototype.finish = function() {
  10248. var state = this.state;
  10249. if (state.lastStroke != undefined && state.lastStroke != this.coordinates.length) {
  10250. this.instructions.push([ol.render.canvas.Instruction.STROKE]);
  10251. }
  10252. this.reverseHitDetectionInstructions();
  10253. this.state = null;
  10254. };
  10255. /**
  10256. * @inheritDoc.
  10257. */
  10258. ol.render.canvas.LineStringReplay.prototype.applyStroke = function(state) {
  10259. if (state.lastStroke != undefined && state.lastStroke != this.coordinates.length) {
  10260. this.instructions.push([ol.render.canvas.Instruction.STROKE]);
  10261. state.lastStroke = this.coordinates.length;
  10262. }
  10263. state.lastStroke = 0;
  10264. ol.render.canvas.Replay.prototype.applyStroke.call(this, state);
  10265. this.instructions.push([ol.render.canvas.Instruction.BEGIN_PATH]);
  10266. };
  10267. /**
  10268. * @constructor
  10269. * @extends {ol.render.canvas.Replay}
  10270. * @param {number} tolerance Tolerance.
  10271. * @param {ol.Extent} maxExtent Maximum extent.
  10272. * @param {number} resolution Resolution.
  10273. * @param {number} pixelRatio Pixel ratio.
  10274. * @param {boolean} overlaps The replay can have overlapping geometries.
  10275. * @param {?} declutterTree Declutter tree.
  10276. * @struct
  10277. */
  10278. ol.render.canvas.PolygonReplay = function(
  10279. tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) {
  10280. ol.render.canvas.Replay.call(this,
  10281. tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree);
  10282. };
  10283. ol.inherits(ol.render.canvas.PolygonReplay, ol.render.canvas.Replay);
  10284. /**
  10285. * @param {Array.<number>} flatCoordinates Flat coordinates.
  10286. * @param {number} offset Offset.
  10287. * @param {Array.<number>} ends Ends.
  10288. * @param {number} stride Stride.
  10289. * @private
  10290. * @return {number} End.
  10291. */
  10292. ol.render.canvas.PolygonReplay.prototype.drawFlatCoordinatess_ = function(flatCoordinates, offset, ends, stride) {
  10293. var state = this.state;
  10294. var fill = state.fillStyle !== undefined;
  10295. var stroke = state.strokeStyle != undefined;
  10296. var numEnds = ends.length;
  10297. var beginPathInstruction = [ol.render.canvas.Instruction.BEGIN_PATH];
  10298. this.instructions.push(beginPathInstruction);
  10299. this.hitDetectionInstructions.push(beginPathInstruction);
  10300. for (var i = 0; i < numEnds; ++i) {
  10301. var end = ends[i];
  10302. var myBegin = this.coordinates.length;
  10303. var myEnd = this.appendFlatCoordinates(
  10304. flatCoordinates, offset, end, stride, true, !stroke);
  10305. var moveToLineToInstruction =
  10306. [ol.render.canvas.Instruction.MOVE_TO_LINE_TO, myBegin, myEnd];
  10307. this.instructions.push(moveToLineToInstruction);
  10308. this.hitDetectionInstructions.push(moveToLineToInstruction);
  10309. if (stroke) {
  10310. // Performance optimization: only call closePath() when we have a stroke.
  10311. // Otherwise the ring is closed already (see appendFlatCoordinates above).
  10312. var closePathInstruction = [ol.render.canvas.Instruction.CLOSE_PATH];
  10313. this.instructions.push(closePathInstruction);
  10314. this.hitDetectionInstructions.push(closePathInstruction);
  10315. }
  10316. offset = end;
  10317. }
  10318. var fillInstruction = [ol.render.canvas.Instruction.FILL];
  10319. this.hitDetectionInstructions.push(fillInstruction);
  10320. if (fill) {
  10321. this.instructions.push(fillInstruction);
  10322. }
  10323. if (stroke) {
  10324. var strokeInstruction = [ol.render.canvas.Instruction.STROKE];
  10325. this.instructions.push(strokeInstruction);
  10326. this.hitDetectionInstructions.push(strokeInstruction);
  10327. }
  10328. return offset;
  10329. };
  10330. /**
  10331. * @inheritDoc
  10332. */
  10333. ol.render.canvas.PolygonReplay.prototype.drawCircle = function(circleGeometry, feature) {
  10334. var state = this.state;
  10335. var fillStyle = state.fillStyle;
  10336. var strokeStyle = state.strokeStyle;
  10337. if (fillStyle === undefined && strokeStyle === undefined) {
  10338. return;
  10339. }
  10340. this.setFillStrokeStyles_(circleGeometry);
  10341. this.beginGeometry(circleGeometry, feature);
  10342. // always fill the circle for hit detection
  10343. this.hitDetectionInstructions.push([
  10344. ol.render.canvas.Instruction.SET_FILL_STYLE,
  10345. ol.color.asString(ol.render.canvas.defaultFillStyle)
  10346. ]);
  10347. if (state.strokeStyle !== undefined) {
  10348. this.hitDetectionInstructions.push([
  10349. ol.render.canvas.Instruction.SET_STROKE_STYLE,
  10350. state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
  10351. state.miterLimit, state.lineDash, state.lineDashOffset
  10352. ]);
  10353. }
  10354. var flatCoordinates = circleGeometry.getFlatCoordinates();
  10355. var stride = circleGeometry.getStride();
  10356. var myBegin = this.coordinates.length;
  10357. this.appendFlatCoordinates(
  10358. flatCoordinates, 0, flatCoordinates.length, stride, false, false);
  10359. var beginPathInstruction = [ol.render.canvas.Instruction.BEGIN_PATH];
  10360. var circleInstruction = [ol.render.canvas.Instruction.CIRCLE, myBegin];
  10361. this.instructions.push(beginPathInstruction, circleInstruction);
  10362. this.hitDetectionInstructions.push(beginPathInstruction, circleInstruction);
  10363. var fillInstruction = [ol.render.canvas.Instruction.FILL];
  10364. this.hitDetectionInstructions.push(fillInstruction);
  10365. if (state.fillStyle !== undefined) {
  10366. this.instructions.push(fillInstruction);
  10367. }
  10368. if (state.strokeStyle !== undefined) {
  10369. var strokeInstruction = [ol.render.canvas.Instruction.STROKE];
  10370. this.instructions.push(strokeInstruction);
  10371. this.hitDetectionInstructions.push(strokeInstruction);
  10372. }
  10373. this.endGeometry(circleGeometry, feature);
  10374. };
  10375. /**
  10376. * @inheritDoc
  10377. */
  10378. ol.render.canvas.PolygonReplay.prototype.drawPolygon = function(polygonGeometry, feature) {
  10379. var state = this.state;
  10380. this.setFillStrokeStyles_(polygonGeometry);
  10381. this.beginGeometry(polygonGeometry, feature);
  10382. // always fill the polygon for hit detection
  10383. this.hitDetectionInstructions.push([
  10384. ol.render.canvas.Instruction.SET_FILL_STYLE,
  10385. ol.color.asString(ol.render.canvas.defaultFillStyle)]
  10386. );
  10387. if (state.strokeStyle !== undefined) {
  10388. this.hitDetectionInstructions.push([
  10389. ol.render.canvas.Instruction.SET_STROKE_STYLE,
  10390. state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
  10391. state.miterLimit, state.lineDash, state.lineDashOffset
  10392. ]);
  10393. }
  10394. var ends = polygonGeometry.getEnds();
  10395. var flatCoordinates = polygonGeometry.getOrientedFlatCoordinates();
  10396. var stride = polygonGeometry.getStride();
  10397. this.drawFlatCoordinatess_(flatCoordinates, 0, ends, stride);
  10398. this.endGeometry(polygonGeometry, feature);
  10399. };
  10400. /**
  10401. * @inheritDoc
  10402. */
  10403. ol.render.canvas.PolygonReplay.prototype.drawMultiPolygon = function(multiPolygonGeometry, feature) {
  10404. var state = this.state;
  10405. var fillStyle = state.fillStyle;
  10406. var strokeStyle = state.strokeStyle;
  10407. if (fillStyle === undefined && strokeStyle === undefined) {
  10408. return;
  10409. }
  10410. this.setFillStrokeStyles_(multiPolygonGeometry);
  10411. this.beginGeometry(multiPolygonGeometry, feature);
  10412. // always fill the multi-polygon for hit detection
  10413. this.hitDetectionInstructions.push([
  10414. ol.render.canvas.Instruction.SET_FILL_STYLE,
  10415. ol.color.asString(ol.render.canvas.defaultFillStyle)
  10416. ]);
  10417. if (state.strokeStyle !== undefined) {
  10418. this.hitDetectionInstructions.push([
  10419. ol.render.canvas.Instruction.SET_STROKE_STYLE,
  10420. state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin,
  10421. state.miterLimit, state.lineDash, state.lineDashOffset
  10422. ]);
  10423. }
  10424. var endss = multiPolygonGeometry.getEndss();
  10425. var flatCoordinates = multiPolygonGeometry.getOrientedFlatCoordinates();
  10426. var stride = multiPolygonGeometry.getStride();
  10427. var offset = 0;
  10428. var i, ii;
  10429. for (i = 0, ii = endss.length; i < ii; ++i) {
  10430. offset = this.drawFlatCoordinatess_(
  10431. flatCoordinates, offset, endss[i], stride);
  10432. }
  10433. this.endGeometry(multiPolygonGeometry, feature);
  10434. };
  10435. /**
  10436. * @inheritDoc
  10437. */
  10438. ol.render.canvas.PolygonReplay.prototype.finish = function() {
  10439. this.reverseHitDetectionInstructions();
  10440. this.state = null;
  10441. // We want to preserve topology when drawing polygons. Polygons are
  10442. // simplified using quantization and point elimination. However, we might
  10443. // have received a mix of quantized and non-quantized geometries, so ensure
  10444. // that all are quantized by quantizing all coordinates in the batch.
  10445. var tolerance = this.tolerance;
  10446. if (tolerance !== 0) {
  10447. var coordinates = this.coordinates;
  10448. var i, ii;
  10449. for (i = 0, ii = coordinates.length; i < ii; ++i) {
  10450. coordinates[i] = ol.geom.flat.simplify.snap(coordinates[i], tolerance);
  10451. }
  10452. }
  10453. };
  10454. /**
  10455. * @private
  10456. * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
  10457. */
  10458. ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyles_ = function(geometry) {
  10459. var state = this.state;
  10460. var fillStyle = state.fillStyle;
  10461. if (fillStyle !== undefined) {
  10462. this.updateFillStyle(state, this.applyFill, geometry);
  10463. }
  10464. if (state.strokeStyle !== undefined) {
  10465. this.updateStrokeStyle(state, this.applyStroke);
  10466. }
  10467. };
  10468. ol.geom.flat.straightchunk = {};
  10469. ol.geom.flat.straightchunk.lineString = function(maxAngle, flatCoordinates, offset, end, stride) {
  10470. var chunkStart = offset;
  10471. var chunkEnd = offset;
  10472. var chunkM = 0;
  10473. var m = 0;
  10474. var start = offset;
  10475. var acos, i, m12, m23, x1, y1, x12, y12, x23, y23;
  10476. for (i = offset; i < end; i += stride) {
  10477. var x2 = flatCoordinates[i];
  10478. var y2 = flatCoordinates[i + 1];
  10479. if (x1 !== undefined) {
  10480. x23 = x2 - x1;
  10481. y23 = y2 - y1;
  10482. m23 = Math.sqrt(x23 * x23 + y23 * y23);
  10483. if (x12 !== undefined) {
  10484. m += m12;
  10485. acos = Math.acos((x12 * x23 + y12 * y23) / (m12 * m23));
  10486. if (acos > maxAngle) {
  10487. if (m > chunkM) {
  10488. chunkM = m;
  10489. chunkStart = start;
  10490. chunkEnd = i;
  10491. }
  10492. m = 0;
  10493. start = i - stride;
  10494. }
  10495. }
  10496. m12 = m23;
  10497. x12 = x23;
  10498. y12 = y23;
  10499. }
  10500. x1 = x2;
  10501. y1 = y2;
  10502. }
  10503. m += m23;
  10504. return m > chunkM ? [start, i] : [chunkStart, chunkEnd];
  10505. };
  10506. ol.style.TextPlacement = {
  10507. POINT: 'point',
  10508. LINE: 'line'
  10509. };
  10510. ol.render.canvas.TextReplay = function(
  10511. tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) {
  10512. ol.render.canvas.Replay.call(this,
  10513. tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree);
  10514. /**
  10515. * @private
  10516. * @type {ol.DeclutterGroup}
  10517. */
  10518. this.declutterGroup_;
  10519. /**
  10520. * @private
  10521. * @type {Array.<HTMLCanvasElement>}
  10522. */
  10523. this.labels_ = null;
  10524. /**
  10525. * @private
  10526. * @type {string}
  10527. */
  10528. this.text_ = '';
  10529. /**
  10530. * @private
  10531. * @type {number}
  10532. */
  10533. this.textOffsetX_ = 0;
  10534. /**
  10535. * @private
  10536. * @type {number}
  10537. */
  10538. this.textOffsetY_ = 0;
  10539. /**
  10540. * @private
  10541. * @type {boolean|undefined}
  10542. */
  10543. this.textRotateWithView_ = undefined;
  10544. /**
  10545. * @private
  10546. * @type {number}
  10547. */
  10548. this.textRotation_ = 0;
  10549. /**
  10550. * @private
  10551. * @type {?ol.CanvasFillState}
  10552. */
  10553. this.textFillState_ = null;
  10554. /**
  10555. * @type {Object.<string, ol.CanvasFillState>}
  10556. */
  10557. this.fillStates = {};
  10558. /**
  10559. * @private
  10560. * @type {?ol.CanvasStrokeState}
  10561. */
  10562. this.textStrokeState_ = null;
  10563. /**
  10564. * @type {Object.<string, ol.CanvasStrokeState>}
  10565. */
  10566. this.strokeStates = {};
  10567. /**
  10568. * @private
  10569. * @type {ol.CanvasTextState}
  10570. */
  10571. this.textState_ = /** @type {ol.CanvasTextState} */ ({});
  10572. /**
  10573. * @type {Object.<string, ol.CanvasTextState>}
  10574. */
  10575. this.textStates = {};
  10576. /**
  10577. * @private
  10578. * @type {string}
  10579. */
  10580. this.textKey_ = '';
  10581. /**
  10582. * @private
  10583. * @type {string}
  10584. */
  10585. this.fillKey_ = '';
  10586. /**
  10587. * @private
  10588. * @type {string}
  10589. */
  10590. this.strokeKey_ = '';
  10591. /**
  10592. * @private
  10593. * @type {Object.<string, Object.<string, number>>}
  10594. */
  10595. this.widths_ = {};
  10596. var labelCache = ol.render.canvas.labelCache;
  10597. labelCache.prune();
  10598. };
  10599. ol.inherits(ol.render.canvas.TextReplay, ol.render.canvas.Replay);
  10600. /**
  10601. * @param {string} font Font to use for measuring.
  10602. * @param {Array.<string>} lines Lines to measure.
  10603. * @param {Array.<number>} widths Array will be populated with the widths of
  10604. * each line.
  10605. * @return {number} Width of the whole text.
  10606. */
  10607. ol.render.canvas.TextReplay.measureTextWidths = function(font, lines, widths) {
  10608. var numLines = lines.length;
  10609. var width = 0;
  10610. var currentWidth, i;
  10611. for (i = 0; i < numLines; ++i) {
  10612. currentWidth = ol.render.canvas.measureTextWidth(font, lines[i]);
  10613. width = Math.max(width, currentWidth);
  10614. widths.push(currentWidth);
  10615. }
  10616. return width;
  10617. };
  10618. /**
  10619. * @inheritDoc
  10620. */
  10621. ol.render.canvas.TextReplay.prototype.drawText = function(geometry, feature) {
  10622. var fillState = this.textFillState_;
  10623. var strokeState = this.textStrokeState_;
  10624. var textState = this.textState_;
  10625. if (this.text_ === '' || !textState || (!fillState && !strokeState)) {
  10626. return;
  10627. }
  10628. var begin = this.coordinates.length;
  10629. var geometryType = geometry.getType();
  10630. var flatCoordinates = null;
  10631. var end = 2;
  10632. var stride = 2;
  10633. var i, ii;
  10634. if (textState.placement === ol.style.TextPlacement.LINE) {
  10635. if (!ol.extent.intersects(this.getBufferedMaxExtent(), geometry.getExtent())) {
  10636. return;
  10637. }
  10638. var ends;
  10639. flatCoordinates = geometry.getFlatCoordinates();
  10640. stride = geometry.getStride();
  10641. if (geometryType == ol.geom.GeometryType.LINE_STRING) {
  10642. ends = [flatCoordinates.length];
  10643. } else if (geometryType == ol.geom.GeometryType.MULTI_LINE_STRING) {
  10644. ends = geometry.getEnds();
  10645. } else if (geometryType == ol.geom.GeometryType.POLYGON) {
  10646. ends = geometry.getEnds().slice(0, 1);
  10647. } else if (geometryType == ol.geom.GeometryType.MULTI_POLYGON) {
  10648. var endss = geometry.getEndss();
  10649. ends = [];
  10650. for (i = 0, ii = endss.length; i < ii; ++i) {
  10651. ends.push(endss[i][0]);
  10652. }
  10653. }
  10654. this.beginGeometry(geometry, feature);
  10655. var textAlign = textState.textAlign;
  10656. var flatOffset = 0;
  10657. var flatEnd;
  10658. for (var o = 0, oo = ends.length; o < oo; ++o) {
  10659. if (textAlign == undefined) {
  10660. var range = ol.geom.flat.straightchunk.lineString(
  10661. textState.maxAngle, flatCoordinates, flatOffset, ends[o], stride);
  10662. flatOffset = range[0];
  10663. flatEnd = range[1];
  10664. } else {
  10665. flatEnd = ends[o];
  10666. }
  10667. for (i = flatOffset; i < flatEnd; i += stride) {
  10668. this.coordinates.push(flatCoordinates[i], flatCoordinates[i + 1]);
  10669. }
  10670. end = this.coordinates.length;
  10671. flatOffset = ends[o];
  10672. this.drawChars_(begin, end, this.declutterGroup_);
  10673. begin = end;
  10674. }
  10675. this.endGeometry(geometry, feature);
  10676. } else {
  10677. var label = this.getImage(this.text_, this.textKey_, this.fillKey_, this.strokeKey_);
  10678. var width = label.width / this.pixelRatio;
  10679. switch (geometryType) {
  10680. case ol.geom.GeometryType.POINT:
  10681. case ol.geom.GeometryType.MULTI_POINT:
  10682. flatCoordinates = geometry.getFlatCoordinates();
  10683. end = flatCoordinates.length;
  10684. break;
  10685. case ol.geom.GeometryType.LINE_STRING:
  10686. flatCoordinates = /** @type {ol.geom.LineString} */ (geometry).getFlatMidpoint();
  10687. break;
  10688. case ol.geom.GeometryType.CIRCLE:
  10689. flatCoordinates = /** @type {ol.geom.Circle} */ (geometry).getCenter();
  10690. break;
  10691. case ol.geom.GeometryType.MULTI_LINE_STRING:
  10692. flatCoordinates = /** @type {ol.geom.MultiLineString} */ (geometry).getFlatMidpoints();
  10693. end = flatCoordinates.length;
  10694. break;
  10695. case ol.geom.GeometryType.POLYGON:
  10696. flatCoordinates = /** @type {ol.geom.Polygon} */ (geometry).getFlatInteriorPoint();
  10697. if (!textState.overflow && flatCoordinates[2] / this.resolution < width) {
  10698. return;
  10699. }
  10700. stride = 3;
  10701. break;
  10702. case ol.geom.GeometryType.MULTI_POLYGON:
  10703. var interiorPoints = /** @type {ol.geom.MultiPolygon} */ (geometry).getFlatInteriorPoints();
  10704. flatCoordinates = [];
  10705. for (i = 0, ii = interiorPoints.length; i < ii; i += 3) {
  10706. if (textState.overflow || interiorPoints[i + 2] / this.resolution >= width) {
  10707. flatCoordinates.push(interiorPoints[i], interiorPoints[i + 1]);
  10708. }
  10709. }
  10710. end = flatCoordinates.length;
  10711. if (end == 0) {
  10712. return;
  10713. }
  10714. break;
  10715. }
  10716. end = this.appendFlatCoordinates(flatCoordinates, 0, end, stride, false, false);
  10717. this.beginGeometry(geometry, feature);
  10718. if (textState.backgroundFill || textState.backgroundStroke) {
  10719. this.setFillStrokeStyle(textState.backgroundFill, textState.backgroundStroke);
  10720. this.updateFillStyle(this.state, this.applyFill, geometry);
  10721. this.updateStrokeStyle(this.state, this.applyStroke);
  10722. }
  10723. this.drawTextImage_(label, begin, end);
  10724. this.endGeometry(geometry, feature);
  10725. }
  10726. };
  10727. /**
  10728. * @param {string} text Text.
  10729. * @param {string} textKey Text style key.
  10730. * @param {string} fillKey Fill style key.
  10731. * @param {string} strokeKey Stroke style key.
  10732. * @return {HTMLCanvasElement} Image.
  10733. */
  10734. ol.render.canvas.TextReplay.prototype.getImage = function(text, textKey, fillKey, strokeKey) {
  10735. var label;
  10736. var key = strokeKey + textKey + text + fillKey + this.pixelRatio;
  10737. var labelCache = ol.render.canvas.labelCache;
  10738. if (!labelCache.containsKey(key)) {
  10739. var strokeState = strokeKey ? this.strokeStates[strokeKey] || this.textStrokeState_ : null;
  10740. var fillState = fillKey ? this.fillStates[fillKey] || this.textFillState_ : null;
  10741. var textState = this.textStates[textKey] || this.textState_;
  10742. var pixelRatio = this.pixelRatio;
  10743. var scale = textState.scale * pixelRatio;
  10744. var align = ol.render.replay.TEXT_ALIGN[textState.textAlign || ol.render.canvas.defaultTextAlign];
  10745. var strokeWidth = strokeKey && strokeState.lineWidth ? strokeState.lineWidth : 0;
  10746. var lines = text.split('\n');
  10747. var numLines = lines.length;
  10748. var widths = [];
  10749. var width = ol.render.canvas.TextReplay.measureTextWidths(textState.font, lines, widths);
  10750. var lineHeight = ol.render.canvas.measureTextHeight(textState.font);
  10751. var height = lineHeight * numLines;
  10752. var renderWidth = (width + strokeWidth);
  10753. var context = ol.dom.createCanvasContext2D(
  10754. Math.ceil(renderWidth * scale),
  10755. Math.ceil((height + strokeWidth) * scale));
  10756. label = context.canvas;
  10757. labelCache.set(key, label);
  10758. if (scale != 1) {
  10759. context.scale(scale, scale);
  10760. }
  10761. context.font = textState.font;
  10762. if (strokeKey) {
  10763. context.strokeStyle = strokeState.strokeStyle;
  10764. context.lineWidth = strokeWidth * (ol.has.SAFARI ? scale : 1);
  10765. context.lineCap = strokeState.lineCap;
  10766. context.lineJoin = strokeState.lineJoin;
  10767. context.miterLimit = strokeState.miterLimit;
  10768. if (ol.has.CANVAS_LINE_DASH && strokeState.lineDash.length) {
  10769. context.setLineDash(strokeState.lineDash);
  10770. context.lineDashOffset = strokeState.lineDashOffset;
  10771. }
  10772. }
  10773. if (fillKey) {
  10774. context.fillStyle = fillState.fillStyle;
  10775. }
  10776. context.textBaseline = 'middle';
  10777. context.textAlign = 'center';
  10778. var leftRight = (0.5 - align);
  10779. var x = align * label.width / scale + leftRight * strokeWidth;
  10780. var i;
  10781. if (strokeKey) {
  10782. for (i = 0; i < numLines; ++i) {
  10783. context.strokeText(lines[i], x + leftRight * widths[i], 0.5 * (strokeWidth + lineHeight) + i * lineHeight);
  10784. }
  10785. }
  10786. if (fillKey) {
  10787. for (i = 0; i < numLines; ++i) {
  10788. context.fillText(lines[i], x + leftRight * widths[i], 0.5 * (strokeWidth + lineHeight) + i * lineHeight);
  10789. }
  10790. }
  10791. }
  10792. return labelCache.get(key);
  10793. };
  10794. /**
  10795. * @private
  10796. * @param {HTMLCanvasElement} label Label.
  10797. * @param {number} begin Begin.
  10798. * @param {number} end End.
  10799. */
  10800. ol.render.canvas.TextReplay.prototype.drawTextImage_ = function(label, begin, end) {
  10801. var textState = this.textState_;
  10802. var strokeState = this.textStrokeState_;
  10803. var pixelRatio = this.pixelRatio;
  10804. var align = ol.render.replay.TEXT_ALIGN[textState.textAlign || ol.render.canvas.defaultTextAlign];
  10805. var baseline = ol.render.replay.TEXT_ALIGN[textState.textBaseline];
  10806. var strokeWidth = strokeState && strokeState.lineWidth ? strokeState.lineWidth : 0;
  10807. var anchorX = align * label.width / pixelRatio + 2 * (0.5 - align) * strokeWidth;
  10808. var anchorY = baseline * label.height / pixelRatio + 2 * (0.5 - baseline) * strokeWidth;
  10809. this.instructions.push([ol.render.canvas.Instruction.DRAW_IMAGE, begin, end,
  10810. label, (anchorX - this.textOffsetX_) * pixelRatio, (anchorY - this.textOffsetY_) * pixelRatio,
  10811. this.declutterGroup_, label.height, 1, 0, 0, this.textRotateWithView_, this.textRotation_,
  10812. 1, true, label.width,
  10813. textState.padding == ol.render.canvas.defaultPadding ?
  10814. ol.render.canvas.defaultPadding : textState.padding.map(function(p) {
  10815. return p * pixelRatio;
  10816. }),
  10817. !!textState.backgroundFill, !!textState.backgroundStroke
  10818. ]);
  10819. this.hitDetectionInstructions.push([ol.render.canvas.Instruction.DRAW_IMAGE, begin, end,
  10820. label, (anchorX - this.textOffsetX_) * pixelRatio, (anchorY - this.textOffsetY_) * pixelRatio,
  10821. this.declutterGroup_, label.height, 1, 0, 0, this.textRotateWithView_, this.textRotation_,
  10822. 1 / pixelRatio, true, label.width, textState.padding,
  10823. !!textState.backgroundFill, !!textState.backgroundStroke
  10824. ]);
  10825. };
  10826. /**
  10827. * @private
  10828. * @param {number} begin Begin.
  10829. * @param {number} end End.
  10830. * @param {ol.DeclutterGroup} declutterGroup Declutter group.
  10831. */
  10832. ol.render.canvas.TextReplay.prototype.drawChars_ = function(begin, end, declutterGroup) {
  10833. var strokeState = this.textStrokeState_;
  10834. var textState = this.textState_;
  10835. var fillState = this.textFillState_;
  10836. var strokeKey = this.strokeKey_;
  10837. if (strokeState) {
  10838. if (!(strokeKey in this.strokeStates)) {
  10839. this.strokeStates[strokeKey] = /** @type {ol.CanvasStrokeState} */ ({
  10840. strokeStyle: strokeState.strokeStyle,
  10841. lineCap: strokeState.lineCap,
  10842. lineDashOffset: strokeState.lineDashOffset,
  10843. lineWidth: strokeState.lineWidth,
  10844. lineJoin: strokeState.lineJoin,
  10845. miterLimit: strokeState.miterLimit,
  10846. lineDash: strokeState.lineDash
  10847. });
  10848. }
  10849. }
  10850. var textKey = this.textKey_;
  10851. if (!(this.textKey_ in this.textStates)) {
  10852. this.textStates[this.textKey_] = /** @type {ol.CanvasTextState} */ ({
  10853. font: textState.font,
  10854. textAlign: textState.textAlign || ol.render.canvas.defaultTextAlign,
  10855. scale: textState.scale
  10856. });
  10857. }
  10858. var fillKey = this.fillKey_;
  10859. if (fillState) {
  10860. if (!(fillKey in this.fillStates)) {
  10861. this.fillStates[fillKey] = /** @type {ol.CanvasFillState} */ ({
  10862. fillStyle: fillState.fillStyle
  10863. });
  10864. }
  10865. }
  10866. var pixelRatio = this.pixelRatio;
  10867. var baseline = ol.render.replay.TEXT_ALIGN[textState.textBaseline];
  10868. var offsetY = this.textOffsetY_ * pixelRatio;
  10869. var text = this.text_;
  10870. var font = textState.font;
  10871. var textScale = textState.scale;
  10872. var strokeWidth = strokeState ? strokeState.lineWidth * textScale / 2 : 0;
  10873. var widths = this.widths_[font];
  10874. if (!widths) {
  10875. this.widths_[font] = widths = {};
  10876. }
  10877. this.instructions.push([ol.render.canvas.Instruction.DRAW_CHARS,
  10878. begin, end, baseline, declutterGroup,
  10879. textState.overflow, fillKey, textState.maxAngle,
  10880. function(text) {
  10881. var width = widths[text];
  10882. if (!width) {
  10883. width = widths[text] = ol.render.canvas.measureTextWidth(font, text);
  10884. }
  10885. return width * textScale * pixelRatio;
  10886. },
  10887. offsetY, strokeKey, strokeWidth * pixelRatio, text, textKey, 1
  10888. ]);
  10889. this.hitDetectionInstructions.push([ol.render.canvas.Instruction.DRAW_CHARS,
  10890. begin, end, baseline, declutterGroup,
  10891. textState.overflow, fillKey, textState.maxAngle,
  10892. function(text) {
  10893. var width = widths[text];
  10894. if (!width) {
  10895. width = widths[text] = ol.render.canvas.measureTextWidth(font, text);
  10896. }
  10897. return width * textScale;
  10898. },
  10899. offsetY, strokeKey, strokeWidth, text, textKey, 1 / pixelRatio
  10900. ]);
  10901. };
  10902. /**
  10903. * @inheritDoc
  10904. */
  10905. ol.render.canvas.TextReplay.prototype.setTextStyle = function(textStyle, declutterGroup) {
  10906. var textState, fillState, strokeState;
  10907. if (!textStyle) {
  10908. this.text_ = '';
  10909. } else {
  10910. this.declutterGroup_ = /** @type {ol.DeclutterGroup} */ (declutterGroup);
  10911. var textFillStyle = textStyle.getFill();
  10912. if (!textFillStyle) {
  10913. fillState = this.textFillState_ = null;
  10914. } else {
  10915. fillState = this.textFillState_;
  10916. if (!fillState) {
  10917. fillState = this.textFillState_ = /** @type {ol.CanvasFillState} */ ({});
  10918. }
  10919. fillState.fillStyle = ol.colorlike.asColorLike(
  10920. textFillStyle.getColor() || ol.render.canvas.defaultFillStyle);
  10921. }
  10922. var textStrokeStyle = textStyle.getStroke();
  10923. if (!textStrokeStyle) {
  10924. strokeState = this.textStrokeState_ = null;
  10925. } else {
  10926. strokeState = this.textStrokeState_;
  10927. if (!strokeState) {
  10928. strokeState = this.textStrokeState_ = /** @type {ol.CanvasStrokeState} */ ({});
  10929. }
  10930. var lineDash = textStrokeStyle.getLineDash();
  10931. var lineDashOffset = textStrokeStyle.getLineDashOffset();
  10932. var lineWidth = textStrokeStyle.getWidth();
  10933. var miterLimit = textStrokeStyle.getMiterLimit();
  10934. strokeState.lineCap = textStrokeStyle.getLineCap() || ol.render.canvas.defaultLineCap;
  10935. strokeState.lineDash = lineDash ? lineDash.slice() : ol.render.canvas.defaultLineDash;
  10936. strokeState.lineDashOffset =
  10937. lineDashOffset === undefined ? ol.render.canvas.defaultLineDashOffset : lineDashOffset;
  10938. strokeState.lineJoin = textStrokeStyle.getLineJoin() || ol.render.canvas.defaultLineJoin;
  10939. strokeState.lineWidth =
  10940. lineWidth === undefined ? ol.render.canvas.defaultLineWidth : lineWidth;
  10941. strokeState.miterLimit =
  10942. miterLimit === undefined ? ol.render.canvas.defaultMiterLimit : miterLimit;
  10943. strokeState.strokeStyle = ol.colorlike.asColorLike(
  10944. textStrokeStyle.getColor() || ol.render.canvas.defaultStrokeStyle);
  10945. }
  10946. textState = this.textState_;
  10947. var font = textStyle.getFont() || ol.render.canvas.defaultFont;
  10948. //ol.render.canvas.checkFont(font); // FIXME sunyl
  10949. var textScale = textStyle.getScale();
  10950. textState.overflow = textStyle.getOverflow();
  10951. textState.font = font;
  10952. textState.maxAngle = textStyle.getMaxAngle();
  10953. textState.placement = textStyle.getPlacement();
  10954. textState.textAlign = textStyle.getTextAlign();
  10955. textState.textBaseline = textStyle.getTextBaseline() || ol.render.canvas.defaultTextBaseline;
  10956. textState.backgroundFill = textStyle.getBackgroundFill();
  10957. textState.backgroundStroke = textStyle.getBackgroundStroke();
  10958. textState.padding = textStyle.getPadding() || ol.render.canvas.defaultPadding;
  10959. textState.scale = textScale === undefined ? 1 : textScale;
  10960. var textOffsetX = textStyle.getOffsetX();
  10961. var textOffsetY = textStyle.getOffsetY();
  10962. var textRotateWithView = textStyle.getRotateWithView();
  10963. var textRotation = textStyle.getRotation();
  10964. this.text_ = textStyle.getText() || '';
  10965. this.textOffsetX_ = textOffsetX === undefined ? 0 : textOffsetX;
  10966. this.textOffsetY_ = textOffsetY === undefined ? 0 : textOffsetY;
  10967. this.textRotateWithView_ = textRotateWithView === undefined ? false : textRotateWithView;
  10968. this.textRotation_ = textRotation === undefined ? 0 : textRotation;
  10969. this.strokeKey_ = strokeState ?
  10970. (typeof strokeState.strokeStyle == 'string' ? strokeState.strokeStyle : ol.getUid(strokeState.strokeStyle)) +
  10971. strokeState.lineCap + strokeState.lineDashOffset + '|' + strokeState.lineWidth +
  10972. strokeState.lineJoin + strokeState.miterLimit + '[' + strokeState.lineDash.join() + ']' :
  10973. '';
  10974. this.textKey_ = textState.font + textState.scale + (textState.textAlign || '?');
  10975. this.fillKey_ = fillState ?
  10976. (typeof fillState.fillStyle == 'string' ? fillState.fillStyle : ('|' + ol.getUid(fillState.fillStyle))) :
  10977. '';
  10978. }
  10979. };
  10980. /**
  10981. * @constructor
  10982. * @extends {ol.render.ReplayGroup}
  10983. * @param {number} tolerance Tolerance.
  10984. * @param {ol.Extent} maxExtent Max extent.
  10985. * @param {number} resolution Resolution.
  10986. * @param {number} pixelRatio Pixel ratio.
  10987. * @param {boolean} overlaps The replay group can have overlapping geometries.
  10988. * @param {?} declutterTree Declutter tree
  10989. * for declutter processing in postrender.
  10990. * @param {number=} opt_renderBuffer Optional rendering buffer.
  10991. * @struct
  10992. */
  10993. ol.render.canvas.ReplayGroup = function(
  10994. tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree, opt_renderBuffer) {
  10995. ol.render.ReplayGroup.call(this);
  10996. /**
  10997. * Declutter tree.
  10998. * @private
  10999. */
  11000. this.declutterTree_ = declutterTree;
  11001. /**
  11002. * @type {ol.DeclutterGroup}
  11003. * @private
  11004. */
  11005. this.declutterGroup_ = null;
  11006. /**
  11007. * @private
  11008. * @type {number}
  11009. */
  11010. this.tolerance_ = tolerance;
  11011. /**
  11012. * @private
  11013. * @type {ol.Extent}
  11014. */
  11015. this.maxExtent_ = maxExtent;
  11016. /**
  11017. * @private
  11018. * @type {boolean}
  11019. */
  11020. this.overlaps_ = overlaps;
  11021. /**
  11022. * @private
  11023. * @type {number}
  11024. */
  11025. this.pixelRatio_ = pixelRatio;
  11026. /**
  11027. * @private
  11028. * @type {number}
  11029. */
  11030. this.resolution_ = resolution;
  11031. /**
  11032. * @private
  11033. * @type {number|undefined}
  11034. */
  11035. this.renderBuffer_ = opt_renderBuffer;
  11036. /**
  11037. * @private
  11038. * @type {!Object.<string,
  11039. * Object.<ol.render.ReplayType, ol.render.canvas.Replay>>}
  11040. */
  11041. this.replaysByZIndex_ = {};
  11042. /**
  11043. * @private
  11044. * @type {CanvasRenderingContext2D}
  11045. */
  11046. // FIXME
  11047. this.hitDetectionContext_ = null;
  11048. /**
  11049. * @private
  11050. * @type {ol.Transform}
  11051. */
  11052. this.hitDetectionTransform_ = ol.transform.create();
  11053. };
  11054. ol.inherits(ol.render.canvas.ReplayGroup, ol.render.ReplayGroup);
  11055. /**
  11056. * This cache is used for storing calculated pixel circles for increasing performance.
  11057. * It is a static property to allow each Replaygroup to access it.
  11058. * @type {Object.<number, Array.<Array.<(boolean|undefined)>>>}
  11059. * @private
  11060. */
  11061. ol.render.canvas.ReplayGroup.circleArrayCache_ = {
  11062. 0: [[true]]
  11063. };
  11064. /**
  11065. * This method fills a row in the array from the given coordinate to the
  11066. * middle with `true`.
  11067. * @param {Array.<Array.<(boolean|undefined)>>} array The array that will be altered.
  11068. * @param {number} x X coordinate.
  11069. * @param {number} y Y coordinate.
  11070. * @private
  11071. */
  11072. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_ = function(array, x, y) {
  11073. var i;
  11074. var radius = Math.floor(array.length / 2);
  11075. if (x >= radius) {
  11076. for (i = radius; i < x; i++) {
  11077. array[i][y] = true;
  11078. }
  11079. } else if (x < radius) {
  11080. for (i = x + 1; i < radius; i++) {
  11081. array[i][y] = true;
  11082. }
  11083. }
  11084. };
  11085. /**
  11086. * This methods creates a circle inside a fitting array. Points inside the
  11087. * circle are marked by true, points on the outside are undefined.
  11088. * It uses the midpoint circle algorithm.
  11089. * A cache is used to increase performance.
  11090. * @param {number} radius Radius.
  11091. * @returns {Array.<Array.<(boolean|undefined)>>} An array with marked circle points.
  11092. * @private
  11093. */
  11094. ol.render.canvas.ReplayGroup.getCircleArray_ = function(radius) {
  11095. if (ol.render.canvas.ReplayGroup.circleArrayCache_[radius] !== undefined) {
  11096. return ol.render.canvas.ReplayGroup.circleArrayCache_[radius];
  11097. }
  11098. var arraySize = radius * 2 + 1;
  11099. var arr = new Array(arraySize);
  11100. for (var i = 0; i < arraySize; i++) {
  11101. arr[i] = new Array(arraySize);
  11102. }
  11103. var x = radius;
  11104. var y = 0;
  11105. var error = 0;
  11106. while (x >= y) {
  11107. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + x, radius + y);
  11108. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + y, radius + x);
  11109. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - y, radius + x);
  11110. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - x, radius + y);
  11111. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - x, radius - y);
  11112. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - y, radius - x);
  11113. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + y, radius - x);
  11114. ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + x, radius - y);
  11115. y++;
  11116. error += 1 + 2 * y;
  11117. if (2 * (error - x) + 1 > 0) {
  11118. x -= 1;
  11119. error += 1 - 2 * x;
  11120. }
  11121. }
  11122. ol.render.canvas.ReplayGroup.circleArrayCache_[radius] = arr;
  11123. return arr;
  11124. };
  11125. /**
  11126. * @param {!Object.<string, Array.<*>>} declutterReplays Declutter replays.
  11127. * @param {CanvasRenderingContext2D} context Context.
  11128. * @param {number} rotation Rotation.
  11129. */
  11130. ol.render.canvas.ReplayGroup.replayDeclutter = function(declutterReplays, context, rotation) {
  11131. var zs = Object.keys(declutterReplays).map(Number).sort(ol.array.numberSafeCompareFunction);
  11132. var skippedFeatureUids = {};
  11133. for (var z = 0, zz = zs.length; z < zz; ++z) {
  11134. var replayData = declutterReplays[zs[z].toString()];
  11135. for (var i = 0, ii = replayData.length; i < ii;) {
  11136. var replay = replayData[i++];
  11137. var transform = replayData[i++];
  11138. replay.replay(context, transform, rotation, skippedFeatureUids);
  11139. }
  11140. }
  11141. };
  11142. /**
  11143. * @param {boolean} group Group with previous replay.
  11144. * @return {ol.DeclutterGroup} Declutter instruction group.
  11145. */
  11146. ol.render.canvas.ReplayGroup.prototype.addDeclutter = function(group) {
  11147. var declutter = null;
  11148. if (this.declutterTree_) {
  11149. if (group) {
  11150. declutter = this.declutterGroup_;
  11151. /** @type {number} */ (declutter[4])++;
  11152. } else {
  11153. declutter = this.declutterGroup_ = ol.extent.createEmpty();
  11154. declutter.push(1);
  11155. }
  11156. }
  11157. return declutter;
  11158. };
  11159. /**
  11160. * @param {CanvasRenderingContext2D} context Context.
  11161. * @param {ol.Transform} transform Transform.
  11162. */
  11163. ol.render.canvas.ReplayGroup.prototype.clip = function(context, transform) {
  11164. var flatClipCoords = this.getClipCoords(transform);
  11165. context.beginPath();
  11166. context.moveTo(flatClipCoords[0], flatClipCoords[1]);
  11167. context.lineTo(flatClipCoords[2], flatClipCoords[3]);
  11168. context.lineTo(flatClipCoords[4], flatClipCoords[5]);
  11169. context.lineTo(flatClipCoords[6], flatClipCoords[7]);
  11170. context.clip();
  11171. };
  11172. /**
  11173. * @param {Array.<ol.render.ReplayType>} replays Replays.
  11174. * @return {boolean} Has replays of the provided types.
  11175. */
  11176. ol.render.canvas.ReplayGroup.prototype.hasReplays = function(replays) {
  11177. for (var zIndex in this.replaysByZIndex_) {
  11178. var candidates = this.replaysByZIndex_[zIndex];
  11179. for (var i = 0, ii = replays.length; i < ii; ++i) {
  11180. if (replays[i] in candidates) {
  11181. return true;
  11182. }
  11183. }
  11184. }
  11185. return false;
  11186. };
  11187. /**
  11188. * FIXME empty description for jsdoc
  11189. */
  11190. ol.render.canvas.ReplayGroup.prototype.finish = function() {
  11191. var zKey;
  11192. for (zKey in this.replaysByZIndex_) {
  11193. var replays = this.replaysByZIndex_[zKey];
  11194. var replayKey;
  11195. for (replayKey in replays) {
  11196. replays[replayKey].finish();
  11197. }
  11198. }
  11199. };
  11200. /**
  11201. * @param {ol.Coordinate} coordinate Coordinate.
  11202. * @param {number} resolution Resolution.
  11203. * @param {number} rotation Rotation.
  11204. * @param {number} hitTolerance Hit tolerance in pixels.
  11205. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  11206. * to skip.
  11207. * @param {function((ol.Feature|ol.render.Feature)): T} callback Feature
  11208. * callback.
  11209. * @param {Object.<string, ol.DeclutterGroup>} declutterReplays Declutter
  11210. * replays.
  11211. * @return {T|undefined} Callback result.
  11212. * @template T
  11213. */
  11214. ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
  11215. coordinate, resolution, rotation, hitTolerance, skippedFeaturesHash, callback, declutterReplays) {
  11216. hitTolerance = Math.round(hitTolerance);
  11217. var contextSize = hitTolerance * 2 + 1;
  11218. var transform = ol.transform.compose(this.hitDetectionTransform_,
  11219. hitTolerance + 0.5, hitTolerance + 0.5,
  11220. 1 / resolution, -1 / resolution,
  11221. -rotation,
  11222. -coordinate[0], -coordinate[1]);
  11223. var context = this.hitDetectionContext_;
  11224. if (context.canvas.width !== contextSize || context.canvas.height !== contextSize) {
  11225. context.canvas.width = contextSize;
  11226. context.canvas.height = contextSize;
  11227. } else {
  11228. context.clearRect(0, 0, contextSize, contextSize);
  11229. }
  11230. /**
  11231. * @type {ol.Extent}
  11232. */
  11233. var hitExtent;
  11234. if (this.renderBuffer_ !== undefined) {
  11235. hitExtent = ol.extent.createEmpty();
  11236. ol.extent.extendCoordinate(hitExtent, coordinate);
  11237. ol.extent.buffer(hitExtent, resolution * (this.renderBuffer_ + hitTolerance), hitExtent);
  11238. }
  11239. var mask = ol.render.canvas.ReplayGroup.getCircleArray_(hitTolerance);
  11240. var declutteredFeatures;
  11241. if (this.declutterTree_) {
  11242. declutteredFeatures = this.declutterTree_.all().map(function(entry) {
  11243. return entry.value;
  11244. });
  11245. }
  11246. var replayType;
  11247. /**
  11248. * @param {ol.Feature|ol.render.Feature} feature Feature.
  11249. * @return {?} Callback result.
  11250. */
  11251. function featureCallback(feature) {
  11252. var imageData = context.getImageData(0, 0, contextSize, contextSize).data;
  11253. for (var i = 0; i < contextSize; i++) {
  11254. for (var j = 0; j < contextSize; j++) {
  11255. if (mask[i][j]) {
  11256. if (imageData[(j * contextSize + i) * 4 + 3] > 0) {
  11257. var result;
  11258. if (!(declutteredFeatures && (replayType == ol.render.ReplayType.IMAGE || replayType == ol.render.ReplayType.TEXT)) ||
  11259. declutteredFeatures.indexOf(feature) !== -1) {
  11260. result = callback(feature);
  11261. }
  11262. if (result) {
  11263. return result;
  11264. } else {
  11265. context.clearRect(0, 0, contextSize, contextSize);
  11266. return undefined;
  11267. }
  11268. }
  11269. }
  11270. }
  11271. }
  11272. }
  11273. /** @type {Array.<number>} */
  11274. var zs = Object.keys(this.replaysByZIndex_).map(Number);
  11275. zs.sort(ol.array.numberSafeCompareFunction);
  11276. var i, j, replays, replay, result;
  11277. for (i = zs.length - 1; i >= 0; --i) {
  11278. var zIndexKey = zs[i].toString();
  11279. replays = this.replaysByZIndex_[zIndexKey];
  11280. for (j = ol.render.replay.ORDER.length - 1; j >= 0; --j) {
  11281. replayType = ol.render.replay.ORDER[j];
  11282. replay = replays[replayType];
  11283. if (replay !== undefined) {
  11284. if (declutterReplays &&
  11285. (replayType == ol.render.ReplayType.IMAGE || replayType == ol.render.ReplayType.TEXT)) {
  11286. var declutter = declutterReplays[zIndexKey];
  11287. if (!declutter) {
  11288. declutterReplays[zIndexKey] = [replay, transform.slice(0)];
  11289. } else {
  11290. declutter.push(replay, transform.slice(0));
  11291. }
  11292. } else {
  11293. result = replay.replayHitDetection(context, transform, rotation,
  11294. skippedFeaturesHash, featureCallback, hitExtent);
  11295. if (result) {
  11296. return result;
  11297. }
  11298. }
  11299. }
  11300. }
  11301. }
  11302. return undefined;
  11303. };
  11304. /**
  11305. * @param {ol.Transform} transform Transform.
  11306. * @return {Array.<number>} Clip coordinates.
  11307. */
  11308. ol.render.canvas.ReplayGroup.prototype.getClipCoords = function(transform) {
  11309. var maxExtent = this.maxExtent_;
  11310. var minX = maxExtent[0];
  11311. var minY = maxExtent[1];
  11312. var maxX = maxExtent[2];
  11313. var maxY = maxExtent[3];
  11314. var flatClipCoords = [minX, minY, minX, maxY, maxX, maxY, maxX, minY];
  11315. ol.geom.flat.transform.transform2D(
  11316. flatClipCoords, 0, 8, 2, transform, flatClipCoords);
  11317. return flatClipCoords;
  11318. };
  11319. /**
  11320. * @inheritDoc
  11321. */
  11322. ol.render.canvas.ReplayGroup.prototype.getReplay = function(zIndex, replayType) {
  11323. var zIndexKey = zIndex !== undefined ? zIndex.toString() : '0';
  11324. var replays = this.replaysByZIndex_[zIndexKey];
  11325. if (replays === undefined) {
  11326. replays = {};
  11327. this.replaysByZIndex_[zIndexKey] = replays;
  11328. }
  11329. var replay = replays[replayType];
  11330. if (replay === undefined) {
  11331. var Constructor = ol.render.canvas.ReplayGroup.BATCH_CONSTRUCTORS_[replayType];
  11332. replay = new Constructor(this.tolerance_, this.maxExtent_,
  11333. this.resolution_, this.pixelRatio_, this.overlaps_, this.declutterTree_);
  11334. replays[replayType] = replay;
  11335. }
  11336. return replay;
  11337. };
  11338. /**
  11339. * @return {Object.<string, Object.<ol.render.ReplayType, ol.render.canvas.Replay>>} Replays.
  11340. */
  11341. ol.render.canvas.ReplayGroup.prototype.getReplays = function() {
  11342. return this.replaysByZIndex_;
  11343. };
  11344. /**
  11345. * @inheritDoc
  11346. */
  11347. ol.render.canvas.ReplayGroup.prototype.isEmpty = function() {
  11348. return ol.obj.isEmpty(this.replaysByZIndex_);
  11349. };
  11350. /**
  11351. * @param {CanvasRenderingContext2D} context Context.
  11352. * @param {ol.Transform} transform Transform.
  11353. * @param {number} viewRotation View rotation.
  11354. * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
  11355. * to skip.
  11356. * @param {Array.<ol.render.ReplayType>=} opt_replayTypes Ordered replay types
  11357. * to replay. Default is {@link ol.render.replay.ORDER}
  11358. * @param {Object.<string, ol.DeclutterGroup>=} opt_declutterReplays Declutter
  11359. * replays.
  11360. */
  11361. ol.render.canvas.ReplayGroup.prototype.replay = function(context,
  11362. transform, viewRotation, skippedFeaturesHash, opt_replayTypes, opt_declutterReplays) {
  11363. /** @type {Array.<number>} */
  11364. var zs = Object.keys(this.replaysByZIndex_).map(Number);
  11365. zs.sort(ol.array.numberSafeCompareFunction);
  11366. // setup clipping so that the parts of over-simplified geometries are not
  11367. // visible outside the current extent when panning
  11368. context.save();
  11369. this.clip(context, transform);
  11370. var replayTypes = opt_replayTypes ? opt_replayTypes : ol.render.replay.ORDER;
  11371. var i, ii, j, jj, replays, replay;
  11372. for (i = 0, ii = zs.length; i < ii; ++i) {
  11373. var zIndexKey = zs[i].toString();
  11374. replays = this.replaysByZIndex_[zIndexKey];
  11375. for (j = 0, jj = replayTypes.length; j < jj; ++j) {
  11376. var replayType = replayTypes[j];
  11377. replay = replays[replayType];
  11378. if (replay !== undefined) {
  11379. if (opt_declutterReplays &&
  11380. (replayType == ol.render.ReplayType.IMAGE || replayType == ol.render.ReplayType.TEXT)) {
  11381. var declutter = opt_declutterReplays[zIndexKey];
  11382. if (!declutter) {
  11383. opt_declutterReplays[zIndexKey] = [replay, transform.slice(0)];
  11384. } else {
  11385. declutter.push(replay, transform.slice(0));
  11386. }
  11387. } else {
  11388. replay.replay(context, transform, viewRotation, skippedFeaturesHash);
  11389. }
  11390. }
  11391. }
  11392. }
  11393. context.restore();
  11394. };
  11395. /**
  11396. * @const
  11397. * @private
  11398. * @type {Object.<ol.render.ReplayType,
  11399. * function(new: ol.render.canvas.Replay, number, ol.Extent,
  11400. * number, number, boolean, Array.<ol.DeclutterGroup>)>}
  11401. */
  11402. ol.render.canvas.ReplayGroup.BATCH_CONSTRUCTORS_ = {
  11403. 'Circle': ol.render.canvas.PolygonReplay,
  11404. 'Default': ol.render.canvas.Replay,
  11405. 'Image': ol.render.canvas.ImageReplay,
  11406. 'LineString': ol.render.canvas.LineStringReplay,
  11407. 'Polygon': ol.render.canvas.PolygonReplay,
  11408. 'Text': ol.render.canvas.TextReplay
  11409. };
  11410. ol.renderer = {};
  11411. ol.renderer.vector = {};
  11412. /**
  11413. * @param {ol.Feature|ol.render.Feature} feature1 Feature 1.
  11414. * @param {ol.Feature|ol.render.Feature} feature2 Feature 2.
  11415. * @return {number} Order.
  11416. */
  11417. ol.renderer.vector.defaultOrder = function(feature1, feature2) {
  11418. return ol.getUid(feature1) - ol.getUid(feature2);
  11419. };
  11420. /**
  11421. * @param {number} resolution Resolution.
  11422. * @param {number} pixelRatio Pixel ratio.
  11423. * @return {number} Squared pixel tolerance.
  11424. */
  11425. ol.renderer.vector.getSquaredTolerance = function(resolution, pixelRatio) {
  11426. var tolerance = ol.renderer.vector.getTolerance(resolution, pixelRatio);
  11427. return tolerance * tolerance;
  11428. };
  11429. /**
  11430. * @param {number} resolution Resolution.
  11431. * @param {number} pixelRatio Pixel ratio.
  11432. * @return {number} Pixel tolerance.
  11433. */
  11434. ol.renderer.vector.getTolerance = function(resolution, pixelRatio) {
  11435. return ol.SIMPLIFY_TOLERANCE * resolution / pixelRatio;
  11436. };
  11437. /**
  11438. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  11439. * @param {ol.geom.Circle} geometry Geometry.
  11440. * @param {ol.style.Style} style Style.
  11441. * @param {ol.Feature} feature Feature.
  11442. * @private
  11443. */
  11444. ol.renderer.vector.renderCircleGeometry_ = function(replayGroup, geometry, style, feature) {
  11445. var fillStyle = style.getFill();
  11446. var strokeStyle = style.getStroke();
  11447. if (fillStyle || strokeStyle) {
  11448. var circleReplay = replayGroup.getReplay(
  11449. style.getZIndex(), ol.render.ReplayType.CIRCLE);
  11450. circleReplay.setFillStrokeStyle(fillStyle, strokeStyle);
  11451. circleReplay.drawCircle(geometry, feature);
  11452. }
  11453. var textStyle = style.getText();
  11454. if (textStyle) {
  11455. var textReplay = replayGroup.getReplay(
  11456. style.getZIndex(), ol.render.ReplayType.TEXT);
  11457. textReplay.setTextStyle(textStyle, replayGroup.addDeclutter(false));
  11458. textReplay.drawText(geometry, feature);
  11459. }
  11460. };
  11461. /**
  11462. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  11463. * @param {ol.Feature|ol.render.Feature} feature Feature.
  11464. * @param {ol.style.Style} style Style.
  11465. * @param {number} squaredTolerance Squared tolerance.
  11466. * @param {function(this: T, ol.events.Event)} listener Listener function.
  11467. * @param {T} thisArg Value to use as `this` when executing `listener`.
  11468. * @return {boolean} `true` if style is loading.
  11469. * @template T
  11470. */
  11471. ol.renderer.vector.renderFeature = function(
  11472. replayGroup, feature, style, squaredTolerance, listener, thisArg) {
  11473. var loading = false;
  11474. var imageStyle, imageState;
  11475. imageStyle = style.getImage();
  11476. if (imageStyle) {
  11477. imageState = imageStyle.getImageState();
  11478. if (imageState == ol.ImageState.LOADED ||
  11479. imageState == ol.ImageState.ERROR) {
  11480. imageStyle.unlistenImageChange(listener, thisArg);
  11481. } else {
  11482. if (imageState == ol.ImageState.IDLE) {
  11483. imageStyle.load();
  11484. }
  11485. imageState = imageStyle.getImageState();
  11486. imageStyle.listenImageChange(listener, thisArg);
  11487. loading = true;
  11488. }
  11489. }
  11490. ol.renderer.vector.renderFeature_(replayGroup, feature, style,
  11491. squaredTolerance);
  11492. return loading;
  11493. };
  11494. /**
  11495. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  11496. * @param {ol.Feature|ol.render.Feature} feature Feature.
  11497. * @param {ol.style.Style} style Style.
  11498. * @param {number} squaredTolerance Squared tolerance.
  11499. * @private
  11500. */
  11501. ol.renderer.vector.renderFeature_ = function(
  11502. replayGroup, feature, style, squaredTolerance) {
  11503. var geometry = style.getGeometryFunction()(feature);
  11504. if (!geometry) {
  11505. return;
  11506. }
  11507. var simplifiedGeometry = geometry.getSimplifiedGeometry(squaredTolerance);
  11508. var renderer = style.getRenderer();
  11509. if (renderer) {
  11510. ol.renderer.vector.renderGeometry_(replayGroup, simplifiedGeometry, style, feature);
  11511. } else {
  11512. var geometryRenderer =
  11513. ol.renderer.vector.GEOMETRY_RENDERERS_[simplifiedGeometry.getType()];
  11514. geometryRenderer(replayGroup, simplifiedGeometry, style, feature);
  11515. }
  11516. };
  11517. /**
  11518. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  11519. * @param {ol.geom.Geometry} geometry Geometry.
  11520. * @param {ol.style.Style} style Style.
  11521. * @param {ol.Feature|ol.render.Feature} feature Feature.
  11522. * @private
  11523. */
  11524. ol.renderer.vector.renderGeometry_ = function(replayGroup, geometry, style, feature) {
  11525. if (geometry.getType() == ol.geom.GeometryType.GEOMETRY_COLLECTION) {
  11526. var geometries = /** @type {ol.geom.GeometryCollection} */ (geometry).getGeometries();
  11527. for (var i = 0, ii = geometries.length; i < ii; ++i) {
  11528. ol.renderer.vector.renderGeometry_(replayGroup, geometries[i], style, feature);
  11529. }
  11530. return;
  11531. }
  11532. var replay = replayGroup.getReplay(style.getZIndex(), ol.render.ReplayType.DEFAULT);
  11533. replay.drawCustom(/** @type {ol.geom.SimpleGeometry} */ (geometry), feature, style.getRenderer());
  11534. };
  11535. /**
  11536. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  11537. * @param {ol.geom.GeometryCollection} geometry Geometry.
  11538. * @param {ol.style.Style} style Style.
  11539. * @param {ol.Feature} feature Feature.
  11540. * @private
  11541. */
  11542. ol.renderer.vector.renderGeometryCollectionGeometry_ = function(replayGroup, geometry, style, feature) {
  11543. var geometries = geometry.getGeometriesArray();
  11544. var i, ii;
  11545. for (i = 0, ii = geometries.length; i < ii; ++i) {
  11546. var geometryRenderer =
  11547. ol.renderer.vector.GEOMETRY_RENDERERS_[geometries[i].getType()];
  11548. geometryRenderer(replayGroup, geometries[i], style, feature);
  11549. }
  11550. };
  11551. /**
  11552. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  11553. * @param {ol.geom.LineString|ol.render.Feature} geometry Geometry.
  11554. * @param {ol.style.Style} style Style.
  11555. * @param {ol.Feature|ol.render.Feature} feature Feature.
  11556. * @private
  11557. */
  11558. ol.renderer.vector.renderLineStringGeometry_ = function(replayGroup, geometry, style, feature) {
  11559. var strokeStyle = style.getStroke();
  11560. if (strokeStyle) {
  11561. var lineStringReplay = replayGroup.getReplay(
  11562. style.getZIndex(), ol.render.ReplayType.LINE_STRING);
  11563. lineStringReplay.setFillStrokeStyle(null, strokeStyle);
  11564. lineStringReplay.drawLineString(geometry, feature);
  11565. }
  11566. var textStyle = style.getText();
  11567. if (textStyle) {
  11568. var textReplay = replayGroup.getReplay(
  11569. style.getZIndex(), ol.render.ReplayType.TEXT);
  11570. textReplay.setTextStyle(textStyle, replayGroup.addDeclutter(false));
  11571. textReplay.drawText(geometry, feature);
  11572. }
  11573. };
  11574. /**
  11575. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  11576. * @param {ol.geom.MultiLineString|ol.render.Feature} geometry Geometry.
  11577. * @param {ol.style.Style} style Style.
  11578. * @param {ol.Feature|ol.render.Feature} feature Feature.
  11579. * @private
  11580. */
  11581. ol.renderer.vector.renderMultiLineStringGeometry_ = function(replayGroup, geometry, style, feature) {
  11582. var strokeStyle = style.getStroke();
  11583. if (strokeStyle) {
  11584. var lineStringReplay = replayGroup.getReplay(
  11585. style.getZIndex(), ol.render.ReplayType.LINE_STRING);
  11586. lineStringReplay.setFillStrokeStyle(null, strokeStyle);
  11587. lineStringReplay.drawMultiLineString(geometry, feature);
  11588. }
  11589. var textStyle = style.getText();
  11590. if (textStyle) {
  11591. var textReplay = replayGroup.getReplay(
  11592. style.getZIndex(), ol.render.ReplayType.TEXT);
  11593. textReplay.setTextStyle(textStyle, replayGroup.addDeclutter(false));
  11594. textReplay.drawText(geometry, feature);
  11595. }
  11596. };
  11597. /**
  11598. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  11599. * @param {ol.geom.MultiPolygon} geometry Geometry.
  11600. * @param {ol.style.Style} style Style.
  11601. * @param {ol.Feature} feature Feature.
  11602. * @private
  11603. */
  11604. ol.renderer.vector.renderMultiPolygonGeometry_ = function(replayGroup, geometry, style, feature) {
  11605. var fillStyle = style.getFill();
  11606. var strokeStyle = style.getStroke();
  11607. if (strokeStyle || fillStyle) {
  11608. var polygonReplay = replayGroup.getReplay(
  11609. style.getZIndex(), ol.render.ReplayType.POLYGON);
  11610. polygonReplay.setFillStrokeStyle(fillStyle, strokeStyle);
  11611. polygonReplay.drawMultiPolygon(geometry, feature);
  11612. }
  11613. var textStyle = style.getText();
  11614. if (textStyle) {
  11615. var textReplay = replayGroup.getReplay(
  11616. style.getZIndex(), ol.render.ReplayType.TEXT);
  11617. textReplay.setTextStyle(textStyle, replayGroup.addDeclutter(false));
  11618. textReplay.drawText(geometry, feature);
  11619. }
  11620. };
  11621. /**
  11622. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  11623. * @param {ol.geom.Point|ol.render.Feature} geometry Geometry.
  11624. * @param {ol.style.Style} style Style.
  11625. * @param {ol.Feature|ol.render.Feature} feature Feature.
  11626. * @private
  11627. */
  11628. ol.renderer.vector.renderPointGeometry_ = function(replayGroup, geometry, style, feature) {
  11629. var imageStyle = style.getImage();
  11630. if (imageStyle) {
  11631. if (imageStyle.getImageState() != ol.ImageState.LOADED) {
  11632. return;
  11633. }
  11634. var imageReplay = replayGroup.getReplay(
  11635. style.getZIndex(), ol.render.ReplayType.IMAGE);
  11636. imageReplay.setImageStyle(imageStyle, replayGroup.addDeclutter(false));
  11637. imageReplay.drawPoint(geometry, feature);
  11638. }
  11639. var textStyle = style.getText();
  11640. if (textStyle) {
  11641. var textReplay = replayGroup.getReplay(
  11642. style.getZIndex(), ol.render.ReplayType.TEXT);
  11643. textReplay.setTextStyle(textStyle, replayGroup.addDeclutter(!!imageStyle));
  11644. textReplay.drawText(geometry, feature);
  11645. }
  11646. };
  11647. /**
  11648. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  11649. * @param {ol.geom.MultiPoint|ol.render.Feature} geometry Geometry.
  11650. * @param {ol.style.Style} style Style.
  11651. * @param {ol.Feature|ol.render.Feature} feature Feature.
  11652. * @private
  11653. */
  11654. ol.renderer.vector.renderMultiPointGeometry_ = function(replayGroup, geometry, style, feature) {
  11655. var imageStyle = style.getImage();
  11656. if (imageStyle) {
  11657. if (imageStyle.getImageState() != ol.ImageState.LOADED) {
  11658. return;
  11659. }
  11660. var imageReplay = replayGroup.getReplay(
  11661. style.getZIndex(), ol.render.ReplayType.IMAGE);
  11662. imageReplay.setImageStyle(imageStyle, replayGroup.addDeclutter(false));
  11663. imageReplay.drawMultiPoint(geometry, feature);
  11664. }
  11665. var textStyle = style.getText();
  11666. if (textStyle) {
  11667. var textReplay = replayGroup.getReplay(
  11668. style.getZIndex(), ol.render.ReplayType.TEXT);
  11669. textReplay.setTextStyle(textStyle, replayGroup.addDeclutter(!!imageStyle));
  11670. textReplay.drawText(geometry, feature);
  11671. }
  11672. };
  11673. /**
  11674. * @param {ol.render.ReplayGroup} replayGroup Replay group.
  11675. * @param {ol.geom.Polygon|ol.render.Feature} geometry Geometry.
  11676. * @param {ol.style.Style} style Style.
  11677. * @param {ol.Feature|ol.render.Feature} feature Feature.
  11678. * @private
  11679. */
  11680. ol.renderer.vector.renderPolygonGeometry_ = function(replayGroup, geometry, style, feature) {
  11681. var fillStyle = style.getFill();
  11682. var strokeStyle = style.getStroke();
  11683. if (fillStyle || strokeStyle) {
  11684. var polygonReplay = replayGroup.getReplay(
  11685. style.getZIndex(), ol.render.ReplayType.POLYGON);
  11686. polygonReplay.setFillStrokeStyle(fillStyle, strokeStyle);
  11687. polygonReplay.drawPolygon(geometry, feature);
  11688. }
  11689. var textStyle = style.getText();
  11690. if (textStyle) {
  11691. var textReplay = replayGroup.getReplay(
  11692. style.getZIndex(), ol.render.ReplayType.TEXT);
  11693. textReplay.setTextStyle(textStyle, replayGroup.addDeclutter(false));
  11694. textReplay.drawText(geometry, feature);
  11695. }
  11696. };
  11697. /**
  11698. * @const
  11699. * @private
  11700. * @type {Object.<ol.geom.GeometryType,
  11701. * function(ol.render.ReplayGroup, ol.geom.Geometry,
  11702. * ol.style.Style, Object)>}
  11703. */
  11704. ol.renderer.vector.GEOMETRY_RENDERERS_ = {
  11705. 'Point': ol.renderer.vector.renderPointGeometry_,
  11706. 'LineString': ol.renderer.vector.renderLineStringGeometry_,
  11707. 'Polygon': ol.renderer.vector.renderPolygonGeometry_,
  11708. 'MultiPoint': ol.renderer.vector.renderMultiPointGeometry_,
  11709. 'MultiLineString': ol.renderer.vector.renderMultiLineStringGeometry_,
  11710. 'MultiPolygon': ol.renderer.vector.renderMultiPolygonGeometry_,
  11711. 'GeometryCollection': ol.renderer.vector.renderGeometryCollectionGeometry_,
  11712. 'Circle': ol.renderer.vector.renderCircleGeometry_
  11713. };
  11714. var spriteImageCanvas = {};
  11715. var mvtStyleClass = new MvtStyle(ol, true);
  11716. var mvtRenderer2D = new MvtRenderer2D({
  11717. mvtStyle: mvtStyleClass,
  11718. openlayer: ol,
  11719. useOffscreen: true
  11720. });
  11721. function MVTWorker(parameters, transferableObjects) {
  11722. var canvas = new OffscreenCanvas(parameters.canvasWidth, parameters.canvasWidth);
  11723. var idCanvas = new OffscreenCanvas(parameters.canvasWidth, parameters.canvasWidth);
  11724. var pbfData = parameters.pbfData;
  11725. var layers = parameters.layers;
  11726. var transform = parameters.transform;
  11727. var squaredTolerance = parameters.squaredTolerance;
  11728. var spriteImageDatas = parameters.spriteImageDatas;
  11729. var keepProperties = parameters.keepProperties;
  11730. var tileLevel = parameters.tileLevel;
  11731. var needSourceLayerNames = parameters.needSourceLayerNames;
  11732. var selectEnabled = parameters.selectEnabled;
  11733. var featureProperties = {};
  11734. try {
  11735. var mvtParser = new ol.format.MVT({
  11736. featureClass: ol.Feature
  11737. });
  11738. var features = mvtParser.readFeatures(pbfData, {
  11739. needSourceLayerNames: needSourceLayerNames
  11740. });
  11741. var renderResult = mvtRenderer2D.renderFeatures({
  11742. colorCanvas: canvas,
  11743. idCanvas: idCanvas,
  11744. transform: transform,
  11745. layers: layers,
  11746. features: features,
  11747. tileLevel: tileLevel,
  11748. spriteImageCanvas: spriteImageCanvas,
  11749. spriteImageDatas: spriteImageDatas,
  11750. squaredTolerance: squaredTolerance,
  11751. selectEnabled: selectEnabled,
  11752. showBillboard: false
  11753. });
  11754. if (keepProperties) {
  11755. var featuresToRender = renderResult.idFeatures;
  11756. var featuresToRenderLength = featuresToRender.length;
  11757. for (var i = 0; i < featuresToRenderLength; i++) {
  11758. var feature = featuresToRender[i];
  11759. var featureID = getFeatureID$1(feature);
  11760. var propertiesWithoutGeometry = feature.getProperties();
  11761. if (when.defined(propertiesWithoutGeometry.geometry)) {
  11762. delete propertiesWithoutGeometry.geometry;
  11763. }
  11764. featureProperties[featureID] = propertiesWithoutGeometry;
  11765. }
  11766. }
  11767. }
  11768. catch (err) {
  11769. }
  11770. var imageBitmap = canvas.transferToImageBitmap();
  11771. var idImageBitmap = selectEnabled ? idCanvas.transferToImageBitmap() : null;
  11772. transferableObjects.push(imageBitmap);
  11773. return {
  11774. buffer: imageBitmap,
  11775. idBuffer: idImageBitmap,
  11776. properties: featureProperties
  11777. };
  11778. }
  11779. function getFeatureID$1(feature) {
  11780. var id = feature.getId();
  11781. // 只在颜色中记录256*256*256这么大范围的ID,超过这个范围的ID舍去
  11782. var discard = Math.floor(id / 16777216);
  11783. id = id - discard * 16777216;
  11784. return id;
  11785. }
  11786. var MVTWorker$1 = createTaskProcessorWorker(MVTWorker);
  11787. return MVTWorker$1;
  11788. });