proj4-src.js 214 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  3. typeof define === 'function' && define.amd ? define(factory) :
  4. (global.proj4 = factory());
  5. }(this, (function () { 'use strict';
  6. var globals = function(defs) {
  7. defs('EPSG:4326', "+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees");
  8. defs('EPSG:4269', "+title=NAD83 (long/lat) +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees");
  9. defs('EPSG:3857', "+title=WGS 84 / Pseudo-Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs");
  10. defs.WGS84 = defs['EPSG:4326'];
  11. defs['EPSG:3785'] = defs['EPSG:3857']; // maintain backward compat, official code is 3857
  12. defs.GOOGLE = defs['EPSG:3857'];
  13. defs['EPSG:900913'] = defs['EPSG:3857'];
  14. defs['EPSG:102113'] = defs['EPSG:3857'];
  15. };
  16. var PJD_3PARAM = 1;
  17. var PJD_7PARAM = 2;
  18. var PJD_GRIDSHIFT = 3;
  19. var PJD_WGS84 = 4; // WGS84 or equivalent
  20. var PJD_NODATUM = 5; // WGS84 or equivalent
  21. var SRS_WGS84_SEMIMAJOR = 6378137.0; // only used in grid shift transforms
  22. var SRS_WGS84_SEMIMINOR = 6356752.314; // only used in grid shift transforms
  23. var SRS_WGS84_ESQUARED = 0.0066943799901413165; // only used in grid shift transforms
  24. var SEC_TO_RAD = 4.84813681109535993589914102357e-6;
  25. var HALF_PI = Math.PI/2;
  26. // ellipoid pj_set_ell.c
  27. var SIXTH = 0.1666666666666666667;
  28. /* 1/6 */
  29. var RA4 = 0.04722222222222222222;
  30. /* 17/360 */
  31. var RA6 = 0.02215608465608465608;
  32. var EPSLN = 1.0e-10;
  33. // you'd think you could use Number.EPSILON above but that makes
  34. // Mollweide get into an infinate loop.
  35. var D2R = 0.01745329251994329577;
  36. var R2D = 57.29577951308232088;
  37. var FORTPI = Math.PI/4;
  38. var TWO_PI = Math.PI * 2;
  39. // SPI is slightly greater than Math.PI, so values that exceed the -180..180
  40. // degree range by a tiny amount don't get wrapped. This prevents points that
  41. // have drifted from their original location along the 180th meridian (due to
  42. // floating point error) from changing their sign.
  43. var SPI = 3.14159265359;
  44. var exports$1 = {};
  45. exports$1.greenwich = 0.0; //"0dE",
  46. exports$1.lisbon = -9.131906111111; //"9d07'54.862\"W",
  47. exports$1.paris = 2.337229166667; //"2d20'14.025\"E",
  48. exports$1.bogota = -74.080916666667; //"74d04'51.3\"W",
  49. exports$1.madrid = -3.687938888889; //"3d41'16.58\"W",
  50. exports$1.rome = 12.452333333333; //"12d27'8.4\"E",
  51. exports$1.bern = 7.439583333333; //"7d26'22.5\"E",
  52. exports$1.jakarta = 106.807719444444; //"106d48'27.79\"E",
  53. exports$1.ferro = -17.666666666667; //"17d40'W",
  54. exports$1.brussels = 4.367975; //"4d22'4.71\"E",
  55. exports$1.stockholm = 18.058277777778; //"18d3'29.8\"E",
  56. exports$1.athens = 23.7163375; //"23d42'58.815\"E",
  57. exports$1.oslo = 10.722916666667; //"10d43'22.5\"E"
  58. var units = {
  59. ft: {to_meter: 0.3048},
  60. 'us-ft': {to_meter: 1200 / 3937}
  61. };
  62. var ignoredChar = /[\s_\-\/\(\)]/g;
  63. function match(obj, key) {
  64. if (obj[key]) {
  65. return obj[key];
  66. }
  67. var keys = Object.keys(obj);
  68. var lkey = key.toLowerCase().replace(ignoredChar, '');
  69. var i = -1;
  70. var testkey, processedKey;
  71. while (++i < keys.length) {
  72. testkey = keys[i];
  73. processedKey = testkey.toLowerCase().replace(ignoredChar, '');
  74. if (processedKey === lkey) {
  75. return obj[testkey];
  76. }
  77. }
  78. }
  79. var parseProj = function(defData) {
  80. var self = {};
  81. var paramObj = defData.split('+').map(function(v) {
  82. return v.trim();
  83. }).filter(function(a) {
  84. return a;
  85. }).reduce(function(p, a) {
  86. var split = a.split('=');
  87. split.push(true);
  88. p[split[0].toLowerCase()] = split[1];
  89. return p;
  90. }, {});
  91. var paramName, paramVal, paramOutname;
  92. var params = {
  93. proj: 'projName',
  94. datum: 'datumCode',
  95. rf: function(v) {
  96. self.rf = parseFloat(v);
  97. },
  98. lat_0: function(v) {
  99. self.lat0 = v * D2R;
  100. },
  101. lat_1: function(v) {
  102. self.lat1 = v * D2R;
  103. },
  104. lat_2: function(v) {
  105. self.lat2 = v * D2R;
  106. },
  107. lat_ts: function(v) {
  108. self.lat_ts = v * D2R;
  109. },
  110. lon_0: function(v) {
  111. self.long0 = v * D2R;
  112. },
  113. lon_1: function(v) {
  114. self.long1 = v * D2R;
  115. },
  116. lon_2: function(v) {
  117. self.long2 = v * D2R;
  118. },
  119. alpha: function(v) {
  120. self.alpha = parseFloat(v) * D2R;
  121. },
  122. gamma: function(v) {
  123. self.rectified_grid_angle = parseFloat(v);
  124. },
  125. lonc: function(v) {
  126. self.longc = v * D2R;
  127. },
  128. x_0: function(v) {
  129. self.x0 = parseFloat(v);
  130. },
  131. y_0: function(v) {
  132. self.y0 = parseFloat(v);
  133. },
  134. k_0: function(v) {
  135. self.k0 = parseFloat(v);
  136. },
  137. k: function(v) {
  138. self.k0 = parseFloat(v);
  139. },
  140. a: function(v) {
  141. self.a = parseFloat(v);
  142. },
  143. b: function(v) {
  144. self.b = parseFloat(v);
  145. },
  146. r_a: function() {
  147. self.R_A = true;
  148. },
  149. zone: function(v) {
  150. self.zone = parseInt(v, 10);
  151. },
  152. south: function() {
  153. self.utmSouth = true;
  154. },
  155. towgs84: function(v) {
  156. self.datum_params = v.split(",").map(function(a) {
  157. return parseFloat(a);
  158. });
  159. },
  160. to_meter: function(v) {
  161. self.to_meter = parseFloat(v);
  162. },
  163. units: function(v) {
  164. self.units = v;
  165. var unit = match(units, v);
  166. if (unit) {
  167. self.to_meter = unit.to_meter;
  168. }
  169. },
  170. from_greenwich: function(v) {
  171. self.from_greenwich = v * D2R;
  172. },
  173. pm: function(v) {
  174. var pm = match(exports$1, v);
  175. self.from_greenwich = (pm ? pm : parseFloat(v)) * D2R;
  176. },
  177. nadgrids: function(v) {
  178. if (v === '@null') {
  179. self.datumCode = 'none';
  180. }
  181. else {
  182. self.nadgrids = v;
  183. }
  184. },
  185. axis: function(v) {
  186. var legalAxis = "ewnsud";
  187. if (v.length === 3 && legalAxis.indexOf(v.substr(0, 1)) !== -1 && legalAxis.indexOf(v.substr(1, 1)) !== -1 && legalAxis.indexOf(v.substr(2, 1)) !== -1) {
  188. self.axis = v;
  189. }
  190. },
  191. approx: function() {
  192. self.approx = true;
  193. }
  194. };
  195. for (paramName in paramObj) {
  196. paramVal = paramObj[paramName];
  197. if (paramName in params) {
  198. paramOutname = params[paramName];
  199. if (typeof paramOutname === 'function') {
  200. paramOutname(paramVal);
  201. }
  202. else {
  203. self[paramOutname] = paramVal;
  204. }
  205. }
  206. else {
  207. self[paramName] = paramVal;
  208. }
  209. }
  210. if(typeof self.datumCode === 'string' && self.datumCode !== "WGS84"){
  211. self.datumCode = self.datumCode.toLowerCase();
  212. }
  213. return self;
  214. };
  215. var NEUTRAL = 1;
  216. var KEYWORD = 2;
  217. var NUMBER = 3;
  218. var QUOTED = 4;
  219. var AFTERQUOTE = 5;
  220. var ENDED = -1;
  221. var whitespace = /\s/;
  222. var latin = /[A-Za-z]/;
  223. var keyword = /[A-Za-z84]/;
  224. var endThings = /[,\]]/;
  225. var digets = /[\d\.E\-\+]/;
  226. // const ignoredChar = /[\s_\-\/\(\)]/g;
  227. function Parser(text) {
  228. if (typeof text !== 'string') {
  229. throw new Error('not a string');
  230. }
  231. this.text = text.trim();
  232. this.level = 0;
  233. this.place = 0;
  234. this.root = null;
  235. this.stack = [];
  236. this.currentObject = null;
  237. this.state = NEUTRAL;
  238. }
  239. Parser.prototype.readCharicter = function() {
  240. var char = this.text[this.place++];
  241. if (this.state !== QUOTED) {
  242. while (whitespace.test(char)) {
  243. if (this.place >= this.text.length) {
  244. return;
  245. }
  246. char = this.text[this.place++];
  247. }
  248. }
  249. switch (this.state) {
  250. case NEUTRAL:
  251. return this.neutral(char);
  252. case KEYWORD:
  253. return this.keyword(char)
  254. case QUOTED:
  255. return this.quoted(char);
  256. case AFTERQUOTE:
  257. return this.afterquote(char);
  258. case NUMBER:
  259. return this.number(char);
  260. case ENDED:
  261. return;
  262. }
  263. };
  264. Parser.prototype.afterquote = function(char) {
  265. if (char === '"') {
  266. this.word += '"';
  267. this.state = QUOTED;
  268. return;
  269. }
  270. if (endThings.test(char)) {
  271. this.word = this.word.trim();
  272. this.afterItem(char);
  273. return;
  274. }
  275. throw new Error('havn\'t handled "' +char + '" in afterquote yet, index ' + this.place);
  276. };
  277. Parser.prototype.afterItem = function(char) {
  278. if (char === ',') {
  279. if (this.word !== null) {
  280. this.currentObject.push(this.word);
  281. }
  282. this.word = null;
  283. this.state = NEUTRAL;
  284. return;
  285. }
  286. if (char === ']') {
  287. this.level--;
  288. if (this.word !== null) {
  289. this.currentObject.push(this.word);
  290. this.word = null;
  291. }
  292. this.state = NEUTRAL;
  293. this.currentObject = this.stack.pop();
  294. if (!this.currentObject) {
  295. this.state = ENDED;
  296. }
  297. return;
  298. }
  299. };
  300. Parser.prototype.number = function(char) {
  301. if (digets.test(char)) {
  302. this.word += char;
  303. return;
  304. }
  305. if (endThings.test(char)) {
  306. this.word = parseFloat(this.word);
  307. this.afterItem(char);
  308. return;
  309. }
  310. throw new Error('havn\'t handled "' +char + '" in number yet, index ' + this.place);
  311. };
  312. Parser.prototype.quoted = function(char) {
  313. if (char === '"') {
  314. this.state = AFTERQUOTE;
  315. return;
  316. }
  317. this.word += char;
  318. return;
  319. };
  320. Parser.prototype.keyword = function(char) {
  321. if (keyword.test(char)) {
  322. this.word += char;
  323. return;
  324. }
  325. if (char === '[') {
  326. var newObjects = [];
  327. newObjects.push(this.word);
  328. this.level++;
  329. if (this.root === null) {
  330. this.root = newObjects;
  331. } else {
  332. this.currentObject.push(newObjects);
  333. }
  334. this.stack.push(this.currentObject);
  335. this.currentObject = newObjects;
  336. this.state = NEUTRAL;
  337. return;
  338. }
  339. if (endThings.test(char)) {
  340. this.afterItem(char);
  341. return;
  342. }
  343. throw new Error('havn\'t handled "' +char + '" in keyword yet, index ' + this.place);
  344. };
  345. Parser.prototype.neutral = function(char) {
  346. if (latin.test(char)) {
  347. this.word = char;
  348. this.state = KEYWORD;
  349. return;
  350. }
  351. if (char === '"') {
  352. this.word = '';
  353. this.state = QUOTED;
  354. return;
  355. }
  356. if (digets.test(char)) {
  357. this.word = char;
  358. this.state = NUMBER;
  359. return;
  360. }
  361. if (endThings.test(char)) {
  362. this.afterItem(char);
  363. return;
  364. }
  365. throw new Error('havn\'t handled "' +char + '" in neutral yet, index ' + this.place);
  366. };
  367. Parser.prototype.output = function() {
  368. while (this.place < this.text.length) {
  369. this.readCharicter();
  370. }
  371. if (this.state === ENDED) {
  372. return this.root;
  373. }
  374. throw new Error('unable to parse string "' +this.text + '". State is ' + this.state);
  375. };
  376. function parseString(txt) {
  377. var parser = new Parser(txt);
  378. return parser.output();
  379. }
  380. function mapit(obj, key, value) {
  381. if (Array.isArray(key)) {
  382. value.unshift(key);
  383. key = null;
  384. }
  385. var thing = key ? {} : obj;
  386. var out = value.reduce(function(newObj, item) {
  387. sExpr(item, newObj);
  388. return newObj
  389. }, thing);
  390. if (key) {
  391. obj[key] = out;
  392. }
  393. }
  394. function sExpr(v, obj) {
  395. if (!Array.isArray(v)) {
  396. obj[v] = true;
  397. return;
  398. }
  399. var key = v.shift();
  400. if (key === 'PARAMETER') {
  401. key = v.shift();
  402. }
  403. if (v.length === 1) {
  404. if (Array.isArray(v[0])) {
  405. obj[key] = {};
  406. sExpr(v[0], obj[key]);
  407. return;
  408. }
  409. obj[key] = v[0];
  410. return;
  411. }
  412. if (!v.length) {
  413. obj[key] = true;
  414. return;
  415. }
  416. if (key === 'TOWGS84') {
  417. obj[key] = v;
  418. return;
  419. }
  420. if (key === 'AXIS') {
  421. if (!(key in obj)) {
  422. obj[key] = [];
  423. }
  424. obj[key].push(v);
  425. return;
  426. }
  427. if (!Array.isArray(key)) {
  428. obj[key] = {};
  429. }
  430. var i;
  431. switch (key) {
  432. case 'UNIT':
  433. case 'PRIMEM':
  434. case 'VERT_DATUM':
  435. obj[key] = {
  436. name: v[0].toLowerCase(),
  437. convert: v[1]
  438. };
  439. if (v.length === 3) {
  440. sExpr(v[2], obj[key]);
  441. }
  442. return;
  443. case 'SPHEROID':
  444. case 'ELLIPSOID':
  445. obj[key] = {
  446. name: v[0],
  447. a: v[1],
  448. rf: v[2]
  449. };
  450. if (v.length === 4) {
  451. sExpr(v[3], obj[key]);
  452. }
  453. return;
  454. case 'PROJECTEDCRS':
  455. case 'PROJCRS':
  456. case 'GEOGCS':
  457. case 'GEOCCS':
  458. case 'PROJCS':
  459. case 'LOCAL_CS':
  460. case 'GEODCRS':
  461. case 'GEODETICCRS':
  462. case 'GEODETICDATUM':
  463. case 'EDATUM':
  464. case 'ENGINEERINGDATUM':
  465. case 'VERT_CS':
  466. case 'VERTCRS':
  467. case 'VERTICALCRS':
  468. case 'COMPD_CS':
  469. case 'COMPOUNDCRS':
  470. case 'ENGINEERINGCRS':
  471. case 'ENGCRS':
  472. case 'FITTED_CS':
  473. case 'LOCAL_DATUM':
  474. case 'DATUM':
  475. v[0] = ['name', v[0]];
  476. mapit(obj, key, v);
  477. return;
  478. default:
  479. i = -1;
  480. while (++i < v.length) {
  481. if (!Array.isArray(v[i])) {
  482. return sExpr(v, obj[key]);
  483. }
  484. }
  485. return mapit(obj, key, v);
  486. }
  487. }
  488. var D2R$1 = 0.01745329251994329577;
  489. function rename(obj, params) {
  490. var outName = params[0];
  491. var inName = params[1];
  492. if (!(outName in obj) && (inName in obj)) {
  493. obj[outName] = obj[inName];
  494. if (params.length === 3) {
  495. obj[outName] = params[2](obj[outName]);
  496. }
  497. }
  498. }
  499. function d2r(input) {
  500. return input * D2R$1;
  501. }
  502. function cleanWKT(wkt) {
  503. if (wkt.type === 'GEOGCS') {
  504. wkt.projName = 'longlat';
  505. } else if (wkt.type === 'LOCAL_CS') {
  506. wkt.projName = 'identity';
  507. wkt.local = true;
  508. } else {
  509. if (typeof wkt.PROJECTION === 'object') {
  510. wkt.projName = Object.keys(wkt.PROJECTION)[0];
  511. } else {
  512. wkt.projName = wkt.PROJECTION;
  513. }
  514. }
  515. if (wkt.AXIS) {
  516. var axisOrder = '';
  517. for (var i = 0, ii = wkt.AXIS.length; i < ii; ++i) {
  518. var axis = [wkt.AXIS[i][0].toLowerCase(), wkt.AXIS[i][1].toLowerCase()];
  519. if (axis[0].indexOf('north') !== -1 || ((axis[0] === 'y' || axis[0] === 'lat') && axis[1] === 'north')) {
  520. axisOrder += 'n';
  521. } else if (axis[0].indexOf('south') !== -1 || ((axis[0] === 'y' || axis[0] === 'lat') && axis[1] === 'south')) {
  522. axisOrder += 's';
  523. } else if (axis[0].indexOf('east') !== -1 || ((axis[0] === 'x' || axis[0] === 'lon') && axis[1] === 'east')) {
  524. axisOrder += 'e';
  525. } else if (axis[0].indexOf('west') !== -1 || ((axis[0] === 'x' || axis[0] === 'lon') && axis[1] === 'west')) {
  526. axisOrder += 'w';
  527. }
  528. }
  529. if (axisOrder.length === 2) {
  530. axisOrder += 'u';
  531. }
  532. if (axisOrder.length === 3) {
  533. wkt.axis = axisOrder;
  534. }
  535. }
  536. if (wkt.UNIT) {
  537. wkt.units = wkt.UNIT.name.toLowerCase();
  538. if (wkt.units === 'metre') {
  539. wkt.units = 'meter';
  540. }
  541. if (wkt.UNIT.convert) {
  542. if (wkt.type === 'GEOGCS') {
  543. if (wkt.DATUM && wkt.DATUM.SPHEROID) {
  544. wkt.to_meter = wkt.UNIT.convert*wkt.DATUM.SPHEROID.a;
  545. }
  546. } else {
  547. wkt.to_meter = wkt.UNIT.convert;
  548. }
  549. }
  550. }
  551. var geogcs = wkt.GEOGCS;
  552. if (wkt.type === 'GEOGCS') {
  553. geogcs = wkt;
  554. }
  555. if (geogcs) {
  556. //if(wkt.GEOGCS.PRIMEM&&wkt.GEOGCS.PRIMEM.convert){
  557. // wkt.from_greenwich=wkt.GEOGCS.PRIMEM.convert*D2R;
  558. //}
  559. if (geogcs.DATUM) {
  560. wkt.datumCode = geogcs.DATUM.name.toLowerCase();
  561. } else {
  562. wkt.datumCode = geogcs.name.toLowerCase();
  563. }
  564. if (wkt.datumCode.slice(0, 2) === 'd_') {
  565. wkt.datumCode = wkt.datumCode.slice(2);
  566. }
  567. if (wkt.datumCode === 'new_zealand_geodetic_datum_1949' || wkt.datumCode === 'new_zealand_1949') {
  568. wkt.datumCode = 'nzgd49';
  569. }
  570. if (wkt.datumCode === 'wgs_1984' || wkt.datumCode === 'world_geodetic_system_1984') {
  571. if (wkt.PROJECTION === 'Mercator_Auxiliary_Sphere') {
  572. wkt.sphere = true;
  573. }
  574. wkt.datumCode = 'wgs84';
  575. }
  576. if (wkt.datumCode.slice(-6) === '_ferro') {
  577. wkt.datumCode = wkt.datumCode.slice(0, - 6);
  578. }
  579. if (wkt.datumCode.slice(-8) === '_jakarta') {
  580. wkt.datumCode = wkt.datumCode.slice(0, - 8);
  581. }
  582. if (~wkt.datumCode.indexOf('belge')) {
  583. wkt.datumCode = 'rnb72';
  584. }
  585. if (geogcs.DATUM && geogcs.DATUM.SPHEROID) {
  586. wkt.ellps = geogcs.DATUM.SPHEROID.name.replace('_19', '').replace(/[Cc]larke\_18/, 'clrk');
  587. if (wkt.ellps.toLowerCase().slice(0, 13) === 'international') {
  588. wkt.ellps = 'intl';
  589. }
  590. wkt.a = geogcs.DATUM.SPHEROID.a;
  591. wkt.rf = parseFloat(geogcs.DATUM.SPHEROID.rf, 10);
  592. }
  593. if (geogcs.DATUM && geogcs.DATUM.TOWGS84) {
  594. wkt.datum_params = geogcs.DATUM.TOWGS84;
  595. }
  596. if (~wkt.datumCode.indexOf('osgb_1936')) {
  597. wkt.datumCode = 'osgb36';
  598. }
  599. if (~wkt.datumCode.indexOf('osni_1952')) {
  600. wkt.datumCode = 'osni52';
  601. }
  602. if (~wkt.datumCode.indexOf('tm65')
  603. || ~wkt.datumCode.indexOf('geodetic_datum_of_1965')) {
  604. wkt.datumCode = 'ire65';
  605. }
  606. if (wkt.datumCode === 'ch1903+') {
  607. wkt.datumCode = 'ch1903';
  608. }
  609. if (~wkt.datumCode.indexOf('israel')) {
  610. wkt.datumCode = 'isr93';
  611. }
  612. }
  613. if (wkt.b && !isFinite(wkt.b)) {
  614. wkt.b = wkt.a;
  615. }
  616. function toMeter(input) {
  617. var ratio = wkt.to_meter || 1;
  618. return input * ratio;
  619. }
  620. var renamer = function(a) {
  621. return rename(wkt, a);
  622. };
  623. var list = [
  624. ['standard_parallel_1', 'Standard_Parallel_1'],
  625. ['standard_parallel_1', 'Latitude of 1st standard parallel'],
  626. ['standard_parallel_2', 'Standard_Parallel_2'],
  627. ['standard_parallel_2', 'Latitude of 2nd standard parallel'],
  628. ['false_easting', 'False_Easting'],
  629. ['false_easting', 'False easting'],
  630. ['false-easting', 'Easting at false origin'],
  631. ['false_northing', 'False_Northing'],
  632. ['false_northing', 'False northing'],
  633. ['false_northing', 'Northing at false origin'],
  634. ['central_meridian', 'Central_Meridian'],
  635. ['central_meridian', 'Longitude of natural origin'],
  636. ['central_meridian', 'Longitude of false origin'],
  637. ['latitude_of_origin', 'Latitude_Of_Origin'],
  638. ['latitude_of_origin', 'Central_Parallel'],
  639. ['latitude_of_origin', 'Latitude of natural origin'],
  640. ['latitude_of_origin', 'Latitude of false origin'],
  641. ['scale_factor', 'Scale_Factor'],
  642. ['k0', 'scale_factor'],
  643. ['latitude_of_center', 'Latitude_Of_Center'],
  644. ['latitude_of_center', 'Latitude_of_center'],
  645. ['lat0', 'latitude_of_center', d2r],
  646. ['longitude_of_center', 'Longitude_Of_Center'],
  647. ['longitude_of_center', 'Longitude_of_center'],
  648. ['longc', 'longitude_of_center', d2r],
  649. ['x0', 'false_easting', toMeter],
  650. ['y0', 'false_northing', toMeter],
  651. ['long0', 'central_meridian', d2r],
  652. ['lat0', 'latitude_of_origin', d2r],
  653. ['lat0', 'standard_parallel_1', d2r],
  654. ['lat1', 'standard_parallel_1', d2r],
  655. ['lat2', 'standard_parallel_2', d2r],
  656. ['azimuth', 'Azimuth'],
  657. ['alpha', 'azimuth', d2r],
  658. ['srsCode', 'name']
  659. ];
  660. list.forEach(renamer);
  661. if (!wkt.long0 && wkt.longc && (wkt.projName === 'Albers_Conic_Equal_Area' || wkt.projName === 'Lambert_Azimuthal_Equal_Area')) {
  662. wkt.long0 = wkt.longc;
  663. }
  664. if (!wkt.lat_ts && wkt.lat1 && (wkt.projName === 'Stereographic_South_Pole' || wkt.projName === 'Polar Stereographic (variant B)')) {
  665. wkt.lat0 = d2r(wkt.lat1 > 0 ? 90 : -90);
  666. wkt.lat_ts = wkt.lat1;
  667. }
  668. }
  669. var wkt = function(wkt) {
  670. var lisp = parseString(wkt);
  671. var type = lisp.shift();
  672. var name = lisp.shift();
  673. lisp.unshift(['name', name]);
  674. lisp.unshift(['type', type]);
  675. var obj = {};
  676. sExpr(lisp, obj);
  677. cleanWKT(obj);
  678. return obj;
  679. };
  680. function defs(name) {
  681. /*global console*/
  682. var that = this;
  683. if (arguments.length === 2) {
  684. var def = arguments[1];
  685. if (typeof def === 'string') {
  686. if (def.charAt(0) === '+') {
  687. defs[name] = parseProj(arguments[1]);
  688. }
  689. else {
  690. defs[name] = wkt(arguments[1]);
  691. }
  692. } else {
  693. defs[name] = def;
  694. }
  695. }
  696. else if (arguments.length === 1) {
  697. if (Array.isArray(name)) {
  698. return name.map(function(v) {
  699. if (Array.isArray(v)) {
  700. defs.apply(that, v);
  701. }
  702. else {
  703. defs(v);
  704. }
  705. });
  706. }
  707. else if (typeof name === 'string') {
  708. if (name in defs) {
  709. return defs[name];
  710. }
  711. }
  712. else if ('EPSG' in name) {
  713. defs['EPSG:' + name.EPSG] = name;
  714. }
  715. else if ('ESRI' in name) {
  716. defs['ESRI:' + name.ESRI] = name;
  717. }
  718. else if ('IAU2000' in name) {
  719. defs['IAU2000:' + name.IAU2000] = name;
  720. }
  721. else {
  722. console.log(name);
  723. }
  724. return;
  725. }
  726. }
  727. globals(defs);
  728. function testObj(code){
  729. return typeof code === 'string';
  730. }
  731. function testDef(code){
  732. return code in defs;
  733. }
  734. var codeWords = ['PROJECTEDCRS', 'PROJCRS', 'GEOGCS','GEOCCS','PROJCS','LOCAL_CS', 'GEODCRS', 'GEODETICCRS', 'GEODETICDATUM', 'ENGCRS', 'ENGINEERINGCRS'];
  735. function testWKT(code){
  736. return codeWords.some(function (word) {
  737. return code.indexOf(word) > -1;
  738. });
  739. }
  740. var codes = ['3857', '900913', '3785', '102113'];
  741. function checkMercator(item) {
  742. var auth = match(item, 'authority');
  743. if (!auth) {
  744. return;
  745. }
  746. var code = match(auth, 'epsg');
  747. return code && codes.indexOf(code) > -1;
  748. }
  749. function checkProjStr(item) {
  750. var ext = match(item, 'extension');
  751. if (!ext) {
  752. return;
  753. }
  754. return match(ext, 'proj4');
  755. }
  756. function testProj(code){
  757. return code[0] === '+';
  758. }
  759. function parse(code){
  760. if (testObj(code)) {
  761. //check to see if this is a WKT string
  762. if (testDef(code)) {
  763. return defs[code];
  764. }
  765. if (testWKT(code)) {
  766. var out = wkt(code);
  767. // test of spetial case, due to this being a very common and often malformed
  768. if (checkMercator(out)) {
  769. return defs['EPSG:3857'];
  770. }
  771. var maybeProjStr = checkProjStr(out);
  772. if (maybeProjStr) {
  773. return parseProj(maybeProjStr);
  774. }
  775. return out;
  776. }
  777. if (testProj(code)) {
  778. return parseProj(code);
  779. }
  780. }else{
  781. return code;
  782. }
  783. }
  784. var extend = function(destination, source) {
  785. destination = destination || {};
  786. var value, property;
  787. if (!source) {
  788. return destination;
  789. }
  790. for (property in source) {
  791. value = source[property];
  792. if (value !== undefined) {
  793. destination[property] = value;
  794. }
  795. }
  796. return destination;
  797. };
  798. var msfnz = function(eccent, sinphi, cosphi) {
  799. var con = eccent * sinphi;
  800. return cosphi / (Math.sqrt(1 - con * con));
  801. };
  802. var sign = function(x) {
  803. return x<0 ? -1 : 1;
  804. };
  805. var adjust_lon = function(x) {
  806. return (Math.abs(x) <= SPI) ? x : (x - (sign(x) * TWO_PI));
  807. };
  808. var tsfnz = function(eccent, phi, sinphi) {
  809. var con = eccent * sinphi;
  810. var com = 0.5 * eccent;
  811. con = Math.pow(((1 - con) / (1 + con)), com);
  812. return (Math.tan(0.5 * (HALF_PI - phi)) / con);
  813. };
  814. var phi2z = function(eccent, ts) {
  815. var eccnth = 0.5 * eccent;
  816. var con, dphi;
  817. var phi = HALF_PI - 2 * Math.atan(ts);
  818. for (var i = 0; i <= 15; i++) {
  819. con = eccent * Math.sin(phi);
  820. dphi = HALF_PI - 2 * Math.atan(ts * (Math.pow(((1 - con) / (1 + con)), eccnth))) - phi;
  821. phi += dphi;
  822. if (Math.abs(dphi) <= 0.0000000001) {
  823. return phi;
  824. }
  825. }
  826. //console.log("phi2z has NoConvergence");
  827. return -9999;
  828. };
  829. function init() {
  830. var con = this.b / this.a;
  831. this.es = 1 - con * con;
  832. if(!('x0' in this)){
  833. this.x0 = 0;
  834. }
  835. if(!('y0' in this)){
  836. this.y0 = 0;
  837. }
  838. this.e = Math.sqrt(this.es);
  839. if (this.lat_ts) {
  840. if (this.sphere) {
  841. this.k0 = Math.cos(this.lat_ts);
  842. }
  843. else {
  844. this.k0 = msfnz(this.e, Math.sin(this.lat_ts), Math.cos(this.lat_ts));
  845. }
  846. }
  847. else {
  848. if (!this.k0) {
  849. if (this.k) {
  850. this.k0 = this.k;
  851. }
  852. else {
  853. this.k0 = 1;
  854. }
  855. }
  856. }
  857. }
  858. /* Mercator forward equations--mapping lat,long to x,y
  859. --------------------------------------------------*/
  860. function forward(p) {
  861. var lon = p.x;
  862. var lat = p.y;
  863. // convert to radians
  864. if (lat * R2D > 90 && lat * R2D < -90 && lon * R2D > 180 && lon * R2D < -180) {
  865. return null;
  866. }
  867. var x, y;
  868. if (Math.abs(Math.abs(lat) - HALF_PI) <= EPSLN) {
  869. return null;
  870. }
  871. else {
  872. if (this.sphere) {
  873. x = this.x0 + this.a * this.k0 * adjust_lon(lon - this.long0);
  874. y = this.y0 + this.a * this.k0 * Math.log(Math.tan(FORTPI + 0.5 * lat));
  875. }
  876. else {
  877. var sinphi = Math.sin(lat);
  878. var ts = tsfnz(this.e, lat, sinphi);
  879. x = this.x0 + this.a * this.k0 * adjust_lon(lon - this.long0);
  880. y = this.y0 - this.a * this.k0 * Math.log(ts);
  881. }
  882. p.x = x;
  883. p.y = y;
  884. return p;
  885. }
  886. }
  887. /* Mercator inverse equations--mapping x,y to lat/long
  888. --------------------------------------------------*/
  889. function inverse(p) {
  890. var x = p.x - this.x0;
  891. var y = p.y - this.y0;
  892. var lon, lat;
  893. if (this.sphere) {
  894. lat = HALF_PI - 2 * Math.atan(Math.exp(-y / (this.a * this.k0)));
  895. }
  896. else {
  897. var ts = Math.exp(-y / (this.a * this.k0));
  898. lat = phi2z(this.e, ts);
  899. if (lat === -9999) {
  900. return null;
  901. }
  902. }
  903. lon = adjust_lon(this.long0 + x / (this.a * this.k0));
  904. p.x = lon;
  905. p.y = lat;
  906. return p;
  907. }
  908. var names$1 = ["Mercator", "Popular Visualisation Pseudo Mercator", "Mercator_1SP", "Mercator_Auxiliary_Sphere", "merc"];
  909. var merc = {
  910. init: init,
  911. forward: forward,
  912. inverse: inverse,
  913. names: names$1
  914. };
  915. function init$1() {
  916. //no-op for longlat
  917. }
  918. function identity(pt) {
  919. return pt;
  920. }
  921. var names$2 = ["longlat", "identity"];
  922. var longlat = {
  923. init: init$1,
  924. forward: identity,
  925. inverse: identity,
  926. names: names$2
  927. };
  928. var projs = [merc, longlat];
  929. var names = {};
  930. var projStore = [];
  931. function add(proj, i) {
  932. var len = projStore.length;
  933. if (!proj.names) {
  934. console.log(i);
  935. return true;
  936. }
  937. projStore[len] = proj;
  938. proj.names.forEach(function(n) {
  939. names[n.toLowerCase()] = len;
  940. });
  941. return this;
  942. }
  943. function get(name) {
  944. if (!name) {
  945. return false;
  946. }
  947. var n = name.toLowerCase();
  948. if (typeof names[n] !== 'undefined' && projStore[names[n]]) {
  949. return projStore[names[n]];
  950. }
  951. }
  952. function start() {
  953. projs.forEach(add);
  954. }
  955. var projections = {
  956. start: start,
  957. add: add,
  958. get: get
  959. };
  960. var exports$2 = {};
  961. exports$2.MERIT = {
  962. a: 6378137.0,
  963. rf: 298.257,
  964. ellipseName: "MERIT 1983"
  965. };
  966. exports$2.SGS85 = {
  967. a: 6378136.0,
  968. rf: 298.257,
  969. ellipseName: "Soviet Geodetic System 85"
  970. };
  971. exports$2.GRS80 = {
  972. a: 6378137.0,
  973. rf: 298.257222101,
  974. ellipseName: "GRS 1980(IUGG, 1980)"
  975. };
  976. exports$2.IAU76 = {
  977. a: 6378140.0,
  978. rf: 298.257,
  979. ellipseName: "IAU 1976"
  980. };
  981. exports$2.airy = {
  982. a: 6377563.396,
  983. b: 6356256.910,
  984. ellipseName: "Airy 1830"
  985. };
  986. exports$2.APL4 = {
  987. a: 6378137,
  988. rf: 298.25,
  989. ellipseName: "Appl. Physics. 1965"
  990. };
  991. exports$2.NWL9D = {
  992. a: 6378145.0,
  993. rf: 298.25,
  994. ellipseName: "Naval Weapons Lab., 1965"
  995. };
  996. exports$2.mod_airy = {
  997. a: 6377340.189,
  998. b: 6356034.446,
  999. ellipseName: "Modified Airy"
  1000. };
  1001. exports$2.andrae = {
  1002. a: 6377104.43,
  1003. rf: 300.0,
  1004. ellipseName: "Andrae 1876 (Den., Iclnd.)"
  1005. };
  1006. exports$2.aust_SA = {
  1007. a: 6378160.0,
  1008. rf: 298.25,
  1009. ellipseName: "Australian Natl & S. Amer. 1969"
  1010. };
  1011. exports$2.GRS67 = {
  1012. a: 6378160.0,
  1013. rf: 298.2471674270,
  1014. ellipseName: "GRS 67(IUGG 1967)"
  1015. };
  1016. exports$2.bessel = {
  1017. a: 6377397.155,
  1018. rf: 299.1528128,
  1019. ellipseName: "Bessel 1841"
  1020. };
  1021. exports$2.bess_nam = {
  1022. a: 6377483.865,
  1023. rf: 299.1528128,
  1024. ellipseName: "Bessel 1841 (Namibia)"
  1025. };
  1026. exports$2.clrk66 = {
  1027. a: 6378206.4,
  1028. b: 6356583.8,
  1029. ellipseName: "Clarke 1866"
  1030. };
  1031. exports$2.clrk80 = {
  1032. a: 6378249.145,
  1033. rf: 293.4663,
  1034. ellipseName: "Clarke 1880 mod."
  1035. };
  1036. exports$2.clrk58 = {
  1037. a: 6378293.645208759,
  1038. rf: 294.2606763692654,
  1039. ellipseName: "Clarke 1858"
  1040. };
  1041. exports$2.CPM = {
  1042. a: 6375738.7,
  1043. rf: 334.29,
  1044. ellipseName: "Comm. des Poids et Mesures 1799"
  1045. };
  1046. exports$2.delmbr = {
  1047. a: 6376428.0,
  1048. rf: 311.5,
  1049. ellipseName: "Delambre 1810 (Belgium)"
  1050. };
  1051. exports$2.engelis = {
  1052. a: 6378136.05,
  1053. rf: 298.2566,
  1054. ellipseName: "Engelis 1985"
  1055. };
  1056. exports$2.evrst30 = {
  1057. a: 6377276.345,
  1058. rf: 300.8017,
  1059. ellipseName: "Everest 1830"
  1060. };
  1061. exports$2.evrst48 = {
  1062. a: 6377304.063,
  1063. rf: 300.8017,
  1064. ellipseName: "Everest 1948"
  1065. };
  1066. exports$2.evrst56 = {
  1067. a: 6377301.243,
  1068. rf: 300.8017,
  1069. ellipseName: "Everest 1956"
  1070. };
  1071. exports$2.evrst69 = {
  1072. a: 6377295.664,
  1073. rf: 300.8017,
  1074. ellipseName: "Everest 1969"
  1075. };
  1076. exports$2.evrstSS = {
  1077. a: 6377298.556,
  1078. rf: 300.8017,
  1079. ellipseName: "Everest (Sabah & Sarawak)"
  1080. };
  1081. exports$2.fschr60 = {
  1082. a: 6378166.0,
  1083. rf: 298.3,
  1084. ellipseName: "Fischer (Mercury Datum) 1960"
  1085. };
  1086. exports$2.fschr60m = {
  1087. a: 6378155.0,
  1088. rf: 298.3,
  1089. ellipseName: "Fischer 1960"
  1090. };
  1091. exports$2.fschr68 = {
  1092. a: 6378150.0,
  1093. rf: 298.3,
  1094. ellipseName: "Fischer 1968"
  1095. };
  1096. exports$2.helmert = {
  1097. a: 6378200.0,
  1098. rf: 298.3,
  1099. ellipseName: "Helmert 1906"
  1100. };
  1101. exports$2.hough = {
  1102. a: 6378270.0,
  1103. rf: 297.0,
  1104. ellipseName: "Hough"
  1105. };
  1106. exports$2.intl = {
  1107. a: 6378388.0,
  1108. rf: 297.0,
  1109. ellipseName: "International 1909 (Hayford)"
  1110. };
  1111. exports$2.kaula = {
  1112. a: 6378163.0,
  1113. rf: 298.24,
  1114. ellipseName: "Kaula 1961"
  1115. };
  1116. exports$2.lerch = {
  1117. a: 6378139.0,
  1118. rf: 298.257,
  1119. ellipseName: "Lerch 1979"
  1120. };
  1121. exports$2.mprts = {
  1122. a: 6397300.0,
  1123. rf: 191.0,
  1124. ellipseName: "Maupertius 1738"
  1125. };
  1126. exports$2.new_intl = {
  1127. a: 6378157.5,
  1128. b: 6356772.2,
  1129. ellipseName: "New International 1967"
  1130. };
  1131. exports$2.plessis = {
  1132. a: 6376523.0,
  1133. rf: 6355863.0,
  1134. ellipseName: "Plessis 1817 (France)"
  1135. };
  1136. exports$2.krass = {
  1137. a: 6378245.0,
  1138. rf: 298.3,
  1139. ellipseName: "Krassovsky, 1942"
  1140. };
  1141. exports$2.SEasia = {
  1142. a: 6378155.0,
  1143. b: 6356773.3205,
  1144. ellipseName: "Southeast Asia"
  1145. };
  1146. exports$2.walbeck = {
  1147. a: 6376896.0,
  1148. b: 6355834.8467,
  1149. ellipseName: "Walbeck"
  1150. };
  1151. exports$2.WGS60 = {
  1152. a: 6378165.0,
  1153. rf: 298.3,
  1154. ellipseName: "WGS 60"
  1155. };
  1156. exports$2.WGS66 = {
  1157. a: 6378145.0,
  1158. rf: 298.25,
  1159. ellipseName: "WGS 66"
  1160. };
  1161. exports$2.WGS7 = {
  1162. a: 6378135.0,
  1163. rf: 298.26,
  1164. ellipseName: "WGS 72"
  1165. };
  1166. var WGS84 = exports$2.WGS84 = {
  1167. a: 6378137.0,
  1168. rf: 298.257223563,
  1169. ellipseName: "WGS 84"
  1170. };
  1171. exports$2.sphere = {
  1172. a: 6370997.0,
  1173. b: 6370997.0,
  1174. ellipseName: "Normal Sphere (r=6370997)"
  1175. };
  1176. function eccentricity(a, b, rf, R_A) {
  1177. var a2 = a * a; // used in geocentric
  1178. var b2 = b * b; // used in geocentric
  1179. var es = (a2 - b2) / a2; // e ^ 2
  1180. var e = 0;
  1181. if (R_A) {
  1182. a *= 1 - es * (SIXTH + es * (RA4 + es * RA6));
  1183. a2 = a * a;
  1184. es = 0;
  1185. } else {
  1186. e = Math.sqrt(es); // eccentricity
  1187. }
  1188. var ep2 = (a2 - b2) / b2; // used in geocentric
  1189. return {
  1190. es: es,
  1191. e: e,
  1192. ep2: ep2
  1193. };
  1194. }
  1195. function sphere(a, b, rf, ellps, sphere) {
  1196. if (!a) { // do we have an ellipsoid?
  1197. var ellipse = match(exports$2, ellps);
  1198. if (!ellipse) {
  1199. ellipse = WGS84;
  1200. }
  1201. a = ellipse.a;
  1202. b = ellipse.b;
  1203. rf = ellipse.rf;
  1204. }
  1205. if (rf && !b) {
  1206. b = (1.0 - 1.0 / rf) * a;
  1207. }
  1208. if (rf === 0 || Math.abs(a - b) < EPSLN) {
  1209. sphere = true;
  1210. b = a;
  1211. }
  1212. return {
  1213. a: a,
  1214. b: b,
  1215. rf: rf,
  1216. sphere: sphere
  1217. };
  1218. }
  1219. var exports$3 = {};
  1220. exports$3.wgs84 = {
  1221. towgs84: "0,0,0",
  1222. ellipse: "WGS84",
  1223. datumName: "WGS84"
  1224. };
  1225. exports$3.ch1903 = {
  1226. towgs84: "674.374,15.056,405.346",
  1227. ellipse: "bessel",
  1228. datumName: "swiss"
  1229. };
  1230. exports$3.ggrs87 = {
  1231. towgs84: "-199.87,74.79,246.62",
  1232. ellipse: "GRS80",
  1233. datumName: "Greek_Geodetic_Reference_System_1987"
  1234. };
  1235. exports$3.nad83 = {
  1236. towgs84: "0,0,0",
  1237. ellipse: "GRS80",
  1238. datumName: "North_American_Datum_1983"
  1239. };
  1240. exports$3.nad27 = {
  1241. nadgrids: "@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat",
  1242. ellipse: "clrk66",
  1243. datumName: "North_American_Datum_1927"
  1244. };
  1245. exports$3.potsdam = {
  1246. towgs84: "598.1,73.7,418.2,0.202,0.045,-2.455,6.7",
  1247. ellipse: "bessel",
  1248. datumName: "Potsdam Rauenberg 1950 DHDN"
  1249. };
  1250. exports$3.carthage = {
  1251. towgs84: "-263.0,6.0,431.0",
  1252. ellipse: "clark80",
  1253. datumName: "Carthage 1934 Tunisia"
  1254. };
  1255. exports$3.hermannskogel = {
  1256. towgs84: "577.326,90.129,463.919,5.137,1.474,5.297,2.4232",
  1257. ellipse: "bessel",
  1258. datumName: "Hermannskogel"
  1259. };
  1260. exports$3.osni52 = {
  1261. towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15",
  1262. ellipse: "airy",
  1263. datumName: "Irish National"
  1264. };
  1265. exports$3.ire65 = {
  1266. towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15",
  1267. ellipse: "mod_airy",
  1268. datumName: "Ireland 1965"
  1269. };
  1270. exports$3.rassadiran = {
  1271. towgs84: "-133.63,-157.5,-158.62",
  1272. ellipse: "intl",
  1273. datumName: "Rassadiran"
  1274. };
  1275. exports$3.nzgd49 = {
  1276. towgs84: "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993",
  1277. ellipse: "intl",
  1278. datumName: "New Zealand Geodetic Datum 1949"
  1279. };
  1280. exports$3.osgb36 = {
  1281. towgs84: "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894",
  1282. ellipse: "airy",
  1283. datumName: "Airy 1830"
  1284. };
  1285. exports$3.s_jtsk = {
  1286. towgs84: "589,76,480",
  1287. ellipse: 'bessel',
  1288. datumName: 'S-JTSK (Ferro)'
  1289. };
  1290. exports$3.beduaram = {
  1291. towgs84: '-106,-87,188',
  1292. ellipse: 'clrk80',
  1293. datumName: 'Beduaram'
  1294. };
  1295. exports$3.gunung_segara = {
  1296. towgs84: '-403,684,41',
  1297. ellipse: 'bessel',
  1298. datumName: 'Gunung Segara Jakarta'
  1299. };
  1300. exports$3.rnb72 = {
  1301. towgs84: "106.869,-52.2978,103.724,-0.33657,0.456955,-1.84218,1",
  1302. ellipse: "intl",
  1303. datumName: "Reseau National Belge 1972"
  1304. };
  1305. function datum(datumCode, datum_params, a, b, es, ep2, nadgrids) {
  1306. var out = {};
  1307. if (datumCode === undefined || datumCode === 'none') {
  1308. out.datum_type = PJD_NODATUM;
  1309. } else {
  1310. out.datum_type = PJD_WGS84;
  1311. }
  1312. if (datum_params) {
  1313. out.datum_params = datum_params.map(parseFloat);
  1314. if (out.datum_params[0] !== 0 || out.datum_params[1] !== 0 || out.datum_params[2] !== 0) {
  1315. out.datum_type = PJD_3PARAM;
  1316. }
  1317. if (out.datum_params.length > 3) {
  1318. if (out.datum_params[3] !== 0 || out.datum_params[4] !== 0 || out.datum_params[5] !== 0 || out.datum_params[6] !== 0) {
  1319. out.datum_type = PJD_7PARAM;
  1320. out.datum_params[3] *= SEC_TO_RAD;
  1321. out.datum_params[4] *= SEC_TO_RAD;
  1322. out.datum_params[5] *= SEC_TO_RAD;
  1323. out.datum_params[6] = (out.datum_params[6] / 1000000.0) + 1.0;
  1324. }
  1325. }
  1326. }
  1327. if (nadgrids) {
  1328. out.datum_type = PJD_GRIDSHIFT;
  1329. out.grids = nadgrids;
  1330. }
  1331. out.a = a; //datum object also uses these values
  1332. out.b = b;
  1333. out.es = es;
  1334. out.ep2 = ep2;
  1335. return out;
  1336. }
  1337. /**
  1338. * Resources for details of NTv2 file formats:
  1339. * - https://web.archive.org/web/20140127204822if_/http://www.mgs.gov.on.ca:80/stdprodconsume/groups/content/@mgs/@iandit/documents/resourcelist/stel02_047447.pdf
  1340. * - http://mimaka.com/help/gs/html/004_NTV2%20Data%20Format.htm
  1341. */
  1342. var loadedNadgrids = {};
  1343. /**
  1344. * Load a binary NTv2 file (.gsb) to a key that can be used in a proj string like +nadgrids=<key>. Pass the NTv2 file
  1345. * as an ArrayBuffer.
  1346. */
  1347. function nadgrid(key, data) {
  1348. var view = new DataView(data);
  1349. var isLittleEndian = detectLittleEndian(view);
  1350. var header = readHeader(view, isLittleEndian);
  1351. if (header.nSubgrids > 1) {
  1352. console.log('Only single NTv2 subgrids are currently supported, subsequent sub grids are ignored');
  1353. }
  1354. var subgrids = readSubgrids(view, header, isLittleEndian);
  1355. var nadgrid = {header: header, subgrids: subgrids};
  1356. loadedNadgrids[key] = nadgrid;
  1357. return nadgrid;
  1358. }
  1359. /**
  1360. * Given a proj4 value for nadgrids, return an array of loaded grids
  1361. */
  1362. function getNadgrids(nadgrids) {
  1363. // Format details: http://proj.maptools.org/gen_parms.html
  1364. if (nadgrids === undefined) { return null; }
  1365. var grids = nadgrids.split(',');
  1366. return grids.map(parseNadgridString);
  1367. }
  1368. function parseNadgridString(value) {
  1369. if (value.length === 0) {
  1370. return null;
  1371. }
  1372. var optional = value[0] === '@';
  1373. if (optional) {
  1374. value = value.slice(1);
  1375. }
  1376. if (value === 'null') {
  1377. return {name: 'null', mandatory: !optional, grid: null, isNull: true};
  1378. }
  1379. return {
  1380. name: value,
  1381. mandatory: !optional,
  1382. grid: loadedNadgrids[value] || null,
  1383. isNull: false
  1384. };
  1385. }
  1386. function secondsToRadians(seconds) {
  1387. return (seconds / 3600) * Math.PI / 180;
  1388. }
  1389. function detectLittleEndian(view) {
  1390. var nFields = view.getInt32(8, false);
  1391. if (nFields === 11) {
  1392. return false;
  1393. }
  1394. nFields = view.getInt32(8, true);
  1395. if (nFields !== 11) {
  1396. console.warn('Failed to detect nadgrid endian-ness, defaulting to little-endian');
  1397. }
  1398. return true;
  1399. }
  1400. function readHeader(view, isLittleEndian) {
  1401. return {
  1402. nFields: view.getInt32(8, isLittleEndian),
  1403. nSubgridFields: view.getInt32(24, isLittleEndian),
  1404. nSubgrids: view.getInt32(40, isLittleEndian),
  1405. shiftType: decodeString(view, 56, 56 + 8).trim(),
  1406. fromSemiMajorAxis: view.getFloat64(120, isLittleEndian),
  1407. fromSemiMinorAxis: view.getFloat64(136, isLittleEndian),
  1408. toSemiMajorAxis: view.getFloat64(152, isLittleEndian),
  1409. toSemiMinorAxis: view.getFloat64(168, isLittleEndian),
  1410. };
  1411. }
  1412. function decodeString(view, start, end) {
  1413. return String.fromCharCode.apply(null, new Uint8Array(view.buffer.slice(start, end)));
  1414. }
  1415. function readSubgrids(view, header, isLittleEndian) {
  1416. var gridOffset = 176;
  1417. var grids = [];
  1418. for (var i = 0; i < header.nSubgrids; i++) {
  1419. var subHeader = readGridHeader(view, gridOffset, isLittleEndian);
  1420. var nodes = readGridNodes(view, gridOffset, subHeader, isLittleEndian);
  1421. var lngColumnCount = Math.round(
  1422. 1 + (subHeader.upperLongitude - subHeader.lowerLongitude) / subHeader.longitudeInterval);
  1423. var latColumnCount = Math.round(
  1424. 1 + (subHeader.upperLatitude - subHeader.lowerLatitude) / subHeader.latitudeInterval);
  1425. // Proj4 operates on radians whereas the coordinates are in seconds in the grid
  1426. grids.push({
  1427. ll: [secondsToRadians(subHeader.lowerLongitude), secondsToRadians(subHeader.lowerLatitude)],
  1428. del: [secondsToRadians(subHeader.longitudeInterval), secondsToRadians(subHeader.latitudeInterval)],
  1429. lim: [lngColumnCount, latColumnCount],
  1430. count: subHeader.gridNodeCount,
  1431. cvs: mapNodes(nodes)
  1432. });
  1433. }
  1434. return grids;
  1435. }
  1436. function mapNodes(nodes) {
  1437. return nodes.map(function (r) {return [secondsToRadians(r.longitudeShift), secondsToRadians(r.latitudeShift)];});
  1438. }
  1439. function readGridHeader(view, offset, isLittleEndian) {
  1440. return {
  1441. name: decodeString(view, offset + 8, offset + 16).trim(),
  1442. parent: decodeString(view, offset + 24, offset + 24 + 8).trim(),
  1443. lowerLatitude: view.getFloat64(offset + 72, isLittleEndian),
  1444. upperLatitude: view.getFloat64(offset + 88, isLittleEndian),
  1445. lowerLongitude: view.getFloat64(offset + 104, isLittleEndian),
  1446. upperLongitude: view.getFloat64(offset + 120, isLittleEndian),
  1447. latitudeInterval: view.getFloat64(offset + 136, isLittleEndian),
  1448. longitudeInterval: view.getFloat64(offset + 152, isLittleEndian),
  1449. gridNodeCount: view.getInt32(offset + 168, isLittleEndian)
  1450. };
  1451. }
  1452. function readGridNodes(view, offset, gridHeader, isLittleEndian) {
  1453. var nodesOffset = offset + 176;
  1454. var gridRecordLength = 16;
  1455. var gridShiftRecords = [];
  1456. for (var i = 0; i < gridHeader.gridNodeCount; i++) {
  1457. var record = {
  1458. latitudeShift: view.getFloat32(nodesOffset + i * gridRecordLength, isLittleEndian),
  1459. longitudeShift: view.getFloat32(nodesOffset + i * gridRecordLength + 4, isLittleEndian),
  1460. latitudeAccuracy: view.getFloat32(nodesOffset + i * gridRecordLength + 8, isLittleEndian),
  1461. longitudeAccuracy: view.getFloat32(nodesOffset + i * gridRecordLength + 12, isLittleEndian),
  1462. };
  1463. gridShiftRecords.push(record);
  1464. }
  1465. return gridShiftRecords;
  1466. }
  1467. function Projection(srsCode,callback) {
  1468. if (!(this instanceof Projection)) {
  1469. return new Projection(srsCode);
  1470. }
  1471. callback = callback || function(error){
  1472. if(error){
  1473. throw error;
  1474. }
  1475. };
  1476. var json = parse(srsCode);
  1477. if(typeof json !== 'object'){
  1478. callback(srsCode);
  1479. return;
  1480. }
  1481. var ourProj = Projection.projections.get(json.projName);
  1482. if(!ourProj){
  1483. callback(srsCode);
  1484. return;
  1485. }
  1486. if (json.datumCode && json.datumCode !== 'none') {
  1487. var datumDef = match(exports$3, json.datumCode);
  1488. if (datumDef) {
  1489. json.datum_params = json.datum_params || (datumDef.towgs84 ? datumDef.towgs84.split(',') : null);
  1490. json.ellps = datumDef.ellipse;
  1491. json.datumName = datumDef.datumName ? datumDef.datumName : json.datumCode;
  1492. }
  1493. }
  1494. json.k0 = json.k0 || 1.0;
  1495. json.axis = json.axis || 'enu';
  1496. json.ellps = json.ellps || 'wgs84';
  1497. json.lat1 = json.lat1 || json.lat0; // Lambert_Conformal_Conic_1SP, for example, needs this
  1498. var sphere_ = sphere(json.a, json.b, json.rf, json.ellps, json.sphere);
  1499. var ecc = eccentricity(sphere_.a, sphere_.b, sphere_.rf, json.R_A);
  1500. var nadgrids = getNadgrids(json.nadgrids);
  1501. var datumObj = json.datum || datum(json.datumCode, json.datum_params, sphere_.a, sphere_.b, ecc.es, ecc.ep2,
  1502. nadgrids);
  1503. extend(this, json); // transfer everything over from the projection because we don't know what we'll need
  1504. extend(this, ourProj); // transfer all the methods from the projection
  1505. // copy the 4 things over we calulated in deriveConstants.sphere
  1506. this.a = sphere_.a;
  1507. this.b = sphere_.b;
  1508. this.rf = sphere_.rf;
  1509. this.sphere = sphere_.sphere;
  1510. // copy the 3 things we calculated in deriveConstants.eccentricity
  1511. this.es = ecc.es;
  1512. this.e = ecc.e;
  1513. this.ep2 = ecc.ep2;
  1514. // add in the datum object
  1515. this.datum = datumObj;
  1516. // init the projection
  1517. this.init();
  1518. // legecy callback from back in the day when it went to spatialreference.org
  1519. callback(null, this);
  1520. }
  1521. Projection.projections = projections;
  1522. Projection.projections.start();
  1523. 'use strict';
  1524. function compareDatums(source, dest) {
  1525. if (source.datum_type !== dest.datum_type) {
  1526. return false; // false, datums are not equal
  1527. } else if (source.a !== dest.a || Math.abs(source.es - dest.es) > 0.000000000050) {
  1528. // the tolerance for es is to ensure that GRS80 and WGS84
  1529. // are considered identical
  1530. return false;
  1531. } else if (source.datum_type === PJD_3PARAM) {
  1532. return (source.datum_params[0] === dest.datum_params[0] && source.datum_params[1] === dest.datum_params[1] && source.datum_params[2] === dest.datum_params[2]);
  1533. } else if (source.datum_type === PJD_7PARAM) {
  1534. return (source.datum_params[0] === dest.datum_params[0] && source.datum_params[1] === dest.datum_params[1] && source.datum_params[2] === dest.datum_params[2] && source.datum_params[3] === dest.datum_params[3] && source.datum_params[4] === dest.datum_params[4] && source.datum_params[5] === dest.datum_params[5] && source.datum_params[6] === dest.datum_params[6]);
  1535. } else {
  1536. return true; // datums are equal
  1537. }
  1538. } // cs_compare_datums()
  1539. /*
  1540. * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates
  1541. * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z),
  1542. * according to the current ellipsoid parameters.
  1543. *
  1544. * Latitude : Geodetic latitude in radians (input)
  1545. * Longitude : Geodetic longitude in radians (input)
  1546. * Height : Geodetic height, in meters (input)
  1547. * X : Calculated Geocentric X coordinate, in meters (output)
  1548. * Y : Calculated Geocentric Y coordinate, in meters (output)
  1549. * Z : Calculated Geocentric Z coordinate, in meters (output)
  1550. *
  1551. */
  1552. function geodeticToGeocentric(p, es, a) {
  1553. var Longitude = p.x;
  1554. var Latitude = p.y;
  1555. var Height = p.z ? p.z : 0; //Z value not always supplied
  1556. var Rn; /* Earth radius at location */
  1557. var Sin_Lat; /* Math.sin(Latitude) */
  1558. var Sin2_Lat; /* Square of Math.sin(Latitude) */
  1559. var Cos_Lat; /* Math.cos(Latitude) */
  1560. /*
  1561. ** Don't blow up if Latitude is just a little out of the value
  1562. ** range as it may just be a rounding issue. Also removed longitude
  1563. ** test, it should be wrapped by Math.cos() and Math.sin(). NFW for PROJ.4, Sep/2001.
  1564. */
  1565. if (Latitude < -HALF_PI && Latitude > -1.001 * HALF_PI) {
  1566. Latitude = -HALF_PI;
  1567. } else if (Latitude > HALF_PI && Latitude < 1.001 * HALF_PI) {
  1568. Latitude = HALF_PI;
  1569. } else if (Latitude < -HALF_PI) {
  1570. /* Latitude out of range */
  1571. //..reportError('geocent:lat out of range:' + Latitude);
  1572. return { x: -Infinity, y: -Infinity, z: p.z };
  1573. } else if (Latitude > HALF_PI) {
  1574. /* Latitude out of range */
  1575. return { x: Infinity, y: Infinity, z: p.z };
  1576. }
  1577. if (Longitude > Math.PI) {
  1578. Longitude -= (2 * Math.PI);
  1579. }
  1580. Sin_Lat = Math.sin(Latitude);
  1581. Cos_Lat = Math.cos(Latitude);
  1582. Sin2_Lat = Sin_Lat * Sin_Lat;
  1583. Rn = a / (Math.sqrt(1.0e0 - es * Sin2_Lat));
  1584. return {
  1585. x: (Rn + Height) * Cos_Lat * Math.cos(Longitude),
  1586. y: (Rn + Height) * Cos_Lat * Math.sin(Longitude),
  1587. z: ((Rn * (1 - es)) + Height) * Sin_Lat
  1588. };
  1589. } // cs_geodetic_to_geocentric()
  1590. function geocentricToGeodetic(p, es, a, b) {
  1591. /* local defintions and variables */
  1592. /* end-criterium of loop, accuracy of sin(Latitude) */
  1593. var genau = 1e-12;
  1594. var genau2 = (genau * genau);
  1595. var maxiter = 30;
  1596. var P; /* distance between semi-minor axis and location */
  1597. var RR; /* distance between center and location */
  1598. var CT; /* sin of geocentric latitude */
  1599. var ST; /* cos of geocentric latitude */
  1600. var RX;
  1601. var RK;
  1602. var RN; /* Earth radius at location */
  1603. var CPHI0; /* cos of start or old geodetic latitude in iterations */
  1604. var SPHI0; /* sin of start or old geodetic latitude in iterations */
  1605. var CPHI; /* cos of searched geodetic latitude */
  1606. var SPHI; /* sin of searched geodetic latitude */
  1607. var SDPHI; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */
  1608. var iter; /* # of continous iteration, max. 30 is always enough (s.a.) */
  1609. var X = p.x;
  1610. var Y = p.y;
  1611. var Z = p.z ? p.z : 0.0; //Z value not always supplied
  1612. var Longitude;
  1613. var Latitude;
  1614. var Height;
  1615. P = Math.sqrt(X * X + Y * Y);
  1616. RR = Math.sqrt(X * X + Y * Y + Z * Z);
  1617. /* special cases for latitude and longitude */
  1618. if (P / a < genau) {
  1619. /* special case, if P=0. (X=0., Y=0.) */
  1620. Longitude = 0.0;
  1621. /* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis
  1622. * of ellipsoid (=center of mass), Latitude becomes PI/2 */
  1623. if (RR / a < genau) {
  1624. Latitude = HALF_PI;
  1625. Height = -b;
  1626. return {
  1627. x: p.x,
  1628. y: p.y,
  1629. z: p.z
  1630. };
  1631. }
  1632. } else {
  1633. /* ellipsoidal (geodetic) longitude
  1634. * interval: -PI < Longitude <= +PI */
  1635. Longitude = Math.atan2(Y, X);
  1636. }
  1637. /* --------------------------------------------------------------
  1638. * Following iterative algorithm was developped by
  1639. * "Institut for Erdmessung", University of Hannover, July 1988.
  1640. * Internet: www.ife.uni-hannover.de
  1641. * Iterative computation of CPHI,SPHI and Height.
  1642. * Iteration of CPHI and SPHI to 10**-12 radian resp.
  1643. * 2*10**-7 arcsec.
  1644. * --------------------------------------------------------------
  1645. */
  1646. CT = Z / RR;
  1647. ST = P / RR;
  1648. RX = 1.0 / Math.sqrt(1.0 - es * (2.0 - es) * ST * ST);
  1649. CPHI0 = ST * (1.0 - es) * RX;
  1650. SPHI0 = CT * RX;
  1651. iter = 0;
  1652. /* loop to find sin(Latitude) resp. Latitude
  1653. * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */
  1654. do {
  1655. iter++;
  1656. RN = a / Math.sqrt(1.0 - es * SPHI0 * SPHI0);
  1657. /* ellipsoidal (geodetic) height */
  1658. Height = P * CPHI0 + Z * SPHI0 - RN * (1.0 - es * SPHI0 * SPHI0);
  1659. RK = es * RN / (RN + Height);
  1660. RX = 1.0 / Math.sqrt(1.0 - RK * (2.0 - RK) * ST * ST);
  1661. CPHI = ST * (1.0 - RK) * RX;
  1662. SPHI = CT * RX;
  1663. SDPHI = SPHI * CPHI0 - CPHI * SPHI0;
  1664. CPHI0 = CPHI;
  1665. SPHI0 = SPHI;
  1666. }
  1667. while (SDPHI * SDPHI > genau2 && iter < maxiter);
  1668. /* ellipsoidal (geodetic) latitude */
  1669. Latitude = Math.atan(SPHI / Math.abs(CPHI));
  1670. return {
  1671. x: Longitude,
  1672. y: Latitude,
  1673. z: Height
  1674. };
  1675. } // cs_geocentric_to_geodetic()
  1676. /****************************************************************/
  1677. // pj_geocentic_to_wgs84( p )
  1678. // p = point to transform in geocentric coordinates (x,y,z)
  1679. /** point object, nothing fancy, just allows values to be
  1680. passed back and forth by reference rather than by value.
  1681. Other point classes may be used as long as they have
  1682. x and y properties, which will get modified in the transform method.
  1683. */
  1684. function geocentricToWgs84(p, datum_type, datum_params) {
  1685. if (datum_type === PJD_3PARAM) {
  1686. // if( x[io] === HUGE_VAL )
  1687. // continue;
  1688. return {
  1689. x: p.x + datum_params[0],
  1690. y: p.y + datum_params[1],
  1691. z: p.z + datum_params[2],
  1692. };
  1693. } else if (datum_type === PJD_7PARAM) {
  1694. var Dx_BF = datum_params[0];
  1695. var Dy_BF = datum_params[1];
  1696. var Dz_BF = datum_params[2];
  1697. var Rx_BF = datum_params[3];
  1698. var Ry_BF = datum_params[4];
  1699. var Rz_BF = datum_params[5];
  1700. var M_BF = datum_params[6];
  1701. // if( x[io] === HUGE_VAL )
  1702. // continue;
  1703. return {
  1704. x: M_BF * (p.x - Rz_BF * p.y + Ry_BF * p.z) + Dx_BF,
  1705. y: M_BF * (Rz_BF * p.x + p.y - Rx_BF * p.z) + Dy_BF,
  1706. z: M_BF * (-Ry_BF * p.x + Rx_BF * p.y + p.z) + Dz_BF
  1707. };
  1708. }
  1709. } // cs_geocentric_to_wgs84
  1710. /****************************************************************/
  1711. // pj_geocentic_from_wgs84()
  1712. // coordinate system definition,
  1713. // point to transform in geocentric coordinates (x,y,z)
  1714. function geocentricFromWgs84(p, datum_type, datum_params) {
  1715. if (datum_type === PJD_3PARAM) {
  1716. //if( x[io] === HUGE_VAL )
  1717. // continue;
  1718. return {
  1719. x: p.x - datum_params[0],
  1720. y: p.y - datum_params[1],
  1721. z: p.z - datum_params[2],
  1722. };
  1723. } else if (datum_type === PJD_7PARAM) {
  1724. var Dx_BF = datum_params[0];
  1725. var Dy_BF = datum_params[1];
  1726. var Dz_BF = datum_params[2];
  1727. var Rx_BF = datum_params[3];
  1728. var Ry_BF = datum_params[4];
  1729. var Rz_BF = datum_params[5];
  1730. var M_BF = datum_params[6];
  1731. var x_tmp = (p.x - Dx_BF) / M_BF;
  1732. var y_tmp = (p.y - Dy_BF) / M_BF;
  1733. var z_tmp = (p.z - Dz_BF) / M_BF;
  1734. //if( x[io] === HUGE_VAL )
  1735. // continue;
  1736. return {
  1737. x: x_tmp + Rz_BF * y_tmp - Ry_BF * z_tmp,
  1738. y: -Rz_BF * x_tmp + y_tmp + Rx_BF * z_tmp,
  1739. z: Ry_BF * x_tmp - Rx_BF * y_tmp + z_tmp
  1740. };
  1741. } //cs_geocentric_from_wgs84()
  1742. }
  1743. function checkParams(type) {
  1744. return (type === PJD_3PARAM || type === PJD_7PARAM);
  1745. }
  1746. var datum_transform = function(source, dest, point) {
  1747. // Short cut if the datums are identical.
  1748. if (compareDatums(source, dest)) {
  1749. return point; // in this case, zero is sucess,
  1750. // whereas cs_compare_datums returns 1 to indicate TRUE
  1751. // confusing, should fix this
  1752. }
  1753. // Explicitly skip datum transform by setting 'datum=none' as parameter for either source or dest
  1754. if (source.datum_type === PJD_NODATUM || dest.datum_type === PJD_NODATUM) {
  1755. return point;
  1756. }
  1757. // If this datum requires grid shifts, then apply it to geodetic coordinates.
  1758. var source_a = source.a;
  1759. var source_es = source.es;
  1760. if (source.datum_type === PJD_GRIDSHIFT) {
  1761. var gridShiftCode = applyGridShift(source, false, point);
  1762. if (gridShiftCode !== 0) {
  1763. return undefined;
  1764. }
  1765. source_a = SRS_WGS84_SEMIMAJOR;
  1766. source_es = SRS_WGS84_ESQUARED;
  1767. }
  1768. var dest_a = dest.a;
  1769. var dest_b = dest.b;
  1770. var dest_es = dest.es;
  1771. if (dest.datum_type === PJD_GRIDSHIFT) {
  1772. dest_a = SRS_WGS84_SEMIMAJOR;
  1773. dest_b = SRS_WGS84_SEMIMINOR;
  1774. dest_es = SRS_WGS84_ESQUARED;
  1775. }
  1776. // Do we need to go through geocentric coordinates?
  1777. if (source_es === dest_es && source_a === dest_a && !checkParams(source.datum_type) && !checkParams(dest.datum_type)) {
  1778. return point;
  1779. }
  1780. // Convert to geocentric coordinates.
  1781. point = geodeticToGeocentric(point, source_es, source_a);
  1782. // Convert between datums
  1783. if (checkParams(source.datum_type)) {
  1784. point = geocentricToWgs84(point, source.datum_type, source.datum_params);
  1785. }
  1786. if (checkParams(dest.datum_type)) {
  1787. point = geocentricFromWgs84(point, dest.datum_type, dest.datum_params);
  1788. }
  1789. point = geocentricToGeodetic(point, dest_es, dest_a, dest_b);
  1790. if (dest.datum_type === PJD_GRIDSHIFT) {
  1791. var destGridShiftResult = applyGridShift(dest, true, point);
  1792. if (destGridShiftResult !== 0) {
  1793. return undefined;
  1794. }
  1795. }
  1796. return point;
  1797. };
  1798. function applyGridShift(source, inverse, point) {
  1799. if (source.grids === null || source.grids.length === 0) {
  1800. console.log('Grid shift grids not found');
  1801. return -1;
  1802. }
  1803. var input = {x: -point.x, y: point.y};
  1804. var output = {x: Number.NaN, y: Number.NaN};
  1805. var attemptedGrids = [];
  1806. for (var i = 0; i < source.grids.length; i++) {
  1807. var grid = source.grids[i];
  1808. attemptedGrids.push(grid.name);
  1809. if (grid.isNull) {
  1810. output = input;
  1811. break;
  1812. }
  1813. if (grid.grid === null) {
  1814. if (grid.mandatory) {
  1815. console.log("Unable to find mandatory grid '" + grid.name + "'");
  1816. return -1;
  1817. }
  1818. continue;
  1819. }
  1820. var subgrid = grid.grid.subgrids[0];
  1821. // skip tables that don't match our point at all
  1822. var epsilon = (Math.abs(subgrid.del[1]) + Math.abs(subgrid.del[0])) / 10000.0;
  1823. var minX = subgrid.ll[0] - epsilon;
  1824. var minY = subgrid.ll[1] - epsilon;
  1825. var maxX = subgrid.ll[0] + (subgrid.lim[0] - 1) * subgrid.del[0] + epsilon;
  1826. var maxY = subgrid.ll[1] + (subgrid.lim[1] - 1) * subgrid.del[1] + epsilon;
  1827. if (minY > input.y || minX > input.x || maxY < input.y || maxX < input.x ) {
  1828. continue;
  1829. }
  1830. output = applySubgridShift(input, inverse, subgrid);
  1831. if (!isNaN(output.x)) {
  1832. break;
  1833. }
  1834. }
  1835. if (isNaN(output.x)) {
  1836. console.log("Failed to find a grid shift table for location '"+
  1837. -input.x * R2D + " " + input.y * R2D + " tried: '" + attemptedGrids + "'");
  1838. return -1;
  1839. }
  1840. point.x = -output.x;
  1841. point.y = output.y;
  1842. return 0;
  1843. }
  1844. function applySubgridShift(pin, inverse, ct) {
  1845. var val = {x: Number.NaN, y: Number.NaN};
  1846. if (isNaN(pin.x)) { return val; }
  1847. var tb = {x: pin.x, y: pin.y};
  1848. tb.x -= ct.ll[0];
  1849. tb.y -= ct.ll[1];
  1850. tb.x = adjust_lon(tb.x - Math.PI) + Math.PI;
  1851. var t = nadInterpolate(tb, ct);
  1852. if (inverse) {
  1853. if (isNaN(t.x)) {
  1854. return val;
  1855. }
  1856. t.x = tb.x - t.x;
  1857. t.y = tb.y - t.y;
  1858. var i = 9, tol = 1e-12;
  1859. var dif, del;
  1860. do {
  1861. del = nadInterpolate(t, ct);
  1862. if (isNaN(del.x)) {
  1863. console.log("Inverse grid shift iteration failed, presumably at grid edge. Using first approximation.");
  1864. break;
  1865. }
  1866. dif = {x: tb.x - (del.x + t.x), y: tb.y - (del.y + t.y)};
  1867. t.x += dif.x;
  1868. t.y += dif.y;
  1869. } while (i-- && Math.abs(dif.x) > tol && Math.abs(dif.y) > tol);
  1870. if (i < 0) {
  1871. console.log("Inverse grid shift iterator failed to converge.");
  1872. return val;
  1873. }
  1874. val.x = adjust_lon(t.x + ct.ll[0]);
  1875. val.y = t.y + ct.ll[1];
  1876. } else {
  1877. if (!isNaN(t.x)) {
  1878. val.x = pin.x + t.x;
  1879. val.y = pin.y + t.y;
  1880. }
  1881. }
  1882. return val;
  1883. }
  1884. function nadInterpolate(pin, ct) {
  1885. var t = {x: pin.x / ct.del[0], y: pin.y / ct.del[1]};
  1886. var indx = {x: Math.floor(t.x), y: Math.floor(t.y)};
  1887. var frct = {x: t.x - 1.0 * indx.x, y: t.y - 1.0 * indx.y};
  1888. var val= {x: Number.NaN, y: Number.NaN};
  1889. var inx;
  1890. if (indx.x < 0 || indx.x >= ct.lim[0]) {
  1891. return val;
  1892. }
  1893. if (indx.y < 0 || indx.y >= ct.lim[1]) {
  1894. return val;
  1895. }
  1896. inx = (indx.y * ct.lim[0]) + indx.x;
  1897. var f00 = {x: ct.cvs[inx][0], y: ct.cvs[inx][1]};
  1898. inx++;
  1899. var f10= {x: ct.cvs[inx][0], y: ct.cvs[inx][1]};
  1900. inx += ct.lim[0];
  1901. var f11 = {x: ct.cvs[inx][0], y: ct.cvs[inx][1]};
  1902. inx--;
  1903. var f01 = {x: ct.cvs[inx][0], y: ct.cvs[inx][1]};
  1904. var m11 = frct.x * frct.y, m10 = frct.x * (1.0 - frct.y),
  1905. m00 = (1.0 - frct.x) * (1.0 - frct.y), m01 = (1.0 - frct.x) * frct.y;
  1906. val.x = (m00 * f00.x + m10 * f10.x + m01 * f01.x + m11 * f11.x);
  1907. val.y = (m00 * f00.y + m10 * f10.y + m01 * f01.y + m11 * f11.y);
  1908. return val;
  1909. }
  1910. var adjust_axis = function(crs, denorm, point) {
  1911. var xin = point.x,
  1912. yin = point.y,
  1913. zin = point.z || 0.0;
  1914. var v, t, i;
  1915. var out = {};
  1916. for (i = 0; i < 3; i++) {
  1917. if (denorm && i === 2 && point.z === undefined) {
  1918. continue;
  1919. }
  1920. if (i === 0) {
  1921. v = xin;
  1922. if ("ew".indexOf(crs.axis[i]) !== -1) {
  1923. t = 'x';
  1924. } else {
  1925. t = 'y';
  1926. }
  1927. }
  1928. else if (i === 1) {
  1929. v = yin;
  1930. if ("ns".indexOf(crs.axis[i]) !== -1) {
  1931. t = 'y';
  1932. } else {
  1933. t = 'x';
  1934. }
  1935. }
  1936. else {
  1937. v = zin;
  1938. t = 'z';
  1939. }
  1940. switch (crs.axis[i]) {
  1941. case 'e':
  1942. out[t] = v;
  1943. break;
  1944. case 'w':
  1945. out[t] = -v;
  1946. break;
  1947. case 'n':
  1948. out[t] = v;
  1949. break;
  1950. case 's':
  1951. out[t] = -v;
  1952. break;
  1953. case 'u':
  1954. if (point[t] !== undefined) {
  1955. out.z = v;
  1956. }
  1957. break;
  1958. case 'd':
  1959. if (point[t] !== undefined) {
  1960. out.z = -v;
  1961. }
  1962. break;
  1963. default:
  1964. //console.log("ERROR: unknow axis ("+crs.axis[i]+") - check definition of "+crs.projName);
  1965. return null;
  1966. }
  1967. }
  1968. return out;
  1969. };
  1970. var toPoint = function (array){
  1971. var out = {
  1972. x: array[0],
  1973. y: array[1]
  1974. };
  1975. if (array.length>2) {
  1976. out.z = array[2];
  1977. }
  1978. if (array.length>3) {
  1979. out.m = array[3];
  1980. }
  1981. return out;
  1982. };
  1983. var checkSanity = function (point) {
  1984. checkCoord(point.x);
  1985. checkCoord(point.y);
  1986. };
  1987. function checkCoord(num) {
  1988. if (typeof Number.isFinite === 'function') {
  1989. if (Number.isFinite(num)) {
  1990. return;
  1991. }
  1992. throw new TypeError('coordinates must be finite numbers');
  1993. }
  1994. if (typeof num !== 'number' || num !== num || !isFinite(num)) {
  1995. throw new TypeError('coordinates must be finite numbers');
  1996. }
  1997. }
  1998. function checkNotWGS(source, dest) {
  1999. return ((source.datum.datum_type === PJD_3PARAM || source.datum.datum_type === PJD_7PARAM) && dest.datumCode !== 'WGS84') || ((dest.datum.datum_type === PJD_3PARAM || dest.datum.datum_type === PJD_7PARAM) && source.datumCode !== 'WGS84');
  2000. }
  2001. function transform(source, dest, point, enforceAxis) {
  2002. var wgs84;
  2003. if (Array.isArray(point)) {
  2004. point = toPoint(point);
  2005. }
  2006. checkSanity(point);
  2007. // Workaround for datum shifts towgs84, if either source or destination projection is not wgs84
  2008. if (source.datum && dest.datum && checkNotWGS(source, dest)) {
  2009. wgs84 = new Projection('WGS84');
  2010. point = transform(source, wgs84, point, enforceAxis);
  2011. source = wgs84;
  2012. }
  2013. // DGR, 2010/11/12
  2014. if (enforceAxis && source.axis !== 'enu') {
  2015. point = adjust_axis(source, false, point);
  2016. }
  2017. // Transform source points to long/lat, if they aren't already.
  2018. if (source.projName === 'longlat') {
  2019. point = {
  2020. x: point.x * D2R,
  2021. y: point.y * D2R,
  2022. z: point.z || 0
  2023. };
  2024. } else {
  2025. if (source.to_meter) {
  2026. point = {
  2027. x: point.x * source.to_meter,
  2028. y: point.y * source.to_meter,
  2029. z: point.z || 0
  2030. };
  2031. }
  2032. point = source.inverse(point); // Convert Cartesian to longlat
  2033. if (!point) {
  2034. return;
  2035. }
  2036. }
  2037. // Adjust for the prime meridian if necessary
  2038. if (source.from_greenwich) {
  2039. point.x += source.from_greenwich;
  2040. }
  2041. // Convert datums if needed, and if possible.
  2042. point = datum_transform(source.datum, dest.datum, point);
  2043. if (!point) {
  2044. return;
  2045. }
  2046. // Adjust for the prime meridian if necessary
  2047. if (dest.from_greenwich) {
  2048. point = {
  2049. x: point.x - dest.from_greenwich,
  2050. y: point.y,
  2051. z: point.z || 0
  2052. };
  2053. }
  2054. if (dest.projName === 'longlat') {
  2055. // convert radians to decimal degrees
  2056. point = {
  2057. x: point.x * R2D,
  2058. y: point.y * R2D,
  2059. z: point.z || 0
  2060. };
  2061. } else { // else project
  2062. point = dest.forward(point);
  2063. if (dest.to_meter) {
  2064. point = {
  2065. x: point.x / dest.to_meter,
  2066. y: point.y / dest.to_meter,
  2067. z: point.z || 0
  2068. };
  2069. }
  2070. }
  2071. // DGR, 2010/11/12
  2072. if (enforceAxis && dest.axis !== 'enu') {
  2073. return adjust_axis(dest, true, point);
  2074. }
  2075. return point;
  2076. }
  2077. var wgs84 = Projection('WGS84');
  2078. function transformer(from, to, coords, enforceAxis) {
  2079. var transformedArray, out, keys;
  2080. if (Array.isArray(coords)) {
  2081. transformedArray = transform(from, to, coords, enforceAxis) || {x: NaN, y: NaN};
  2082. if (coords.length > 2) {
  2083. if ((typeof from.name !== 'undefined' && from.name === 'geocent') || (typeof to.name !== 'undefined' && to.name === 'geocent')) {
  2084. if (typeof transformedArray.z === 'number') {
  2085. return [transformedArray.x, transformedArray.y, transformedArray.z].concat(coords.splice(3));
  2086. } else {
  2087. return [transformedArray.x, transformedArray.y, coords[2]].concat(coords.splice(3));
  2088. }
  2089. } else {
  2090. return [transformedArray.x, transformedArray.y].concat(coords.splice(2));
  2091. }
  2092. } else {
  2093. return [transformedArray.x, transformedArray.y];
  2094. }
  2095. } else {
  2096. out = transform(from, to, coords, enforceAxis);
  2097. keys = Object.keys(coords);
  2098. if (keys.length === 2) {
  2099. return out;
  2100. }
  2101. keys.forEach(function (key) {
  2102. if ((typeof from.name !== 'undefined' && from.name === 'geocent') || (typeof to.name !== 'undefined' && to.name === 'geocent')) {
  2103. if (key === 'x' || key === 'y' || key === 'z') {
  2104. return;
  2105. }
  2106. } else {
  2107. if (key === 'x' || key === 'y') {
  2108. return;
  2109. }
  2110. }
  2111. out[key] = coords[key];
  2112. });
  2113. return out;
  2114. }
  2115. }
  2116. function checkProj(item) {
  2117. if (item instanceof Projection) {
  2118. return item;
  2119. }
  2120. if (item.oProj) {
  2121. return item.oProj;
  2122. }
  2123. return Projection(item);
  2124. }
  2125. function proj4$1(fromProj, toProj, coord) {
  2126. fromProj = checkProj(fromProj);
  2127. var single = false;
  2128. var obj;
  2129. if (typeof toProj === 'undefined') {
  2130. toProj = fromProj;
  2131. fromProj = wgs84;
  2132. single = true;
  2133. } else if (typeof toProj.x !== 'undefined' || Array.isArray(toProj)) {
  2134. coord = toProj;
  2135. toProj = fromProj;
  2136. fromProj = wgs84;
  2137. single = true;
  2138. }
  2139. toProj = checkProj(toProj);
  2140. if (coord) {
  2141. return transformer(fromProj, toProj, coord);
  2142. } else {
  2143. obj = {
  2144. forward: function (coords, enforceAxis) {
  2145. return transformer(fromProj, toProj, coords, enforceAxis);
  2146. },
  2147. inverse: function (coords, enforceAxis) {
  2148. return transformer(toProj, fromProj, coords, enforceAxis);
  2149. }
  2150. };
  2151. if (single) {
  2152. obj.oProj = toProj;
  2153. }
  2154. return obj;
  2155. }
  2156. }
  2157. /**
  2158. * UTM zones are grouped, and assigned to one of a group of 6
  2159. * sets.
  2160. *
  2161. * {int} @private
  2162. */
  2163. var NUM_100K_SETS = 6;
  2164. /**
  2165. * The column letters (for easting) of the lower left value, per
  2166. * set.
  2167. *
  2168. * {string} @private
  2169. */
  2170. var SET_ORIGIN_COLUMN_LETTERS = 'AJSAJS';
  2171. /**
  2172. * The row letters (for northing) of the lower left value, per
  2173. * set.
  2174. *
  2175. * {string} @private
  2176. */
  2177. var SET_ORIGIN_ROW_LETTERS = 'AFAFAF';
  2178. var A = 65; // A
  2179. var I = 73; // I
  2180. var O = 79; // O
  2181. var V = 86; // V
  2182. var Z = 90; // Z
  2183. var mgrs = {
  2184. forward: forward$1,
  2185. inverse: inverse$1,
  2186. toPoint: toPoint$1
  2187. };
  2188. /**
  2189. * Conversion of lat/lon to MGRS.
  2190. *
  2191. * @param {object} ll Object literal with lat and lon properties on a
  2192. * WGS84 ellipsoid.
  2193. * @param {int} accuracy Accuracy in digits (5 for 1 m, 4 for 10 m, 3 for
  2194. * 100 m, 2 for 1000 m or 1 for 10000 m). Optional, default is 5.
  2195. * @return {string} the MGRS string for the given location and accuracy.
  2196. */
  2197. function forward$1(ll, accuracy) {
  2198. accuracy = accuracy || 5; // default accuracy 1m
  2199. return encode(LLtoUTM({
  2200. lat: ll[1],
  2201. lon: ll[0]
  2202. }), accuracy);
  2203. }
  2204. /**
  2205. * Conversion of MGRS to lat/lon.
  2206. *
  2207. * @param {string} mgrs MGRS string.
  2208. * @return {array} An array with left (longitude), bottom (latitude), right
  2209. * (longitude) and top (latitude) values in WGS84, representing the
  2210. * bounding box for the provided MGRS reference.
  2211. */
  2212. function inverse$1(mgrs) {
  2213. var bbox = UTMtoLL(decode(mgrs.toUpperCase()));
  2214. if (bbox.lat && bbox.lon) {
  2215. return [bbox.lon, bbox.lat, bbox.lon, bbox.lat];
  2216. }
  2217. return [bbox.left, bbox.bottom, bbox.right, bbox.top];
  2218. }
  2219. function toPoint$1(mgrs) {
  2220. var bbox = UTMtoLL(decode(mgrs.toUpperCase()));
  2221. if (bbox.lat && bbox.lon) {
  2222. return [bbox.lon, bbox.lat];
  2223. }
  2224. return [(bbox.left + bbox.right) / 2, (bbox.top + bbox.bottom) / 2];
  2225. }
  2226. /**
  2227. * Conversion from degrees to radians.
  2228. *
  2229. * @private
  2230. * @param {number} deg the angle in degrees.
  2231. * @return {number} the angle in radians.
  2232. */
  2233. function degToRad(deg) {
  2234. return (deg * (Math.PI / 180.0));
  2235. }
  2236. /**
  2237. * Conversion from radians to degrees.
  2238. *
  2239. * @private
  2240. * @param {number} rad the angle in radians.
  2241. * @return {number} the angle in degrees.
  2242. */
  2243. function radToDeg(rad) {
  2244. return (180.0 * (rad / Math.PI));
  2245. }
  2246. /**
  2247. * Converts a set of Longitude and Latitude co-ordinates to UTM
  2248. * using the WGS84 ellipsoid.
  2249. *
  2250. * @private
  2251. * @param {object} ll Object literal with lat and lon properties
  2252. * representing the WGS84 coordinate to be converted.
  2253. * @return {object} Object literal containing the UTM value with easting,
  2254. * northing, zoneNumber and zoneLetter properties, and an optional
  2255. * accuracy property in digits. Returns null if the conversion failed.
  2256. */
  2257. function LLtoUTM(ll) {
  2258. var Lat = ll.lat;
  2259. var Long = ll.lon;
  2260. var a = 6378137.0; //ellip.radius;
  2261. var eccSquared = 0.00669438; //ellip.eccsq;
  2262. var k0 = 0.9996;
  2263. var LongOrigin;
  2264. var eccPrimeSquared;
  2265. var N, T, C, A, M;
  2266. var LatRad = degToRad(Lat);
  2267. var LongRad = degToRad(Long);
  2268. var LongOriginRad;
  2269. var ZoneNumber;
  2270. // (int)
  2271. ZoneNumber = Math.floor((Long + 180) / 6) + 1;
  2272. //Make sure the longitude 180.00 is in Zone 60
  2273. if (Long === 180) {
  2274. ZoneNumber = 60;
  2275. }
  2276. // Special zone for Norway
  2277. if (Lat >= 56.0 && Lat < 64.0 && Long >= 3.0 && Long < 12.0) {
  2278. ZoneNumber = 32;
  2279. }
  2280. // Special zones for Svalbard
  2281. if (Lat >= 72.0 && Lat < 84.0) {
  2282. if (Long >= 0.0 && Long < 9.0) {
  2283. ZoneNumber = 31;
  2284. }
  2285. else if (Long >= 9.0 && Long < 21.0) {
  2286. ZoneNumber = 33;
  2287. }
  2288. else if (Long >= 21.0 && Long < 33.0) {
  2289. ZoneNumber = 35;
  2290. }
  2291. else if (Long >= 33.0 && Long < 42.0) {
  2292. ZoneNumber = 37;
  2293. }
  2294. }
  2295. LongOrigin = (ZoneNumber - 1) * 6 - 180 + 3; //+3 puts origin
  2296. // in middle of
  2297. // zone
  2298. LongOriginRad = degToRad(LongOrigin);
  2299. eccPrimeSquared = (eccSquared) / (1 - eccSquared);
  2300. N = a / Math.sqrt(1 - eccSquared * Math.sin(LatRad) * Math.sin(LatRad));
  2301. T = Math.tan(LatRad) * Math.tan(LatRad);
  2302. C = eccPrimeSquared * Math.cos(LatRad) * Math.cos(LatRad);
  2303. A = Math.cos(LatRad) * (LongRad - LongOriginRad);
  2304. M = a * ((1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256) * LatRad - (3 * eccSquared / 8 + 3 * eccSquared * eccSquared / 32 + 45 * eccSquared * eccSquared * eccSquared / 1024) * Math.sin(2 * LatRad) + (15 * eccSquared * eccSquared / 256 + 45 * eccSquared * eccSquared * eccSquared / 1024) * Math.sin(4 * LatRad) - (35 * eccSquared * eccSquared * eccSquared / 3072) * Math.sin(6 * LatRad));
  2305. var UTMEasting = (k0 * N * (A + (1 - T + C) * A * A * A / 6.0 + (5 - 18 * T + T * T + 72 * C - 58 * eccPrimeSquared) * A * A * A * A * A / 120.0) + 500000.0);
  2306. var UTMNorthing = (k0 * (M + N * Math.tan(LatRad) * (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * A * A * A * A / 24.0 + (61 - 58 * T + T * T + 600 * C - 330 * eccPrimeSquared) * A * A * A * A * A * A / 720.0)));
  2307. if (Lat < 0.0) {
  2308. UTMNorthing += 10000000.0; //10000000 meter offset for
  2309. // southern hemisphere
  2310. }
  2311. return {
  2312. northing: Math.round(UTMNorthing),
  2313. easting: Math.round(UTMEasting),
  2314. zoneNumber: ZoneNumber,
  2315. zoneLetter: getLetterDesignator(Lat)
  2316. };
  2317. }
  2318. /**
  2319. * Converts UTM coords to lat/long, using the WGS84 ellipsoid. This is a convenience
  2320. * class where the Zone can be specified as a single string eg."60N" which
  2321. * is then broken down into the ZoneNumber and ZoneLetter.
  2322. *
  2323. * @private
  2324. * @param {object} utm An object literal with northing, easting, zoneNumber
  2325. * and zoneLetter properties. If an optional accuracy property is
  2326. * provided (in meters), a bounding box will be returned instead of
  2327. * latitude and longitude.
  2328. * @return {object} An object literal containing either lat and lon values
  2329. * (if no accuracy was provided), or top, right, bottom and left values
  2330. * for the bounding box calculated according to the provided accuracy.
  2331. * Returns null if the conversion failed.
  2332. */
  2333. function UTMtoLL(utm) {
  2334. var UTMNorthing = utm.northing;
  2335. var UTMEasting = utm.easting;
  2336. var zoneLetter = utm.zoneLetter;
  2337. var zoneNumber = utm.zoneNumber;
  2338. // check the ZoneNummber is valid
  2339. if (zoneNumber < 0 || zoneNumber > 60) {
  2340. return null;
  2341. }
  2342. var k0 = 0.9996;
  2343. var a = 6378137.0; //ellip.radius;
  2344. var eccSquared = 0.00669438; //ellip.eccsq;
  2345. var eccPrimeSquared;
  2346. var e1 = (1 - Math.sqrt(1 - eccSquared)) / (1 + Math.sqrt(1 - eccSquared));
  2347. var N1, T1, C1, R1, D, M;
  2348. var LongOrigin;
  2349. var mu, phi1Rad;
  2350. // remove 500,000 meter offset for longitude
  2351. var x = UTMEasting - 500000.0;
  2352. var y = UTMNorthing;
  2353. // We must know somehow if we are in the Northern or Southern
  2354. // hemisphere, this is the only time we use the letter So even
  2355. // if the Zone letter isn't exactly correct it should indicate
  2356. // the hemisphere correctly
  2357. if (zoneLetter < 'N') {
  2358. y -= 10000000.0; // remove 10,000,000 meter offset used
  2359. // for southern hemisphere
  2360. }
  2361. // There are 60 zones with zone 1 being at West -180 to -174
  2362. LongOrigin = (zoneNumber - 1) * 6 - 180 + 3; // +3 puts origin
  2363. // in middle of
  2364. // zone
  2365. eccPrimeSquared = (eccSquared) / (1 - eccSquared);
  2366. M = y / k0;
  2367. mu = M / (a * (1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256));
  2368. phi1Rad = mu + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * Math.sin(2 * mu) + (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * Math.sin(4 * mu) + (151 * e1 * e1 * e1 / 96) * Math.sin(6 * mu);
  2369. // double phi1 = ProjMath.radToDeg(phi1Rad);
  2370. N1 = a / Math.sqrt(1 - eccSquared * Math.sin(phi1Rad) * Math.sin(phi1Rad));
  2371. T1 = Math.tan(phi1Rad) * Math.tan(phi1Rad);
  2372. C1 = eccPrimeSquared * Math.cos(phi1Rad) * Math.cos(phi1Rad);
  2373. R1 = a * (1 - eccSquared) / Math.pow(1 - eccSquared * Math.sin(phi1Rad) * Math.sin(phi1Rad), 1.5);
  2374. D = x / (N1 * k0);
  2375. var lat = phi1Rad - (N1 * Math.tan(phi1Rad) / R1) * (D * D / 2 - (5 + 3 * T1 + 10 * C1 - 4 * C1 * C1 - 9 * eccPrimeSquared) * D * D * D * D / 24 + (61 + 90 * T1 + 298 * C1 + 45 * T1 * T1 - 252 * eccPrimeSquared - 3 * C1 * C1) * D * D * D * D * D * D / 720);
  2376. lat = radToDeg(lat);
  2377. var lon = (D - (1 + 2 * T1 + C1) * D * D * D / 6 + (5 - 2 * C1 + 28 * T1 - 3 * C1 * C1 + 8 * eccPrimeSquared + 24 * T1 * T1) * D * D * D * D * D / 120) / Math.cos(phi1Rad);
  2378. lon = LongOrigin + radToDeg(lon);
  2379. var result;
  2380. if (utm.accuracy) {
  2381. var topRight = UTMtoLL({
  2382. northing: utm.northing + utm.accuracy,
  2383. easting: utm.easting + utm.accuracy,
  2384. zoneLetter: utm.zoneLetter,
  2385. zoneNumber: utm.zoneNumber
  2386. });
  2387. result = {
  2388. top: topRight.lat,
  2389. right: topRight.lon,
  2390. bottom: lat,
  2391. left: lon
  2392. };
  2393. }
  2394. else {
  2395. result = {
  2396. lat: lat,
  2397. lon: lon
  2398. };
  2399. }
  2400. return result;
  2401. }
  2402. /**
  2403. * Calculates the MGRS letter designator for the given latitude.
  2404. *
  2405. * @private
  2406. * @param {number} lat The latitude in WGS84 to get the letter designator
  2407. * for.
  2408. * @return {char} The letter designator.
  2409. */
  2410. function getLetterDesignator(lat) {
  2411. //This is here as an error flag to show that the Latitude is
  2412. //outside MGRS limits
  2413. var LetterDesignator = 'Z';
  2414. if ((84 >= lat) && (lat >= 72)) {
  2415. LetterDesignator = 'X';
  2416. }
  2417. else if ((72 > lat) && (lat >= 64)) {
  2418. LetterDesignator = 'W';
  2419. }
  2420. else if ((64 > lat) && (lat >= 56)) {
  2421. LetterDesignator = 'V';
  2422. }
  2423. else if ((56 > lat) && (lat >= 48)) {
  2424. LetterDesignator = 'U';
  2425. }
  2426. else if ((48 > lat) && (lat >= 40)) {
  2427. LetterDesignator = 'T';
  2428. }
  2429. else if ((40 > lat) && (lat >= 32)) {
  2430. LetterDesignator = 'S';
  2431. }
  2432. else if ((32 > lat) && (lat >= 24)) {
  2433. LetterDesignator = 'R';
  2434. }
  2435. else if ((24 > lat) && (lat >= 16)) {
  2436. LetterDesignator = 'Q';
  2437. }
  2438. else if ((16 > lat) && (lat >= 8)) {
  2439. LetterDesignator = 'P';
  2440. }
  2441. else if ((8 > lat) && (lat >= 0)) {
  2442. LetterDesignator = 'N';
  2443. }
  2444. else if ((0 > lat) && (lat >= -8)) {
  2445. LetterDesignator = 'M';
  2446. }
  2447. else if ((-8 > lat) && (lat >= -16)) {
  2448. LetterDesignator = 'L';
  2449. }
  2450. else if ((-16 > lat) && (lat >= -24)) {
  2451. LetterDesignator = 'K';
  2452. }
  2453. else if ((-24 > lat) && (lat >= -32)) {
  2454. LetterDesignator = 'J';
  2455. }
  2456. else if ((-32 > lat) && (lat >= -40)) {
  2457. LetterDesignator = 'H';
  2458. }
  2459. else if ((-40 > lat) && (lat >= -48)) {
  2460. LetterDesignator = 'G';
  2461. }
  2462. else if ((-48 > lat) && (lat >= -56)) {
  2463. LetterDesignator = 'F';
  2464. }
  2465. else if ((-56 > lat) && (lat >= -64)) {
  2466. LetterDesignator = 'E';
  2467. }
  2468. else if ((-64 > lat) && (lat >= -72)) {
  2469. LetterDesignator = 'D';
  2470. }
  2471. else if ((-72 > lat) && (lat >= -80)) {
  2472. LetterDesignator = 'C';
  2473. }
  2474. return LetterDesignator;
  2475. }
  2476. /**
  2477. * Encodes a UTM location as MGRS string.
  2478. *
  2479. * @private
  2480. * @param {object} utm An object literal with easting, northing,
  2481. * zoneLetter, zoneNumber
  2482. * @param {number} accuracy Accuracy in digits (1-5).
  2483. * @return {string} MGRS string for the given UTM location.
  2484. */
  2485. function encode(utm, accuracy) {
  2486. // prepend with leading zeroes
  2487. var seasting = "00000" + utm.easting,
  2488. snorthing = "00000" + utm.northing;
  2489. return utm.zoneNumber + utm.zoneLetter + get100kID(utm.easting, utm.northing, utm.zoneNumber) + seasting.substr(seasting.length - 5, accuracy) + snorthing.substr(snorthing.length - 5, accuracy);
  2490. }
  2491. /**
  2492. * Get the two letter 100k designator for a given UTM easting,
  2493. * northing and zone number value.
  2494. *
  2495. * @private
  2496. * @param {number} easting
  2497. * @param {number} northing
  2498. * @param {number} zoneNumber
  2499. * @return the two letter 100k designator for the given UTM location.
  2500. */
  2501. function get100kID(easting, northing, zoneNumber) {
  2502. var setParm = get100kSetForZone(zoneNumber);
  2503. var setColumn = Math.floor(easting / 100000);
  2504. var setRow = Math.floor(northing / 100000) % 20;
  2505. return getLetter100kID(setColumn, setRow, setParm);
  2506. }
  2507. /**
  2508. * Given a UTM zone number, figure out the MGRS 100K set it is in.
  2509. *
  2510. * @private
  2511. * @param {number} i An UTM zone number.
  2512. * @return {number} the 100k set the UTM zone is in.
  2513. */
  2514. function get100kSetForZone(i) {
  2515. var setParm = i % NUM_100K_SETS;
  2516. if (setParm === 0) {
  2517. setParm = NUM_100K_SETS;
  2518. }
  2519. return setParm;
  2520. }
  2521. /**
  2522. * Get the two-letter MGRS 100k designator given information
  2523. * translated from the UTM northing, easting and zone number.
  2524. *
  2525. * @private
  2526. * @param {number} column the column index as it relates to the MGRS
  2527. * 100k set spreadsheet, created from the UTM easting.
  2528. * Values are 1-8.
  2529. * @param {number} row the row index as it relates to the MGRS 100k set
  2530. * spreadsheet, created from the UTM northing value. Values
  2531. * are from 0-19.
  2532. * @param {number} parm the set block, as it relates to the MGRS 100k set
  2533. * spreadsheet, created from the UTM zone. Values are from
  2534. * 1-60.
  2535. * @return two letter MGRS 100k code.
  2536. */
  2537. function getLetter100kID(column, row, parm) {
  2538. // colOrigin and rowOrigin are the letters at the origin of the set
  2539. var index = parm - 1;
  2540. var colOrigin = SET_ORIGIN_COLUMN_LETTERS.charCodeAt(index);
  2541. var rowOrigin = SET_ORIGIN_ROW_LETTERS.charCodeAt(index);
  2542. // colInt and rowInt are the letters to build to return
  2543. var colInt = colOrigin + column - 1;
  2544. var rowInt = rowOrigin + row;
  2545. var rollover = false;
  2546. if (colInt > Z) {
  2547. colInt = colInt - Z + A - 1;
  2548. rollover = true;
  2549. }
  2550. if (colInt === I || (colOrigin < I && colInt > I) || ((colInt > I || colOrigin < I) && rollover)) {
  2551. colInt++;
  2552. }
  2553. if (colInt === O || (colOrigin < O && colInt > O) || ((colInt > O || colOrigin < O) && rollover)) {
  2554. colInt++;
  2555. if (colInt === I) {
  2556. colInt++;
  2557. }
  2558. }
  2559. if (colInt > Z) {
  2560. colInt = colInt - Z + A - 1;
  2561. }
  2562. if (rowInt > V) {
  2563. rowInt = rowInt - V + A - 1;
  2564. rollover = true;
  2565. }
  2566. else {
  2567. rollover = false;
  2568. }
  2569. if (((rowInt === I) || ((rowOrigin < I) && (rowInt > I))) || (((rowInt > I) || (rowOrigin < I)) && rollover)) {
  2570. rowInt++;
  2571. }
  2572. if (((rowInt === O) || ((rowOrigin < O) && (rowInt > O))) || (((rowInt > O) || (rowOrigin < O)) && rollover)) {
  2573. rowInt++;
  2574. if (rowInt === I) {
  2575. rowInt++;
  2576. }
  2577. }
  2578. if (rowInt > V) {
  2579. rowInt = rowInt - V + A - 1;
  2580. }
  2581. var twoLetter = String.fromCharCode(colInt) + String.fromCharCode(rowInt);
  2582. return twoLetter;
  2583. }
  2584. /**
  2585. * Decode the UTM parameters from a MGRS string.
  2586. *
  2587. * @private
  2588. * @param {string} mgrsString an UPPERCASE coordinate string is expected.
  2589. * @return {object} An object literal with easting, northing, zoneLetter,
  2590. * zoneNumber and accuracy (in meters) properties.
  2591. */
  2592. function decode(mgrsString) {
  2593. if (mgrsString && mgrsString.length === 0) {
  2594. throw ("MGRSPoint coverting from nothing");
  2595. }
  2596. var length = mgrsString.length;
  2597. var hunK = null;
  2598. var sb = "";
  2599. var testChar;
  2600. var i = 0;
  2601. // get Zone number
  2602. while (!(/[A-Z]/).test(testChar = mgrsString.charAt(i))) {
  2603. if (i >= 2) {
  2604. throw ("MGRSPoint bad conversion from: " + mgrsString);
  2605. }
  2606. sb += testChar;
  2607. i++;
  2608. }
  2609. var zoneNumber = parseInt(sb, 10);
  2610. if (i === 0 || i + 3 > length) {
  2611. // A good MGRS string has to be 4-5 digits long,
  2612. // ##AAA/#AAA at least.
  2613. throw ("MGRSPoint bad conversion from: " + mgrsString);
  2614. }
  2615. var zoneLetter = mgrsString.charAt(i++);
  2616. // Should we check the zone letter here? Why not.
  2617. if (zoneLetter <= 'A' || zoneLetter === 'B' || zoneLetter === 'Y' || zoneLetter >= 'Z' || zoneLetter === 'I' || zoneLetter === 'O') {
  2618. throw ("MGRSPoint zone letter " + zoneLetter + " not handled: " + mgrsString);
  2619. }
  2620. hunK = mgrsString.substring(i, i += 2);
  2621. var set = get100kSetForZone(zoneNumber);
  2622. var east100k = getEastingFromChar(hunK.charAt(0), set);
  2623. var north100k = getNorthingFromChar(hunK.charAt(1), set);
  2624. // We have a bug where the northing may be 2000000 too low.
  2625. // How
  2626. // do we know when to roll over?
  2627. while (north100k < getMinNorthing(zoneLetter)) {
  2628. north100k += 2000000;
  2629. }
  2630. // calculate the char index for easting/northing separator
  2631. var remainder = length - i;
  2632. if (remainder % 2 !== 0) {
  2633. throw ("MGRSPoint has to have an even number \nof digits after the zone letter and two 100km letters - front \nhalf for easting meters, second half for \nnorthing meters" + mgrsString);
  2634. }
  2635. var sep = remainder / 2;
  2636. var sepEasting = 0.0;
  2637. var sepNorthing = 0.0;
  2638. var accuracyBonus, sepEastingString, sepNorthingString, easting, northing;
  2639. if (sep > 0) {
  2640. accuracyBonus = 100000.0 / Math.pow(10, sep);
  2641. sepEastingString = mgrsString.substring(i, i + sep);
  2642. sepEasting = parseFloat(sepEastingString) * accuracyBonus;
  2643. sepNorthingString = mgrsString.substring(i + sep);
  2644. sepNorthing = parseFloat(sepNorthingString) * accuracyBonus;
  2645. }
  2646. easting = sepEasting + east100k;
  2647. northing = sepNorthing + north100k;
  2648. return {
  2649. easting: easting,
  2650. northing: northing,
  2651. zoneLetter: zoneLetter,
  2652. zoneNumber: zoneNumber,
  2653. accuracy: accuracyBonus
  2654. };
  2655. }
  2656. /**
  2657. * Given the first letter from a two-letter MGRS 100k zone, and given the
  2658. * MGRS table set for the zone number, figure out the easting value that
  2659. * should be added to the other, secondary easting value.
  2660. *
  2661. * @private
  2662. * @param {char} e The first letter from a two-letter MGRS 100´k zone.
  2663. * @param {number} set The MGRS table set for the zone number.
  2664. * @return {number} The easting value for the given letter and set.
  2665. */
  2666. function getEastingFromChar(e, set) {
  2667. // colOrigin is the letter at the origin of the set for the
  2668. // column
  2669. var curCol = SET_ORIGIN_COLUMN_LETTERS.charCodeAt(set - 1);
  2670. var eastingValue = 100000.0;
  2671. var rewindMarker = false;
  2672. while (curCol !== e.charCodeAt(0)) {
  2673. curCol++;
  2674. if (curCol === I) {
  2675. curCol++;
  2676. }
  2677. if (curCol === O) {
  2678. curCol++;
  2679. }
  2680. if (curCol > Z) {
  2681. if (rewindMarker) {
  2682. throw ("Bad character: " + e);
  2683. }
  2684. curCol = A;
  2685. rewindMarker = true;
  2686. }
  2687. eastingValue += 100000.0;
  2688. }
  2689. return eastingValue;
  2690. }
  2691. /**
  2692. * Given the second letter from a two-letter MGRS 100k zone, and given the
  2693. * MGRS table set for the zone number, figure out the northing value that
  2694. * should be added to the other, secondary northing value. You have to
  2695. * remember that Northings are determined from the equator, and the vertical
  2696. * cycle of letters mean a 2000000 additional northing meters. This happens
  2697. * approx. every 18 degrees of latitude. This method does *NOT* count any
  2698. * additional northings. You have to figure out how many 2000000 meters need
  2699. * to be added for the zone letter of the MGRS coordinate.
  2700. *
  2701. * @private
  2702. * @param {char} n Second letter of the MGRS 100k zone
  2703. * @param {number} set The MGRS table set number, which is dependent on the
  2704. * UTM zone number.
  2705. * @return {number} The northing value for the given letter and set.
  2706. */
  2707. function getNorthingFromChar(n, set) {
  2708. if (n > 'V') {
  2709. throw ("MGRSPoint given invalid Northing " + n);
  2710. }
  2711. // rowOrigin is the letter at the origin of the set for the
  2712. // column
  2713. var curRow = SET_ORIGIN_ROW_LETTERS.charCodeAt(set - 1);
  2714. var northingValue = 0.0;
  2715. var rewindMarker = false;
  2716. while (curRow !== n.charCodeAt(0)) {
  2717. curRow++;
  2718. if (curRow === I) {
  2719. curRow++;
  2720. }
  2721. if (curRow === O) {
  2722. curRow++;
  2723. }
  2724. // fixing a bug making whole application hang in this loop
  2725. // when 'n' is a wrong character
  2726. if (curRow > V) {
  2727. if (rewindMarker) { // making sure that this loop ends
  2728. throw ("Bad character: " + n);
  2729. }
  2730. curRow = A;
  2731. rewindMarker = true;
  2732. }
  2733. northingValue += 100000.0;
  2734. }
  2735. return northingValue;
  2736. }
  2737. /**
  2738. * The function getMinNorthing returns the minimum northing value of a MGRS
  2739. * zone.
  2740. *
  2741. * Ported from Geotrans' c Lattitude_Band_Value structure table.
  2742. *
  2743. * @private
  2744. * @param {char} zoneLetter The MGRS zone to get the min northing for.
  2745. * @return {number}
  2746. */
  2747. function getMinNorthing(zoneLetter) {
  2748. var northing;
  2749. switch (zoneLetter) {
  2750. case 'C':
  2751. northing = 1100000.0;
  2752. break;
  2753. case 'D':
  2754. northing = 2000000.0;
  2755. break;
  2756. case 'E':
  2757. northing = 2800000.0;
  2758. break;
  2759. case 'F':
  2760. northing = 3700000.0;
  2761. break;
  2762. case 'G':
  2763. northing = 4600000.0;
  2764. break;
  2765. case 'H':
  2766. northing = 5500000.0;
  2767. break;
  2768. case 'J':
  2769. northing = 6400000.0;
  2770. break;
  2771. case 'K':
  2772. northing = 7300000.0;
  2773. break;
  2774. case 'L':
  2775. northing = 8200000.0;
  2776. break;
  2777. case 'M':
  2778. northing = 9100000.0;
  2779. break;
  2780. case 'N':
  2781. northing = 0.0;
  2782. break;
  2783. case 'P':
  2784. northing = 800000.0;
  2785. break;
  2786. case 'Q':
  2787. northing = 1700000.0;
  2788. break;
  2789. case 'R':
  2790. northing = 2600000.0;
  2791. break;
  2792. case 'S':
  2793. northing = 3500000.0;
  2794. break;
  2795. case 'T':
  2796. northing = 4400000.0;
  2797. break;
  2798. case 'U':
  2799. northing = 5300000.0;
  2800. break;
  2801. case 'V':
  2802. northing = 6200000.0;
  2803. break;
  2804. case 'W':
  2805. northing = 7000000.0;
  2806. break;
  2807. case 'X':
  2808. northing = 7900000.0;
  2809. break;
  2810. default:
  2811. northing = -1.0;
  2812. }
  2813. if (northing >= 0.0) {
  2814. return northing;
  2815. }
  2816. else {
  2817. throw ("Invalid zone letter: " + zoneLetter);
  2818. }
  2819. }
  2820. function Point(x, y, z) {
  2821. if (!(this instanceof Point)) {
  2822. return new Point(x, y, z);
  2823. }
  2824. if (Array.isArray(x)) {
  2825. this.x = x[0];
  2826. this.y = x[1];
  2827. this.z = x[2] || 0.0;
  2828. } else if(typeof x === 'object') {
  2829. this.x = x.x;
  2830. this.y = x.y;
  2831. this.z = x.z || 0.0;
  2832. } else if (typeof x === 'string' && typeof y === 'undefined') {
  2833. var coords = x.split(',');
  2834. this.x = parseFloat(coords[0], 10);
  2835. this.y = parseFloat(coords[1], 10);
  2836. this.z = parseFloat(coords[2], 10) || 0.0;
  2837. } else {
  2838. this.x = x;
  2839. this.y = y;
  2840. this.z = z || 0.0;
  2841. }
  2842. console.warn('proj4.Point will be removed in version 3, use proj4.toPoint');
  2843. }
  2844. Point.fromMGRS = function(mgrsStr) {
  2845. return new Point(toPoint$1(mgrsStr));
  2846. };
  2847. Point.prototype.toMGRS = function(accuracy) {
  2848. return forward$1([this.x, this.y], accuracy);
  2849. };
  2850. var C00 = 1;
  2851. var C02 = 0.25;
  2852. var C04 = 0.046875;
  2853. var C06 = 0.01953125;
  2854. var C08 = 0.01068115234375;
  2855. var C22 = 0.75;
  2856. var C44 = 0.46875;
  2857. var C46 = 0.01302083333333333333;
  2858. var C48 = 0.00712076822916666666;
  2859. var C66 = 0.36458333333333333333;
  2860. var C68 = 0.00569661458333333333;
  2861. var C88 = 0.3076171875;
  2862. var pj_enfn = function(es) {
  2863. var en = [];
  2864. en[0] = C00 - es * (C02 + es * (C04 + es * (C06 + es * C08)));
  2865. en[1] = es * (C22 - es * (C04 + es * (C06 + es * C08)));
  2866. var t = es * es;
  2867. en[2] = t * (C44 - es * (C46 + es * C48));
  2868. t *= es;
  2869. en[3] = t * (C66 - es * C68);
  2870. en[4] = t * es * C88;
  2871. return en;
  2872. };
  2873. var pj_mlfn = function(phi, sphi, cphi, en) {
  2874. cphi *= sphi;
  2875. sphi *= sphi;
  2876. return (en[0] * phi - cphi * (en[1] + sphi * (en[2] + sphi * (en[3] + sphi * en[4]))));
  2877. };
  2878. var MAX_ITER = 20;
  2879. var pj_inv_mlfn = function(arg, es, en) {
  2880. var k = 1 / (1 - es);
  2881. var phi = arg;
  2882. for (var i = MAX_ITER; i; --i) { /* rarely goes over 2 iterations */
  2883. var s = Math.sin(phi);
  2884. var t = 1 - es * s * s;
  2885. //t = this.pj_mlfn(phi, s, Math.cos(phi), en) - arg;
  2886. //phi -= t * (t * Math.sqrt(t)) * k;
  2887. t = (pj_mlfn(phi, s, Math.cos(phi), en) - arg) * (t * Math.sqrt(t)) * k;
  2888. phi -= t;
  2889. if (Math.abs(t) < EPSLN) {
  2890. return phi;
  2891. }
  2892. }
  2893. //..reportError("cass:pj_inv_mlfn: Convergence error");
  2894. return phi;
  2895. };
  2896. // Heavily based on this tmerc projection implementation
  2897. // https://github.com/mbloch/mapshaper-proj/blob/master/src/projections/tmerc.js
  2898. function init$2() {
  2899. this.x0 = this.x0 !== undefined ? this.x0 : 0;
  2900. this.y0 = this.y0 !== undefined ? this.y0 : 0;
  2901. this.long0 = this.long0 !== undefined ? this.long0 : 0;
  2902. this.lat0 = this.lat0 !== undefined ? this.lat0 : 0;
  2903. if (this.es) {
  2904. this.en = pj_enfn(this.es);
  2905. this.ml0 = pj_mlfn(this.lat0, Math.sin(this.lat0), Math.cos(this.lat0), this.en);
  2906. }
  2907. }
  2908. /**
  2909. Transverse Mercator Forward - long/lat to x/y
  2910. long/lat in radians
  2911. */
  2912. function forward$2(p) {
  2913. var lon = p.x;
  2914. var lat = p.y;
  2915. var delta_lon = adjust_lon(lon - this.long0);
  2916. var con;
  2917. var x, y;
  2918. var sin_phi = Math.sin(lat);
  2919. var cos_phi = Math.cos(lat);
  2920. if (!this.es) {
  2921. var b = cos_phi * Math.sin(delta_lon);
  2922. if ((Math.abs(Math.abs(b) - 1)) < EPSLN) {
  2923. return (93);
  2924. }
  2925. else {
  2926. x = 0.5 * this.a * this.k0 * Math.log((1 + b) / (1 - b)) + this.x0;
  2927. y = cos_phi * Math.cos(delta_lon) / Math.sqrt(1 - Math.pow(b, 2));
  2928. b = Math.abs(y);
  2929. if (b >= 1) {
  2930. if ((b - 1) > EPSLN) {
  2931. return (93);
  2932. }
  2933. else {
  2934. y = 0;
  2935. }
  2936. }
  2937. else {
  2938. y = Math.acos(y);
  2939. }
  2940. if (lat < 0) {
  2941. y = -y;
  2942. }
  2943. y = this.a * this.k0 * (y - this.lat0) + this.y0;
  2944. }
  2945. }
  2946. else {
  2947. var al = cos_phi * delta_lon;
  2948. var als = Math.pow(al, 2);
  2949. var c = this.ep2 * Math.pow(cos_phi, 2);
  2950. var cs = Math.pow(c, 2);
  2951. var tq = Math.abs(cos_phi) > EPSLN ? Math.tan(lat) : 0;
  2952. var t = Math.pow(tq, 2);
  2953. var ts = Math.pow(t, 2);
  2954. con = 1 - this.es * Math.pow(sin_phi, 2);
  2955. al = al / Math.sqrt(con);
  2956. var ml = pj_mlfn(lat, sin_phi, cos_phi, this.en);
  2957. x = this.a * (this.k0 * al * (1 +
  2958. als / 6 * (1 - t + c +
  2959. als / 20 * (5 - 18 * t + ts + 14 * c - 58 * t * c +
  2960. als / 42 * (61 + 179 * ts - ts * t - 479 * t))))) +
  2961. this.x0;
  2962. y = this.a * (this.k0 * (ml - this.ml0 +
  2963. sin_phi * delta_lon * al / 2 * (1 +
  2964. als / 12 * (5 - t + 9 * c + 4 * cs +
  2965. als / 30 * (61 + ts - 58 * t + 270 * c - 330 * t * c +
  2966. als / 56 * (1385 + 543 * ts - ts * t - 3111 * t)))))) +
  2967. this.y0;
  2968. }
  2969. p.x = x;
  2970. p.y = y;
  2971. return p;
  2972. }
  2973. /**
  2974. Transverse Mercator Inverse - x/y to long/lat
  2975. */
  2976. function inverse$2(p) {
  2977. var con, phi;
  2978. var lat, lon;
  2979. var x = (p.x - this.x0) * (1 / this.a);
  2980. var y = (p.y - this.y0) * (1 / this.a);
  2981. if (!this.es) {
  2982. var f = Math.exp(x / this.k0);
  2983. var g = 0.5 * (f - 1 / f);
  2984. var temp = this.lat0 + y / this.k0;
  2985. var h = Math.cos(temp);
  2986. con = Math.sqrt((1 - Math.pow(h, 2)) / (1 + Math.pow(g, 2)));
  2987. lat = Math.asin(con);
  2988. if (y < 0) {
  2989. lat = -lat;
  2990. }
  2991. if ((g === 0) && (h === 0)) {
  2992. lon = 0;
  2993. }
  2994. else {
  2995. lon = adjust_lon(Math.atan2(g, h) + this.long0);
  2996. }
  2997. }
  2998. else { // ellipsoidal form
  2999. con = this.ml0 + y / this.k0;
  3000. phi = pj_inv_mlfn(con, this.es, this.en);
  3001. if (Math.abs(phi) < HALF_PI) {
  3002. var sin_phi = Math.sin(phi);
  3003. var cos_phi = Math.cos(phi);
  3004. var tan_phi = Math.abs(cos_phi) > EPSLN ? Math.tan(phi) : 0;
  3005. var c = this.ep2 * Math.pow(cos_phi, 2);
  3006. var cs = Math.pow(c, 2);
  3007. var t = Math.pow(tan_phi, 2);
  3008. var ts = Math.pow(t, 2);
  3009. con = 1 - this.es * Math.pow(sin_phi, 2);
  3010. var d = x * Math.sqrt(con) / this.k0;
  3011. var ds = Math.pow(d, 2);
  3012. con = con * tan_phi;
  3013. lat = phi - (con * ds / (1 - this.es)) * 0.5 * (1 -
  3014. ds / 12 * (5 + 3 * t - 9 * c * t + c - 4 * cs -
  3015. ds / 30 * (61 + 90 * t - 252 * c * t + 45 * ts + 46 * c -
  3016. ds / 56 * (1385 + 3633 * t + 4095 * ts + 1574 * ts * t))));
  3017. lon = adjust_lon(this.long0 + (d * (1 -
  3018. ds / 6 * (1 + 2 * t + c -
  3019. ds / 20 * (5 + 28 * t + 24 * ts + 8 * c * t + 6 * c -
  3020. ds / 42 * (61 + 662 * t + 1320 * ts + 720 * ts * t)))) / cos_phi));
  3021. }
  3022. else {
  3023. lat = HALF_PI * sign(y);
  3024. lon = 0;
  3025. }
  3026. }
  3027. p.x = lon;
  3028. p.y = lat;
  3029. return p;
  3030. }
  3031. var names$3 = ["Fast_Transverse_Mercator", "Fast Transverse Mercator"];
  3032. var tmerc = {
  3033. init: init$2,
  3034. forward: forward$2,
  3035. inverse: inverse$2,
  3036. names: names$3
  3037. };
  3038. var sinh = function(x) {
  3039. var r = Math.exp(x);
  3040. r = (r - 1 / r) / 2;
  3041. return r;
  3042. };
  3043. var hypot = function(x, y) {
  3044. x = Math.abs(x);
  3045. y = Math.abs(y);
  3046. var a = Math.max(x, y);
  3047. var b = Math.min(x, y) / (a ? a : 1);
  3048. return a * Math.sqrt(1 + Math.pow(b, 2));
  3049. };
  3050. var log1py = function(x) {
  3051. var y = 1 + x;
  3052. var z = y - 1;
  3053. return z === 0 ? x : x * Math.log(y) / z;
  3054. };
  3055. var asinhy = function(x) {
  3056. var y = Math.abs(x);
  3057. y = log1py(y * (1 + y / (hypot(1, y) + 1)));
  3058. return x < 0 ? -y : y;
  3059. };
  3060. var gatg = function(pp, B) {
  3061. var cos_2B = 2 * Math.cos(2 * B);
  3062. var i = pp.length - 1;
  3063. var h1 = pp[i];
  3064. var h2 = 0;
  3065. var h;
  3066. while (--i >= 0) {
  3067. h = -h2 + cos_2B * h1 + pp[i];
  3068. h2 = h1;
  3069. h1 = h;
  3070. }
  3071. return (B + h * Math.sin(2 * B));
  3072. };
  3073. var clens = function(pp, arg_r) {
  3074. var r = 2 * Math.cos(arg_r);
  3075. var i = pp.length - 1;
  3076. var hr1 = pp[i];
  3077. var hr2 = 0;
  3078. var hr;
  3079. while (--i >= 0) {
  3080. hr = -hr2 + r * hr1 + pp[i];
  3081. hr2 = hr1;
  3082. hr1 = hr;
  3083. }
  3084. return Math.sin(arg_r) * hr;
  3085. };
  3086. var cosh = function(x) {
  3087. var r = Math.exp(x);
  3088. r = (r + 1 / r) / 2;
  3089. return r;
  3090. };
  3091. var clens_cmplx = function(pp, arg_r, arg_i) {
  3092. var sin_arg_r = Math.sin(arg_r);
  3093. var cos_arg_r = Math.cos(arg_r);
  3094. var sinh_arg_i = sinh(arg_i);
  3095. var cosh_arg_i = cosh(arg_i);
  3096. var r = 2 * cos_arg_r * cosh_arg_i;
  3097. var i = -2 * sin_arg_r * sinh_arg_i;
  3098. var j = pp.length - 1;
  3099. var hr = pp[j];
  3100. var hi1 = 0;
  3101. var hr1 = 0;
  3102. var hi = 0;
  3103. var hr2;
  3104. var hi2;
  3105. while (--j >= 0) {
  3106. hr2 = hr1;
  3107. hi2 = hi1;
  3108. hr1 = hr;
  3109. hi1 = hi;
  3110. hr = -hr2 + r * hr1 - i * hi1 + pp[j];
  3111. hi = -hi2 + i * hr1 + r * hi1;
  3112. }
  3113. r = sin_arg_r * cosh_arg_i;
  3114. i = cos_arg_r * sinh_arg_i;
  3115. return [r * hr - i * hi, r * hi + i * hr];
  3116. };
  3117. // Heavily based on this etmerc projection implementation
  3118. // https://github.com/mbloch/mapshaper-proj/blob/master/src/projections/etmerc.js
  3119. function init$3() {
  3120. if (!this.approx && (isNaN(this.es) || this.es <= 0)) {
  3121. throw new Error('Incorrect elliptical usage. Try using the +approx option in the proj string, or PROJECTION["Fast_Transverse_Mercator"] in the WKT.');
  3122. }
  3123. if (this.approx) {
  3124. // When '+approx' is set, use tmerc instead
  3125. tmerc.init.apply(this);
  3126. this.forward = tmerc.forward;
  3127. this.inverse = tmerc.inverse;
  3128. }
  3129. this.x0 = this.x0 !== undefined ? this.x0 : 0;
  3130. this.y0 = this.y0 !== undefined ? this.y0 : 0;
  3131. this.long0 = this.long0 !== undefined ? this.long0 : 0;
  3132. this.lat0 = this.lat0 !== undefined ? this.lat0 : 0;
  3133. this.cgb = [];
  3134. this.cbg = [];
  3135. this.utg = [];
  3136. this.gtu = [];
  3137. var f = this.es / (1 + Math.sqrt(1 - this.es));
  3138. var n = f / (2 - f);
  3139. var np = n;
  3140. this.cgb[0] = n * (2 + n * (-2 / 3 + n * (-2 + n * (116 / 45 + n * (26 / 45 + n * (-2854 / 675 ))))));
  3141. this.cbg[0] = n * (-2 + n * ( 2 / 3 + n * ( 4 / 3 + n * (-82 / 45 + n * (32 / 45 + n * (4642 / 4725))))));
  3142. np = np * n;
  3143. this.cgb[1] = np * (7 / 3 + n * (-8 / 5 + n * (-227 / 45 + n * (2704 / 315 + n * (2323 / 945)))));
  3144. this.cbg[1] = np * (5 / 3 + n * (-16 / 15 + n * ( -13 / 9 + n * (904 / 315 + n * (-1522 / 945)))));
  3145. np = np * n;
  3146. this.cgb[2] = np * (56 / 15 + n * (-136 / 35 + n * (-1262 / 105 + n * (73814 / 2835))));
  3147. this.cbg[2] = np * (-26 / 15 + n * (34 / 21 + n * (8 / 5 + n * (-12686 / 2835))));
  3148. np = np * n;
  3149. this.cgb[3] = np * (4279 / 630 + n * (-332 / 35 + n * (-399572 / 14175)));
  3150. this.cbg[3] = np * (1237 / 630 + n * (-12 / 5 + n * ( -24832 / 14175)));
  3151. np = np * n;
  3152. this.cgb[4] = np * (4174 / 315 + n * (-144838 / 6237));
  3153. this.cbg[4] = np * (-734 / 315 + n * (109598 / 31185));
  3154. np = np * n;
  3155. this.cgb[5] = np * (601676 / 22275);
  3156. this.cbg[5] = np * (444337 / 155925);
  3157. np = Math.pow(n, 2);
  3158. this.Qn = this.k0 / (1 + n) * (1 + np * (1 / 4 + np * (1 / 64 + np / 256)));
  3159. this.utg[0] = n * (-0.5 + n * ( 2 / 3 + n * (-37 / 96 + n * ( 1 / 360 + n * (81 / 512 + n * (-96199 / 604800))))));
  3160. this.gtu[0] = n * (0.5 + n * (-2 / 3 + n * (5 / 16 + n * (41 / 180 + n * (-127 / 288 + n * (7891 / 37800))))));
  3161. this.utg[1] = np * (-1 / 48 + n * (-1 / 15 + n * (437 / 1440 + n * (-46 / 105 + n * (1118711 / 3870720)))));
  3162. this.gtu[1] = np * (13 / 48 + n * (-3 / 5 + n * (557 / 1440 + n * (281 / 630 + n * (-1983433 / 1935360)))));
  3163. np = np * n;
  3164. this.utg[2] = np * (-17 / 480 + n * (37 / 840 + n * (209 / 4480 + n * (-5569 / 90720 ))));
  3165. this.gtu[2] = np * (61 / 240 + n * (-103 / 140 + n * (15061 / 26880 + n * (167603 / 181440))));
  3166. np = np * n;
  3167. this.utg[3] = np * (-4397 / 161280 + n * (11 / 504 + n * (830251 / 7257600)));
  3168. this.gtu[3] = np * (49561 / 161280 + n * (-179 / 168 + n * (6601661 / 7257600)));
  3169. np = np * n;
  3170. this.utg[4] = np * (-4583 / 161280 + n * (108847 / 3991680));
  3171. this.gtu[4] = np * (34729 / 80640 + n * (-3418889 / 1995840));
  3172. np = np * n;
  3173. this.utg[5] = np * (-20648693 / 638668800);
  3174. this.gtu[5] = np * (212378941 / 319334400);
  3175. var Z = gatg(this.cbg, this.lat0);
  3176. this.Zb = -this.Qn * (Z + clens(this.gtu, 2 * Z));
  3177. }
  3178. function forward$3(p) {
  3179. var Ce = adjust_lon(p.x - this.long0);
  3180. var Cn = p.y;
  3181. Cn = gatg(this.cbg, Cn);
  3182. var sin_Cn = Math.sin(Cn);
  3183. var cos_Cn = Math.cos(Cn);
  3184. var sin_Ce = Math.sin(Ce);
  3185. var cos_Ce = Math.cos(Ce);
  3186. Cn = Math.atan2(sin_Cn, cos_Ce * cos_Cn);
  3187. Ce = Math.atan2(sin_Ce * cos_Cn, hypot(sin_Cn, cos_Cn * cos_Ce));
  3188. Ce = asinhy(Math.tan(Ce));
  3189. var tmp = clens_cmplx(this.gtu, 2 * Cn, 2 * Ce);
  3190. Cn = Cn + tmp[0];
  3191. Ce = Ce + tmp[1];
  3192. var x;
  3193. var y;
  3194. if (Math.abs(Ce) <= 2.623395162778) {
  3195. x = this.a * (this.Qn * Ce) + this.x0;
  3196. y = this.a * (this.Qn * Cn + this.Zb) + this.y0;
  3197. }
  3198. else {
  3199. x = Infinity;
  3200. y = Infinity;
  3201. }
  3202. p.x = x;
  3203. p.y = y;
  3204. return p;
  3205. }
  3206. function inverse$3(p) {
  3207. var Ce = (p.x - this.x0) * (1 / this.a);
  3208. var Cn = (p.y - this.y0) * (1 / this.a);
  3209. Cn = (Cn - this.Zb) / this.Qn;
  3210. Ce = Ce / this.Qn;
  3211. var lon;
  3212. var lat;
  3213. if (Math.abs(Ce) <= 2.623395162778) {
  3214. var tmp = clens_cmplx(this.utg, 2 * Cn, 2 * Ce);
  3215. Cn = Cn + tmp[0];
  3216. Ce = Ce + tmp[1];
  3217. Ce = Math.atan(sinh(Ce));
  3218. var sin_Cn = Math.sin(Cn);
  3219. var cos_Cn = Math.cos(Cn);
  3220. var sin_Ce = Math.sin(Ce);
  3221. var cos_Ce = Math.cos(Ce);
  3222. Cn = Math.atan2(sin_Cn * cos_Ce, hypot(sin_Ce, cos_Ce * cos_Cn));
  3223. Ce = Math.atan2(sin_Ce, cos_Ce * cos_Cn);
  3224. lon = adjust_lon(Ce + this.long0);
  3225. lat = gatg(this.cgb, Cn);
  3226. }
  3227. else {
  3228. lon = Infinity;
  3229. lat = Infinity;
  3230. }
  3231. p.x = lon;
  3232. p.y = lat;
  3233. return p;
  3234. }
  3235. var names$4 = ["Extended_Transverse_Mercator", "Extended Transverse Mercator", "etmerc", "Transverse_Mercator", "Transverse Mercator", "tmerc"];
  3236. var etmerc = {
  3237. init: init$3,
  3238. forward: forward$3,
  3239. inverse: inverse$3,
  3240. names: names$4
  3241. };
  3242. var adjust_zone = function(zone, lon) {
  3243. if (zone === undefined) {
  3244. zone = Math.floor((adjust_lon(lon) + Math.PI) * 30 / Math.PI) + 1;
  3245. if (zone < 0) {
  3246. return 0;
  3247. } else if (zone > 60) {
  3248. return 60;
  3249. }
  3250. }
  3251. return zone;
  3252. };
  3253. var dependsOn = 'etmerc';
  3254. function init$4() {
  3255. var zone = adjust_zone(this.zone, this.long0);
  3256. if (zone === undefined) {
  3257. throw new Error('unknown utm zone');
  3258. }
  3259. this.lat0 = 0;
  3260. this.long0 = ((6 * Math.abs(zone)) - 183) * D2R;
  3261. this.x0 = 500000;
  3262. this.y0 = this.utmSouth ? 10000000 : 0;
  3263. this.k0 = 0.9996;
  3264. etmerc.init.apply(this);
  3265. this.forward = etmerc.forward;
  3266. this.inverse = etmerc.inverse;
  3267. }
  3268. var names$5 = ["Universal Transverse Mercator System", "utm"];
  3269. var utm = {
  3270. init: init$4,
  3271. names: names$5,
  3272. dependsOn: dependsOn
  3273. };
  3274. var srat = function(esinp, exp) {
  3275. return (Math.pow((1 - esinp) / (1 + esinp), exp));
  3276. };
  3277. var MAX_ITER$1 = 20;
  3278. function init$6() {
  3279. var sphi = Math.sin(this.lat0);
  3280. var cphi = Math.cos(this.lat0);
  3281. cphi *= cphi;
  3282. this.rc = Math.sqrt(1 - this.es) / (1 - this.es * sphi * sphi);
  3283. this.C = Math.sqrt(1 + this.es * cphi * cphi / (1 - this.es));
  3284. this.phic0 = Math.asin(sphi / this.C);
  3285. this.ratexp = 0.5 * this.C * this.e;
  3286. this.K = Math.tan(0.5 * this.phic0 + FORTPI) / (Math.pow(Math.tan(0.5 * this.lat0 + FORTPI), this.C) * srat(this.e * sphi, this.ratexp));
  3287. }
  3288. function forward$5(p) {
  3289. var lon = p.x;
  3290. var lat = p.y;
  3291. p.y = 2 * Math.atan(this.K * Math.pow(Math.tan(0.5 * lat + FORTPI), this.C) * srat(this.e * Math.sin(lat), this.ratexp)) - HALF_PI;
  3292. p.x = this.C * lon;
  3293. return p;
  3294. }
  3295. function inverse$5(p) {
  3296. var DEL_TOL = 1e-14;
  3297. var lon = p.x / this.C;
  3298. var lat = p.y;
  3299. var num = Math.pow(Math.tan(0.5 * lat + FORTPI) / this.K, 1 / this.C);
  3300. for (var i = MAX_ITER$1; i > 0; --i) {
  3301. lat = 2 * Math.atan(num * srat(this.e * Math.sin(p.y), - 0.5 * this.e)) - HALF_PI;
  3302. if (Math.abs(lat - p.y) < DEL_TOL) {
  3303. break;
  3304. }
  3305. p.y = lat;
  3306. }
  3307. /* convergence failed */
  3308. if (!i) {
  3309. return null;
  3310. }
  3311. p.x = lon;
  3312. p.y = lat;
  3313. return p;
  3314. }
  3315. var names$7 = ["gauss"];
  3316. var gauss = {
  3317. init: init$6,
  3318. forward: forward$5,
  3319. inverse: inverse$5,
  3320. names: names$7
  3321. };
  3322. function init$5() {
  3323. gauss.init.apply(this);
  3324. if (!this.rc) {
  3325. return;
  3326. }
  3327. this.sinc0 = Math.sin(this.phic0);
  3328. this.cosc0 = Math.cos(this.phic0);
  3329. this.R2 = 2 * this.rc;
  3330. if (!this.title) {
  3331. this.title = "Oblique Stereographic Alternative";
  3332. }
  3333. }
  3334. function forward$4(p) {
  3335. var sinc, cosc, cosl, k;
  3336. p.x = adjust_lon(p.x - this.long0);
  3337. gauss.forward.apply(this, [p]);
  3338. sinc = Math.sin(p.y);
  3339. cosc = Math.cos(p.y);
  3340. cosl = Math.cos(p.x);
  3341. k = this.k0 * this.R2 / (1 + this.sinc0 * sinc + this.cosc0 * cosc * cosl);
  3342. p.x = k * cosc * Math.sin(p.x);
  3343. p.y = k * (this.cosc0 * sinc - this.sinc0 * cosc * cosl);
  3344. p.x = this.a * p.x + this.x0;
  3345. p.y = this.a * p.y + this.y0;
  3346. return p;
  3347. }
  3348. function inverse$4(p) {
  3349. var sinc, cosc, lon, lat, rho;
  3350. p.x = (p.x - this.x0) / this.a;
  3351. p.y = (p.y - this.y0) / this.a;
  3352. p.x /= this.k0;
  3353. p.y /= this.k0;
  3354. if ((rho = Math.sqrt(p.x * p.x + p.y * p.y))) {
  3355. var c = 2 * Math.atan2(rho, this.R2);
  3356. sinc = Math.sin(c);
  3357. cosc = Math.cos(c);
  3358. lat = Math.asin(cosc * this.sinc0 + p.y * sinc * this.cosc0 / rho);
  3359. lon = Math.atan2(p.x * sinc, rho * this.cosc0 * cosc - p.y * this.sinc0 * sinc);
  3360. }
  3361. else {
  3362. lat = this.phic0;
  3363. lon = 0;
  3364. }
  3365. p.x = lon;
  3366. p.y = lat;
  3367. gauss.inverse.apply(this, [p]);
  3368. p.x = adjust_lon(p.x + this.long0);
  3369. return p;
  3370. }
  3371. var names$6 = ["Stereographic_North_Pole", "Oblique_Stereographic", "Polar_Stereographic", "sterea","Oblique Stereographic Alternative","Double_Stereographic"];
  3372. var sterea = {
  3373. init: init$5,
  3374. forward: forward$4,
  3375. inverse: inverse$4,
  3376. names: names$6
  3377. };
  3378. function ssfn_(phit, sinphi, eccen) {
  3379. sinphi *= eccen;
  3380. return (Math.tan(0.5 * (HALF_PI + phit)) * Math.pow((1 - sinphi) / (1 + sinphi), 0.5 * eccen));
  3381. }
  3382. function init$7() {
  3383. this.coslat0 = Math.cos(this.lat0);
  3384. this.sinlat0 = Math.sin(this.lat0);
  3385. if (this.sphere) {
  3386. if (this.k0 === 1 && !isNaN(this.lat_ts) && Math.abs(this.coslat0) <= EPSLN) {
  3387. this.k0 = 0.5 * (1 + sign(this.lat0) * Math.sin(this.lat_ts));
  3388. }
  3389. }
  3390. else {
  3391. if (Math.abs(this.coslat0) <= EPSLN) {
  3392. if (this.lat0 > 0) {
  3393. //North pole
  3394. //trace('stere:north pole');
  3395. this.con = 1;
  3396. }
  3397. else {
  3398. //South pole
  3399. //trace('stere:south pole');
  3400. this.con = -1;
  3401. }
  3402. }
  3403. this.cons = Math.sqrt(Math.pow(1 + this.e, 1 + this.e) * Math.pow(1 - this.e, 1 - this.e));
  3404. if (this.k0 === 1 && !isNaN(this.lat_ts) && Math.abs(this.coslat0) <= EPSLN) {
  3405. this.k0 = 0.5 * this.cons * msfnz(this.e, Math.sin(this.lat_ts), Math.cos(this.lat_ts)) / tsfnz(this.e, this.con * this.lat_ts, this.con * Math.sin(this.lat_ts));
  3406. }
  3407. this.ms1 = msfnz(this.e, this.sinlat0, this.coslat0);
  3408. this.X0 = 2 * Math.atan(this.ssfn_(this.lat0, this.sinlat0, this.e)) - HALF_PI;
  3409. this.cosX0 = Math.cos(this.X0);
  3410. this.sinX0 = Math.sin(this.X0);
  3411. }
  3412. }
  3413. // Stereographic forward equations--mapping lat,long to x,y
  3414. function forward$6(p) {
  3415. var lon = p.x;
  3416. var lat = p.y;
  3417. var sinlat = Math.sin(lat);
  3418. var coslat = Math.cos(lat);
  3419. var A, X, sinX, cosX, ts, rh;
  3420. var dlon = adjust_lon(lon - this.long0);
  3421. if (Math.abs(Math.abs(lon - this.long0) - Math.PI) <= EPSLN && Math.abs(lat + this.lat0) <= EPSLN) {
  3422. //case of the origine point
  3423. //trace('stere:this is the origin point');
  3424. p.x = NaN;
  3425. p.y = NaN;
  3426. return p;
  3427. }
  3428. if (this.sphere) {
  3429. //trace('stere:sphere case');
  3430. A = 2 * this.k0 / (1 + this.sinlat0 * sinlat + this.coslat0 * coslat * Math.cos(dlon));
  3431. p.x = this.a * A * coslat * Math.sin(dlon) + this.x0;
  3432. p.y = this.a * A * (this.coslat0 * sinlat - this.sinlat0 * coslat * Math.cos(dlon)) + this.y0;
  3433. return p;
  3434. }
  3435. else {
  3436. X = 2 * Math.atan(this.ssfn_(lat, sinlat, this.e)) - HALF_PI;
  3437. cosX = Math.cos(X);
  3438. sinX = Math.sin(X);
  3439. if (Math.abs(this.coslat0) <= EPSLN) {
  3440. ts = tsfnz(this.e, lat * this.con, this.con * sinlat);
  3441. rh = 2 * this.a * this.k0 * ts / this.cons;
  3442. p.x = this.x0 + rh * Math.sin(lon - this.long0);
  3443. p.y = this.y0 - this.con * rh * Math.cos(lon - this.long0);
  3444. //trace(p.toString());
  3445. return p;
  3446. }
  3447. else if (Math.abs(this.sinlat0) < EPSLN) {
  3448. //Eq
  3449. //trace('stere:equateur');
  3450. A = 2 * this.a * this.k0 / (1 + cosX * Math.cos(dlon));
  3451. p.y = A * sinX;
  3452. }
  3453. else {
  3454. //other case
  3455. //trace('stere:normal case');
  3456. A = 2 * this.a * this.k0 * this.ms1 / (this.cosX0 * (1 + this.sinX0 * sinX + this.cosX0 * cosX * Math.cos(dlon)));
  3457. p.y = A * (this.cosX0 * sinX - this.sinX0 * cosX * Math.cos(dlon)) + this.y0;
  3458. }
  3459. p.x = A * cosX * Math.sin(dlon) + this.x0;
  3460. }
  3461. //trace(p.toString());
  3462. return p;
  3463. }
  3464. //* Stereographic inverse equations--mapping x,y to lat/long
  3465. function inverse$6(p) {
  3466. p.x -= this.x0;
  3467. p.y -= this.y0;
  3468. var lon, lat, ts, ce, Chi;
  3469. var rh = Math.sqrt(p.x * p.x + p.y * p.y);
  3470. if (this.sphere) {
  3471. var c = 2 * Math.atan(rh / (2 * this.a * this.k0));
  3472. lon = this.long0;
  3473. lat = this.lat0;
  3474. if (rh <= EPSLN) {
  3475. p.x = lon;
  3476. p.y = lat;
  3477. return p;
  3478. }
  3479. lat = Math.asin(Math.cos(c) * this.sinlat0 + p.y * Math.sin(c) * this.coslat0 / rh);
  3480. if (Math.abs(this.coslat0) < EPSLN) {
  3481. if (this.lat0 > 0) {
  3482. lon = adjust_lon(this.long0 + Math.atan2(p.x, - 1 * p.y));
  3483. }
  3484. else {
  3485. lon = adjust_lon(this.long0 + Math.atan2(p.x, p.y));
  3486. }
  3487. }
  3488. else {
  3489. lon = adjust_lon(this.long0 + Math.atan2(p.x * Math.sin(c), rh * this.coslat0 * Math.cos(c) - p.y * this.sinlat0 * Math.sin(c)));
  3490. }
  3491. p.x = lon;
  3492. p.y = lat;
  3493. return p;
  3494. }
  3495. else {
  3496. if (Math.abs(this.coslat0) <= EPSLN) {
  3497. if (rh <= EPSLN) {
  3498. lat = this.lat0;
  3499. lon = this.long0;
  3500. p.x = lon;
  3501. p.y = lat;
  3502. //trace(p.toString());
  3503. return p;
  3504. }
  3505. p.x *= this.con;
  3506. p.y *= this.con;
  3507. ts = rh * this.cons / (2 * this.a * this.k0);
  3508. lat = this.con * phi2z(this.e, ts);
  3509. lon = this.con * adjust_lon(this.con * this.long0 + Math.atan2(p.x, - 1 * p.y));
  3510. }
  3511. else {
  3512. ce = 2 * Math.atan(rh * this.cosX0 / (2 * this.a * this.k0 * this.ms1));
  3513. lon = this.long0;
  3514. if (rh <= EPSLN) {
  3515. Chi = this.X0;
  3516. }
  3517. else {
  3518. Chi = Math.asin(Math.cos(ce) * this.sinX0 + p.y * Math.sin(ce) * this.cosX0 / rh);
  3519. lon = adjust_lon(this.long0 + Math.atan2(p.x * Math.sin(ce), rh * this.cosX0 * Math.cos(ce) - p.y * this.sinX0 * Math.sin(ce)));
  3520. }
  3521. lat = -1 * phi2z(this.e, Math.tan(0.5 * (HALF_PI + Chi)));
  3522. }
  3523. }
  3524. p.x = lon;
  3525. p.y = lat;
  3526. //trace(p.toString());
  3527. return p;
  3528. }
  3529. var names$8 = ["stere", "Stereographic_South_Pole", "Polar Stereographic (variant B)"];
  3530. var stere = {
  3531. init: init$7,
  3532. forward: forward$6,
  3533. inverse: inverse$6,
  3534. names: names$8,
  3535. ssfn_: ssfn_
  3536. };
  3537. /*
  3538. references:
  3539. Formules et constantes pour le Calcul pour la
  3540. projection cylindrique conforme à axe oblique et pour la transformation entre
  3541. des systèmes de référence.
  3542. http://www.swisstopo.admin.ch/internet/swisstopo/fr/home/topics/survey/sys/refsys/switzerland.parsysrelated1.31216.downloadList.77004.DownloadFile.tmp/swissprojectionfr.pdf
  3543. */
  3544. function init$8() {
  3545. var phy0 = this.lat0;
  3546. this.lambda0 = this.long0;
  3547. var sinPhy0 = Math.sin(phy0);
  3548. var semiMajorAxis = this.a;
  3549. var invF = this.rf;
  3550. var flattening = 1 / invF;
  3551. var e2 = 2 * flattening - Math.pow(flattening, 2);
  3552. var e = this.e = Math.sqrt(e2);
  3553. this.R = this.k0 * semiMajorAxis * Math.sqrt(1 - e2) / (1 - e2 * Math.pow(sinPhy0, 2));
  3554. this.alpha = Math.sqrt(1 + e2 / (1 - e2) * Math.pow(Math.cos(phy0), 4));
  3555. this.b0 = Math.asin(sinPhy0 / this.alpha);
  3556. var k1 = Math.log(Math.tan(Math.PI / 4 + this.b0 / 2));
  3557. var k2 = Math.log(Math.tan(Math.PI / 4 + phy0 / 2));
  3558. var k3 = Math.log((1 + e * sinPhy0) / (1 - e * sinPhy0));
  3559. this.K = k1 - this.alpha * k2 + this.alpha * e / 2 * k3;
  3560. }
  3561. function forward$7(p) {
  3562. var Sa1 = Math.log(Math.tan(Math.PI / 4 - p.y / 2));
  3563. var Sa2 = this.e / 2 * Math.log((1 + this.e * Math.sin(p.y)) / (1 - this.e * Math.sin(p.y)));
  3564. var S = -this.alpha * (Sa1 + Sa2) + this.K;
  3565. // spheric latitude
  3566. var b = 2 * (Math.atan(Math.exp(S)) - Math.PI / 4);
  3567. // spheric longitude
  3568. var I = this.alpha * (p.x - this.lambda0);
  3569. // psoeudo equatorial rotation
  3570. var rotI = Math.atan(Math.sin(I) / (Math.sin(this.b0) * Math.tan(b) + Math.cos(this.b0) * Math.cos(I)));
  3571. var rotB = Math.asin(Math.cos(this.b0) * Math.sin(b) - Math.sin(this.b0) * Math.cos(b) * Math.cos(I));
  3572. p.y = this.R / 2 * Math.log((1 + Math.sin(rotB)) / (1 - Math.sin(rotB))) + this.y0;
  3573. p.x = this.R * rotI + this.x0;
  3574. return p;
  3575. }
  3576. function inverse$7(p) {
  3577. var Y = p.x - this.x0;
  3578. var X = p.y - this.y0;
  3579. var rotI = Y / this.R;
  3580. var rotB = 2 * (Math.atan(Math.exp(X / this.R)) - Math.PI / 4);
  3581. var b = Math.asin(Math.cos(this.b0) * Math.sin(rotB) + Math.sin(this.b0) * Math.cos(rotB) * Math.cos(rotI));
  3582. var I = Math.atan(Math.sin(rotI) / (Math.cos(this.b0) * Math.cos(rotI) - Math.sin(this.b0) * Math.tan(rotB)));
  3583. var lambda = this.lambda0 + I / this.alpha;
  3584. var S = 0;
  3585. var phy = b;
  3586. var prevPhy = -1000;
  3587. var iteration = 0;
  3588. while (Math.abs(phy - prevPhy) > 0.0000001) {
  3589. if (++iteration > 20) {
  3590. //...reportError("omercFwdInfinity");
  3591. return;
  3592. }
  3593. //S = Math.log(Math.tan(Math.PI / 4 + phy / 2));
  3594. S = 1 / this.alpha * (Math.log(Math.tan(Math.PI / 4 + b / 2)) - this.K) + this.e * Math.log(Math.tan(Math.PI / 4 + Math.asin(this.e * Math.sin(phy)) / 2));
  3595. prevPhy = phy;
  3596. phy = 2 * Math.atan(Math.exp(S)) - Math.PI / 2;
  3597. }
  3598. p.x = lambda;
  3599. p.y = phy;
  3600. return p;
  3601. }
  3602. var names$9 = ["somerc"];
  3603. var somerc = {
  3604. init: init$8,
  3605. forward: forward$7,
  3606. inverse: inverse$7,
  3607. names: names$9
  3608. };
  3609. var TOL = 1e-7;
  3610. function isTypeA(P) {
  3611. var typeAProjections = ['Hotine_Oblique_Mercator','Hotine_Oblique_Mercator_Azimuth_Natural_Origin'];
  3612. var projectionName = typeof P.PROJECTION === "object" ? Object.keys(P.PROJECTION)[0] : P.PROJECTION;
  3613. return 'no_uoff' in P || 'no_off' in P || typeAProjections.indexOf(projectionName) !== -1;
  3614. }
  3615. /* Initialize the Oblique Mercator projection
  3616. ------------------------------------------*/
  3617. function init$9() {
  3618. var con, com, cosph0, D, F, H, L, sinph0, p, J, gamma = 0,
  3619. gamma0, lamc = 0, lam1 = 0, lam2 = 0, phi1 = 0, phi2 = 0, alpha_c = 0;
  3620. // only Type A uses the no_off or no_uoff property
  3621. // https://github.com/OSGeo/proj.4/issues/104
  3622. this.no_off = isTypeA(this);
  3623. this.no_rot = 'no_rot' in this;
  3624. var alp = false;
  3625. if ("alpha" in this) {
  3626. alp = true;
  3627. }
  3628. var gam = false;
  3629. if ("rectified_grid_angle" in this) {
  3630. gam = true;
  3631. }
  3632. if (alp) {
  3633. alpha_c = this.alpha;
  3634. }
  3635. if (gam) {
  3636. gamma = (this.rectified_grid_angle * D2R);
  3637. }
  3638. if (alp || gam) {
  3639. lamc = this.longc;
  3640. } else {
  3641. lam1 = this.long1;
  3642. phi1 = this.lat1;
  3643. lam2 = this.long2;
  3644. phi2 = this.lat2;
  3645. if (Math.abs(phi1 - phi2) <= TOL || (con = Math.abs(phi1)) <= TOL ||
  3646. Math.abs(con - HALF_PI) <= TOL || Math.abs(Math.abs(this.lat0) - HALF_PI) <= TOL ||
  3647. Math.abs(Math.abs(phi2) - HALF_PI) <= TOL) {
  3648. throw new Error();
  3649. }
  3650. }
  3651. var one_es = 1.0 - this.es;
  3652. com = Math.sqrt(one_es);
  3653. if (Math.abs(this.lat0) > EPSLN) {
  3654. sinph0 = Math.sin(this.lat0);
  3655. cosph0 = Math.cos(this.lat0);
  3656. con = 1 - this.es * sinph0 * sinph0;
  3657. this.B = cosph0 * cosph0;
  3658. this.B = Math.sqrt(1 + this.es * this.B * this.B / one_es);
  3659. this.A = this.B * this.k0 * com / con;
  3660. D = this.B * com / (cosph0 * Math.sqrt(con));
  3661. F = D * D -1;
  3662. if (F <= 0) {
  3663. F = 0;
  3664. } else {
  3665. F = Math.sqrt(F);
  3666. if (this.lat0 < 0) {
  3667. F = -F;
  3668. }
  3669. }
  3670. this.E = F += D;
  3671. this.E *= Math.pow(tsfnz(this.e, this.lat0, sinph0), this.B);
  3672. } else {
  3673. this.B = 1 / com;
  3674. this.A = this.k0;
  3675. this.E = D = F = 1;
  3676. }
  3677. if (alp || gam) {
  3678. if (alp) {
  3679. gamma0 = Math.asin(Math.sin(alpha_c) / D);
  3680. if (!gam) {
  3681. gamma = alpha_c;
  3682. }
  3683. } else {
  3684. gamma0 = gamma;
  3685. alpha_c = Math.asin(D * Math.sin(gamma0));
  3686. }
  3687. this.lam0 = lamc - Math.asin(0.5 * (F - 1 / F) * Math.tan(gamma0)) / this.B;
  3688. } else {
  3689. H = Math.pow(tsfnz(this.e, phi1, Math.sin(phi1)), this.B);
  3690. L = Math.pow(tsfnz(this.e, phi2, Math.sin(phi2)), this.B);
  3691. F = this.E / H;
  3692. p = (L - H) / (L + H);
  3693. J = this.E * this.E;
  3694. J = (J - L * H) / (J + L * H);
  3695. con = lam1 - lam2;
  3696. if (con < -Math.pi) {
  3697. lam2 -=TWO_PI;
  3698. } else if (con > Math.pi) {
  3699. lam2 += TWO_PI;
  3700. }
  3701. this.lam0 = adjust_lon(0.5 * (lam1 + lam2) - Math.atan(J * Math.tan(0.5 * this.B * (lam1 - lam2)) / p) / this.B);
  3702. gamma0 = Math.atan(2 * Math.sin(this.B * adjust_lon(lam1 - this.lam0)) / (F - 1 / F));
  3703. gamma = alpha_c = Math.asin(D * Math.sin(gamma0));
  3704. }
  3705. this.singam = Math.sin(gamma0);
  3706. this.cosgam = Math.cos(gamma0);
  3707. this.sinrot = Math.sin(gamma);
  3708. this.cosrot = Math.cos(gamma);
  3709. this.rB = 1 / this.B;
  3710. this.ArB = this.A * this.rB;
  3711. this.BrA = 1 / this.ArB;
  3712. if (this.no_off) {
  3713. this.u_0 = 0;
  3714. } else {
  3715. this.u_0 = Math.abs(this.ArB * Math.atan(Math.sqrt(D * D - 1) / Math.cos(alpha_c)));
  3716. if (this.lat0 < 0) {
  3717. this.u_0 = - this.u_0;
  3718. }
  3719. }
  3720. F = 0.5 * gamma0;
  3721. this.v_pole_n = this.ArB * Math.log(Math.tan(FORTPI - F));
  3722. this.v_pole_s = this.ArB * Math.log(Math.tan(FORTPI + F));
  3723. }
  3724. /* Oblique Mercator forward equations--mapping lat,long to x,y
  3725. ----------------------------------------------------------*/
  3726. function forward$8(p) {
  3727. var coords = {};
  3728. var S, T, U, V, W, temp, u, v;
  3729. p.x = p.x - this.lam0;
  3730. if (Math.abs(Math.abs(p.y) - HALF_PI) > EPSLN) {
  3731. W = this.E / Math.pow(tsfnz(this.e, p.y, Math.sin(p.y)), this.B);
  3732. temp = 1 / W;
  3733. S = 0.5 * (W - temp);
  3734. T = 0.5 * (W + temp);
  3735. V = Math.sin(this.B * p.x);
  3736. U = (S * this.singam - V * this.cosgam) / T;
  3737. if (Math.abs(Math.abs(U) - 1.0) < EPSLN) {
  3738. throw new Error();
  3739. }
  3740. v = 0.5 * this.ArB * Math.log((1 - U)/(1 + U));
  3741. temp = Math.cos(this.B * p.x);
  3742. if (Math.abs(temp) < TOL) {
  3743. u = this.A * p.x;
  3744. } else {
  3745. u = this.ArB * Math.atan2((S * this.cosgam + V * this.singam), temp);
  3746. }
  3747. } else {
  3748. v = p.y > 0 ? this.v_pole_n : this.v_pole_s;
  3749. u = this.ArB * p.y;
  3750. }
  3751. if (this.no_rot) {
  3752. coords.x = u;
  3753. coords.y = v;
  3754. } else {
  3755. u -= this.u_0;
  3756. coords.x = v * this.cosrot + u * this.sinrot;
  3757. coords.y = u * this.cosrot - v * this.sinrot;
  3758. }
  3759. coords.x = (this.a * coords.x + this.x0);
  3760. coords.y = (this.a * coords.y + this.y0);
  3761. return coords;
  3762. }
  3763. function inverse$8(p) {
  3764. var u, v, Qp, Sp, Tp, Vp, Up;
  3765. var coords = {};
  3766. p.x = (p.x - this.x0) * (1.0 / this.a);
  3767. p.y = (p.y - this.y0) * (1.0 / this.a);
  3768. if (this.no_rot) {
  3769. v = p.y;
  3770. u = p.x;
  3771. } else {
  3772. v = p.x * this.cosrot - p.y * this.sinrot;
  3773. u = p.y * this.cosrot + p.x * this.sinrot + this.u_0;
  3774. }
  3775. Qp = Math.exp(-this.BrA * v);
  3776. Sp = 0.5 * (Qp - 1 / Qp);
  3777. Tp = 0.5 * (Qp + 1 / Qp);
  3778. Vp = Math.sin(this.BrA * u);
  3779. Up = (Vp * this.cosgam + Sp * this.singam) / Tp;
  3780. if (Math.abs(Math.abs(Up) - 1) < EPSLN) {
  3781. coords.x = 0;
  3782. coords.y = Up < 0 ? -HALF_PI : HALF_PI;
  3783. } else {
  3784. coords.y = this.E / Math.sqrt((1 + Up) / (1 - Up));
  3785. coords.y = phi2z(this.e, Math.pow(coords.y, 1 / this.B));
  3786. if (coords.y === Infinity) {
  3787. throw new Error();
  3788. }
  3789. coords.x = -this.rB * Math.atan2((Sp * this.cosgam - Vp * this.singam), Math.cos(this.BrA * u));
  3790. }
  3791. coords.x += this.lam0;
  3792. return coords;
  3793. }
  3794. var names$10 = ["Hotine_Oblique_Mercator", "Hotine Oblique Mercator", "Hotine_Oblique_Mercator_Azimuth_Natural_Origin", "Hotine_Oblique_Mercator_Two_Point_Natural_Origin", "Hotine_Oblique_Mercator_Azimuth_Center", "Oblique_Mercator", "omerc"];
  3795. var omerc = {
  3796. init: init$9,
  3797. forward: forward$8,
  3798. inverse: inverse$8,
  3799. names: names$10
  3800. };
  3801. function init$10() {
  3802. //double lat0; /* the reference latitude */
  3803. //double long0; /* the reference longitude */
  3804. //double lat1; /* first standard parallel */
  3805. //double lat2; /* second standard parallel */
  3806. //double r_maj; /* major axis */
  3807. //double r_min; /* minor axis */
  3808. //double false_east; /* x offset in meters */
  3809. //double false_north; /* y offset in meters */
  3810. //the above value can be set with proj4.defs
  3811. //example: proj4.defs("EPSG:2154","+proj=lcc +lat_1=49 +lat_2=44 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs");
  3812. if (!this.lat2) {
  3813. this.lat2 = this.lat1;
  3814. } //if lat2 is not defined
  3815. if (!this.k0) {
  3816. this.k0 = 1;
  3817. }
  3818. this.x0 = this.x0 || 0;
  3819. this.y0 = this.y0 || 0;
  3820. // Standard Parallels cannot be equal and on opposite sides of the equator
  3821. if (Math.abs(this.lat1 + this.lat2) < EPSLN) {
  3822. return;
  3823. }
  3824. var temp = this.b / this.a;
  3825. this.e = Math.sqrt(1 - temp * temp);
  3826. var sin1 = Math.sin(this.lat1);
  3827. var cos1 = Math.cos(this.lat1);
  3828. var ms1 = msfnz(this.e, sin1, cos1);
  3829. var ts1 = tsfnz(this.e, this.lat1, sin1);
  3830. var sin2 = Math.sin(this.lat2);
  3831. var cos2 = Math.cos(this.lat2);
  3832. var ms2 = msfnz(this.e, sin2, cos2);
  3833. var ts2 = tsfnz(this.e, this.lat2, sin2);
  3834. var ts0 = tsfnz(this.e, this.lat0, Math.sin(this.lat0));
  3835. if (Math.abs(this.lat1 - this.lat2) > EPSLN) {
  3836. this.ns = Math.log(ms1 / ms2) / Math.log(ts1 / ts2);
  3837. }
  3838. else {
  3839. this.ns = sin1;
  3840. }
  3841. if (isNaN(this.ns)) {
  3842. this.ns = sin1;
  3843. }
  3844. this.f0 = ms1 / (this.ns * Math.pow(ts1, this.ns));
  3845. this.rh = this.a * this.f0 * Math.pow(ts0, this.ns);
  3846. if (!this.title) {
  3847. this.title = "Lambert Conformal Conic";
  3848. }
  3849. }
  3850. // Lambert Conformal conic forward equations--mapping lat,long to x,y
  3851. // -----------------------------------------------------------------
  3852. function forward$9(p) {
  3853. var lon = p.x;
  3854. var lat = p.y;
  3855. // singular cases :
  3856. if (Math.abs(2 * Math.abs(lat) - Math.PI) <= EPSLN) {
  3857. lat = sign(lat) * (HALF_PI - 2 * EPSLN);
  3858. }
  3859. var con = Math.abs(Math.abs(lat) - HALF_PI);
  3860. var ts, rh1;
  3861. if (con > EPSLN) {
  3862. ts = tsfnz(this.e, lat, Math.sin(lat));
  3863. rh1 = this.a * this.f0 * Math.pow(ts, this.ns);
  3864. }
  3865. else {
  3866. con = lat * this.ns;
  3867. if (con <= 0) {
  3868. return null;
  3869. }
  3870. rh1 = 0;
  3871. }
  3872. var theta = this.ns * adjust_lon(lon - this.long0);
  3873. p.x = this.k0 * (rh1 * Math.sin(theta)) + this.x0;
  3874. p.y = this.k0 * (this.rh - rh1 * Math.cos(theta)) + this.y0;
  3875. return p;
  3876. }
  3877. // Lambert Conformal Conic inverse equations--mapping x,y to lat/long
  3878. // -----------------------------------------------------------------
  3879. function inverse$9(p) {
  3880. var rh1, con, ts;
  3881. var lat, lon;
  3882. var x = (p.x - this.x0) / this.k0;
  3883. var y = (this.rh - (p.y - this.y0) / this.k0);
  3884. if (this.ns > 0) {
  3885. rh1 = Math.sqrt(x * x + y * y);
  3886. con = 1;
  3887. }
  3888. else {
  3889. rh1 = -Math.sqrt(x * x + y * y);
  3890. con = -1;
  3891. }
  3892. var theta = 0;
  3893. if (rh1 !== 0) {
  3894. theta = Math.atan2((con * x), (con * y));
  3895. }
  3896. if ((rh1 !== 0) || (this.ns > 0)) {
  3897. con = 1 / this.ns;
  3898. ts = Math.pow((rh1 / (this.a * this.f0)), con);
  3899. lat = phi2z(this.e, ts);
  3900. if (lat === -9999) {
  3901. return null;
  3902. }
  3903. }
  3904. else {
  3905. lat = -HALF_PI;
  3906. }
  3907. lon = adjust_lon(theta / this.ns + this.long0);
  3908. p.x = lon;
  3909. p.y = lat;
  3910. return p;
  3911. }
  3912. var names$11 = [
  3913. "Lambert Tangential Conformal Conic Projection",
  3914. "Lambert_Conformal_Conic",
  3915. "Lambert_Conformal_Conic_1SP",
  3916. "Lambert_Conformal_Conic_2SP",
  3917. "lcc"
  3918. ];
  3919. var lcc = {
  3920. init: init$10,
  3921. forward: forward$9,
  3922. inverse: inverse$9,
  3923. names: names$11
  3924. };
  3925. function init$11() {
  3926. this.a = 6377397.155;
  3927. this.es = 0.006674372230614;
  3928. this.e = Math.sqrt(this.es);
  3929. if (!this.lat0) {
  3930. this.lat0 = 0.863937979737193;
  3931. }
  3932. if (!this.long0) {
  3933. this.long0 = 0.7417649320975901 - 0.308341501185665;
  3934. }
  3935. /* if scale not set default to 0.9999 */
  3936. if (!this.k0) {
  3937. this.k0 = 0.9999;
  3938. }
  3939. this.s45 = 0.785398163397448; /* 45 */
  3940. this.s90 = 2 * this.s45;
  3941. this.fi0 = this.lat0;
  3942. this.e2 = this.es;
  3943. this.e = Math.sqrt(this.e2);
  3944. this.alfa = Math.sqrt(1 + (this.e2 * Math.pow(Math.cos(this.fi0), 4)) / (1 - this.e2));
  3945. this.uq = 1.04216856380474;
  3946. this.u0 = Math.asin(Math.sin(this.fi0) / this.alfa);
  3947. this.g = Math.pow((1 + this.e * Math.sin(this.fi0)) / (1 - this.e * Math.sin(this.fi0)), this.alfa * this.e / 2);
  3948. this.k = Math.tan(this.u0 / 2 + this.s45) / Math.pow(Math.tan(this.fi0 / 2 + this.s45), this.alfa) * this.g;
  3949. this.k1 = this.k0;
  3950. this.n0 = this.a * Math.sqrt(1 - this.e2) / (1 - this.e2 * Math.pow(Math.sin(this.fi0), 2));
  3951. this.s0 = 1.37008346281555;
  3952. this.n = Math.sin(this.s0);
  3953. this.ro0 = this.k1 * this.n0 / Math.tan(this.s0);
  3954. this.ad = this.s90 - this.uq;
  3955. }
  3956. /* ellipsoid */
  3957. /* calculate xy from lat/lon */
  3958. /* Constants, identical to inverse transform function */
  3959. function forward$10(p) {
  3960. var gfi, u, deltav, s, d, eps, ro;
  3961. var lon = p.x;
  3962. var lat = p.y;
  3963. var delta_lon = adjust_lon(lon - this.long0);
  3964. /* Transformation */
  3965. gfi = Math.pow(((1 + this.e * Math.sin(lat)) / (1 - this.e * Math.sin(lat))), (this.alfa * this.e / 2));
  3966. u = 2 * (Math.atan(this.k * Math.pow(Math.tan(lat / 2 + this.s45), this.alfa) / gfi) - this.s45);
  3967. deltav = -delta_lon * this.alfa;
  3968. s = Math.asin(Math.cos(this.ad) * Math.sin(u) + Math.sin(this.ad) * Math.cos(u) * Math.cos(deltav));
  3969. d = Math.asin(Math.cos(u) * Math.sin(deltav) / Math.cos(s));
  3970. eps = this.n * d;
  3971. ro = this.ro0 * Math.pow(Math.tan(this.s0 / 2 + this.s45), this.n) / Math.pow(Math.tan(s / 2 + this.s45), this.n);
  3972. p.y = ro * Math.cos(eps) / 1;
  3973. p.x = ro * Math.sin(eps) / 1;
  3974. if (!this.czech) {
  3975. p.y *= -1;
  3976. p.x *= -1;
  3977. }
  3978. return (p);
  3979. }
  3980. /* calculate lat/lon from xy */
  3981. function inverse$10(p) {
  3982. var u, deltav, s, d, eps, ro, fi1;
  3983. var ok;
  3984. /* Transformation */
  3985. /* revert y, x*/
  3986. var tmp = p.x;
  3987. p.x = p.y;
  3988. p.y = tmp;
  3989. if (!this.czech) {
  3990. p.y *= -1;
  3991. p.x *= -1;
  3992. }
  3993. ro = Math.sqrt(p.x * p.x + p.y * p.y);
  3994. eps = Math.atan2(p.y, p.x);
  3995. d = eps / Math.sin(this.s0);
  3996. s = 2 * (Math.atan(Math.pow(this.ro0 / ro, 1 / this.n) * Math.tan(this.s0 / 2 + this.s45)) - this.s45);
  3997. u = Math.asin(Math.cos(this.ad) * Math.sin(s) - Math.sin(this.ad) * Math.cos(s) * Math.cos(d));
  3998. deltav = Math.asin(Math.cos(s) * Math.sin(d) / Math.cos(u));
  3999. p.x = this.long0 - deltav / this.alfa;
  4000. fi1 = u;
  4001. ok = 0;
  4002. var iter = 0;
  4003. do {
  4004. p.y = 2 * (Math.atan(Math.pow(this.k, - 1 / this.alfa) * Math.pow(Math.tan(u / 2 + this.s45), 1 / this.alfa) * Math.pow((1 + this.e * Math.sin(fi1)) / (1 - this.e * Math.sin(fi1)), this.e / 2)) - this.s45);
  4005. if (Math.abs(fi1 - p.y) < 0.0000000001) {
  4006. ok = 1;
  4007. }
  4008. fi1 = p.y;
  4009. iter += 1;
  4010. } while (ok === 0 && iter < 15);
  4011. if (iter >= 15) {
  4012. return null;
  4013. }
  4014. return (p);
  4015. }
  4016. var names$12 = ["Krovak", "krovak"];
  4017. var krovak = {
  4018. init: init$11,
  4019. forward: forward$10,
  4020. inverse: inverse$10,
  4021. names: names$12
  4022. };
  4023. var mlfn = function(e0, e1, e2, e3, phi) {
  4024. return (e0 * phi - e1 * Math.sin(2 * phi) + e2 * Math.sin(4 * phi) - e3 * Math.sin(6 * phi));
  4025. };
  4026. var e0fn = function(x) {
  4027. return (1 - 0.25 * x * (1 + x / 16 * (3 + 1.25 * x)));
  4028. };
  4029. var e1fn = function(x) {
  4030. return (0.375 * x * (1 + 0.25 * x * (1 + 0.46875 * x)));
  4031. };
  4032. var e2fn = function(x) {
  4033. return (0.05859375 * x * x * (1 + 0.75 * x));
  4034. };
  4035. var e3fn = function(x) {
  4036. return (x * x * x * (35 / 3072));
  4037. };
  4038. var gN = function(a, e, sinphi) {
  4039. var temp = e * sinphi;
  4040. return a / Math.sqrt(1 - temp * temp);
  4041. };
  4042. var adjust_lat = function(x) {
  4043. return (Math.abs(x) < HALF_PI) ? x : (x - (sign(x) * Math.PI));
  4044. };
  4045. var imlfn = function(ml, e0, e1, e2, e3) {
  4046. var phi;
  4047. var dphi;
  4048. phi = ml / e0;
  4049. for (var i = 0; i < 15; i++) {
  4050. dphi = (ml - (e0 * phi - e1 * Math.sin(2 * phi) + e2 * Math.sin(4 * phi) - e3 * Math.sin(6 * phi))) / (e0 - 2 * e1 * Math.cos(2 * phi) + 4 * e2 * Math.cos(4 * phi) - 6 * e3 * Math.cos(6 * phi));
  4051. phi += dphi;
  4052. if (Math.abs(dphi) <= 0.0000000001) {
  4053. return phi;
  4054. }
  4055. }
  4056. //..reportError("IMLFN-CONV:Latitude failed to converge after 15 iterations");
  4057. return NaN;
  4058. };
  4059. function init$12() {
  4060. if (!this.sphere) {
  4061. this.e0 = e0fn(this.es);
  4062. this.e1 = e1fn(this.es);
  4063. this.e2 = e2fn(this.es);
  4064. this.e3 = e3fn(this.es);
  4065. this.ml0 = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0);
  4066. }
  4067. }
  4068. /* Cassini forward equations--mapping lat,long to x,y
  4069. -----------------------------------------------------------------------*/
  4070. function forward$11(p) {
  4071. /* Forward equations
  4072. -----------------*/
  4073. var x, y;
  4074. var lam = p.x;
  4075. var phi = p.y;
  4076. lam = adjust_lon(lam - this.long0);
  4077. if (this.sphere) {
  4078. x = this.a * Math.asin(Math.cos(phi) * Math.sin(lam));
  4079. y = this.a * (Math.atan2(Math.tan(phi), Math.cos(lam)) - this.lat0);
  4080. }
  4081. else {
  4082. //ellipsoid
  4083. var sinphi = Math.sin(phi);
  4084. var cosphi = Math.cos(phi);
  4085. var nl = gN(this.a, this.e, sinphi);
  4086. var tl = Math.tan(phi) * Math.tan(phi);
  4087. var al = lam * Math.cos(phi);
  4088. var asq = al * al;
  4089. var cl = this.es * cosphi * cosphi / (1 - this.es);
  4090. var ml = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, phi);
  4091. x = nl * al * (1 - asq * tl * (1 / 6 - (8 - tl + 8 * cl) * asq / 120));
  4092. y = ml - this.ml0 + nl * sinphi / cosphi * asq * (0.5 + (5 - tl + 6 * cl) * asq / 24);
  4093. }
  4094. p.x = x + this.x0;
  4095. p.y = y + this.y0;
  4096. return p;
  4097. }
  4098. /* Inverse equations
  4099. -----------------*/
  4100. function inverse$11(p) {
  4101. p.x -= this.x0;
  4102. p.y -= this.y0;
  4103. var x = p.x / this.a;
  4104. var y = p.y / this.a;
  4105. var phi, lam;
  4106. if (this.sphere) {
  4107. var dd = y + this.lat0;
  4108. phi = Math.asin(Math.sin(dd) * Math.cos(x));
  4109. lam = Math.atan2(Math.tan(x), Math.cos(dd));
  4110. }
  4111. else {
  4112. /* ellipsoid */
  4113. var ml1 = this.ml0 / this.a + y;
  4114. var phi1 = imlfn(ml1, this.e0, this.e1, this.e2, this.e3);
  4115. if (Math.abs(Math.abs(phi1) - HALF_PI) <= EPSLN) {
  4116. p.x = this.long0;
  4117. p.y = HALF_PI;
  4118. if (y < 0) {
  4119. p.y *= -1;
  4120. }
  4121. return p;
  4122. }
  4123. var nl1 = gN(this.a, this.e, Math.sin(phi1));
  4124. var rl1 = nl1 * nl1 * nl1 / this.a / this.a * (1 - this.es);
  4125. var tl1 = Math.pow(Math.tan(phi1), 2);
  4126. var dl = x * this.a / nl1;
  4127. var dsq = dl * dl;
  4128. phi = phi1 - nl1 * Math.tan(phi1) / rl1 * dl * dl * (0.5 - (1 + 3 * tl1) * dl * dl / 24);
  4129. lam = dl * (1 - dsq * (tl1 / 3 + (1 + 3 * tl1) * tl1 * dsq / 15)) / Math.cos(phi1);
  4130. }
  4131. p.x = adjust_lon(lam + this.long0);
  4132. p.y = adjust_lat(phi);
  4133. return p;
  4134. }
  4135. var names$13 = ["Cassini", "Cassini_Soldner", "cass"];
  4136. var cass = {
  4137. init: init$12,
  4138. forward: forward$11,
  4139. inverse: inverse$11,
  4140. names: names$13
  4141. };
  4142. var qsfnz = function(eccent, sinphi) {
  4143. var con;
  4144. if (eccent > 1.0e-7) {
  4145. con = eccent * sinphi;
  4146. return ((1 - eccent * eccent) * (sinphi / (1 - con * con) - (0.5 / eccent) * Math.log((1 - con) / (1 + con))));
  4147. }
  4148. else {
  4149. return (2 * sinphi);
  4150. }
  4151. };
  4152. /*
  4153. reference
  4154. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder,
  4155. The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355.
  4156. */
  4157. var S_POLE = 1;
  4158. var N_POLE = 2;
  4159. var EQUIT = 3;
  4160. var OBLIQ = 4;
  4161. /* Initialize the Lambert Azimuthal Equal Area projection
  4162. ------------------------------------------------------*/
  4163. function init$13() {
  4164. var t = Math.abs(this.lat0);
  4165. if (Math.abs(t - HALF_PI) < EPSLN) {
  4166. this.mode = this.lat0 < 0 ? this.S_POLE : this.N_POLE;
  4167. }
  4168. else if (Math.abs(t) < EPSLN) {
  4169. this.mode = this.EQUIT;
  4170. }
  4171. else {
  4172. this.mode = this.OBLIQ;
  4173. }
  4174. if (this.es > 0) {
  4175. var sinphi;
  4176. this.qp = qsfnz(this.e, 1);
  4177. this.mmf = 0.5 / (1 - this.es);
  4178. this.apa = authset(this.es);
  4179. switch (this.mode) {
  4180. case this.N_POLE:
  4181. this.dd = 1;
  4182. break;
  4183. case this.S_POLE:
  4184. this.dd = 1;
  4185. break;
  4186. case this.EQUIT:
  4187. this.rq = Math.sqrt(0.5 * this.qp);
  4188. this.dd = 1 / this.rq;
  4189. this.xmf = 1;
  4190. this.ymf = 0.5 * this.qp;
  4191. break;
  4192. case this.OBLIQ:
  4193. this.rq = Math.sqrt(0.5 * this.qp);
  4194. sinphi = Math.sin(this.lat0);
  4195. this.sinb1 = qsfnz(this.e, sinphi) / this.qp;
  4196. this.cosb1 = Math.sqrt(1 - this.sinb1 * this.sinb1);
  4197. this.dd = Math.cos(this.lat0) / (Math.sqrt(1 - this.es * sinphi * sinphi) * this.rq * this.cosb1);
  4198. this.ymf = (this.xmf = this.rq) / this.dd;
  4199. this.xmf *= this.dd;
  4200. break;
  4201. }
  4202. }
  4203. else {
  4204. if (this.mode === this.OBLIQ) {
  4205. this.sinph0 = Math.sin(this.lat0);
  4206. this.cosph0 = Math.cos(this.lat0);
  4207. }
  4208. }
  4209. }
  4210. /* Lambert Azimuthal Equal Area forward equations--mapping lat,long to x,y
  4211. -----------------------------------------------------------------------*/
  4212. function forward$12(p) {
  4213. /* Forward equations
  4214. -----------------*/
  4215. var x, y, coslam, sinlam, sinphi, q, sinb, cosb, b, cosphi;
  4216. var lam = p.x;
  4217. var phi = p.y;
  4218. lam = adjust_lon(lam - this.long0);
  4219. if (this.sphere) {
  4220. sinphi = Math.sin(phi);
  4221. cosphi = Math.cos(phi);
  4222. coslam = Math.cos(lam);
  4223. if (this.mode === this.OBLIQ || this.mode === this.EQUIT) {
  4224. y = (this.mode === this.EQUIT) ? 1 + cosphi * coslam : 1 + this.sinph0 * sinphi + this.cosph0 * cosphi * coslam;
  4225. if (y <= EPSLN) {
  4226. return null;
  4227. }
  4228. y = Math.sqrt(2 / y);
  4229. x = y * cosphi * Math.sin(lam);
  4230. y *= (this.mode === this.EQUIT) ? sinphi : this.cosph0 * sinphi - this.sinph0 * cosphi * coslam;
  4231. }
  4232. else if (this.mode === this.N_POLE || this.mode === this.S_POLE) {
  4233. if (this.mode === this.N_POLE) {
  4234. coslam = -coslam;
  4235. }
  4236. if (Math.abs(phi + this.lat0) < EPSLN) {
  4237. return null;
  4238. }
  4239. y = FORTPI - phi * 0.5;
  4240. y = 2 * ((this.mode === this.S_POLE) ? Math.cos(y) : Math.sin(y));
  4241. x = y * Math.sin(lam);
  4242. y *= coslam;
  4243. }
  4244. }
  4245. else {
  4246. sinb = 0;
  4247. cosb = 0;
  4248. b = 0;
  4249. coslam = Math.cos(lam);
  4250. sinlam = Math.sin(lam);
  4251. sinphi = Math.sin(phi);
  4252. q = qsfnz(this.e, sinphi);
  4253. if (this.mode === this.OBLIQ || this.mode === this.EQUIT) {
  4254. sinb = q / this.qp;
  4255. cosb = Math.sqrt(1 - sinb * sinb);
  4256. }
  4257. switch (this.mode) {
  4258. case this.OBLIQ:
  4259. b = 1 + this.sinb1 * sinb + this.cosb1 * cosb * coslam;
  4260. break;
  4261. case this.EQUIT:
  4262. b = 1 + cosb * coslam;
  4263. break;
  4264. case this.N_POLE:
  4265. b = HALF_PI + phi;
  4266. q = this.qp - q;
  4267. break;
  4268. case this.S_POLE:
  4269. b = phi - HALF_PI;
  4270. q = this.qp + q;
  4271. break;
  4272. }
  4273. if (Math.abs(b) < EPSLN) {
  4274. return null;
  4275. }
  4276. switch (this.mode) {
  4277. case this.OBLIQ:
  4278. case this.EQUIT:
  4279. b = Math.sqrt(2 / b);
  4280. if (this.mode === this.OBLIQ) {
  4281. y = this.ymf * b * (this.cosb1 * sinb - this.sinb1 * cosb * coslam);
  4282. }
  4283. else {
  4284. y = (b = Math.sqrt(2 / (1 + cosb * coslam))) * sinb * this.ymf;
  4285. }
  4286. x = this.xmf * b * cosb * sinlam;
  4287. break;
  4288. case this.N_POLE:
  4289. case this.S_POLE:
  4290. if (q >= 0) {
  4291. x = (b = Math.sqrt(q)) * sinlam;
  4292. y = coslam * ((this.mode === this.S_POLE) ? b : -b);
  4293. }
  4294. else {
  4295. x = y = 0;
  4296. }
  4297. break;
  4298. }
  4299. }
  4300. p.x = this.a * x + this.x0;
  4301. p.y = this.a * y + this.y0;
  4302. return p;
  4303. }
  4304. /* Inverse equations
  4305. -----------------*/
  4306. function inverse$12(p) {
  4307. p.x -= this.x0;
  4308. p.y -= this.y0;
  4309. var x = p.x / this.a;
  4310. var y = p.y / this.a;
  4311. var lam, phi, cCe, sCe, q, rho, ab;
  4312. if (this.sphere) {
  4313. var cosz = 0,
  4314. rh, sinz = 0;
  4315. rh = Math.sqrt(x * x + y * y);
  4316. phi = rh * 0.5;
  4317. if (phi > 1) {
  4318. return null;
  4319. }
  4320. phi = 2 * Math.asin(phi);
  4321. if (this.mode === this.OBLIQ || this.mode === this.EQUIT) {
  4322. sinz = Math.sin(phi);
  4323. cosz = Math.cos(phi);
  4324. }
  4325. switch (this.mode) {
  4326. case this.EQUIT:
  4327. phi = (Math.abs(rh) <= EPSLN) ? 0 : Math.asin(y * sinz / rh);
  4328. x *= sinz;
  4329. y = cosz * rh;
  4330. break;
  4331. case this.OBLIQ:
  4332. phi = (Math.abs(rh) <= EPSLN) ? this.lat0 : Math.asin(cosz * this.sinph0 + y * sinz * this.cosph0 / rh);
  4333. x *= sinz * this.cosph0;
  4334. y = (cosz - Math.sin(phi) * this.sinph0) * rh;
  4335. break;
  4336. case this.N_POLE:
  4337. y = -y;
  4338. phi = HALF_PI - phi;
  4339. break;
  4340. case this.S_POLE:
  4341. phi -= HALF_PI;
  4342. break;
  4343. }
  4344. lam = (y === 0 && (this.mode === this.EQUIT || this.mode === this.OBLIQ)) ? 0 : Math.atan2(x, y);
  4345. }
  4346. else {
  4347. ab = 0;
  4348. if (this.mode === this.OBLIQ || this.mode === this.EQUIT) {
  4349. x /= this.dd;
  4350. y *= this.dd;
  4351. rho = Math.sqrt(x * x + y * y);
  4352. if (rho < EPSLN) {
  4353. p.x = this.long0;
  4354. p.y = this.lat0;
  4355. return p;
  4356. }
  4357. sCe = 2 * Math.asin(0.5 * rho / this.rq);
  4358. cCe = Math.cos(sCe);
  4359. x *= (sCe = Math.sin(sCe));
  4360. if (this.mode === this.OBLIQ) {
  4361. ab = cCe * this.sinb1 + y * sCe * this.cosb1 / rho;
  4362. q = this.qp * ab;
  4363. y = rho * this.cosb1 * cCe - y * this.sinb1 * sCe;
  4364. }
  4365. else {
  4366. ab = y * sCe / rho;
  4367. q = this.qp * ab;
  4368. y = rho * cCe;
  4369. }
  4370. }
  4371. else if (this.mode === this.N_POLE || this.mode === this.S_POLE) {
  4372. if (this.mode === this.N_POLE) {
  4373. y = -y;
  4374. }
  4375. q = (x * x + y * y);
  4376. if (!q) {
  4377. p.x = this.long0;
  4378. p.y = this.lat0;
  4379. return p;
  4380. }
  4381. ab = 1 - q / this.qp;
  4382. if (this.mode === this.S_POLE) {
  4383. ab = -ab;
  4384. }
  4385. }
  4386. lam = Math.atan2(x, y);
  4387. phi = authlat(Math.asin(ab), this.apa);
  4388. }
  4389. p.x = adjust_lon(this.long0 + lam);
  4390. p.y = phi;
  4391. return p;
  4392. }
  4393. /* determine latitude from authalic latitude */
  4394. var P00 = 0.33333333333333333333;
  4395. var P01 = 0.17222222222222222222;
  4396. var P02 = 0.10257936507936507936;
  4397. var P10 = 0.06388888888888888888;
  4398. var P11 = 0.06640211640211640211;
  4399. var P20 = 0.01641501294219154443;
  4400. function authset(es) {
  4401. var t;
  4402. var APA = [];
  4403. APA[0] = es * P00;
  4404. t = es * es;
  4405. APA[0] += t * P01;
  4406. APA[1] = t * P10;
  4407. t *= es;
  4408. APA[0] += t * P02;
  4409. APA[1] += t * P11;
  4410. APA[2] = t * P20;
  4411. return APA;
  4412. }
  4413. function authlat(beta, APA) {
  4414. var t = beta + beta;
  4415. return (beta + APA[0] * Math.sin(t) + APA[1] * Math.sin(t + t) + APA[2] * Math.sin(t + t + t));
  4416. }
  4417. var names$14 = ["Lambert Azimuthal Equal Area", "Lambert_Azimuthal_Equal_Area", "laea"];
  4418. var laea = {
  4419. init: init$13,
  4420. forward: forward$12,
  4421. inverse: inverse$12,
  4422. names: names$14,
  4423. S_POLE: S_POLE,
  4424. N_POLE: N_POLE,
  4425. EQUIT: EQUIT,
  4426. OBLIQ: OBLIQ
  4427. };
  4428. var asinz = function(x) {
  4429. if (Math.abs(x) > 1) {
  4430. x = (x > 1) ? 1 : -1;
  4431. }
  4432. return Math.asin(x);
  4433. };
  4434. function init$14() {
  4435. if (Math.abs(this.lat1 + this.lat2) < EPSLN) {
  4436. return;
  4437. }
  4438. this.temp = this.b / this.a;
  4439. this.es = 1 - Math.pow(this.temp, 2);
  4440. this.e3 = Math.sqrt(this.es);
  4441. this.sin_po = Math.sin(this.lat1);
  4442. this.cos_po = Math.cos(this.lat1);
  4443. this.t1 = this.sin_po;
  4444. this.con = this.sin_po;
  4445. this.ms1 = msfnz(this.e3, this.sin_po, this.cos_po);
  4446. this.qs1 = qsfnz(this.e3, this.sin_po, this.cos_po);
  4447. this.sin_po = Math.sin(this.lat2);
  4448. this.cos_po = Math.cos(this.lat2);
  4449. this.t2 = this.sin_po;
  4450. this.ms2 = msfnz(this.e3, this.sin_po, this.cos_po);
  4451. this.qs2 = qsfnz(this.e3, this.sin_po, this.cos_po);
  4452. this.sin_po = Math.sin(this.lat0);
  4453. this.cos_po = Math.cos(this.lat0);
  4454. this.t3 = this.sin_po;
  4455. this.qs0 = qsfnz(this.e3, this.sin_po, this.cos_po);
  4456. if (Math.abs(this.lat1 - this.lat2) > EPSLN) {
  4457. this.ns0 = (this.ms1 * this.ms1 - this.ms2 * this.ms2) / (this.qs2 - this.qs1);
  4458. }
  4459. else {
  4460. this.ns0 = this.con;
  4461. }
  4462. this.c = this.ms1 * this.ms1 + this.ns0 * this.qs1;
  4463. this.rh = this.a * Math.sqrt(this.c - this.ns0 * this.qs0) / this.ns0;
  4464. }
  4465. /* Albers Conical Equal Area forward equations--mapping lat,long to x,y
  4466. -------------------------------------------------------------------*/
  4467. function forward$13(p) {
  4468. var lon = p.x;
  4469. var lat = p.y;
  4470. this.sin_phi = Math.sin(lat);
  4471. this.cos_phi = Math.cos(lat);
  4472. var qs = qsfnz(this.e3, this.sin_phi, this.cos_phi);
  4473. var rh1 = this.a * Math.sqrt(this.c - this.ns0 * qs) / this.ns0;
  4474. var theta = this.ns0 * adjust_lon(lon - this.long0);
  4475. var x = rh1 * Math.sin(theta) + this.x0;
  4476. var y = this.rh - rh1 * Math.cos(theta) + this.y0;
  4477. p.x = x;
  4478. p.y = y;
  4479. return p;
  4480. }
  4481. function inverse$13(p) {
  4482. var rh1, qs, con, theta, lon, lat;
  4483. p.x -= this.x0;
  4484. p.y = this.rh - p.y + this.y0;
  4485. if (this.ns0 >= 0) {
  4486. rh1 = Math.sqrt(p.x * p.x + p.y * p.y);
  4487. con = 1;
  4488. }
  4489. else {
  4490. rh1 = -Math.sqrt(p.x * p.x + p.y * p.y);
  4491. con = -1;
  4492. }
  4493. theta = 0;
  4494. if (rh1 !== 0) {
  4495. theta = Math.atan2(con * p.x, con * p.y);
  4496. }
  4497. con = rh1 * this.ns0 / this.a;
  4498. if (this.sphere) {
  4499. lat = Math.asin((this.c - con * con) / (2 * this.ns0));
  4500. }
  4501. else {
  4502. qs = (this.c - con * con) / this.ns0;
  4503. lat = this.phi1z(this.e3, qs);
  4504. }
  4505. lon = adjust_lon(theta / this.ns0 + this.long0);
  4506. p.x = lon;
  4507. p.y = lat;
  4508. return p;
  4509. }
  4510. /* Function to compute phi1, the latitude for the inverse of the
  4511. Albers Conical Equal-Area projection.
  4512. -------------------------------------------*/
  4513. function phi1z(eccent, qs) {
  4514. var sinphi, cosphi, con, com, dphi;
  4515. var phi = asinz(0.5 * qs);
  4516. if (eccent < EPSLN) {
  4517. return phi;
  4518. }
  4519. var eccnts = eccent * eccent;
  4520. for (var i = 1; i <= 25; i++) {
  4521. sinphi = Math.sin(phi);
  4522. cosphi = Math.cos(phi);
  4523. con = eccent * sinphi;
  4524. com = 1 - con * con;
  4525. dphi = 0.5 * com * com / cosphi * (qs / (1 - eccnts) - sinphi / com + 0.5 / eccent * Math.log((1 - con) / (1 + con)));
  4526. phi = phi + dphi;
  4527. if (Math.abs(dphi) <= 1e-7) {
  4528. return phi;
  4529. }
  4530. }
  4531. return null;
  4532. }
  4533. var names$15 = ["Albers_Conic_Equal_Area", "Albers", "aea"];
  4534. var aea = {
  4535. init: init$14,
  4536. forward: forward$13,
  4537. inverse: inverse$13,
  4538. names: names$15,
  4539. phi1z: phi1z
  4540. };
  4541. /*
  4542. reference:
  4543. Wolfram Mathworld "Gnomonic Projection"
  4544. http://mathworld.wolfram.com/GnomonicProjection.html
  4545. Accessed: 12th November 2009
  4546. */
  4547. function init$15() {
  4548. /* Place parameters in static storage for common use
  4549. -------------------------------------------------*/
  4550. this.sin_p14 = Math.sin(this.lat0);
  4551. this.cos_p14 = Math.cos(this.lat0);
  4552. // Approximation for projecting points to the horizon (infinity)
  4553. this.infinity_dist = 1000 * this.a;
  4554. this.rc = 1;
  4555. }
  4556. /* Gnomonic forward equations--mapping lat,long to x,y
  4557. ---------------------------------------------------*/
  4558. function forward$14(p) {
  4559. var sinphi, cosphi; /* sin and cos value */
  4560. var dlon; /* delta longitude value */
  4561. var coslon; /* cos of longitude */
  4562. var ksp; /* scale factor */
  4563. var g;
  4564. var x, y;
  4565. var lon = p.x;
  4566. var lat = p.y;
  4567. /* Forward equations
  4568. -----------------*/
  4569. dlon = adjust_lon(lon - this.long0);
  4570. sinphi = Math.sin(lat);
  4571. cosphi = Math.cos(lat);
  4572. coslon = Math.cos(dlon);
  4573. g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon;
  4574. ksp = 1;
  4575. if ((g > 0) || (Math.abs(g) <= EPSLN)) {
  4576. x = this.x0 + this.a * ksp * cosphi * Math.sin(dlon) / g;
  4577. y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon) / g;
  4578. }
  4579. else {
  4580. // Point is in the opposing hemisphere and is unprojectable
  4581. // We still need to return a reasonable point, so we project
  4582. // to infinity, on a bearing
  4583. // equivalent to the northern hemisphere equivalent
  4584. // This is a reasonable approximation for short shapes and lines that
  4585. // straddle the horizon.
  4586. x = this.x0 + this.infinity_dist * cosphi * Math.sin(dlon);
  4587. y = this.y0 + this.infinity_dist * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon);
  4588. }
  4589. p.x = x;
  4590. p.y = y;
  4591. return p;
  4592. }
  4593. function inverse$14(p) {
  4594. var rh; /* Rho */
  4595. var sinc, cosc;
  4596. var c;
  4597. var lon, lat;
  4598. /* Inverse equations
  4599. -----------------*/
  4600. p.x = (p.x - this.x0) / this.a;
  4601. p.y = (p.y - this.y0) / this.a;
  4602. p.x /= this.k0;
  4603. p.y /= this.k0;
  4604. if ((rh = Math.sqrt(p.x * p.x + p.y * p.y))) {
  4605. c = Math.atan2(rh, this.rc);
  4606. sinc = Math.sin(c);
  4607. cosc = Math.cos(c);
  4608. lat = asinz(cosc * this.sin_p14 + (p.y * sinc * this.cos_p14) / rh);
  4609. lon = Math.atan2(p.x * sinc, rh * this.cos_p14 * cosc - p.y * this.sin_p14 * sinc);
  4610. lon = adjust_lon(this.long0 + lon);
  4611. }
  4612. else {
  4613. lat = this.phic0;
  4614. lon = 0;
  4615. }
  4616. p.x = lon;
  4617. p.y = lat;
  4618. return p;
  4619. }
  4620. var names$16 = ["gnom"];
  4621. var gnom = {
  4622. init: init$15,
  4623. forward: forward$14,
  4624. inverse: inverse$14,
  4625. names: names$16
  4626. };
  4627. var iqsfnz = function(eccent, q) {
  4628. var temp = 1 - (1 - eccent * eccent) / (2 * eccent) * Math.log((1 - eccent) / (1 + eccent));
  4629. if (Math.abs(Math.abs(q) - temp) < 1.0E-6) {
  4630. if (q < 0) {
  4631. return (-1 * HALF_PI);
  4632. }
  4633. else {
  4634. return HALF_PI;
  4635. }
  4636. }
  4637. //var phi = 0.5* q/(1-eccent*eccent);
  4638. var phi = Math.asin(0.5 * q);
  4639. var dphi;
  4640. var sin_phi;
  4641. var cos_phi;
  4642. var con;
  4643. for (var i = 0; i < 30; i++) {
  4644. sin_phi = Math.sin(phi);
  4645. cos_phi = Math.cos(phi);
  4646. con = eccent * sin_phi;
  4647. dphi = Math.pow(1 - con * con, 2) / (2 * cos_phi) * (q / (1 - eccent * eccent) - sin_phi / (1 - con * con) + 0.5 / eccent * Math.log((1 - con) / (1 + con)));
  4648. phi += dphi;
  4649. if (Math.abs(dphi) <= 0.0000000001) {
  4650. return phi;
  4651. }
  4652. }
  4653. //console.log("IQSFN-CONV:Latitude failed to converge after 30 iterations");
  4654. return NaN;
  4655. };
  4656. /*
  4657. reference:
  4658. "Cartographic Projection Procedures for the UNIX Environment-
  4659. A User's Manual" by Gerald I. Evenden,
  4660. USGS Open File Report 90-284and Release 4 Interim Reports (2003)
  4661. */
  4662. function init$16() {
  4663. //no-op
  4664. if (!this.sphere) {
  4665. this.k0 = msfnz(this.e, Math.sin(this.lat_ts), Math.cos(this.lat_ts));
  4666. }
  4667. }
  4668. /* Cylindrical Equal Area forward equations--mapping lat,long to x,y
  4669. ------------------------------------------------------------*/
  4670. function forward$15(p) {
  4671. var lon = p.x;
  4672. var lat = p.y;
  4673. var x, y;
  4674. /* Forward equations
  4675. -----------------*/
  4676. var dlon = adjust_lon(lon - this.long0);
  4677. if (this.sphere) {
  4678. x = this.x0 + this.a * dlon * Math.cos(this.lat_ts);
  4679. y = this.y0 + this.a * Math.sin(lat) / Math.cos(this.lat_ts);
  4680. }
  4681. else {
  4682. var qs = qsfnz(this.e, Math.sin(lat));
  4683. x = this.x0 + this.a * this.k0 * dlon;
  4684. y = this.y0 + this.a * qs * 0.5 / this.k0;
  4685. }
  4686. p.x = x;
  4687. p.y = y;
  4688. return p;
  4689. }
  4690. /* Cylindrical Equal Area inverse equations--mapping x,y to lat/long
  4691. ------------------------------------------------------------*/
  4692. function inverse$15(p) {
  4693. p.x -= this.x0;
  4694. p.y -= this.y0;
  4695. var lon, lat;
  4696. if (this.sphere) {
  4697. lon = adjust_lon(this.long0 + (p.x / this.a) / Math.cos(this.lat_ts));
  4698. lat = Math.asin((p.y / this.a) * Math.cos(this.lat_ts));
  4699. }
  4700. else {
  4701. lat = iqsfnz(this.e, 2 * p.y * this.k0 / this.a);
  4702. lon = adjust_lon(this.long0 + p.x / (this.a * this.k0));
  4703. }
  4704. p.x = lon;
  4705. p.y = lat;
  4706. return p;
  4707. }
  4708. var names$17 = ["cea"];
  4709. var cea = {
  4710. init: init$16,
  4711. forward: forward$15,
  4712. inverse: inverse$15,
  4713. names: names$17
  4714. };
  4715. function init$17() {
  4716. this.x0 = this.x0 || 0;
  4717. this.y0 = this.y0 || 0;
  4718. this.lat0 = this.lat0 || 0;
  4719. this.long0 = this.long0 || 0;
  4720. this.lat_ts = this.lat_ts || 0;
  4721. this.title = this.title || "Equidistant Cylindrical (Plate Carre)";
  4722. this.rc = Math.cos(this.lat_ts);
  4723. }
  4724. // forward equations--mapping lat,long to x,y
  4725. // -----------------------------------------------------------------
  4726. function forward$16(p) {
  4727. var lon = p.x;
  4728. var lat = p.y;
  4729. var dlon = adjust_lon(lon - this.long0);
  4730. var dlat = adjust_lat(lat - this.lat0);
  4731. p.x = this.x0 + (this.a * dlon * this.rc);
  4732. p.y = this.y0 + (this.a * dlat);
  4733. return p;
  4734. }
  4735. // inverse equations--mapping x,y to lat/long
  4736. // -----------------------------------------------------------------
  4737. function inverse$16(p) {
  4738. var x = p.x;
  4739. var y = p.y;
  4740. p.x = adjust_lon(this.long0 + ((x - this.x0) / (this.a * this.rc)));
  4741. p.y = adjust_lat(this.lat0 + ((y - this.y0) / (this.a)));
  4742. return p;
  4743. }
  4744. var names$18 = ["Equirectangular", "Equidistant_Cylindrical", "eqc"];
  4745. var eqc = {
  4746. init: init$17,
  4747. forward: forward$16,
  4748. inverse: inverse$16,
  4749. names: names$18
  4750. };
  4751. var MAX_ITER$2 = 20;
  4752. function init$18() {
  4753. /* Place parameters in static storage for common use
  4754. -------------------------------------------------*/
  4755. this.temp = this.b / this.a;
  4756. this.es = 1 - Math.pow(this.temp, 2); // devait etre dans tmerc.js mais n y est pas donc je commente sinon retour de valeurs nulles
  4757. this.e = Math.sqrt(this.es);
  4758. this.e0 = e0fn(this.es);
  4759. this.e1 = e1fn(this.es);
  4760. this.e2 = e2fn(this.es);
  4761. this.e3 = e3fn(this.es);
  4762. this.ml0 = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0); //si que des zeros le calcul ne se fait pas
  4763. }
  4764. /* Polyconic forward equations--mapping lat,long to x,y
  4765. ---------------------------------------------------*/
  4766. function forward$17(p) {
  4767. var lon = p.x;
  4768. var lat = p.y;
  4769. var x, y, el;
  4770. var dlon = adjust_lon(lon - this.long0);
  4771. el = dlon * Math.sin(lat);
  4772. if (this.sphere) {
  4773. if (Math.abs(lat) <= EPSLN) {
  4774. x = this.a * dlon;
  4775. y = -1 * this.a * this.lat0;
  4776. }
  4777. else {
  4778. x = this.a * Math.sin(el) / Math.tan(lat);
  4779. y = this.a * (adjust_lat(lat - this.lat0) + (1 - Math.cos(el)) / Math.tan(lat));
  4780. }
  4781. }
  4782. else {
  4783. if (Math.abs(lat) <= EPSLN) {
  4784. x = this.a * dlon;
  4785. y = -1 * this.ml0;
  4786. }
  4787. else {
  4788. var nl = gN(this.a, this.e, Math.sin(lat)) / Math.tan(lat);
  4789. x = nl * Math.sin(el);
  4790. y = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, lat) - this.ml0 + nl * (1 - Math.cos(el));
  4791. }
  4792. }
  4793. p.x = x + this.x0;
  4794. p.y = y + this.y0;
  4795. return p;
  4796. }
  4797. /* Inverse equations
  4798. -----------------*/
  4799. function inverse$17(p) {
  4800. var lon, lat, x, y, i;
  4801. var al, bl;
  4802. var phi, dphi;
  4803. x = p.x - this.x0;
  4804. y = p.y - this.y0;
  4805. if (this.sphere) {
  4806. if (Math.abs(y + this.a * this.lat0) <= EPSLN) {
  4807. lon = adjust_lon(x / this.a + this.long0);
  4808. lat = 0;
  4809. }
  4810. else {
  4811. al = this.lat0 + y / this.a;
  4812. bl = x * x / this.a / this.a + al * al;
  4813. phi = al;
  4814. var tanphi;
  4815. for (i = MAX_ITER$2; i; --i) {
  4816. tanphi = Math.tan(phi);
  4817. dphi = -1 * (al * (phi * tanphi + 1) - phi - 0.5 * (phi * phi + bl) * tanphi) / ((phi - al) / tanphi - 1);
  4818. phi += dphi;
  4819. if (Math.abs(dphi) <= EPSLN) {
  4820. lat = phi;
  4821. break;
  4822. }
  4823. }
  4824. lon = adjust_lon(this.long0 + (Math.asin(x * Math.tan(phi) / this.a)) / Math.sin(lat));
  4825. }
  4826. }
  4827. else {
  4828. if (Math.abs(y + this.ml0) <= EPSLN) {
  4829. lat = 0;
  4830. lon = adjust_lon(this.long0 + x / this.a);
  4831. }
  4832. else {
  4833. al = (this.ml0 + y) / this.a;
  4834. bl = x * x / this.a / this.a + al * al;
  4835. phi = al;
  4836. var cl, mln, mlnp, ma;
  4837. var con;
  4838. for (i = MAX_ITER$2; i; --i) {
  4839. con = this.e * Math.sin(phi);
  4840. cl = Math.sqrt(1 - con * con) * Math.tan(phi);
  4841. mln = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, phi);
  4842. mlnp = this.e0 - 2 * this.e1 * Math.cos(2 * phi) + 4 * this.e2 * Math.cos(4 * phi) - 6 * this.e3 * Math.cos(6 * phi);
  4843. ma = mln / this.a;
  4844. dphi = (al * (cl * ma + 1) - ma - 0.5 * cl * (ma * ma + bl)) / (this.es * Math.sin(2 * phi) * (ma * ma + bl - 2 * al * ma) / (4 * cl) + (al - ma) * (cl * mlnp - 2 / Math.sin(2 * phi)) - mlnp);
  4845. phi -= dphi;
  4846. if (Math.abs(dphi) <= EPSLN) {
  4847. lat = phi;
  4848. break;
  4849. }
  4850. }
  4851. //lat=phi4z(this.e,this.e0,this.e1,this.e2,this.e3,al,bl,0,0);
  4852. cl = Math.sqrt(1 - this.es * Math.pow(Math.sin(lat), 2)) * Math.tan(lat);
  4853. lon = adjust_lon(this.long0 + Math.asin(x * cl / this.a) / Math.sin(lat));
  4854. }
  4855. }
  4856. p.x = lon;
  4857. p.y = lat;
  4858. return p;
  4859. }
  4860. var names$19 = ["Polyconic", "poly"];
  4861. var poly = {
  4862. init: init$18,
  4863. forward: forward$17,
  4864. inverse: inverse$17,
  4865. names: names$19
  4866. };
  4867. /*
  4868. reference
  4869. Department of Land and Survey Technical Circular 1973/32
  4870. http://www.linz.govt.nz/docs/miscellaneous/nz-map-definition.pdf
  4871. OSG Technical Report 4.1
  4872. http://www.linz.govt.nz/docs/miscellaneous/nzmg.pdf
  4873. */
  4874. /**
  4875. * iterations: Number of iterations to refine inverse transform.
  4876. * 0 -> km accuracy
  4877. * 1 -> m accuracy -- suitable for most mapping applications
  4878. * 2 -> mm accuracy
  4879. */
  4880. function init$19() {
  4881. this.A = [];
  4882. this.A[1] = 0.6399175073;
  4883. this.A[2] = -0.1358797613;
  4884. this.A[3] = 0.063294409;
  4885. this.A[4] = -0.02526853;
  4886. this.A[5] = 0.0117879;
  4887. this.A[6] = -0.0055161;
  4888. this.A[7] = 0.0026906;
  4889. this.A[8] = -0.001333;
  4890. this.A[9] = 0.00067;
  4891. this.A[10] = -0.00034;
  4892. this.B_re = [];
  4893. this.B_im = [];
  4894. this.B_re[1] = 0.7557853228;
  4895. this.B_im[1] = 0;
  4896. this.B_re[2] = 0.249204646;
  4897. this.B_im[2] = 0.003371507;
  4898. this.B_re[3] = -0.001541739;
  4899. this.B_im[3] = 0.041058560;
  4900. this.B_re[4] = -0.10162907;
  4901. this.B_im[4] = 0.01727609;
  4902. this.B_re[5] = -0.26623489;
  4903. this.B_im[5] = -0.36249218;
  4904. this.B_re[6] = -0.6870983;
  4905. this.B_im[6] = -1.1651967;
  4906. this.C_re = [];
  4907. this.C_im = [];
  4908. this.C_re[1] = 1.3231270439;
  4909. this.C_im[1] = 0;
  4910. this.C_re[2] = -0.577245789;
  4911. this.C_im[2] = -0.007809598;
  4912. this.C_re[3] = 0.508307513;
  4913. this.C_im[3] = -0.112208952;
  4914. this.C_re[4] = -0.15094762;
  4915. this.C_im[4] = 0.18200602;
  4916. this.C_re[5] = 1.01418179;
  4917. this.C_im[5] = 1.64497696;
  4918. this.C_re[6] = 1.9660549;
  4919. this.C_im[6] = 2.5127645;
  4920. this.D = [];
  4921. this.D[1] = 1.5627014243;
  4922. this.D[2] = 0.5185406398;
  4923. this.D[3] = -0.03333098;
  4924. this.D[4] = -0.1052906;
  4925. this.D[5] = -0.0368594;
  4926. this.D[6] = 0.007317;
  4927. this.D[7] = 0.01220;
  4928. this.D[8] = 0.00394;
  4929. this.D[9] = -0.0013;
  4930. }
  4931. /**
  4932. New Zealand Map Grid Forward - long/lat to x/y
  4933. long/lat in radians
  4934. */
  4935. function forward$18(p) {
  4936. var n;
  4937. var lon = p.x;
  4938. var lat = p.y;
  4939. var delta_lat = lat - this.lat0;
  4940. var delta_lon = lon - this.long0;
  4941. // 1. Calculate d_phi and d_psi ... // and d_lambda
  4942. // For this algorithm, delta_latitude is in seconds of arc x 10-5, so we need to scale to those units. Longitude is radians.
  4943. var d_phi = delta_lat / SEC_TO_RAD * 1E-5;
  4944. var d_lambda = delta_lon;
  4945. var d_phi_n = 1; // d_phi^0
  4946. var d_psi = 0;
  4947. for (n = 1; n <= 10; n++) {
  4948. d_phi_n = d_phi_n * d_phi;
  4949. d_psi = d_psi + this.A[n] * d_phi_n;
  4950. }
  4951. // 2. Calculate theta
  4952. var th_re = d_psi;
  4953. var th_im = d_lambda;
  4954. // 3. Calculate z
  4955. var th_n_re = 1;
  4956. var th_n_im = 0; // theta^0
  4957. var th_n_re1;
  4958. var th_n_im1;
  4959. var z_re = 0;
  4960. var z_im = 0;
  4961. for (n = 1; n <= 6; n++) {
  4962. th_n_re1 = th_n_re * th_re - th_n_im * th_im;
  4963. th_n_im1 = th_n_im * th_re + th_n_re * th_im;
  4964. th_n_re = th_n_re1;
  4965. th_n_im = th_n_im1;
  4966. z_re = z_re + this.B_re[n] * th_n_re - this.B_im[n] * th_n_im;
  4967. z_im = z_im + this.B_im[n] * th_n_re + this.B_re[n] * th_n_im;
  4968. }
  4969. // 4. Calculate easting and northing
  4970. p.x = (z_im * this.a) + this.x0;
  4971. p.y = (z_re * this.a) + this.y0;
  4972. return p;
  4973. }
  4974. /**
  4975. New Zealand Map Grid Inverse - x/y to long/lat
  4976. */
  4977. function inverse$18(p) {
  4978. var n;
  4979. var x = p.x;
  4980. var y = p.y;
  4981. var delta_x = x - this.x0;
  4982. var delta_y = y - this.y0;
  4983. // 1. Calculate z
  4984. var z_re = delta_y / this.a;
  4985. var z_im = delta_x / this.a;
  4986. // 2a. Calculate theta - first approximation gives km accuracy
  4987. var z_n_re = 1;
  4988. var z_n_im = 0; // z^0
  4989. var z_n_re1;
  4990. var z_n_im1;
  4991. var th_re = 0;
  4992. var th_im = 0;
  4993. for (n = 1; n <= 6; n++) {
  4994. z_n_re1 = z_n_re * z_re - z_n_im * z_im;
  4995. z_n_im1 = z_n_im * z_re + z_n_re * z_im;
  4996. z_n_re = z_n_re1;
  4997. z_n_im = z_n_im1;
  4998. th_re = th_re + this.C_re[n] * z_n_re - this.C_im[n] * z_n_im;
  4999. th_im = th_im + this.C_im[n] * z_n_re + this.C_re[n] * z_n_im;
  5000. }
  5001. // 2b. Iterate to refine the accuracy of the calculation
  5002. // 0 iterations gives km accuracy
  5003. // 1 iteration gives m accuracy -- good enough for most mapping applications
  5004. // 2 iterations bives mm accuracy
  5005. for (var i = 0; i < this.iterations; i++) {
  5006. var th_n_re = th_re;
  5007. var th_n_im = th_im;
  5008. var th_n_re1;
  5009. var th_n_im1;
  5010. var num_re = z_re;
  5011. var num_im = z_im;
  5012. for (n = 2; n <= 6; n++) {
  5013. th_n_re1 = th_n_re * th_re - th_n_im * th_im;
  5014. th_n_im1 = th_n_im * th_re + th_n_re * th_im;
  5015. th_n_re = th_n_re1;
  5016. th_n_im = th_n_im1;
  5017. num_re = num_re + (n - 1) * (this.B_re[n] * th_n_re - this.B_im[n] * th_n_im);
  5018. num_im = num_im + (n - 1) * (this.B_im[n] * th_n_re + this.B_re[n] * th_n_im);
  5019. }
  5020. th_n_re = 1;
  5021. th_n_im = 0;
  5022. var den_re = this.B_re[1];
  5023. var den_im = this.B_im[1];
  5024. for (n = 2; n <= 6; n++) {
  5025. th_n_re1 = th_n_re * th_re - th_n_im * th_im;
  5026. th_n_im1 = th_n_im * th_re + th_n_re * th_im;
  5027. th_n_re = th_n_re1;
  5028. th_n_im = th_n_im1;
  5029. den_re = den_re + n * (this.B_re[n] * th_n_re - this.B_im[n] * th_n_im);
  5030. den_im = den_im + n * (this.B_im[n] * th_n_re + this.B_re[n] * th_n_im);
  5031. }
  5032. // Complex division
  5033. var den2 = den_re * den_re + den_im * den_im;
  5034. th_re = (num_re * den_re + num_im * den_im) / den2;
  5035. th_im = (num_im * den_re - num_re * den_im) / den2;
  5036. }
  5037. // 3. Calculate d_phi ... // and d_lambda
  5038. var d_psi = th_re;
  5039. var d_lambda = th_im;
  5040. var d_psi_n = 1; // d_psi^0
  5041. var d_phi = 0;
  5042. for (n = 1; n <= 9; n++) {
  5043. d_psi_n = d_psi_n * d_psi;
  5044. d_phi = d_phi + this.D[n] * d_psi_n;
  5045. }
  5046. // 4. Calculate latitude and longitude
  5047. // d_phi is calcuated in second of arc * 10^-5, so we need to scale back to radians. d_lambda is in radians.
  5048. var lat = this.lat0 + (d_phi * SEC_TO_RAD * 1E5);
  5049. var lon = this.long0 + d_lambda;
  5050. p.x = lon;
  5051. p.y = lat;
  5052. return p;
  5053. }
  5054. var names$20 = ["New_Zealand_Map_Grid", "nzmg"];
  5055. var nzmg = {
  5056. init: init$19,
  5057. forward: forward$18,
  5058. inverse: inverse$18,
  5059. names: names$20
  5060. };
  5061. /*
  5062. reference
  5063. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder,
  5064. The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355.
  5065. */
  5066. /* Initialize the Miller Cylindrical projection
  5067. -------------------------------------------*/
  5068. function init$20() {
  5069. //no-op
  5070. }
  5071. /* Miller Cylindrical forward equations--mapping lat,long to x,y
  5072. ------------------------------------------------------------*/
  5073. function forward$19(p) {
  5074. var lon = p.x;
  5075. var lat = p.y;
  5076. /* Forward equations
  5077. -----------------*/
  5078. var dlon = adjust_lon(lon - this.long0);
  5079. var x = this.x0 + this.a * dlon;
  5080. var y = this.y0 + this.a * Math.log(Math.tan((Math.PI / 4) + (lat / 2.5))) * 1.25;
  5081. p.x = x;
  5082. p.y = y;
  5083. return p;
  5084. }
  5085. /* Miller Cylindrical inverse equations--mapping x,y to lat/long
  5086. ------------------------------------------------------------*/
  5087. function inverse$19(p) {
  5088. p.x -= this.x0;
  5089. p.y -= this.y0;
  5090. var lon = adjust_lon(this.long0 + p.x / this.a);
  5091. var lat = 2.5 * (Math.atan(Math.exp(0.8 * p.y / this.a)) - Math.PI / 4);
  5092. p.x = lon;
  5093. p.y = lat;
  5094. return p;
  5095. }
  5096. var names$21 = ["Miller_Cylindrical", "mill"];
  5097. var mill = {
  5098. init: init$20,
  5099. forward: forward$19,
  5100. inverse: inverse$19,
  5101. names: names$21
  5102. };
  5103. var MAX_ITER$3 = 20;
  5104. function init$21() {
  5105. /* Place parameters in static storage for common use
  5106. -------------------------------------------------*/
  5107. if (!this.sphere) {
  5108. this.en = pj_enfn(this.es);
  5109. }
  5110. else {
  5111. this.n = 1;
  5112. this.m = 0;
  5113. this.es = 0;
  5114. this.C_y = Math.sqrt((this.m + 1) / this.n);
  5115. this.C_x = this.C_y / (this.m + 1);
  5116. }
  5117. }
  5118. /* Sinusoidal forward equations--mapping lat,long to x,y
  5119. -----------------------------------------------------*/
  5120. function forward$20(p) {
  5121. var x, y;
  5122. var lon = p.x;
  5123. var lat = p.y;
  5124. /* Forward equations
  5125. -----------------*/
  5126. lon = adjust_lon(lon - this.long0);
  5127. if (this.sphere) {
  5128. if (!this.m) {
  5129. lat = this.n !== 1 ? Math.asin(this.n * Math.sin(lat)) : lat;
  5130. }
  5131. else {
  5132. var k = this.n * Math.sin(lat);
  5133. for (var i = MAX_ITER$3; i; --i) {
  5134. var V = (this.m * lat + Math.sin(lat) - k) / (this.m + Math.cos(lat));
  5135. lat -= V;
  5136. if (Math.abs(V) < EPSLN) {
  5137. break;
  5138. }
  5139. }
  5140. }
  5141. x = this.a * this.C_x * lon * (this.m + Math.cos(lat));
  5142. y = this.a * this.C_y * lat;
  5143. }
  5144. else {
  5145. var s = Math.sin(lat);
  5146. var c = Math.cos(lat);
  5147. y = this.a * pj_mlfn(lat, s, c, this.en);
  5148. x = this.a * lon * c / Math.sqrt(1 - this.es * s * s);
  5149. }
  5150. p.x = x;
  5151. p.y = y;
  5152. return p;
  5153. }
  5154. function inverse$20(p) {
  5155. var lat, temp, lon, s;
  5156. p.x -= this.x0;
  5157. lon = p.x / this.a;
  5158. p.y -= this.y0;
  5159. lat = p.y / this.a;
  5160. if (this.sphere) {
  5161. lat /= this.C_y;
  5162. lon = lon / (this.C_x * (this.m + Math.cos(lat)));
  5163. if (this.m) {
  5164. lat = asinz((this.m * lat + Math.sin(lat)) / this.n);
  5165. }
  5166. else if (this.n !== 1) {
  5167. lat = asinz(Math.sin(lat) / this.n);
  5168. }
  5169. lon = adjust_lon(lon + this.long0);
  5170. lat = adjust_lat(lat);
  5171. }
  5172. else {
  5173. lat = pj_inv_mlfn(p.y / this.a, this.es, this.en);
  5174. s = Math.abs(lat);
  5175. if (s < HALF_PI) {
  5176. s = Math.sin(lat);
  5177. temp = this.long0 + p.x * Math.sqrt(1 - this.es * s * s) / (this.a * Math.cos(lat));
  5178. //temp = this.long0 + p.x / (this.a * Math.cos(lat));
  5179. lon = adjust_lon(temp);
  5180. }
  5181. else if ((s - EPSLN) < HALF_PI) {
  5182. lon = this.long0;
  5183. }
  5184. }
  5185. p.x = lon;
  5186. p.y = lat;
  5187. return p;
  5188. }
  5189. var names$22 = ["Sinusoidal", "sinu"];
  5190. var sinu = {
  5191. init: init$21,
  5192. forward: forward$20,
  5193. inverse: inverse$20,
  5194. names: names$22
  5195. };
  5196. function init$22() {}
  5197. /* Mollweide forward equations--mapping lat,long to x,y
  5198. ----------------------------------------------------*/
  5199. function forward$21(p) {
  5200. /* Forward equations
  5201. -----------------*/
  5202. var lon = p.x;
  5203. var lat = p.y;
  5204. var delta_lon = adjust_lon(lon - this.long0);
  5205. var theta = lat;
  5206. var con = Math.PI * Math.sin(lat);
  5207. /* Iterate using the Newton-Raphson method to find theta
  5208. -----------------------------------------------------*/
  5209. while (true) {
  5210. var delta_theta = -(theta + Math.sin(theta) - con) / (1 + Math.cos(theta));
  5211. theta += delta_theta;
  5212. if (Math.abs(delta_theta) < EPSLN) {
  5213. break;
  5214. }
  5215. }
  5216. theta /= 2;
  5217. /* If the latitude is 90 deg, force the x coordinate to be "0 + false easting"
  5218. this is done here because of precision problems with "cos(theta)"
  5219. --------------------------------------------------------------------------*/
  5220. if (Math.PI / 2 - Math.abs(lat) < EPSLN) {
  5221. delta_lon = 0;
  5222. }
  5223. var x = 0.900316316158 * this.a * delta_lon * Math.cos(theta) + this.x0;
  5224. var y = 1.4142135623731 * this.a * Math.sin(theta) + this.y0;
  5225. p.x = x;
  5226. p.y = y;
  5227. return p;
  5228. }
  5229. function inverse$21(p) {
  5230. var theta;
  5231. var arg;
  5232. /* Inverse equations
  5233. -----------------*/
  5234. p.x -= this.x0;
  5235. p.y -= this.y0;
  5236. arg = p.y / (1.4142135623731 * this.a);
  5237. /* Because of division by zero problems, 'arg' can not be 1. Therefore
  5238. a number very close to one is used instead.
  5239. -------------------------------------------------------------------*/
  5240. if (Math.abs(arg) > 0.999999999999) {
  5241. arg = 0.999999999999;
  5242. }
  5243. theta = Math.asin(arg);
  5244. var lon = adjust_lon(this.long0 + (p.x / (0.900316316158 * this.a * Math.cos(theta))));
  5245. if (lon < (-Math.PI)) {
  5246. lon = -Math.PI;
  5247. }
  5248. if (lon > Math.PI) {
  5249. lon = Math.PI;
  5250. }
  5251. arg = (2 * theta + Math.sin(2 * theta)) / Math.PI;
  5252. if (Math.abs(arg) > 1) {
  5253. arg = 1;
  5254. }
  5255. var lat = Math.asin(arg);
  5256. p.x = lon;
  5257. p.y = lat;
  5258. return p;
  5259. }
  5260. var names$23 = ["Mollweide", "moll"];
  5261. var moll = {
  5262. init: init$22,
  5263. forward: forward$21,
  5264. inverse: inverse$21,
  5265. names: names$23
  5266. };
  5267. function init$23() {
  5268. /* Place parameters in static storage for common use
  5269. -------------------------------------------------*/
  5270. // Standard Parallels cannot be equal and on opposite sides of the equator
  5271. if (Math.abs(this.lat1 + this.lat2) < EPSLN) {
  5272. return;
  5273. }
  5274. this.lat2 = this.lat2 || this.lat1;
  5275. this.temp = this.b / this.a;
  5276. this.es = 1 - Math.pow(this.temp, 2);
  5277. this.e = Math.sqrt(this.es);
  5278. this.e0 = e0fn(this.es);
  5279. this.e1 = e1fn(this.es);
  5280. this.e2 = e2fn(this.es);
  5281. this.e3 = e3fn(this.es);
  5282. this.sinphi = Math.sin(this.lat1);
  5283. this.cosphi = Math.cos(this.lat1);
  5284. this.ms1 = msfnz(this.e, this.sinphi, this.cosphi);
  5285. this.ml1 = mlfn(this.e0, this.e1, this.e2, this.e3, this.lat1);
  5286. if (Math.abs(this.lat1 - this.lat2) < EPSLN) {
  5287. this.ns = this.sinphi;
  5288. }
  5289. else {
  5290. this.sinphi = Math.sin(this.lat2);
  5291. this.cosphi = Math.cos(this.lat2);
  5292. this.ms2 = msfnz(this.e, this.sinphi, this.cosphi);
  5293. this.ml2 = mlfn(this.e0, this.e1, this.e2, this.e3, this.lat2);
  5294. this.ns = (this.ms1 - this.ms2) / (this.ml2 - this.ml1);
  5295. }
  5296. this.g = this.ml1 + this.ms1 / this.ns;
  5297. this.ml0 = mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0);
  5298. this.rh = this.a * (this.g - this.ml0);
  5299. }
  5300. /* Equidistant Conic forward equations--mapping lat,long to x,y
  5301. -----------------------------------------------------------*/
  5302. function forward$22(p) {
  5303. var lon = p.x;
  5304. var lat = p.y;
  5305. var rh1;
  5306. /* Forward equations
  5307. -----------------*/
  5308. if (this.sphere) {
  5309. rh1 = this.a * (this.g - lat);
  5310. }
  5311. else {
  5312. var ml = mlfn(this.e0, this.e1, this.e2, this.e3, lat);
  5313. rh1 = this.a * (this.g - ml);
  5314. }
  5315. var theta = this.ns * adjust_lon(lon - this.long0);
  5316. var x = this.x0 + rh1 * Math.sin(theta);
  5317. var y = this.y0 + this.rh - rh1 * Math.cos(theta);
  5318. p.x = x;
  5319. p.y = y;
  5320. return p;
  5321. }
  5322. /* Inverse equations
  5323. -----------------*/
  5324. function inverse$22(p) {
  5325. p.x -= this.x0;
  5326. p.y = this.rh - p.y + this.y0;
  5327. var con, rh1, lat, lon;
  5328. if (this.ns >= 0) {
  5329. rh1 = Math.sqrt(p.x * p.x + p.y * p.y);
  5330. con = 1;
  5331. }
  5332. else {
  5333. rh1 = -Math.sqrt(p.x * p.x + p.y * p.y);
  5334. con = -1;
  5335. }
  5336. var theta = 0;
  5337. if (rh1 !== 0) {
  5338. theta = Math.atan2(con * p.x, con * p.y);
  5339. }
  5340. if (this.sphere) {
  5341. lon = adjust_lon(this.long0 + theta / this.ns);
  5342. lat = adjust_lat(this.g - rh1 / this.a);
  5343. p.x = lon;
  5344. p.y = lat;
  5345. return p;
  5346. }
  5347. else {
  5348. var ml = this.g - rh1 / this.a;
  5349. lat = imlfn(ml, this.e0, this.e1, this.e2, this.e3);
  5350. lon = adjust_lon(this.long0 + theta / this.ns);
  5351. p.x = lon;
  5352. p.y = lat;
  5353. return p;
  5354. }
  5355. }
  5356. var names$24 = ["Equidistant_Conic", "eqdc"];
  5357. var eqdc = {
  5358. init: init$23,
  5359. forward: forward$22,
  5360. inverse: inverse$22,
  5361. names: names$24
  5362. };
  5363. /* Initialize the Van Der Grinten projection
  5364. ----------------------------------------*/
  5365. function init$24() {
  5366. //this.R = 6370997; //Radius of earth
  5367. this.R = this.a;
  5368. }
  5369. function forward$23(p) {
  5370. var lon = p.x;
  5371. var lat = p.y;
  5372. /* Forward equations
  5373. -----------------*/
  5374. var dlon = adjust_lon(lon - this.long0);
  5375. var x, y;
  5376. if (Math.abs(lat) <= EPSLN) {
  5377. x = this.x0 + this.R * dlon;
  5378. y = this.y0;
  5379. }
  5380. var theta = asinz(2 * Math.abs(lat / Math.PI));
  5381. if ((Math.abs(dlon) <= EPSLN) || (Math.abs(Math.abs(lat) - HALF_PI) <= EPSLN)) {
  5382. x = this.x0;
  5383. if (lat >= 0) {
  5384. y = this.y0 + Math.PI * this.R * Math.tan(0.5 * theta);
  5385. }
  5386. else {
  5387. y = this.y0 + Math.PI * this.R * -Math.tan(0.5 * theta);
  5388. }
  5389. // return(OK);
  5390. }
  5391. var al = 0.5 * Math.abs((Math.PI / dlon) - (dlon / Math.PI));
  5392. var asq = al * al;
  5393. var sinth = Math.sin(theta);
  5394. var costh = Math.cos(theta);
  5395. var g = costh / (sinth + costh - 1);
  5396. var gsq = g * g;
  5397. var m = g * (2 / sinth - 1);
  5398. var msq = m * m;
  5399. var con = Math.PI * this.R * (al * (g - msq) + Math.sqrt(asq * (g - msq) * (g - msq) - (msq + asq) * (gsq - msq))) / (msq + asq);
  5400. if (dlon < 0) {
  5401. con = -con;
  5402. }
  5403. x = this.x0 + con;
  5404. //con = Math.abs(con / (Math.PI * this.R));
  5405. var q = asq + g;
  5406. con = Math.PI * this.R * (m * q - al * Math.sqrt((msq + asq) * (asq + 1) - q * q)) / (msq + asq);
  5407. if (lat >= 0) {
  5408. //y = this.y0 + Math.PI * this.R * Math.sqrt(1 - con * con - 2 * al * con);
  5409. y = this.y0 + con;
  5410. }
  5411. else {
  5412. //y = this.y0 - Math.PI * this.R * Math.sqrt(1 - con * con - 2 * al * con);
  5413. y = this.y0 - con;
  5414. }
  5415. p.x = x;
  5416. p.y = y;
  5417. return p;
  5418. }
  5419. /* Van Der Grinten inverse equations--mapping x,y to lat/long
  5420. ---------------------------------------------------------*/
  5421. function inverse$23(p) {
  5422. var lon, lat;
  5423. var xx, yy, xys, c1, c2, c3;
  5424. var a1;
  5425. var m1;
  5426. var con;
  5427. var th1;
  5428. var d;
  5429. /* inverse equations
  5430. -----------------*/
  5431. p.x -= this.x0;
  5432. p.y -= this.y0;
  5433. con = Math.PI * this.R;
  5434. xx = p.x / con;
  5435. yy = p.y / con;
  5436. xys = xx * xx + yy * yy;
  5437. c1 = -Math.abs(yy) * (1 + xys);
  5438. c2 = c1 - 2 * yy * yy + xx * xx;
  5439. c3 = -2 * c1 + 1 + 2 * yy * yy + xys * xys;
  5440. d = yy * yy / c3 + (2 * c2 * c2 * c2 / c3 / c3 / c3 - 9 * c1 * c2 / c3 / c3) / 27;
  5441. a1 = (c1 - c2 * c2 / 3 / c3) / c3;
  5442. m1 = 2 * Math.sqrt(-a1 / 3);
  5443. con = ((3 * d) / a1) / m1;
  5444. if (Math.abs(con) > 1) {
  5445. if (con >= 0) {
  5446. con = 1;
  5447. }
  5448. else {
  5449. con = -1;
  5450. }
  5451. }
  5452. th1 = Math.acos(con) / 3;
  5453. if (p.y >= 0) {
  5454. lat = (-m1 * Math.cos(th1 + Math.PI / 3) - c2 / 3 / c3) * Math.PI;
  5455. }
  5456. else {
  5457. lat = -(-m1 * Math.cos(th1 + Math.PI / 3) - c2 / 3 / c3) * Math.PI;
  5458. }
  5459. if (Math.abs(xx) < EPSLN) {
  5460. lon = this.long0;
  5461. }
  5462. else {
  5463. lon = adjust_lon(this.long0 + Math.PI * (xys - 1 + Math.sqrt(1 + 2 * (xx * xx - yy * yy) + xys * xys)) / 2 / xx);
  5464. }
  5465. p.x = lon;
  5466. p.y = lat;
  5467. return p;
  5468. }
  5469. var names$25 = ["Van_der_Grinten_I", "VanDerGrinten", "vandg"];
  5470. var vandg = {
  5471. init: init$24,
  5472. forward: forward$23,
  5473. inverse: inverse$23,
  5474. names: names$25
  5475. };
  5476. function init$25() {
  5477. this.sin_p12 = Math.sin(this.lat0);
  5478. this.cos_p12 = Math.cos(this.lat0);
  5479. }
  5480. function forward$24(p) {
  5481. var lon = p.x;
  5482. var lat = p.y;
  5483. var sinphi = Math.sin(p.y);
  5484. var cosphi = Math.cos(p.y);
  5485. var dlon = adjust_lon(lon - this.long0);
  5486. var e0, e1, e2, e3, Mlp, Ml, tanphi, Nl1, Nl, psi, Az, G, H, GH, Hs, c, kp, cos_c, s, s2, s3, s4, s5;
  5487. if (this.sphere) {
  5488. if (Math.abs(this.sin_p12 - 1) <= EPSLN) {
  5489. //North Pole case
  5490. p.x = this.x0 + this.a * (HALF_PI - lat) * Math.sin(dlon);
  5491. p.y = this.y0 - this.a * (HALF_PI - lat) * Math.cos(dlon);
  5492. return p;
  5493. }
  5494. else if (Math.abs(this.sin_p12 + 1) <= EPSLN) {
  5495. //South Pole case
  5496. p.x = this.x0 + this.a * (HALF_PI + lat) * Math.sin(dlon);
  5497. p.y = this.y0 + this.a * (HALF_PI + lat) * Math.cos(dlon);
  5498. return p;
  5499. }
  5500. else {
  5501. //default case
  5502. cos_c = this.sin_p12 * sinphi + this.cos_p12 * cosphi * Math.cos(dlon);
  5503. c = Math.acos(cos_c);
  5504. kp = c ? c / Math.sin(c) : 1;
  5505. p.x = this.x0 + this.a * kp * cosphi * Math.sin(dlon);
  5506. p.y = this.y0 + this.a * kp * (this.cos_p12 * sinphi - this.sin_p12 * cosphi * Math.cos(dlon));
  5507. return p;
  5508. }
  5509. }
  5510. else {
  5511. e0 = e0fn(this.es);
  5512. e1 = e1fn(this.es);
  5513. e2 = e2fn(this.es);
  5514. e3 = e3fn(this.es);
  5515. if (Math.abs(this.sin_p12 - 1) <= EPSLN) {
  5516. //North Pole case
  5517. Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI);
  5518. Ml = this.a * mlfn(e0, e1, e2, e3, lat);
  5519. p.x = this.x0 + (Mlp - Ml) * Math.sin(dlon);
  5520. p.y = this.y0 - (Mlp - Ml) * Math.cos(dlon);
  5521. return p;
  5522. }
  5523. else if (Math.abs(this.sin_p12 + 1) <= EPSLN) {
  5524. //South Pole case
  5525. Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI);
  5526. Ml = this.a * mlfn(e0, e1, e2, e3, lat);
  5527. p.x = this.x0 + (Mlp + Ml) * Math.sin(dlon);
  5528. p.y = this.y0 + (Mlp + Ml) * Math.cos(dlon);
  5529. return p;
  5530. }
  5531. else {
  5532. //Default case
  5533. tanphi = sinphi / cosphi;
  5534. Nl1 = gN(this.a, this.e, this.sin_p12);
  5535. Nl = gN(this.a, this.e, sinphi);
  5536. psi = Math.atan((1 - this.es) * tanphi + this.es * Nl1 * this.sin_p12 / (Nl * cosphi));
  5537. Az = Math.atan2(Math.sin(dlon), this.cos_p12 * Math.tan(psi) - this.sin_p12 * Math.cos(dlon));
  5538. if (Az === 0) {
  5539. s = Math.asin(this.cos_p12 * Math.sin(psi) - this.sin_p12 * Math.cos(psi));
  5540. }
  5541. else if (Math.abs(Math.abs(Az) - Math.PI) <= EPSLN) {
  5542. s = -Math.asin(this.cos_p12 * Math.sin(psi) - this.sin_p12 * Math.cos(psi));
  5543. }
  5544. else {
  5545. s = Math.asin(Math.sin(dlon) * Math.cos(psi) / Math.sin(Az));
  5546. }
  5547. G = this.e * this.sin_p12 / Math.sqrt(1 - this.es);
  5548. H = this.e * this.cos_p12 * Math.cos(Az) / Math.sqrt(1 - this.es);
  5549. GH = G * H;
  5550. Hs = H * H;
  5551. s2 = s * s;
  5552. s3 = s2 * s;
  5553. s4 = s3 * s;
  5554. s5 = s4 * s;
  5555. c = Nl1 * s * (1 - s2 * Hs * (1 - Hs) / 6 + s3 / 8 * GH * (1 - 2 * Hs) + s4 / 120 * (Hs * (4 - 7 * Hs) - 3 * G * G * (1 - 7 * Hs)) - s5 / 48 * GH);
  5556. p.x = this.x0 + c * Math.sin(Az);
  5557. p.y = this.y0 + c * Math.cos(Az);
  5558. return p;
  5559. }
  5560. }
  5561. }
  5562. function inverse$24(p) {
  5563. p.x -= this.x0;
  5564. p.y -= this.y0;
  5565. var rh, z, sinz, cosz, lon, lat, con, e0, e1, e2, e3, Mlp, M, N1, psi, Az, cosAz, tmp, A, B, D, Ee, F, sinpsi;
  5566. if (this.sphere) {
  5567. rh = Math.sqrt(p.x * p.x + p.y * p.y);
  5568. if (rh > (2 * HALF_PI * this.a)) {
  5569. return;
  5570. }
  5571. z = rh / this.a;
  5572. sinz = Math.sin(z);
  5573. cosz = Math.cos(z);
  5574. lon = this.long0;
  5575. if (Math.abs(rh) <= EPSLN) {
  5576. lat = this.lat0;
  5577. }
  5578. else {
  5579. lat = asinz(cosz * this.sin_p12 + (p.y * sinz * this.cos_p12) / rh);
  5580. con = Math.abs(this.lat0) - HALF_PI;
  5581. if (Math.abs(con) <= EPSLN) {
  5582. if (this.lat0 >= 0) {
  5583. lon = adjust_lon(this.long0 + Math.atan2(p.x, - p.y));
  5584. }
  5585. else {
  5586. lon = adjust_lon(this.long0 - Math.atan2(-p.x, p.y));
  5587. }
  5588. }
  5589. else {
  5590. /*con = cosz - this.sin_p12 * Math.sin(lat);
  5591. if ((Math.abs(con) < EPSLN) && (Math.abs(p.x) < EPSLN)) {
  5592. //no-op, just keep the lon value as is
  5593. } else {
  5594. var temp = Math.atan2((p.x * sinz * this.cos_p12), (con * rh));
  5595. lon = adjust_lon(this.long0 + Math.atan2((p.x * sinz * this.cos_p12), (con * rh)));
  5596. }*/
  5597. lon = adjust_lon(this.long0 + Math.atan2(p.x * sinz, rh * this.cos_p12 * cosz - p.y * this.sin_p12 * sinz));
  5598. }
  5599. }
  5600. p.x = lon;
  5601. p.y = lat;
  5602. return p;
  5603. }
  5604. else {
  5605. e0 = e0fn(this.es);
  5606. e1 = e1fn(this.es);
  5607. e2 = e2fn(this.es);
  5608. e3 = e3fn(this.es);
  5609. if (Math.abs(this.sin_p12 - 1) <= EPSLN) {
  5610. //North pole case
  5611. Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI);
  5612. rh = Math.sqrt(p.x * p.x + p.y * p.y);
  5613. M = Mlp - rh;
  5614. lat = imlfn(M / this.a, e0, e1, e2, e3);
  5615. lon = adjust_lon(this.long0 + Math.atan2(p.x, - 1 * p.y));
  5616. p.x = lon;
  5617. p.y = lat;
  5618. return p;
  5619. }
  5620. else if (Math.abs(this.sin_p12 + 1) <= EPSLN) {
  5621. //South pole case
  5622. Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI);
  5623. rh = Math.sqrt(p.x * p.x + p.y * p.y);
  5624. M = rh - Mlp;
  5625. lat = imlfn(M / this.a, e0, e1, e2, e3);
  5626. lon = adjust_lon(this.long0 + Math.atan2(p.x, p.y));
  5627. p.x = lon;
  5628. p.y = lat;
  5629. return p;
  5630. }
  5631. else {
  5632. //default case
  5633. rh = Math.sqrt(p.x * p.x + p.y * p.y);
  5634. Az = Math.atan2(p.x, p.y);
  5635. N1 = gN(this.a, this.e, this.sin_p12);
  5636. cosAz = Math.cos(Az);
  5637. tmp = this.e * this.cos_p12 * cosAz;
  5638. A = -tmp * tmp / (1 - this.es);
  5639. B = 3 * this.es * (1 - A) * this.sin_p12 * this.cos_p12 * cosAz / (1 - this.es);
  5640. D = rh / N1;
  5641. Ee = D - A * (1 + A) * Math.pow(D, 3) / 6 - B * (1 + 3 * A) * Math.pow(D, 4) / 24;
  5642. F = 1 - A * Ee * Ee / 2 - D * Ee * Ee * Ee / 6;
  5643. psi = Math.asin(this.sin_p12 * Math.cos(Ee) + this.cos_p12 * Math.sin(Ee) * cosAz);
  5644. lon = adjust_lon(this.long0 + Math.asin(Math.sin(Az) * Math.sin(Ee) / Math.cos(psi)));
  5645. sinpsi = Math.sin(psi);
  5646. lat = Math.atan2((sinpsi - this.es * F * this.sin_p12) * Math.tan(psi), sinpsi * (1 - this.es));
  5647. p.x = lon;
  5648. p.y = lat;
  5649. return p;
  5650. }
  5651. }
  5652. }
  5653. var names$26 = ["Azimuthal_Equidistant", "aeqd"];
  5654. var aeqd = {
  5655. init: init$25,
  5656. forward: forward$24,
  5657. inverse: inverse$24,
  5658. names: names$26
  5659. };
  5660. function init$26() {
  5661. //double temp; /* temporary variable */
  5662. /* Place parameters in static storage for common use
  5663. -------------------------------------------------*/
  5664. this.sin_p14 = Math.sin(this.lat0);
  5665. this.cos_p14 = Math.cos(this.lat0);
  5666. }
  5667. /* Orthographic forward equations--mapping lat,long to x,y
  5668. ---------------------------------------------------*/
  5669. function forward$25(p) {
  5670. var sinphi, cosphi; /* sin and cos value */
  5671. var dlon; /* delta longitude value */
  5672. var coslon; /* cos of longitude */
  5673. var ksp; /* scale factor */
  5674. var g, x, y;
  5675. var lon = p.x;
  5676. var lat = p.y;
  5677. /* Forward equations
  5678. -----------------*/
  5679. dlon = adjust_lon(lon - this.long0);
  5680. sinphi = Math.sin(lat);
  5681. cosphi = Math.cos(lat);
  5682. coslon = Math.cos(dlon);
  5683. g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon;
  5684. ksp = 1;
  5685. if ((g > 0) || (Math.abs(g) <= EPSLN)) {
  5686. x = this.a * ksp * cosphi * Math.sin(dlon);
  5687. y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon);
  5688. }
  5689. p.x = x;
  5690. p.y = y;
  5691. return p;
  5692. }
  5693. function inverse$25(p) {
  5694. var rh; /* height above ellipsoid */
  5695. var z; /* angle */
  5696. var sinz, cosz; /* sin of z and cos of z */
  5697. var con;
  5698. var lon, lat;
  5699. /* Inverse equations
  5700. -----------------*/
  5701. p.x -= this.x0;
  5702. p.y -= this.y0;
  5703. rh = Math.sqrt(p.x * p.x + p.y * p.y);
  5704. z = asinz(rh / this.a);
  5705. sinz = Math.sin(z);
  5706. cosz = Math.cos(z);
  5707. lon = this.long0;
  5708. if (Math.abs(rh) <= EPSLN) {
  5709. lat = this.lat0;
  5710. p.x = lon;
  5711. p.y = lat;
  5712. return p;
  5713. }
  5714. lat = asinz(cosz * this.sin_p14 + (p.y * sinz * this.cos_p14) / rh);
  5715. con = Math.abs(this.lat0) - HALF_PI;
  5716. if (Math.abs(con) <= EPSLN) {
  5717. if (this.lat0 >= 0) {
  5718. lon = adjust_lon(this.long0 + Math.atan2(p.x, - p.y));
  5719. }
  5720. else {
  5721. lon = adjust_lon(this.long0 - Math.atan2(-p.x, p.y));
  5722. }
  5723. p.x = lon;
  5724. p.y = lat;
  5725. return p;
  5726. }
  5727. lon = adjust_lon(this.long0 + Math.atan2((p.x * sinz), rh * this.cos_p14 * cosz - p.y * this.sin_p14 * sinz));
  5728. p.x = lon;
  5729. p.y = lat;
  5730. return p;
  5731. }
  5732. var names$27 = ["ortho"];
  5733. var ortho = {
  5734. init: init$26,
  5735. forward: forward$25,
  5736. inverse: inverse$25,
  5737. names: names$27
  5738. };
  5739. // QSC projection rewritten from the original PROJ4
  5740. // https://github.com/OSGeo/proj.4/blob/master/src/PJ_qsc.c
  5741. /* constants */
  5742. var FACE_ENUM = {
  5743. FRONT: 1,
  5744. RIGHT: 2,
  5745. BACK: 3,
  5746. LEFT: 4,
  5747. TOP: 5,
  5748. BOTTOM: 6
  5749. };
  5750. var AREA_ENUM = {
  5751. AREA_0: 1,
  5752. AREA_1: 2,
  5753. AREA_2: 3,
  5754. AREA_3: 4
  5755. };
  5756. function init$27() {
  5757. this.x0 = this.x0 || 0;
  5758. this.y0 = this.y0 || 0;
  5759. this.lat0 = this.lat0 || 0;
  5760. this.long0 = this.long0 || 0;
  5761. this.lat_ts = this.lat_ts || 0;
  5762. this.title = this.title || "Quadrilateralized Spherical Cube";
  5763. /* Determine the cube face from the center of projection. */
  5764. if (this.lat0 >= HALF_PI - FORTPI / 2.0) {
  5765. this.face = FACE_ENUM.TOP;
  5766. } else if (this.lat0 <= -(HALF_PI - FORTPI / 2.0)) {
  5767. this.face = FACE_ENUM.BOTTOM;
  5768. } else if (Math.abs(this.long0) <= FORTPI) {
  5769. this.face = FACE_ENUM.FRONT;
  5770. } else if (Math.abs(this.long0) <= HALF_PI + FORTPI) {
  5771. this.face = this.long0 > 0.0 ? FACE_ENUM.RIGHT : FACE_ENUM.LEFT;
  5772. } else {
  5773. this.face = FACE_ENUM.BACK;
  5774. }
  5775. /* Fill in useful values for the ellipsoid <-> sphere shift
  5776. * described in [LK12]. */
  5777. if (this.es !== 0) {
  5778. this.one_minus_f = 1 - (this.a - this.b) / this.a;
  5779. this.one_minus_f_squared = this.one_minus_f * this.one_minus_f;
  5780. }
  5781. }
  5782. // QSC forward equations--mapping lat,long to x,y
  5783. // -----------------------------------------------------------------
  5784. function forward$26(p) {
  5785. var xy = {x: 0, y: 0};
  5786. var lat, lon;
  5787. var theta, phi;
  5788. var t, mu;
  5789. /* nu; */
  5790. var area = {value: 0};
  5791. // move lon according to projection's lon
  5792. p.x -= this.long0;
  5793. /* Convert the geodetic latitude to a geocentric latitude.
  5794. * This corresponds to the shift from the ellipsoid to the sphere
  5795. * described in [LK12]. */
  5796. if (this.es !== 0) {//if (P->es != 0) {
  5797. lat = Math.atan(this.one_minus_f_squared * Math.tan(p.y));
  5798. } else {
  5799. lat = p.y;
  5800. }
  5801. /* Convert the input lat, lon into theta, phi as used by QSC.
  5802. * This depends on the cube face and the area on it.
  5803. * For the top and bottom face, we can compute theta and phi
  5804. * directly from phi, lam. For the other faces, we must use
  5805. * unit sphere cartesian coordinates as an intermediate step. */
  5806. lon = p.x; //lon = lp.lam;
  5807. if (this.face === FACE_ENUM.TOP) {
  5808. phi = HALF_PI - lat;
  5809. if (lon >= FORTPI && lon <= HALF_PI + FORTPI) {
  5810. area.value = AREA_ENUM.AREA_0;
  5811. theta = lon - HALF_PI;
  5812. } else if (lon > HALF_PI + FORTPI || lon <= -(HALF_PI + FORTPI)) {
  5813. area.value = AREA_ENUM.AREA_1;
  5814. theta = (lon > 0.0 ? lon - SPI : lon + SPI);
  5815. } else if (lon > -(HALF_PI + FORTPI) && lon <= -FORTPI) {
  5816. area.value = AREA_ENUM.AREA_2;
  5817. theta = lon + HALF_PI;
  5818. } else {
  5819. area.value = AREA_ENUM.AREA_3;
  5820. theta = lon;
  5821. }
  5822. } else if (this.face === FACE_ENUM.BOTTOM) {
  5823. phi = HALF_PI + lat;
  5824. if (lon >= FORTPI && lon <= HALF_PI + FORTPI) {
  5825. area.value = AREA_ENUM.AREA_0;
  5826. theta = -lon + HALF_PI;
  5827. } else if (lon < FORTPI && lon >= -FORTPI) {
  5828. area.value = AREA_ENUM.AREA_1;
  5829. theta = -lon;
  5830. } else if (lon < -FORTPI && lon >= -(HALF_PI + FORTPI)) {
  5831. area.value = AREA_ENUM.AREA_2;
  5832. theta = -lon - HALF_PI;
  5833. } else {
  5834. area.value = AREA_ENUM.AREA_3;
  5835. theta = (lon > 0.0 ? -lon + SPI : -lon - SPI);
  5836. }
  5837. } else {
  5838. var q, r, s;
  5839. var sinlat, coslat;
  5840. var sinlon, coslon;
  5841. if (this.face === FACE_ENUM.RIGHT) {
  5842. lon = qsc_shift_lon_origin(lon, +HALF_PI);
  5843. } else if (this.face === FACE_ENUM.BACK) {
  5844. lon = qsc_shift_lon_origin(lon, +SPI);
  5845. } else if (this.face === FACE_ENUM.LEFT) {
  5846. lon = qsc_shift_lon_origin(lon, -HALF_PI);
  5847. }
  5848. sinlat = Math.sin(lat);
  5849. coslat = Math.cos(lat);
  5850. sinlon = Math.sin(lon);
  5851. coslon = Math.cos(lon);
  5852. q = coslat * coslon;
  5853. r = coslat * sinlon;
  5854. s = sinlat;
  5855. if (this.face === FACE_ENUM.FRONT) {
  5856. phi = Math.acos(q);
  5857. theta = qsc_fwd_equat_face_theta(phi, s, r, area);
  5858. } else if (this.face === FACE_ENUM.RIGHT) {
  5859. phi = Math.acos(r);
  5860. theta = qsc_fwd_equat_face_theta(phi, s, -q, area);
  5861. } else if (this.face === FACE_ENUM.BACK) {
  5862. phi = Math.acos(-q);
  5863. theta = qsc_fwd_equat_face_theta(phi, s, -r, area);
  5864. } else if (this.face === FACE_ENUM.LEFT) {
  5865. phi = Math.acos(-r);
  5866. theta = qsc_fwd_equat_face_theta(phi, s, q, area);
  5867. } else {
  5868. /* Impossible */
  5869. phi = theta = 0;
  5870. area.value = AREA_ENUM.AREA_0;
  5871. }
  5872. }
  5873. /* Compute mu and nu for the area of definition.
  5874. * For mu, see Eq. (3-21) in [OL76], but note the typos:
  5875. * compare with Eq. (3-14). For nu, see Eq. (3-38). */
  5876. mu = Math.atan((12 / SPI) * (theta + Math.acos(Math.sin(theta) * Math.cos(FORTPI)) - HALF_PI));
  5877. t = Math.sqrt((1 - Math.cos(phi)) / (Math.cos(mu) * Math.cos(mu)) / (1 - Math.cos(Math.atan(1 / Math.cos(theta)))));
  5878. /* Apply the result to the real area. */
  5879. if (area.value === AREA_ENUM.AREA_1) {
  5880. mu += HALF_PI;
  5881. } else if (area.value === AREA_ENUM.AREA_2) {
  5882. mu += SPI;
  5883. } else if (area.value === AREA_ENUM.AREA_3) {
  5884. mu += 1.5 * SPI;
  5885. }
  5886. /* Now compute x, y from mu and nu */
  5887. xy.x = t * Math.cos(mu);
  5888. xy.y = t * Math.sin(mu);
  5889. xy.x = xy.x * this.a + this.x0;
  5890. xy.y = xy.y * this.a + this.y0;
  5891. p.x = xy.x;
  5892. p.y = xy.y;
  5893. return p;
  5894. }
  5895. // QSC inverse equations--mapping x,y to lat/long
  5896. // -----------------------------------------------------------------
  5897. function inverse$26(p) {
  5898. var lp = {lam: 0, phi: 0};
  5899. var mu, nu, cosmu, tannu;
  5900. var tantheta, theta, cosphi, phi;
  5901. var t;
  5902. var area = {value: 0};
  5903. /* de-offset */
  5904. p.x = (p.x - this.x0) / this.a;
  5905. p.y = (p.y - this.y0) / this.a;
  5906. /* Convert the input x, y to the mu and nu angles as used by QSC.
  5907. * This depends on the area of the cube face. */
  5908. nu = Math.atan(Math.sqrt(p.x * p.x + p.y * p.y));
  5909. mu = Math.atan2(p.y, p.x);
  5910. if (p.x >= 0.0 && p.x >= Math.abs(p.y)) {
  5911. area.value = AREA_ENUM.AREA_0;
  5912. } else if (p.y >= 0.0 && p.y >= Math.abs(p.x)) {
  5913. area.value = AREA_ENUM.AREA_1;
  5914. mu -= HALF_PI;
  5915. } else if (p.x < 0.0 && -p.x >= Math.abs(p.y)) {
  5916. area.value = AREA_ENUM.AREA_2;
  5917. mu = (mu < 0.0 ? mu + SPI : mu - SPI);
  5918. } else {
  5919. area.value = AREA_ENUM.AREA_3;
  5920. mu += HALF_PI;
  5921. }
  5922. /* Compute phi and theta for the area of definition.
  5923. * The inverse projection is not described in the original paper, but some
  5924. * good hints can be found here (as of 2011-12-14):
  5925. * http://fits.gsfc.nasa.gov/fitsbits/saf.93/saf.9302
  5926. * (search for "Message-Id: <9302181759.AA25477 at fits.cv.nrao.edu>") */
  5927. t = (SPI / 12) * Math.tan(mu);
  5928. tantheta = Math.sin(t) / (Math.cos(t) - (1 / Math.sqrt(2)));
  5929. theta = Math.atan(tantheta);
  5930. cosmu = Math.cos(mu);
  5931. tannu = Math.tan(nu);
  5932. cosphi = 1 - cosmu * cosmu * tannu * tannu * (1 - Math.cos(Math.atan(1 / Math.cos(theta))));
  5933. if (cosphi < -1) {
  5934. cosphi = -1;
  5935. } else if (cosphi > +1) {
  5936. cosphi = +1;
  5937. }
  5938. /* Apply the result to the real area on the cube face.
  5939. * For the top and bottom face, we can compute phi and lam directly.
  5940. * For the other faces, we must use unit sphere cartesian coordinates
  5941. * as an intermediate step. */
  5942. if (this.face === FACE_ENUM.TOP) {
  5943. phi = Math.acos(cosphi);
  5944. lp.phi = HALF_PI - phi;
  5945. if (area.value === AREA_ENUM.AREA_0) {
  5946. lp.lam = theta + HALF_PI;
  5947. } else if (area.value === AREA_ENUM.AREA_1) {
  5948. lp.lam = (theta < 0.0 ? theta + SPI : theta - SPI);
  5949. } else if (area.value === AREA_ENUM.AREA_2) {
  5950. lp.lam = theta - HALF_PI;
  5951. } else /* area.value == AREA_ENUM.AREA_3 */ {
  5952. lp.lam = theta;
  5953. }
  5954. } else if (this.face === FACE_ENUM.BOTTOM) {
  5955. phi = Math.acos(cosphi);
  5956. lp.phi = phi - HALF_PI;
  5957. if (area.value === AREA_ENUM.AREA_0) {
  5958. lp.lam = -theta + HALF_PI;
  5959. } else if (area.value === AREA_ENUM.AREA_1) {
  5960. lp.lam = -theta;
  5961. } else if (area.value === AREA_ENUM.AREA_2) {
  5962. lp.lam = -theta - HALF_PI;
  5963. } else /* area.value == AREA_ENUM.AREA_3 */ {
  5964. lp.lam = (theta < 0.0 ? -theta - SPI : -theta + SPI);
  5965. }
  5966. } else {
  5967. /* Compute phi and lam via cartesian unit sphere coordinates. */
  5968. var q, r, s;
  5969. q = cosphi;
  5970. t = q * q;
  5971. if (t >= 1) {
  5972. s = 0;
  5973. } else {
  5974. s = Math.sqrt(1 - t) * Math.sin(theta);
  5975. }
  5976. t += s * s;
  5977. if (t >= 1) {
  5978. r = 0;
  5979. } else {
  5980. r = Math.sqrt(1 - t);
  5981. }
  5982. /* Rotate q,r,s into the correct area. */
  5983. if (area.value === AREA_ENUM.AREA_1) {
  5984. t = r;
  5985. r = -s;
  5986. s = t;
  5987. } else if (area.value === AREA_ENUM.AREA_2) {
  5988. r = -r;
  5989. s = -s;
  5990. } else if (area.value === AREA_ENUM.AREA_3) {
  5991. t = r;
  5992. r = s;
  5993. s = -t;
  5994. }
  5995. /* Rotate q,r,s into the correct cube face. */
  5996. if (this.face === FACE_ENUM.RIGHT) {
  5997. t = q;
  5998. q = -r;
  5999. r = t;
  6000. } else if (this.face === FACE_ENUM.BACK) {
  6001. q = -q;
  6002. r = -r;
  6003. } else if (this.face === FACE_ENUM.LEFT) {
  6004. t = q;
  6005. q = r;
  6006. r = -t;
  6007. }
  6008. /* Now compute phi and lam from the unit sphere coordinates. */
  6009. lp.phi = Math.acos(-s) - HALF_PI;
  6010. lp.lam = Math.atan2(r, q);
  6011. if (this.face === FACE_ENUM.RIGHT) {
  6012. lp.lam = qsc_shift_lon_origin(lp.lam, -HALF_PI);
  6013. } else if (this.face === FACE_ENUM.BACK) {
  6014. lp.lam = qsc_shift_lon_origin(lp.lam, -SPI);
  6015. } else if (this.face === FACE_ENUM.LEFT) {
  6016. lp.lam = qsc_shift_lon_origin(lp.lam, +HALF_PI);
  6017. }
  6018. }
  6019. /* Apply the shift from the sphere to the ellipsoid as described
  6020. * in [LK12]. */
  6021. if (this.es !== 0) {
  6022. var invert_sign;
  6023. var tanphi, xa;
  6024. invert_sign = (lp.phi < 0 ? 1 : 0);
  6025. tanphi = Math.tan(lp.phi);
  6026. xa = this.b / Math.sqrt(tanphi * tanphi + this.one_minus_f_squared);
  6027. lp.phi = Math.atan(Math.sqrt(this.a * this.a - xa * xa) / (this.one_minus_f * xa));
  6028. if (invert_sign) {
  6029. lp.phi = -lp.phi;
  6030. }
  6031. }
  6032. lp.lam += this.long0;
  6033. p.x = lp.lam;
  6034. p.y = lp.phi;
  6035. return p;
  6036. }
  6037. /* Helper function for forward projection: compute the theta angle
  6038. * and determine the area number. */
  6039. function qsc_fwd_equat_face_theta(phi, y, x, area) {
  6040. var theta;
  6041. if (phi < EPSLN) {
  6042. area.value = AREA_ENUM.AREA_0;
  6043. theta = 0.0;
  6044. } else {
  6045. theta = Math.atan2(y, x);
  6046. if (Math.abs(theta) <= FORTPI) {
  6047. area.value = AREA_ENUM.AREA_0;
  6048. } else if (theta > FORTPI && theta <= HALF_PI + FORTPI) {
  6049. area.value = AREA_ENUM.AREA_1;
  6050. theta -= HALF_PI;
  6051. } else if (theta > HALF_PI + FORTPI || theta <= -(HALF_PI + FORTPI)) {
  6052. area.value = AREA_ENUM.AREA_2;
  6053. theta = (theta >= 0.0 ? theta - SPI : theta + SPI);
  6054. } else {
  6055. area.value = AREA_ENUM.AREA_3;
  6056. theta += HALF_PI;
  6057. }
  6058. }
  6059. return theta;
  6060. }
  6061. /* Helper function: shift the longitude. */
  6062. function qsc_shift_lon_origin(lon, offset) {
  6063. var slon = lon + offset;
  6064. if (slon < -SPI) {
  6065. slon += TWO_PI;
  6066. } else if (slon > +SPI) {
  6067. slon -= TWO_PI;
  6068. }
  6069. return slon;
  6070. }
  6071. var names$28 = ["Quadrilateralized Spherical Cube", "Quadrilateralized_Spherical_Cube", "qsc"];
  6072. var qsc = {
  6073. init: init$27,
  6074. forward: forward$26,
  6075. inverse: inverse$26,
  6076. names: names$28
  6077. };
  6078. // Robinson projection
  6079. // Based on https://github.com/OSGeo/proj.4/blob/master/src/PJ_robin.c
  6080. // Polynomial coeficients from http://article.gmane.org/gmane.comp.gis.proj-4.devel/6039
  6081. var COEFS_X = [
  6082. [1.0000, 2.2199e-17, -7.15515e-05, 3.1103e-06],
  6083. [0.9986, -0.000482243, -2.4897e-05, -1.3309e-06],
  6084. [0.9954, -0.00083103, -4.48605e-05, -9.86701e-07],
  6085. [0.9900, -0.00135364, -5.9661e-05, 3.6777e-06],
  6086. [0.9822, -0.00167442, -4.49547e-06, -5.72411e-06],
  6087. [0.9730, -0.00214868, -9.03571e-05, 1.8736e-08],
  6088. [0.9600, -0.00305085, -9.00761e-05, 1.64917e-06],
  6089. [0.9427, -0.00382792, -6.53386e-05, -2.6154e-06],
  6090. [0.9216, -0.00467746, -0.00010457, 4.81243e-06],
  6091. [0.8962, -0.00536223, -3.23831e-05, -5.43432e-06],
  6092. [0.8679, -0.00609363, -0.000113898, 3.32484e-06],
  6093. [0.8350, -0.00698325, -6.40253e-05, 9.34959e-07],
  6094. [0.7986, -0.00755338, -5.00009e-05, 9.35324e-07],
  6095. [0.7597, -0.00798324, -3.5971e-05, -2.27626e-06],
  6096. [0.7186, -0.00851367, -7.01149e-05, -8.6303e-06],
  6097. [0.6732, -0.00986209, -0.000199569, 1.91974e-05],
  6098. [0.6213, -0.010418, 8.83923e-05, 6.24051e-06],
  6099. [0.5722, -0.00906601, 0.000182, 6.24051e-06],
  6100. [0.5322, -0.00677797, 0.000275608, 6.24051e-06]
  6101. ];
  6102. var COEFS_Y = [
  6103. [-5.20417e-18, 0.0124, 1.21431e-18, -8.45284e-11],
  6104. [0.0620, 0.0124, -1.26793e-09, 4.22642e-10],
  6105. [0.1240, 0.0124, 5.07171e-09, -1.60604e-09],
  6106. [0.1860, 0.0123999, -1.90189e-08, 6.00152e-09],
  6107. [0.2480, 0.0124002, 7.10039e-08, -2.24e-08],
  6108. [0.3100, 0.0123992, -2.64997e-07, 8.35986e-08],
  6109. [0.3720, 0.0124029, 9.88983e-07, -3.11994e-07],
  6110. [0.4340, 0.0123893, -3.69093e-06, -4.35621e-07],
  6111. [0.4958, 0.0123198, -1.02252e-05, -3.45523e-07],
  6112. [0.5571, 0.0121916, -1.54081e-05, -5.82288e-07],
  6113. [0.6176, 0.0119938, -2.41424e-05, -5.25327e-07],
  6114. [0.6769, 0.011713, -3.20223e-05, -5.16405e-07],
  6115. [0.7346, 0.0113541, -3.97684e-05, -6.09052e-07],
  6116. [0.7903, 0.0109107, -4.89042e-05, -1.04739e-06],
  6117. [0.8435, 0.0103431, -6.4615e-05, -1.40374e-09],
  6118. [0.8936, 0.00969686, -6.4636e-05, -8.547e-06],
  6119. [0.9394, 0.00840947, -0.000192841, -4.2106e-06],
  6120. [0.9761, 0.00616527, -0.000256, -4.2106e-06],
  6121. [1.0000, 0.00328947, -0.000319159, -4.2106e-06]
  6122. ];
  6123. var FXC = 0.8487;
  6124. var FYC = 1.3523;
  6125. var C1 = R2D/5; // rad to 5-degree interval
  6126. var RC1 = 1/C1;
  6127. var NODES = 18;
  6128. var poly3_val = function(coefs, x) {
  6129. return coefs[0] + x * (coefs[1] + x * (coefs[2] + x * coefs[3]));
  6130. };
  6131. var poly3_der = function(coefs, x) {
  6132. return coefs[1] + x * (2 * coefs[2] + x * 3 * coefs[3]);
  6133. };
  6134. function newton_rapshon(f_df, start, max_err, iters) {
  6135. var x = start;
  6136. for (; iters; --iters) {
  6137. var upd = f_df(x);
  6138. x -= upd;
  6139. if (Math.abs(upd) < max_err) {
  6140. break;
  6141. }
  6142. }
  6143. return x;
  6144. }
  6145. function init$28() {
  6146. this.x0 = this.x0 || 0;
  6147. this.y0 = this.y0 || 0;
  6148. this.long0 = this.long0 || 0;
  6149. this.es = 0;
  6150. this.title = this.title || "Robinson";
  6151. }
  6152. function forward$27(ll) {
  6153. var lon = adjust_lon(ll.x - this.long0);
  6154. var dphi = Math.abs(ll.y);
  6155. var i = Math.floor(dphi * C1);
  6156. if (i < 0) {
  6157. i = 0;
  6158. } else if (i >= NODES) {
  6159. i = NODES - 1;
  6160. }
  6161. dphi = R2D * (dphi - RC1 * i);
  6162. var xy = {
  6163. x: poly3_val(COEFS_X[i], dphi) * lon,
  6164. y: poly3_val(COEFS_Y[i], dphi)
  6165. };
  6166. if (ll.y < 0) {
  6167. xy.y = -xy.y;
  6168. }
  6169. xy.x = xy.x * this.a * FXC + this.x0;
  6170. xy.y = xy.y * this.a * FYC + this.y0;
  6171. return xy;
  6172. }
  6173. function inverse$27(xy) {
  6174. var ll = {
  6175. x: (xy.x - this.x0) / (this.a * FXC),
  6176. y: Math.abs(xy.y - this.y0) / (this.a * FYC)
  6177. };
  6178. if (ll.y >= 1) { // pathologic case
  6179. ll.x /= COEFS_X[NODES][0];
  6180. ll.y = xy.y < 0 ? -HALF_PI : HALF_PI;
  6181. } else {
  6182. // find table interval
  6183. var i = Math.floor(ll.y * NODES);
  6184. if (i < 0) {
  6185. i = 0;
  6186. } else if (i >= NODES) {
  6187. i = NODES - 1;
  6188. }
  6189. for (;;) {
  6190. if (COEFS_Y[i][0] > ll.y) {
  6191. --i;
  6192. } else if (COEFS_Y[i+1][0] <= ll.y) {
  6193. ++i;
  6194. } else {
  6195. break;
  6196. }
  6197. }
  6198. // linear interpolation in 5 degree interval
  6199. var coefs = COEFS_Y[i];
  6200. var t = 5 * (ll.y - coefs[0]) / (COEFS_Y[i+1][0] - coefs[0]);
  6201. // find t so that poly3_val(coefs, t) = ll.y
  6202. t = newton_rapshon(function(x) {
  6203. return (poly3_val(coefs, x) - ll.y) / poly3_der(coefs, x);
  6204. }, t, EPSLN, 100);
  6205. ll.x /= poly3_val(COEFS_X[i], t);
  6206. ll.y = (5 * i + t) * D2R;
  6207. if (xy.y < 0) {
  6208. ll.y = -ll.y;
  6209. }
  6210. }
  6211. ll.x = adjust_lon(ll.x + this.long0);
  6212. return ll;
  6213. }
  6214. var names$29 = ["Robinson", "robin"];
  6215. var robin = {
  6216. init: init$28,
  6217. forward: forward$27,
  6218. inverse: inverse$27,
  6219. names: names$29
  6220. };
  6221. function init$29() {
  6222. this.name = 'geocent';
  6223. }
  6224. function forward$28(p) {
  6225. var point = geodeticToGeocentric(p, this.es, this.a);
  6226. return point;
  6227. }
  6228. function inverse$28(p) {
  6229. var point = geocentricToGeodetic(p, this.es, this.a, this.b);
  6230. return point;
  6231. }
  6232. var names$30 = ["Geocentric", 'geocentric', "geocent", "Geocent"];
  6233. var geocent = {
  6234. init: init$29,
  6235. forward: forward$28,
  6236. inverse: inverse$28,
  6237. names: names$30
  6238. };
  6239. var mode = {
  6240. N_POLE: 0,
  6241. S_POLE: 1,
  6242. EQUIT: 2,
  6243. OBLIQ: 3
  6244. };
  6245. var params = {
  6246. h: { def: 100000, num: true }, // default is Karman line, no default in PROJ.7
  6247. azi: { def: 0, num: true, degrees: true }, // default is North
  6248. tilt: { def: 0, num: true, degrees: true }, // default is Nadir
  6249. long0: { def: 0, num: true }, // default is Greenwich, conversion to rad is automatic
  6250. lat0: { def: 0, num: true } // default is Equator, conversion to rad is automatic
  6251. };
  6252. function init$30() {
  6253. Object.keys(params).forEach(function (p) {
  6254. if (typeof this[p] === "undefined") {
  6255. this[p] = params[p].def;
  6256. } else if (params[p].num && isNaN(this[p])) {
  6257. throw new Error("Invalid parameter value, must be numeric " + p + " = " + this[p]);
  6258. } else if (params[p].num) {
  6259. this[p] = parseFloat(this[p]);
  6260. }
  6261. if (params[p].degrees) {
  6262. this[p] = this[p] * D2R;
  6263. }
  6264. }.bind(this));
  6265. if (Math.abs((Math.abs(this.lat0) - HALF_PI)) < EPSLN) {
  6266. this.mode = this.lat0 < 0 ? mode.S_POLE : mode.N_POLE;
  6267. } else if (Math.abs(this.lat0) < EPSLN) {
  6268. this.mode = mode.EQUIT;
  6269. } else {
  6270. this.mode = mode.OBLIQ;
  6271. this.sinph0 = Math.sin(this.lat0);
  6272. this.cosph0 = Math.cos(this.lat0);
  6273. }
  6274. this.pn1 = this.h / this.a; // Normalize relative to the Earth's radius
  6275. if (this.pn1 <= 0 || this.pn1 > 1e10) {
  6276. throw new Error("Invalid height");
  6277. }
  6278. this.p = 1 + this.pn1;
  6279. this.rp = 1 / this.p;
  6280. this.h1 = 1 / this.pn1;
  6281. this.pfact = (this.p + 1) * this.h1;
  6282. this.es = 0;
  6283. var omega = this.tilt;
  6284. var gamma = this.azi;
  6285. this.cg = Math.cos(gamma);
  6286. this.sg = Math.sin(gamma);
  6287. this.cw = Math.cos(omega);
  6288. this.sw = Math.sin(omega);
  6289. }
  6290. function forward$29(p) {
  6291. p.x -= this.long0;
  6292. var sinphi = Math.sin(p.y);
  6293. var cosphi = Math.cos(p.y);
  6294. var coslam = Math.cos(p.x);
  6295. var x, y;
  6296. switch (this.mode) {
  6297. case mode.OBLIQ:
  6298. y = this.sinph0 * sinphi + this.cosph0 * cosphi * coslam;
  6299. break;
  6300. case mode.EQUIT:
  6301. y = cosphi * coslam;
  6302. break;
  6303. case mode.S_POLE:
  6304. y = -sinphi;
  6305. break;
  6306. case mode.N_POLE:
  6307. y = sinphi;
  6308. break;
  6309. }
  6310. y = this.pn1 / (this.p - y);
  6311. x = y * cosphi * Math.sin(p.x);
  6312. switch (this.mode) {
  6313. case mode.OBLIQ:
  6314. y *= this.cosph0 * sinphi - this.sinph0 * cosphi * coslam;
  6315. break;
  6316. case mode.EQUIT:
  6317. y *= sinphi;
  6318. break;
  6319. case mode.N_POLE:
  6320. y *= -(cosphi * coslam);
  6321. break;
  6322. case mode.S_POLE:
  6323. y *= cosphi * coslam;
  6324. break;
  6325. }
  6326. // Tilt
  6327. var yt, ba;
  6328. yt = y * this.cg + x * this.sg;
  6329. ba = 1 / (yt * this.sw * this.h1 + this.cw);
  6330. x = (x * this.cg - y * this.sg) * this.cw * ba;
  6331. y = yt * ba;
  6332. p.x = x * this.a;
  6333. p.y = y * this.a;
  6334. return p;
  6335. }
  6336. function inverse$29(p) {
  6337. p.x /= this.a;
  6338. p.y /= this.a;
  6339. var r = { x: p.x, y: p.y };
  6340. // Un-Tilt
  6341. var bm, bq, yt;
  6342. yt = 1 / (this.pn1 - p.y * this.sw);
  6343. bm = this.pn1 * p.x * yt;
  6344. bq = this.pn1 * p.y * this.cw * yt;
  6345. p.x = bm * this.cg + bq * this.sg;
  6346. p.y = bq * this.cg - bm * this.sg;
  6347. var rh = hypot(p.x, p.y);
  6348. if (Math.abs(rh) < EPSLN) {
  6349. r.x = 0;
  6350. r.y = p.y;
  6351. } else {
  6352. var cosz, sinz;
  6353. sinz = 1 - rh * rh * this.pfact;
  6354. sinz = (this.p - Math.sqrt(sinz)) / (this.pn1 / rh + rh / this.pn1);
  6355. cosz = Math.sqrt(1 - sinz * sinz);
  6356. switch (this.mode) {
  6357. case mode.OBLIQ:
  6358. r.y = Math.asin(cosz * this.sinph0 + p.y * sinz * this.cosph0 / rh);
  6359. p.y = (cosz - this.sinph0 * Math.sin(r.y)) * rh;
  6360. p.x *= sinz * this.cosph0;
  6361. break;
  6362. case mode.EQUIT:
  6363. r.y = Math.asin(p.y * sinz / rh);
  6364. p.y = cosz * rh;
  6365. p.x *= sinz;
  6366. break;
  6367. case mode.N_POLE:
  6368. r.y = Math.asin(cosz);
  6369. p.y = -p.y;
  6370. break;
  6371. case mode.S_POLE:
  6372. r.y = -Math.asin(cosz);
  6373. break;
  6374. }
  6375. r.x = Math.atan2(p.x, p.y);
  6376. }
  6377. p.x = r.x + this.long0;
  6378. p.y = r.y;
  6379. return p;
  6380. }
  6381. var names$31 = ["Tilted_Perspective", "tpers"];
  6382. var tpers = {
  6383. init: init$30,
  6384. forward: forward$29,
  6385. inverse: inverse$29,
  6386. names: names$31
  6387. };
  6388. var includedProjections = function(proj4){
  6389. proj4.Proj.projections.add(tmerc);
  6390. proj4.Proj.projections.add(etmerc);
  6391. proj4.Proj.projections.add(utm);
  6392. proj4.Proj.projections.add(sterea);
  6393. proj4.Proj.projections.add(stere);
  6394. proj4.Proj.projections.add(somerc);
  6395. proj4.Proj.projections.add(omerc);
  6396. proj4.Proj.projections.add(lcc);
  6397. proj4.Proj.projections.add(krovak);
  6398. proj4.Proj.projections.add(cass);
  6399. proj4.Proj.projections.add(laea);
  6400. proj4.Proj.projections.add(aea);
  6401. proj4.Proj.projections.add(gnom);
  6402. proj4.Proj.projections.add(cea);
  6403. proj4.Proj.projections.add(eqc);
  6404. proj4.Proj.projections.add(poly);
  6405. proj4.Proj.projections.add(nzmg);
  6406. proj4.Proj.projections.add(mill);
  6407. proj4.Proj.projections.add(sinu);
  6408. proj4.Proj.projections.add(moll);
  6409. proj4.Proj.projections.add(eqdc);
  6410. proj4.Proj.projections.add(vandg);
  6411. proj4.Proj.projections.add(aeqd);
  6412. proj4.Proj.projections.add(ortho);
  6413. proj4.Proj.projections.add(qsc);
  6414. proj4.Proj.projections.add(robin);
  6415. proj4.Proj.projections.add(geocent);
  6416. proj4.Proj.projections.add(tpers);
  6417. };
  6418. proj4$1.defaultDatum = 'WGS84'; //default datum
  6419. proj4$1.Proj = Projection;
  6420. proj4$1.WGS84 = new proj4$1.Proj('WGS84');
  6421. proj4$1.Point = Point;
  6422. proj4$1.toPoint = toPoint;
  6423. proj4$1.defs = defs;
  6424. proj4$1.nadgrid = nadgrid;
  6425. proj4$1.transform = transform;
  6426. proj4$1.mgrs = mgrs;
  6427. proj4$1.version = '2.7.5';
  6428. includedProjections(proj4$1);
  6429. return proj4$1;
  6430. })));