1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440 |
- /*
- proj4js.js -- Javascript reprojection library.
-
- Authors: Mike Adair madairATdmsolutions.ca
- Richard Greenwood richATgreenwoodmap.com
- Didier Richard didier.richardATign.fr
- Stephen Irons stephen.ironsATclear.net.nz
- Olivier Terral oterralATgmail.com
-
- License:
- Copyright (c) 2012, Mike Adair, Richard Greenwood, Didier Richard,
- Stephen Irons and Olivier Terral
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the "Software"),
- to deal in the Software without restriction, including without limitation
- the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- DEALINGS IN THE SOFTWARE.
-
- Note: This program is an almost direct port of the C library PROJ.4.
- */
- /* ======================================================================
- proj4js.js
- ====================================================================== */
- /*
- Author: Mike Adair madairATdmsolutions.ca
- Richard Greenwood rich@greenwoodmap.com
- License: LGPL as per: http://www.gnu.org/copyleft/lesser.html
- $Id: Proj.js 2956 2007-07-09 12:17:52Z steven $
- */
- /**
- * Namespace: Proj4js
- *
- * Proj4js is a JavaScript library to transform point coordinates from one
- * coordinate system to another, including datum transformations.
- *
- * This library is a port of both the Proj.4 and GCTCP C libraries to JavaScript.
- * Enabling these transformations in the browser allows geographic data stored
- * in different projections to be combined in browser-based web mapping
- * applications.
- *
- * Proj4js must have access to coordinate system initialization strings (which
- * are the same as for PROJ.4 command line). Thes can be included in your
- * application using a <script> tag or Proj4js can load CS initialization
- * strings from a local directory or a web service such as spatialreference.org.
- *
- * Similarly, Proj4js must have access to projection transform code. These can
- * be included individually using a <script> tag in your page, built into a
- * custom build of Proj4js or loaded dynamically at run-time. Using the
- * -combined and -compressed versions of Proj4js includes all projection class
- * code by default.
- *
- * Note that dynamic loading of defs and code happens ascynchrously, check the
- * Proj.readyToUse flag before using the Proj object. If the defs and code
- * required by your application are loaded through script tags, dynamic loading
- * is not required and the Proj object will be readyToUse on return from the
- * constructor.
- *
- * All coordinates are handled as points which have a .x and a .y property
- * which will be modified in place.
- *
- * Override Proj4js.reportError for output of alerts and warnings.
- *
- * See http://trac.osgeo.org/proj4js/wiki/UserGuide for full details.
- */
- /**
- * Global namespace object for Proj4js library
- */
- var Proj4js = {
- /**
- * Property: defaultDatum
- * The datum to use when no others a specified
- */
- defaultDatum: 'WGS84', //default datum
- /**
- * Method: transform(source, dest, point)
- * Transform a point coordinate from one map projection to another. This is
- * really the only public method you should need to use.
- *
- * Parameters:
- * source - {Proj4js.Proj} source map projection for the transformation
- * dest - {Proj4js.Proj} destination map projection for the transformation
- * point - {Object} point to transform, may be geodetic (long, lat) or
- * projected Cartesian (x,y), but should always have x,y properties.
- */
- transform: function(source, dest, point) {
- if (!source.readyToUse) {
- this.reportError("Proj4js initialization for:"+source.srsCode+" not yet complete");
- return point;
- }
- if (!dest.readyToUse) {
- this.reportError("Proj4js initialization for:"+dest.srsCode+" not yet complete");
- return point;
- }
-
- // Workaround for datum shifts towgs84, if either source or destination projection is not wgs84
- if (source.datum && dest.datum && (
- ((source.datum.datum_type == Proj4js.common.PJD_3PARAM || source.datum.datum_type == Proj4js.common.PJD_7PARAM) && dest.datumCode != "WGS84") ||
- ((dest.datum.datum_type == Proj4js.common.PJD_3PARAM || dest.datum.datum_type == Proj4js.common.PJD_7PARAM) && source.datumCode != "WGS84"))) {
- var wgs84 = Proj4js.WGS84;
- this.transform(source, wgs84, point);
- source = wgs84;
- }
- // DGR, 2010/11/12
- if (source.axis!="enu") {
- this.adjust_axis(source,false,point);
- }
- // Transform source points to long/lat, if they aren't already.
- if ( source.projName=="longlat") {
- point.x *= Proj4js.common.D2R; // convert degrees to radians
- point.y *= Proj4js.common.D2R;
- } else {
- if (source.to_meter) {
- point.x *= source.to_meter;
- point.y *= source.to_meter;
- }
- source.inverse(point); // Convert Cartesian to longlat
- }
- // Adjust for the prime meridian if necessary
- if (source.from_greenwich) {
- point.x += source.from_greenwich;
- }
- // Convert datums if needed, and if possible.
- point = this.datum_transform( source.datum, dest.datum, point );
- // Adjust for the prime meridian if necessary
- if (dest.from_greenwich) {
- point.x -= dest.from_greenwich;
- }
- if( dest.projName=="longlat" ) {
- // convert radians to decimal degrees
- point.x *= Proj4js.common.R2D;
- point.y *= Proj4js.common.R2D;
- } else { // else project
- dest.forward(point);
- if (dest.to_meter) {
- point.x /= dest.to_meter;
- point.y /= dest.to_meter;
- }
- }
- // DGR, 2010/11/12
- if (dest.axis!="enu") {
- this.adjust_axis(dest,true,point);
- }
- return point;
- }, // transform()
- /** datum_transform()
- source coordinate system definition,
- destination coordinate system definition,
- point to transform in geodetic coordinates (long, lat, height)
- */
- datum_transform : function( source, dest, point ) {
- // Short cut if the datums are identical.
- if( source.compare_datums( dest ) ) {
- return point; // in this case, zero is sucess,
- // whereas cs_compare_datums returns 1 to indicate TRUE
- // confusing, should fix this
- }
- // Explicitly skip datum transform by setting 'datum=none' as parameter for either source or dest
- if( source.datum_type == Proj4js.common.PJD_NODATUM
- || dest.datum_type == Proj4js.common.PJD_NODATUM) {
- return point;
- }
- // Do we need to go through geocentric coordinates?
- if( source.es != dest.es || source.a != dest.a
- || source.datum_type == Proj4js.common.PJD_3PARAM
- || source.datum_type == Proj4js.common.PJD_7PARAM
- || dest.datum_type == Proj4js.common.PJD_3PARAM
- || dest.datum_type == Proj4js.common.PJD_7PARAM)
- {
- // Convert to geocentric coordinates.
- source.geodetic_to_geocentric( point );
- // CHECK_RETURN;
- // Convert between datums
- if( source.datum_type == Proj4js.common.PJD_3PARAM || source.datum_type == Proj4js.common.PJD_7PARAM ) {
- source.geocentric_to_wgs84(point);
- // CHECK_RETURN;
- }
- if( dest.datum_type == Proj4js.common.PJD_3PARAM || dest.datum_type == Proj4js.common.PJD_7PARAM ) {
- dest.geocentric_from_wgs84(point);
- // CHECK_RETURN;
- }
- // Convert back to geodetic coordinates
- dest.geocentric_to_geodetic( point );
- // CHECK_RETURN;
- }
- return point;
- }, // cs_datum_transform
- /**
- * Function: adjust_axis
- * Normalize or de-normalized the x/y/z axes. The normal form is "enu"
- * (easting, northing, up).
- * Parameters:
- * crs {Proj4js.Proj} the coordinate reference system
- * denorm {Boolean} when false, normalize
- * point {Object} the coordinates to adjust
- */
- adjust_axis: function(crs, denorm, point) {
- var xin= point.x, yin= point.y, zin= point.z || 0.0;
- var v, t;
- for (var i= 0; i<3; i++) {
- if (denorm && i==2 && point.z===undefined) { continue; }
- if (i==0) { v= xin; t= 'x'; }
- else if (i==1) { v= yin; t= 'y'; }
- else { v= zin; t= 'z'; }
- switch(crs.axis[i]) {
- case 'e':
- point[t]= v;
- break;
- case 'w':
- point[t]= -v;
- break;
- case 'n':
- point[t]= v;
- break;
- case 's':
- point[t]= -v;
- break;
- case 'u':
- if (point[t]!==undefined) { point.z= v; }
- break;
- case 'd':
- if (point[t]!==undefined) { point.z= -v; }
- break;
- default :
- alert("ERROR: unknow axis ("+crs.axis[i]+") - check definition of "+crs.projName);
- return null;
- }
- }
- return point;
- },
- /**
- * Function: reportError
- * An internal method to report errors back to user.
- * Override this in applications to report error messages or throw exceptions.
- */
- reportError: function(msg) {
- //console.log(msg);
- },
- /**
- *
- * Title: Private Methods
- * The following properties and methods are intended for internal use only.
- *
- * This is a minimal implementation of JavaScript inheritance methods so that
- * Proj4js can be used as a stand-alone library.
- * These are copies of the equivalent OpenLayers methods at v2.7
- */
-
- /**
- * Function: extend
- * Copy all properties of a source object to a destination object. Modifies
- * the passed in destination object. Any properties on the source object
- * that are set to undefined will not be (re)set on the destination object.
- *
- * Parameters:
- * destination - {Object} The object that will be modified
- * source - {Object} The object with properties to be set on the destination
- *
- * Returns:
- * {Object} The destination object.
- */
- extend: function(destination, source) {
- destination = destination || {};
- if(source) {
- for(var property in source) {
- var value = source[property];
- if(value !== undefined) {
- destination[property] = value;
- }
- }
- }
- return destination;
- },
- /**
- * Constructor: Class
- * Base class used to construct all other classes. Includes support for
- * multiple inheritance.
- *
- */
- Class: function() {
- var Class = function() {
- this.initialize.apply(this, arguments);
- };
-
- var extended = {};
- var parent;
- for(var i=0; i<arguments.length; ++i) {
- if(typeof arguments[i] == "function") {
- // get the prototype of the superclass
- parent = arguments[i].prototype;
- } else {
- // in this case we're extending with the prototype
- parent = arguments[i];
- }
- Proj4js.extend(extended, parent);
- }
- Class.prototype = extended;
-
- return Class;
- },
- /**
- * Function: bind
- * Bind a function to an object. Method to easily create closures with
- * 'this' altered.
- *
- * Parameters:
- * func - {Function} Input function.
- * object - {Object} The object to bind to the input function (as this).
- *
- * Returns:
- * {Function} A closure with 'this' set to the passed in object.
- */
- bind: function(func, object) {
- // create a reference to all arguments past the second one
- var args = Array.prototype.slice.apply(arguments, [2]);
- return function() {
- // Push on any additional arguments from the actual function call.
- // These will come after those sent to the bind call.
- var newArgs = args.concat(
- Array.prototype.slice.apply(arguments, [0])
- );
- return func.apply(object, newArgs);
- };
- },
-
- /**
- * The following properties and methods handle dynamic loading of JSON objects.
- */
-
- /**
- * Property: scriptName
- * {String} The filename of this script without any path.
- */
- scriptName: "proj4js-combined.js",
- /**
- * Property: defsLookupService
- * AJAX service to retreive projection definition parameters from
- */
- defsLookupService: 'http://spatialreference.org/ref',
- /**
- * Property: libPath
- * internal: http server path to library code.
- */
- libPath: null,
- /**
- * Function: getScriptLocation
- * Return the path to this script.
- *
- * Returns:
- * Path to this script
- */
- getScriptLocation: function () {
- if (this.libPath) return this.libPath;
- var scriptName = this.scriptName;
- var scriptNameLen = scriptName.length;
- var scripts = document.getElementsByTagName('script');
- for (var i = 0; i < scripts.length; i++) {
- var src = scripts[i].getAttribute('src');
- if (src) {
- var index = src.lastIndexOf(scriptName);
- // is it found, at the end of the URL?
- if ((index > -1) && (index + scriptNameLen == src.length)) {
- this.libPath = src.slice(0, -scriptNameLen);
- break;
- }
- }
- }
- return this.libPath||"";
- },
- /**
- * Function: loadScript
- * Load a JS file from a URL into a <script> tag in the page.
- *
- * Parameters:
- * url - {String} The URL containing the script to load
- * onload - {Function} A method to be executed when the script loads successfully
- * onfail - {Function} A method to be executed when there is an error loading the script
- * loadCheck - {Function} A boolean method that checks to see if the script
- * has loaded. Typically this just checks for the existance of
- * an object in the file just loaded.
- */
- loadScript: function(url, onload, onfail, loadCheck) {
- var script = document.createElement('script');
- script.defer = false;
- script.type = "text/javascript";
- script.id = url;
- script.src = url;
- script.onload = onload;
- script.onerror = onfail;
- script.loadCheck = loadCheck;
- if (/MSIE/.test(navigator.userAgent)) {
- script.onreadystatechange = this.checkReadyState;
- }
- document.getElementsByTagName('head')[0].appendChild(script);
- },
-
- /**
- * Function: checkReadyState
- * IE workaround since there is no onerror handler. Calls the user defined
- * loadCheck method to determine if the script is loaded.
- *
- */
- checkReadyState: function() {
- if (this.readyState == 'loaded') {
- if (!this.loadCheck()) {
- this.onerror();
- } else {
- this.onload();
- }
- }
- }
- };
- /**
- * Class: Proj4js.Proj
- *
- * Proj objects provide transformation methods for point coordinates
- * between geodetic latitude/longitude and a projected coordinate system.
- * once they have been initialized with a projection code.
- *
- * Initialization of Proj objects is with a projection code, usually EPSG codes,
- * which is the key that will be used with the Proj4js.defs array.
- *
- * The code passed in will be stripped of colons and converted to uppercase
- * to locate projection definition files.
- *
- * A projection object has properties for units and title strings.
- */
- Proj4js.Proj = Proj4js.Class({
- /**
- * Property: readyToUse
- * Flag to indicate if initialization is complete for this Proj object
- */
- readyToUse: false,
-
- /**
- * Property: title
- * The title to describe the projection
- */
- title: null,
-
- /**
- * Property: projName
- * The projection class for this projection, e.g. lcc (lambert conformal conic,
- * or merc for mercator). These are exactly equivalent to their Proj4
- * counterparts.
- */
- projName: null,
- /**
- * Property: units
- * The units of the projection. Values include 'm' and 'degrees'
- */
- units: null,
- /**
- * Property: datum
- * The datum specified for the projection
- */
- datum: null,
- /**
- * Property: x0
- * The x coordinate origin
- */
- x0: 0,
- /**
- * Property: y0
- * The y coordinate origin
- */
- y0: 0,
- /**
- * Property: localCS
- * Flag to indicate if the projection is a local one in which no transforms
- * are required.
- */
- localCS: false,
- /**
- * Property: queue
- * Buffer (FIFO) to hold callbacks waiting to be called when projection loaded.
- */
- queue: null,
- /**
- * Constructor: initialize
- * Constructor for Proj4js.Proj objects
- *
- * Parameters:
- * srsCode - a code for map projection definition parameters. These are usually
- * (but not always) EPSG codes.
- */
- initialize: function(srsCode, callback) {
- this.srsCodeInput = srsCode;
-
- //Register callbacks prior to attempting to process definition
- this.queue = [];
- if( callback ){
- this.queue.push( callback );
- }
-
- //check to see if this is a WKT string
- if ((srsCode.indexOf('GEOGCS') >= 0) ||
- (srsCode.indexOf('GEOCCS') >= 0) ||
- (srsCode.indexOf('PROJCS') >= 0) ||
- (srsCode.indexOf('LOCAL_CS') >= 0)) {
- this.parseWKT(srsCode);
- this.deriveConstants();
- this.loadProjCode(this.projName);
- return;
- }
-
- // DGR 2008-08-03 : support urn and url
- if (srsCode.indexOf('urn:') == 0) {
- //urn:ORIGINATOR:def:crs:CODESPACE:VERSION:ID
- var urn = srsCode.split(':');
- if ((urn[1] == 'ogc' || urn[1] =='x-ogc') &&
- (urn[2] =='def') &&
- (urn[3] =='crs')) {
- srsCode = urn[4]+':'+urn[urn.length-1];
- }
- } else if (srsCode.indexOf('http://') == 0) {
- //url#ID
- var url = srsCode.split('#');
- if (url[0].match(/epsg.org/)) {
- // http://www.epsg.org/#
- srsCode = 'EPSG:'+url[1];
- } else if (url[0].match(/RIG.xml/)) {
- //http://librairies.ign.fr/geoportail/resources/RIG.xml#
- //http://interop.ign.fr/registers/ign/RIG.xml#
- srsCode = 'IGNF:'+url[1];
- }
- }
- this.srsCode = srsCode.toUpperCase();
- if (this.srsCode.indexOf("EPSG") == 0) {
- this.srsCode = this.srsCode;
- this.srsAuth = 'epsg';
- this.srsProjNumber = this.srsCode.substring(5);
- // DGR 2007-11-20 : authority IGNF
- } else if (this.srsCode.indexOf("IGNF") == 0) {
- this.srsCode = this.srsCode;
- this.srsAuth = 'IGNF';
- this.srsProjNumber = this.srsCode.substring(5);
- // DGR 2008-06-19 : pseudo-authority CRS for WMS
- } else if (this.srsCode.indexOf("CRS") == 0) {
- this.srsCode = this.srsCode;
- this.srsAuth = 'CRS';
- this.srsProjNumber = this.srsCode.substring(4);
- } else {
- this.srsAuth = '';
- this.srsProjNumber = this.srsCode;
- }
-
- this.loadProjDefinition();
- },
-
- /**
- * Function: loadProjDefinition
- * Loads the coordinate system initialization string if required.
- * Note that dynamic loading happens asynchronously so an application must
- * wait for the readyToUse property is set to true.
- * To prevent dynamic loading, include the defs through a script tag in
- * your application.
- *
- */
- loadProjDefinition: function() {
- //check in memory
- if (Proj4js.defs[this.srsCode]) {
- this.defsLoaded();
- return;
- }
- //else check for def on the server
- var url = Proj4js.getScriptLocation() + 'defs/' + this.srsAuth.toUpperCase() + this.srsProjNumber + '.js';
- Proj4js.loadScript(url,
- Proj4js.bind(this.defsLoaded, this),
- Proj4js.bind(this.loadFromService, this),
- Proj4js.bind(this.checkDefsLoaded, this) );
- },
- /**
- * Function: loadFromService
- * Creates the REST URL for loading the definition from a web service and
- * loads it.
- *
- */
- loadFromService: function() {
- //else load from web service
- var url = Proj4js.defsLookupService +'/' + this.srsAuth +'/'+ this.srsProjNumber + '/proj4js/';
- Proj4js.loadScript(url,
- Proj4js.bind(this.defsLoaded, this),
- Proj4js.bind(this.defsFailed, this),
- Proj4js.bind(this.checkDefsLoaded, this) );
- },
- /**
- * Function: defsLoaded
- * Continues the Proj object initilization once the def file is loaded
- *
- */
- defsLoaded: function() {
- this.parseDefs();
- this.loadProjCode(this.projName);
- },
-
- /**
- * Function: checkDefsLoaded
- * This is the loadCheck method to see if the def object exists
- *
- */
- checkDefsLoaded: function() {
- if (Proj4js.defs[this.srsCode]) {
- return true;
- } else {
- return false;
- }
- },
- /**
- * Function: defsFailed
- * Report an error in loading the defs file, but continue on using WGS84
- *
- */
- defsFailed: function() {
- Proj4js.reportError('failed to load projection definition for: '+this.srsCode);
- Proj4js.defs[this.srsCode] = Proj4js.defs['WGS84']; //set it to something so it can at least continue
- this.defsLoaded();
- },
- /**
- * Function: loadProjCode
- * Loads projection class code dynamically if required.
- * Projection code may be included either through a script tag or in
- * a built version of proj4js
- *
- */
- loadProjCode: function(projName) {
- if (Proj4js.Proj[projName]) {
- this.initTransforms();
- return;
- }
- //the URL for the projection code
- var url = Proj4js.getScriptLocation() + 'projCode/' + projName + '.js';
- Proj4js.loadScript(url,
- Proj4js.bind(this.loadProjCodeSuccess, this, projName),
- Proj4js.bind(this.loadProjCodeFailure, this, projName),
- Proj4js.bind(this.checkCodeLoaded, this, projName) );
- },
- /**
- * Function: loadProjCodeSuccess
- * Loads any proj dependencies or continue on to final initialization.
- *
- */
- loadProjCodeSuccess: function(projName) {
- if (Proj4js.Proj[projName].dependsOn){
- this.loadProjCode(Proj4js.Proj[projName].dependsOn);
- } else {
- this.initTransforms();
- }
- },
- /**
- * Function: defsFailed
- * Report an error in loading the proj file. Initialization of the Proj
- * object has failed and the readyToUse flag will never be set.
- *
- */
- loadProjCodeFailure: function(projName) {
- Proj4js.reportError("failed to find projection file for: " + projName);
- //TBD initialize with identity transforms so proj will still work?
- },
-
- /**
- * Function: checkCodeLoaded
- * This is the loadCheck method to see if the projection code is loaded
- *
- */
- checkCodeLoaded: function(projName) {
- if (Proj4js.Proj[projName]) {
- return true;
- } else {
- return false;
- }
- },
- /**
- * Function: initTransforms
- * Finalize the initialization of the Proj object
- *
- */
- initTransforms: function() {
- Proj4js.extend(this, Proj4js.Proj[this.projName]);
- this.init();
- this.readyToUse = true;
- if( this.queue ) {
- var item;
- while( (item = this.queue.shift()) ) {
- item.call( this, this );
- }
- }
- },
- /**
- * Function: parseWKT
- * Parses a WKT string to get initialization parameters
- *
- */
- wktRE: /^(\w+)\[(.*)\]$/,
- parseWKT: function(wkt) {
- var wktMatch = wkt.match(this.wktRE);
- if (!wktMatch) return;
- var wktObject = wktMatch[1];
- var wktContent = wktMatch[2];
- var wktTemp = wktContent.split(",");
- var wktName;
- if (wktObject.toUpperCase() == "TOWGS84") {
- wktName = wktObject; //no name supplied for the TOWGS84 array
- } else {
- wktName = wktTemp.shift();
- }
- wktName = wktName.replace(/^\"/,"");
- wktName = wktName.replace(/\"$/,"");
-
- /*
- wktContent = wktTemp.join(",");
- var wktArray = wktContent.split("],");
- for (var i=0; i<wktArray.length-1; ++i) {
- wktArray[i] += "]";
- }
- */
-
- var wktArray = new Array();
- var bkCount = 0;
- var obj = "";
- for (var i=0; i<wktTemp.length; ++i) {
- var token = wktTemp[i];
- for (var j=0; j<token.length; ++j) {
- if (token.charAt(j) == "[") ++bkCount;
- if (token.charAt(j) == "]") --bkCount;
- }
- obj += token;
- if (bkCount === 0) {
- wktArray.push(obj);
- obj = "";
- } else {
- obj += ",";
- }
- }
-
- //do something based on the type of the wktObject being parsed
- //add in variations in the spelling as required
- switch (wktObject) {
- case 'LOCAL_CS':
- this.projName = 'identity'
- this.localCS = true;
- this.srsCode = wktName;
- break;
- case 'GEOGCS':
- this.projName = 'longlat'
- this.geocsCode = wktName;
- if (!this.srsCode) this.srsCode = wktName;
- break;
- case 'PROJCS':
- this.srsCode = wktName;
- break;
- case 'GEOCCS':
- break;
- case 'PROJECTION':
- this.projName = Proj4js.wktProjections[wktName]
- break;
- case 'DATUM':
- this.datumName = wktName;
- break;
- case 'LOCAL_DATUM':
- this.datumCode = 'none';
- break;
- case 'SPHEROID':
- this.ellps = wktName;
- this.a = parseFloat(wktArray.shift());
- this.rf = parseFloat(wktArray.shift());
- break;
- case 'PRIMEM':
- this.from_greenwich = parseFloat(wktArray.shift()); //to radians?
- break;
- case 'UNIT':
- this.units = wktName;
- this.unitsPerMeter = parseFloat(wktArray.shift());
- break;
- case 'PARAMETER':
- var name = wktName.toLowerCase();
- var value = parseFloat(wktArray.shift());
- //there may be many variations on the wktName values, add in case
- //statements as required
- switch (name) {
- case 'false_easting':
- this.x0 = value;
- break;
- case 'false_northing':
- this.y0 = value;
- break;
- case 'scale_factor':
- this.k0 = value;
- break;
- case 'central_meridian':
- this.long0 = value*Proj4js.common.D2R;
- break;
- case 'latitude_of_origin':
- this.lat0 = value*Proj4js.common.D2R;
- break;
- case 'more_here':
- break;
- default:
- break;
- }
- break;
- case 'TOWGS84':
- this.datum_params = wktArray;
- break;
- //DGR 2010-11-12: AXIS
- case 'AXIS':
- var name= wktName.toLowerCase();
- var value= wktArray.shift();
- switch (value) {
- case 'EAST' : value= 'e'; break;
- case 'WEST' : value= 'w'; break;
- case 'NORTH': value= 'n'; break;
- case 'SOUTH': value= 's'; break;
- case 'UP' : value= 'u'; break;
- case 'DOWN' : value= 'd'; break;
- case 'OTHER':
- default : value= ' '; break;//FIXME
- }
- if (!this.axis) { this.axis= "enu"; }
- switch(name) {
- case 'x': this.axis= value + this.axis.substr(1,2); break;
- case 'y': this.axis= this.axis.substr(0,1) + value + this.axis.substr(2,1); break;
- case 'z': this.axis= this.axis.substr(0,2) + value ; break;
- default : break;
- }
- case 'MORE_HERE':
- break;
- default:
- break;
- }
- for (var i=0; i<wktArray.length; ++i) {
- this.parseWKT(wktArray[i]);
- }
- },
- /**
- * Function: parseDefs
- * Parses the PROJ.4 initialization string and sets the associated properties.
- *
- */
- parseDefs: function() {
- this.defData = Proj4js.defs[this.srsCode];
- var paramName, paramVal;
- if (!this.defData) {
- return;
- }
- var paramArray=this.defData.split("+");
- for (var prop=0; prop<paramArray.length; prop++) {
- var property = paramArray[prop].split("=");
- paramName = property[0].toLowerCase();
- paramVal = property[1];
- switch (paramName.replace(/\s/gi,"")) { // trim out spaces
- case "": break; // throw away nameless parameter
- case "title": this.title = paramVal; break;
- case "proj": this.projName = paramVal.replace(/\s/gi,""); break;
- case "units": this.units = paramVal.replace(/\s/gi,""); break;
- case "datum": this.datumCode = paramVal.replace(/\s/gi,""); break;
- case "nadgrids": this.nagrids = paramVal.replace(/\s/gi,""); break;
- case "ellps": this.ellps = paramVal.replace(/\s/gi,""); break;
- case "a": this.a = parseFloat(paramVal); break; // semi-major radius
- case "b": this.b = parseFloat(paramVal); break; // semi-minor radius
- // DGR 2007-11-20
- case "rf": this.rf = parseFloat(paramVal); break; // inverse flattening rf= a/(a-b)
- case "lat_0": this.lat0 = paramVal*Proj4js.common.D2R; break; // phi0, central latitude
- case "lat_1": this.lat1 = paramVal*Proj4js.common.D2R; break; //standard parallel 1
- case "lat_2": this.lat2 = paramVal*Proj4js.common.D2R; break; //standard parallel 2
- case "lat_ts": this.lat_ts = paramVal*Proj4js.common.D2R; break; // used in merc and eqc
- case "lon_0": this.long0 = paramVal*Proj4js.common.D2R; break; // lam0, central longitude
- case "alpha": this.alpha = parseFloat(paramVal)*Proj4js.common.D2R; break; //for somerc projection
- case "lonc": this.longc = paramVal*Proj4js.common.D2R; break; //for somerc projection
- case "x_0": this.x0 = parseFloat(paramVal); break; // false easting
- case "y_0": this.y0 = parseFloat(paramVal); break; // false northing
- case "k_0": this.k0 = parseFloat(paramVal); break; // projection scale factor
- case "k": this.k0 = parseFloat(paramVal); break; // both forms returned
- case "r_a": this.R_A = true; break; // sphere--area of ellipsoid
- case "zone": this.zone = parseInt(paramVal,10); break; // UTM Zone
- case "south": this.utmSouth = true; break; // UTM north/south
- case "towgs84":this.datum_params = paramVal.split(","); break;
- case "to_meter": this.to_meter = parseFloat(paramVal); break; // cartesian scaling
- case "from_greenwich": this.from_greenwich = paramVal*Proj4js.common.D2R; break;
- // DGR 2008-07-09 : if pm is not a well-known prime meridian take
- // the value instead of 0.0, then convert to radians
- case "pm": paramVal = paramVal.replace(/\s/gi,"");
- this.from_greenwich = Proj4js.PrimeMeridian[paramVal] ?
- Proj4js.PrimeMeridian[paramVal] : parseFloat(paramVal);
- this.from_greenwich *= Proj4js.common.D2R;
- break;
- // DGR 2010-11-12: axis
- case "axis": paramVal = paramVal.replace(/\s/gi,"");
- var legalAxis= "ewnsud";
- if (paramVal.length==3 &&
- legalAxis.indexOf(paramVal.substr(0,1))!=-1 &&
- legalAxis.indexOf(paramVal.substr(1,1))!=-1 &&
- legalAxis.indexOf(paramVal.substr(2,1))!=-1) {
- this.axis= paramVal;
- } //FIXME: be silent ?
- break
- case "no_defs": break;
- default: //alert("Unrecognized parameter: " + paramName);
- } // switch()
- } // for paramArray
- this.deriveConstants();
- },
- /**
- * Function: deriveConstants
- * Sets several derived constant values and initialization of datum and ellipse
- * parameters.
- *
- */
- deriveConstants: function() {
- if (this.nagrids == '@null') this.datumCode = 'none';
- if (this.datumCode && this.datumCode != 'none') {
- var datumDef = Proj4js.Datum[this.datumCode];
- if (datumDef) {
- this.datum_params = datumDef.towgs84 ? datumDef.towgs84.split(',') : null;
- this.ellps = datumDef.ellipse;
- this.datumName = datumDef.datumName ? datumDef.datumName : this.datumCode;
- }
- }
- if (!this.a) { // do we have an ellipsoid?
- var ellipse = Proj4js.Ellipsoid[this.ellps] ? Proj4js.Ellipsoid[this.ellps] : Proj4js.Ellipsoid['WGS84'];
- Proj4js.extend(this, ellipse);
- }
- if (this.rf && !this.b) this.b = (1.0 - 1.0/this.rf) * this.a;
- if (this.rf === 0 || Math.abs(this.a - this.b)<Proj4js.common.EPSLN) {
- this.sphere = true;
- this.b= this.a;
- }
- this.a2 = this.a * this.a; // used in geocentric
- this.b2 = this.b * this.b; // used in geocentric
- this.es = (this.a2-this.b2)/this.a2; // e ^ 2
- this.e = Math.sqrt(this.es); // eccentricity
- if (this.R_A) {
- this.a *= 1. - this.es * (Proj4js.common.SIXTH + this.es * (Proj4js.common.RA4 + this.es * Proj4js.common.RA6));
- this.a2 = this.a * this.a;
- this.b2 = this.b * this.b;
- this.es = 0.;
- }
- this.ep2=(this.a2-this.b2)/this.b2; // used in geocentric
- if (!this.k0) this.k0 = 1.0; //default value
- //DGR 2010-11-12: axis
- if (!this.axis) { this.axis= "enu"; }
- this.datum = new Proj4js.datum(this);
- }
- });
- Proj4js.Proj.longlat = {
- init: function() {
- //no-op for longlat
- },
- forward: function(pt) {
- //identity transform
- return pt;
- },
- inverse: function(pt) {
- //identity transform
- return pt;
- }
- };
- Proj4js.Proj.identity = Proj4js.Proj.longlat;
- /**
- Proj4js.defs is a collection of coordinate system definition objects in the
- PROJ.4 command line format.
- Generally a def is added by means of a separate .js file for example:
- <SCRIPT type="text/javascript" src="defs/EPSG26912.js"></SCRIPT>
- def is a CS definition in PROJ.4 WKT format, for example:
- +proj="tmerc" //longlat, etc.
- +a=majorRadius
- +b=minorRadius
- +lat0=somenumber
- +long=somenumber
- */
- Proj4js.defs = {
- // These are so widely used, we'll go ahead and throw them in
- // without requiring a separate .js file
- 'WGS84': "+title=long/lat:WGS84 +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees",
- 'EPSG:4326': "+title=long/lat:WGS84 +proj=longlat +a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84 +units=degrees",
- 'EPSG:4269': "+title=long/lat:NAD83 +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees",
- 'EPSG:3875': "+title= Google 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"
- };
- Proj4js.defs['EPSG:3785'] = Proj4js.defs['EPSG:3875']; //maintain backward compat, official code is 3875
- Proj4js.defs['GOOGLE'] = Proj4js.defs['EPSG:3875'];
- Proj4js.defs['EPSG:900913'] = Proj4js.defs['EPSG:3875'];
- Proj4js.defs['EPSG:102113'] = Proj4js.defs['EPSG:3875'];
- Proj4js.common = {
- PI : 3.141592653589793238, //Math.PI,
- HALF_PI : 1.570796326794896619, //Math.PI*0.5,
- TWO_PI : 6.283185307179586477, //Math.PI*2,
- FORTPI : 0.78539816339744833,
- R2D : 57.29577951308232088,
- D2R : 0.01745329251994329577,
- SEC_TO_RAD : 4.84813681109535993589914102357e-6, /* SEC_TO_RAD = Pi/180/3600 */
- EPSLN : 1.0e-10,
- MAX_ITER : 20,
- // following constants from geocent.c
- COS_67P5 : 0.38268343236508977, /* cosine of 67.5 degrees */
- AD_C : 1.0026000, /* Toms region 1 constant */
- /* datum_type values */
- PJD_UNKNOWN : 0,
- PJD_3PARAM : 1,
- PJD_7PARAM : 2,
- PJD_GRIDSHIFT: 3,
- PJD_WGS84 : 4, // WGS84 or equivalent
- PJD_NODATUM : 5, // WGS84 or equivalent
- SRS_WGS84_SEMIMAJOR : 6378137.0, // only used in grid shift transforms
- // ellipoid pj_set_ell.c
- SIXTH : .1666666666666666667, /* 1/6 */
- RA4 : .04722222222222222222, /* 17/360 */
- RA6 : .02215608465608465608, /* 67/3024 */
- RV4 : .06944444444444444444, /* 5/72 */
- RV6 : .04243827160493827160, /* 55/1296 */
- // Function to compute the constant small m which is the radius of
- // a parallel of latitude, phi, divided by the semimajor axis.
- // -----------------------------------------------------------------
- msfnz : function(eccent, sinphi, cosphi) {
- var con = eccent * sinphi;
- return cosphi/(Math.sqrt(1.0 - con * con));
- },
- // Function to compute the constant small t for use in the forward
- // computations in the Lambert Conformal Conic and the Polar
- // Stereographic projections.
- // -----------------------------------------------------------------
- tsfnz : function(eccent, phi, sinphi) {
- var con = eccent * sinphi;
- var com = .5 * eccent;
- con = Math.pow(((1.0 - con) / (1.0 + con)), com);
- return (Math.tan(.5 * (this.HALF_PI - phi))/con);
- },
- // Function to compute the latitude angle, phi2, for the inverse of the
- // Lambert Conformal Conic and Polar Stereographic projections.
- // ----------------------------------------------------------------
- phi2z : function(eccent, ts) {
- var eccnth = .5 * eccent;
- var con, dphi;
- var phi = this.HALF_PI - 2 * Math.atan(ts);
- for (var i = 0; i <= 15; i++) {
- con = eccent * Math.sin(phi);
- dphi = this.HALF_PI - 2 * Math.atan(ts *(Math.pow(((1.0 - con)/(1.0 + con)),eccnth))) - phi;
- phi += dphi;
- if (Math.abs(dphi) <= .0000000001) return phi;
- }
- alert("phi2z has NoConvergence");
- return (-9999);
- },
- /* Function to compute constant small q which is the radius of a
- parallel of latitude, phi, divided by the semimajor axis.
- ------------------------------------------------------------*/
- qsfnz : function(eccent,sinphi) {
- var con;
- if (eccent > 1.0e-7) {
- con = eccent * sinphi;
- return (( 1.0- eccent * eccent) * (sinphi /(1.0 - con * con) - (.5/eccent)*Math.log((1.0 - con)/(1.0 + con))));
- } else {
- return(2.0 * sinphi);
- }
- },
- /* Function to eliminate roundoff errors in asin
- ----------------------------------------------*/
- asinz : function(x) {
- if (Math.abs(x)>1.0) {
- x=(x>1.0)?1.0:-1.0;
- }
- return Math.asin(x);
- },
- // following functions from gctpc cproj.c for transverse mercator projections
- e0fn : function(x) {return(1.0-0.25*x*(1.0+x/16.0*(3.0+1.25*x)));},
- e1fn : function(x) {return(0.375*x*(1.0+0.25*x*(1.0+0.46875*x)));},
- e2fn : function(x) {return(0.05859375*x*x*(1.0+0.75*x));},
- e3fn : function(x) {return(x*x*x*(35.0/3072.0));},
- mlfn : function(e0,e1,e2,e3,phi) {return(e0*phi-e1*Math.sin(2.0*phi)+e2*Math.sin(4.0*phi)-e3*Math.sin(6.0*phi));},
- srat : function(esinp, exp) {
- return(Math.pow((1.0-esinp)/(1.0+esinp), exp));
- },
- // Function to return the sign of an argument
- sign : function(x) { if (x < 0.0) return(-1); else return(1);},
- // Function to adjust longitude to -180 to 180; input in radians
- adjust_lon : function(x) {
- x = (Math.abs(x) < this.PI) ? x: (x - (this.sign(x)*this.TWO_PI) );
- return x;
- },
- // IGNF - DGR : algorithms used by IGN France
- // Function to adjust latitude to -90 to 90; input in radians
- adjust_lat : function(x) {
- x= (Math.abs(x) < this.HALF_PI) ? x: (x - (this.sign(x)*this.PI) );
- return x;
- },
- // Latitude Isometrique - close to tsfnz ...
- latiso : function(eccent, phi, sinphi) {
- if (Math.abs(phi) > this.HALF_PI) return +Number.NaN;
- if (phi==this.HALF_PI) return Number.POSITIVE_INFINITY;
- if (phi==-1.0*this.HALF_PI) return -1.0*Number.POSITIVE_INFINITY;
- var con= eccent*sinphi;
- return Math.log(Math.tan((this.HALF_PI+phi)/2.0))+eccent*Math.log((1.0-con)/(1.0+con))/2.0;
- },
- fL : function(x,L) {
- return 2.0*Math.atan(x*Math.exp(L)) - this.HALF_PI;
- },
- // Inverse Latitude Isometrique - close to ph2z
- invlatiso : function(eccent, ts) {
- var phi= this.fL(1.0,ts);
- var Iphi= 0.0;
- var con= 0.0;
- do {
- Iphi= phi;
- con= eccent*Math.sin(Iphi);
- phi= this.fL(Math.exp(eccent*Math.log((1.0+con)/(1.0-con))/2.0),ts)
- } while (Math.abs(phi-Iphi)>1.0e-12);
- return phi;
- },
- // Needed for Gauss Schreiber
- // Original: Denis Makarov (info@binarythings.com)
- // Web Site: http://www.binarythings.com
- sinh : function(x)
- {
- var r= Math.exp(x);
- r= (r-1.0/r)/2.0;
- return r;
- },
- cosh : function(x)
- {
- var r= Math.exp(x);
- r= (r+1.0/r)/2.0;
- return r;
- },
- tanh : function(x)
- {
- var r= Math.exp(x);
- r= (r-1.0/r)/(r+1.0/r);
- return r;
- },
- asinh : function(x)
- {
- var s= (x>= 0? 1.0:-1.0);
- return s*(Math.log( Math.abs(x) + Math.sqrt(x*x+1.0) ));
- },
- acosh : function(x)
- {
- return 2.0*Math.log(Math.sqrt((x+1.0)/2.0) + Math.sqrt((x-1.0)/2.0));
- },
- atanh : function(x)
- {
- return Math.log((x-1.0)/(x+1.0))/2.0;
- },
- // Grande Normale
- gN : function(a,e,sinphi)
- {
- var temp= e*sinphi;
- return a/Math.sqrt(1.0 - temp*temp);
- },
-
- //code from the PROJ.4 pj_mlfn.c file; this may be useful for other projections
- pj_enfn: function(es) {
- var en = new Array();
- en[0] = this.C00 - es * (this.C02 + es * (this.C04 + es * (this.C06 + es * this.C08)));
- en[1] = es * (this.C22 - es * (this.C04 + es * (this.C06 + es * this.C08)));
- var t = es * es;
- en[2] = t * (this.C44 - es * (this.C46 + es * this.C48));
- t *= es;
- en[3] = t * (this.C66 - es * this.C68);
- en[4] = t * es * this.C88;
- return en;
- },
-
- pj_mlfn: function(phi, sphi, cphi, en) {
- cphi *= sphi;
- sphi *= sphi;
- return(en[0] * phi - cphi * (en[1] + sphi*(en[2]+ sphi*(en[3] + sphi*en[4]))));
- },
-
- pj_inv_mlfn: function(arg, es, en) {
- var k = 1./(1.-es);
- var phi = arg;
- for (var i = Proj4js.common.MAX_ITER; i ; --i) { /* rarely goes over 2 iterations */
- var s = Math.sin(phi);
- var t = 1. - es * s * s;
- //t = this.pj_mlfn(phi, s, Math.cos(phi), en) - arg;
- //phi -= t * (t * Math.sqrt(t)) * k;
- t = (this.pj_mlfn(phi, s, Math.cos(phi), en) - arg) * (t * Math.sqrt(t)) * k;
- phi -= t;
- if (Math.abs(t) < Proj4js.common.EPSLN)
- return phi;
- }
- Proj4js.reportError("cass:pj_inv_mlfn: Convergence error");
- return phi;
- },
- /* meridinal distance for ellipsoid and inverse
- ** 8th degree - accurate to < 1e-5 meters when used in conjuction
- ** with typical major axis values.
- ** Inverse determines phi to EPS (1e-11) radians, about 1e-6 seconds.
- */
- C00: 1.0,
- C02: .25,
- C04: .046875,
- C06: .01953125,
- C08: .01068115234375,
- C22: .75,
- C44: .46875,
- C46: .01302083333333333333,
- C48: .00712076822916666666,
- C66: .36458333333333333333,
- C68: .00569661458333333333,
- C88: .3076171875
- };
- /** datum object
- */
- Proj4js.datum = Proj4js.Class({
- initialize : function(proj) {
- this.datum_type = Proj4js.common.PJD_WGS84; //default setting
- if (proj.datumCode && proj.datumCode == 'none') {
- this.datum_type = Proj4js.common.PJD_NODATUM;
- }
- if (proj && proj.datum_params) {
- for (var i=0; i<proj.datum_params.length; i++) {
- proj.datum_params[i]=parseFloat(proj.datum_params[i]);
- }
- if (proj.datum_params[0] != 0 || proj.datum_params[1] != 0 || proj.datum_params[2] != 0 ) {
- this.datum_type = Proj4js.common.PJD_3PARAM;
- }
- if (proj.datum_params.length > 3) {
- if (proj.datum_params[3] != 0 || proj.datum_params[4] != 0 ||
- proj.datum_params[5] != 0 || proj.datum_params[6] != 0 ) {
- this.datum_type = Proj4js.common.PJD_7PARAM;
- proj.datum_params[3] *= Proj4js.common.SEC_TO_RAD;
- proj.datum_params[4] *= Proj4js.common.SEC_TO_RAD;
- proj.datum_params[5] *= Proj4js.common.SEC_TO_RAD;
- proj.datum_params[6] = (proj.datum_params[6]/1000000.0) + 1.0;
- }
- }
- }
- if (proj) {
- this.a = proj.a; //datum object also uses these values
- this.b = proj.b;
- this.es = proj.es;
- this.ep2 = proj.ep2;
- this.datum_params = proj.datum_params;
- }
- },
- /****************************************************************/
- // cs_compare_datums()
- // Returns TRUE if the two datums match, otherwise FALSE.
- compare_datums : function( dest ) {
- if( this.datum_type != dest.datum_type ) {
- return false; // false, datums are not equal
- } else if( this.a != dest.a || Math.abs(this.es-dest.es) > 0.000000000050 ) {
- // the tolerence for es is to ensure that GRS80 and WGS84
- // are considered identical
- return false;
- } else if( this.datum_type == Proj4js.common.PJD_3PARAM ) {
- return (this.datum_params[0] == dest.datum_params[0]
- && this.datum_params[1] == dest.datum_params[1]
- && this.datum_params[2] == dest.datum_params[2]);
- } else if( this.datum_type == Proj4js.common.PJD_7PARAM ) {
- return (this.datum_params[0] == dest.datum_params[0]
- && this.datum_params[1] == dest.datum_params[1]
- && this.datum_params[2] == dest.datum_params[2]
- && this.datum_params[3] == dest.datum_params[3]
- && this.datum_params[4] == dest.datum_params[4]
- && this.datum_params[5] == dest.datum_params[5]
- && this.datum_params[6] == dest.datum_params[6]);
- } else if ( this.datum_type == Proj4js.common.PJD_GRIDSHIFT ||
- dest.datum_type == Proj4js.common.PJD_GRIDSHIFT ) {
- alert("ERROR: Grid shift transformations are not implemented.");
- return false
- } else {
- return true; // datums are equal
- }
- }, // cs_compare_datums()
- /*
- * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates
- * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z),
- * according to the current ellipsoid parameters.
- *
- * Latitude : Geodetic latitude in radians (input)
- * Longitude : Geodetic longitude in radians (input)
- * Height : Geodetic height, in meters (input)
- * X : Calculated Geocentric X coordinate, in meters (output)
- * Y : Calculated Geocentric Y coordinate, in meters (output)
- * Z : Calculated Geocentric Z coordinate, in meters (output)
- *
- */
- geodetic_to_geocentric : function(p) {
- var Longitude = p.x;
- var Latitude = p.y;
- var Height = p.z ? p.z : 0; //Z value not always supplied
- var X; // output
- var Y;
- var Z;
- var Error_Code=0; // GEOCENT_NO_ERROR;
- var Rn; /* Earth radius at location */
- var Sin_Lat; /* Math.sin(Latitude) */
- var Sin2_Lat; /* Square of Math.sin(Latitude) */
- var Cos_Lat; /* Math.cos(Latitude) */
- /*
- ** Don't blow up if Latitude is just a little out of the value
- ** range as it may just be a rounding issue. Also removed longitude
- ** test, it should be wrapped by Math.cos() and Math.sin(). NFW for PROJ.4, Sep/2001.
- */
- if( Latitude < -Proj4js.common.HALF_PI && Latitude > -1.001 * Proj4js.common.HALF_PI ) {
- Latitude = -Proj4js.common.HALF_PI;
- } else if( Latitude > Proj4js.common.HALF_PI && Latitude < 1.001 * Proj4js.common.HALF_PI ) {
- Latitude = Proj4js.common.HALF_PI;
- } else if ((Latitude < -Proj4js.common.HALF_PI) || (Latitude > Proj4js.common.HALF_PI)) {
- /* Latitude out of range */
- Proj4js.reportError('geocent:lat out of range:'+Latitude);
- return null;
- }
- if (Longitude > Proj4js.common.PI) Longitude -= (2*Proj4js.common.PI);
- Sin_Lat = Math.sin(Latitude);
- Cos_Lat = Math.cos(Latitude);
- Sin2_Lat = Sin_Lat * Sin_Lat;
- Rn = this.a / (Math.sqrt(1.0e0 - this.es * Sin2_Lat));
- X = (Rn + Height) * Cos_Lat * Math.cos(Longitude);
- Y = (Rn + Height) * Cos_Lat * Math.sin(Longitude);
- Z = ((Rn * (1 - this.es)) + Height) * Sin_Lat;
- p.x = X;
- p.y = Y;
- p.z = Z;
- return Error_Code;
- }, // cs_geodetic_to_geocentric()
- geocentric_to_geodetic : function (p) {
- /* local defintions and variables */
- /* end-criterium of loop, accuracy of sin(Latitude) */
- var genau = 1.E-12;
- var genau2 = (genau*genau);
- var maxiter = 30;
- var P; /* distance between semi-minor axis and location */
- var RR; /* distance between center and location */
- var CT; /* sin of geocentric latitude */
- var ST; /* cos of geocentric latitude */
- var RX;
- var RK;
- var RN; /* Earth radius at location */
- var CPHI0; /* cos of start or old geodetic latitude in iterations */
- var SPHI0; /* sin of start or old geodetic latitude in iterations */
- var CPHI; /* cos of searched geodetic latitude */
- var SPHI; /* sin of searched geodetic latitude */
- var SDPHI; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */
- var At_Pole; /* indicates location is in polar region */
- var iter; /* # of continous iteration, max. 30 is always enough (s.a.) */
- var X = p.x;
- var Y = p.y;
- var Z = p.z ? p.z : 0.0; //Z value not always supplied
- var Longitude;
- var Latitude;
- var Height;
- At_Pole = false;
- P = Math.sqrt(X*X+Y*Y);
- RR = Math.sqrt(X*X+Y*Y+Z*Z);
- /* special cases for latitude and longitude */
- if (P/this.a < genau) {
- /* special case, if P=0. (X=0., Y=0.) */
- At_Pole = true;
- Longitude = 0.0;
- /* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis
- * of ellipsoid (=center of mass), Latitude becomes PI/2 */
- if (RR/this.a < genau) {
- Latitude = Proj4js.common.HALF_PI;
- Height = -this.b;
- return;
- }
- } else {
- /* ellipsoidal (geodetic) longitude
- * interval: -PI < Longitude <= +PI */
- Longitude=Math.atan2(Y,X);
- }
- /* --------------------------------------------------------------
- * Following iterative algorithm was developped by
- * "Institut f�r Erdmessung", University of Hannover, July 1988.
- * Internet: www.ife.uni-hannover.de
- * Iterative computation of CPHI,SPHI and Height.
- * Iteration of CPHI and SPHI to 10**-12 radian resp.
- * 2*10**-7 arcsec.
- * --------------------------------------------------------------
- */
- CT = Z/RR;
- ST = P/RR;
- RX = 1.0/Math.sqrt(1.0-this.es*(2.0-this.es)*ST*ST);
- CPHI0 = ST*(1.0-this.es)*RX;
- SPHI0 = CT*RX;
- iter = 0;
- /* loop to find sin(Latitude) resp. Latitude
- * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */
- do
- {
- iter++;
- RN = this.a/Math.sqrt(1.0-this.es*SPHI0*SPHI0);
- /* ellipsoidal (geodetic) height */
- Height = P*CPHI0+Z*SPHI0-RN*(1.0-this.es*SPHI0*SPHI0);
- RK = this.es*RN/(RN+Height);
- RX = 1.0/Math.sqrt(1.0-RK*(2.0-RK)*ST*ST);
- CPHI = ST*(1.0-RK)*RX;
- SPHI = CT*RX;
- SDPHI = SPHI*CPHI0-CPHI*SPHI0;
- CPHI0 = CPHI;
- SPHI0 = SPHI;
- }
- while (SDPHI*SDPHI > genau2 && iter < maxiter);
- /* ellipsoidal (geodetic) latitude */
- Latitude=Math.atan(SPHI/Math.abs(CPHI));
- p.x = Longitude;
- p.y = Latitude;
- p.z = Height;
- return p;
- }, // cs_geocentric_to_geodetic()
- /** Convert_Geocentric_To_Geodetic
- * The method used here is derived from 'An Improved Algorithm for
- * Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996
- */
- geocentric_to_geodetic_noniter : function (p) {
- var X = p.x;
- var Y = p.y;
- var Z = p.z ? p.z : 0; //Z value not always supplied
- var Longitude;
- var Latitude;
- var Height;
- var W; /* distance from Z axis */
- var W2; /* square of distance from Z axis */
- var T0; /* initial estimate of vertical component */
- var T1; /* corrected estimate of vertical component */
- var S0; /* initial estimate of horizontal component */
- var S1; /* corrected estimate of horizontal component */
- var Sin_B0; /* Math.sin(B0), B0 is estimate of Bowring aux variable */
- var Sin3_B0; /* cube of Math.sin(B0) */
- var Cos_B0; /* Math.cos(B0) */
- var Sin_p1; /* Math.sin(phi1), phi1 is estimated latitude */
- var Cos_p1; /* Math.cos(phi1) */
- var Rn; /* Earth radius at location */
- var Sum; /* numerator of Math.cos(phi1) */
- var At_Pole; /* indicates location is in polar region */
- X = parseFloat(X); // cast from string to float
- Y = parseFloat(Y);
- Z = parseFloat(Z);
- At_Pole = false;
- if (X != 0.0)
- {
- Longitude = Math.atan2(Y,X);
- }
- else
- {
- if (Y > 0)
- {
- Longitude = Proj4js.common.HALF_PI;
- }
- else if (Y < 0)
- {
- Longitude = -Proj4js.common.HALF_PI;
- }
- else
- {
- At_Pole = true;
- Longitude = 0.0;
- if (Z > 0.0)
- { /* north pole */
- Latitude = Proj4js.common.HALF_PI;
- }
- else if (Z < 0.0)
- { /* south pole */
- Latitude = -Proj4js.common.HALF_PI;
- }
- else
- { /* center of earth */
- Latitude = Proj4js.common.HALF_PI;
- Height = -this.b;
- return;
- }
- }
- }
- W2 = X*X + Y*Y;
- W = Math.sqrt(W2);
- T0 = Z * Proj4js.common.AD_C;
- S0 = Math.sqrt(T0 * T0 + W2);
- Sin_B0 = T0 / S0;
- Cos_B0 = W / S0;
- Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
- T1 = Z + this.b * this.ep2 * Sin3_B0;
- Sum = W - this.a * this.es * Cos_B0 * Cos_B0 * Cos_B0;
- S1 = Math.sqrt(T1*T1 + Sum * Sum);
- Sin_p1 = T1 / S1;
- Cos_p1 = Sum / S1;
- Rn = this.a / Math.sqrt(1.0 - this.es * Sin_p1 * Sin_p1);
- if (Cos_p1 >= Proj4js.common.COS_67P5)
- {
- Height = W / Cos_p1 - Rn;
- }
- else if (Cos_p1 <= -Proj4js.common.COS_67P5)
- {
- Height = W / -Cos_p1 - Rn;
- }
- else
- {
- Height = Z / Sin_p1 + Rn * (this.es - 1.0);
- }
- if (At_Pole == false)
- {
- Latitude = Math.atan(Sin_p1 / Cos_p1);
- }
- p.x = Longitude;
- p.y = Latitude;
- p.z = Height;
- return p;
- }, // geocentric_to_geodetic_noniter()
- /****************************************************************/
- // pj_geocentic_to_wgs84( p )
- // p = point to transform in geocentric coordinates (x,y,z)
- geocentric_to_wgs84 : function ( p ) {
- if( this.datum_type == Proj4js.common.PJD_3PARAM )
- {
- // if( x[io] == HUGE_VAL )
- // continue;
- p.x += this.datum_params[0];
- p.y += this.datum_params[1];
- p.z += this.datum_params[2];
- }
- else if (this.datum_type == Proj4js.common.PJD_7PARAM)
- {
- var Dx_BF =this.datum_params[0];
- var Dy_BF =this.datum_params[1];
- var Dz_BF =this.datum_params[2];
- var Rx_BF =this.datum_params[3];
- var Ry_BF =this.datum_params[4];
- var Rz_BF =this.datum_params[5];
- var M_BF =this.datum_params[6];
- // if( x[io] == HUGE_VAL )
- // continue;
- var x_out = M_BF*( p.x - Rz_BF*p.y + Ry_BF*p.z) + Dx_BF;
- var y_out = M_BF*( Rz_BF*p.x + p.y - Rx_BF*p.z) + Dy_BF;
- var z_out = M_BF*(-Ry_BF*p.x + Rx_BF*p.y + p.z) + Dz_BF;
- p.x = x_out;
- p.y = y_out;
- p.z = z_out;
- }
- }, // cs_geocentric_to_wgs84
- /****************************************************************/
- // pj_geocentic_from_wgs84()
- // coordinate system definition,
- // point to transform in geocentric coordinates (x,y,z)
- geocentric_from_wgs84 : function( p ) {
- if( this.datum_type == Proj4js.common.PJD_3PARAM )
- {
- //if( x[io] == HUGE_VAL )
- // continue;
- p.x -= this.datum_params[0];
- p.y -= this.datum_params[1];
- p.z -= this.datum_params[2];
- }
- else if (this.datum_type == Proj4js.common.PJD_7PARAM)
- {
- var Dx_BF =this.datum_params[0];
- var Dy_BF =this.datum_params[1];
- var Dz_BF =this.datum_params[2];
- var Rx_BF =this.datum_params[3];
- var Ry_BF =this.datum_params[4];
- var Rz_BF =this.datum_params[5];
- var M_BF =this.datum_params[6];
- var x_tmp = (p.x - Dx_BF) / M_BF;
- var y_tmp = (p.y - Dy_BF) / M_BF;
- var z_tmp = (p.z - Dz_BF) / M_BF;
- //if( x[io] == HUGE_VAL )
- // continue;
- p.x = x_tmp + Rz_BF*y_tmp - Ry_BF*z_tmp;
- p.y = -Rz_BF*x_tmp + y_tmp + Rx_BF*z_tmp;
- p.z = Ry_BF*x_tmp - Rx_BF*y_tmp + z_tmp;
- } //cs_geocentric_from_wgs84()
- }
- });
- /** point object, nothing fancy, just allows values to be
- passed back and forth by reference rather than by value.
- Other point classes may be used as long as they have
- x and y properties, which will get modified in the transform method.
- */
- Proj4js.Point = Proj4js.Class({
- /**
- * Constructor: Proj4js.Point
- *
- * Parameters:
- * - x {float} or {Array} either the first coordinates component or
- * the full coordinates
- * - y {float} the second component
- * - z {float} the third component, optional.
- */
- initialize : function(x,y,z) {
- if (typeof x == 'object') {
- this.x = x[0];
- this.y = x[1];
- this.z = x[2] || 0.0;
- } else if (typeof x == 'string' && typeof y == 'undefined') {
- var coords = x.split(',');
- this.x = parseFloat(coords[0]);
- this.y = parseFloat(coords[1]);
- this.z = parseFloat(coords[2]) || 0.0;
- } else {
- this.x = x;
- this.y = y;
- this.z = z || 0.0;
- }
- },
- /**
- * APIMethod: clone
- * Build a copy of a Proj4js.Point object.
- *
- * Return:
- * {Proj4js}.Point the cloned point.
- */
- clone : function() {
- return new Proj4js.Point(this.x, this.y, this.z);
- },
- /**
- * APIMethod: toString
- * Return a readable string version of the point
- *
- * Return:
- * {String} String representation of Proj4js.Point object.
- * (ex. <i>"x=5,y=42"</i>)
- */
- toString : function() {
- return ("x=" + this.x + ",y=" + this.y);
- },
- /**
- * APIMethod: toShortString
- * Return a short string version of the point.
- *
- * Return:
- * {String} Shortened String representation of Proj4js.Point object.
- * (ex. <i>"5, 42"</i>)
- */
- toShortString : function() {
- return (this.x + ", " + this.y);
- }
- });
- Proj4js.PrimeMeridian = {
- "greenwich": 0.0, //"0dE",
- "lisbon": -9.131906111111, //"9d07'54.862\"W",
- "paris": 2.337229166667, //"2d20'14.025\"E",
- "bogota": -74.080916666667, //"74d04'51.3\"W",
- "madrid": -3.687938888889, //"3d41'16.58\"W",
- "rome": 12.452333333333, //"12d27'8.4\"E",
- "bern": 7.439583333333, //"7d26'22.5\"E",
- "jakarta": 106.807719444444, //"106d48'27.79\"E",
- "ferro": -17.666666666667, //"17d40'W",
- "brussels": 4.367975, //"4d22'4.71\"E",
- "stockholm": 18.058277777778, //"18d3'29.8\"E",
- "athens": 23.7163375, //"23d42'58.815\"E",
- "oslo": 10.722916666667 //"10d43'22.5\"E"
- };
- Proj4js.Ellipsoid = {
- "MERIT": {a:6378137.0, rf:298.257, ellipseName:"MERIT 1983"},
- "SGS85": {a:6378136.0, rf:298.257, ellipseName:"Soviet Geodetic System 85"},
- "GRS80": {a:6378137.0, rf:298.257222101, ellipseName:"GRS 1980(IUGG, 1980)"},
- "IAU76": {a:6378140.0, rf:298.257, ellipseName:"IAU 1976"},
- "airy": {a:6377563.396, b:6356256.910, ellipseName:"Airy 1830"},
- "APL4.": {a:6378137, rf:298.25, ellipseName:"Appl. Physics. 1965"},
- "NWL9D": {a:6378145.0, rf:298.25, ellipseName:"Naval Weapons Lab., 1965"},
- "mod_airy": {a:6377340.189, b:6356034.446, ellipseName:"Modified Airy"},
- "andrae": {a:6377104.43, rf:300.0, ellipseName:"Andrae 1876 (Den., Iclnd.)"},
- "aust_SA": {a:6378160.0, rf:298.25, ellipseName:"Australian Natl & S. Amer. 1969"},
- "GRS67": {a:6378160.0, rf:298.2471674270, ellipseName:"GRS 67(IUGG 1967)"},
- "bessel": {a:6377397.155, rf:299.1528128, ellipseName:"Bessel 1841"},
- "bess_nam": {a:6377483.865, rf:299.1528128, ellipseName:"Bessel 1841 (Namibia)"},
- "clrk66": {a:6378206.4, b:6356583.8, ellipseName:"Clarke 1866"},
- "clrk80": {a:6378249.145, rf:293.4663, ellipseName:"Clarke 1880 mod."},
- "CPM": {a:6375738.7, rf:334.29, ellipseName:"Comm. des Poids et Mesures 1799"},
- "delmbr": {a:6376428.0, rf:311.5, ellipseName:"Delambre 1810 (Belgium)"},
- "engelis": {a:6378136.05, rf:298.2566, ellipseName:"Engelis 1985"},
- "evrst30": {a:6377276.345, rf:300.8017, ellipseName:"Everest 1830"},
- "evrst48": {a:6377304.063, rf:300.8017, ellipseName:"Everest 1948"},
- "evrst56": {a:6377301.243, rf:300.8017, ellipseName:"Everest 1956"},
- "evrst69": {a:6377295.664, rf:300.8017, ellipseName:"Everest 1969"},
- "evrstSS": {a:6377298.556, rf:300.8017, ellipseName:"Everest (Sabah & Sarawak)"},
- "fschr60": {a:6378166.0, rf:298.3, ellipseName:"Fischer (Mercury Datum) 1960"},
- "fschr60m": {a:6378155.0, rf:298.3, ellipseName:"Fischer 1960"},
- "fschr68": {a:6378150.0, rf:298.3, ellipseName:"Fischer 1968"},
- "helmert": {a:6378200.0, rf:298.3, ellipseName:"Helmert 1906"},
- "hough": {a:6378270.0, rf:297.0, ellipseName:"Hough"},
- "intl": {a:6378388.0, rf:297.0, ellipseName:"International 1909 (Hayford)"},
- "kaula": {a:6378163.0, rf:298.24, ellipseName:"Kaula 1961"},
- "lerch": {a:6378139.0, rf:298.257, ellipseName:"Lerch 1979"},
- "mprts": {a:6397300.0, rf:191.0, ellipseName:"Maupertius 1738"},
- "new_intl": {a:6378157.5, b:6356772.2, ellipseName:"New International 1967"},
- "plessis": {a:6376523.0, rf:6355863.0, ellipseName:"Plessis 1817 (France)"},
- "krass": {a:6378245.0, rf:298.3, ellipseName:"Krassovsky, 1942"},
- "SEasia": {a:6378155.0, b:6356773.3205, ellipseName:"Southeast Asia"},
- "walbeck": {a:6376896.0, b:6355834.8467, ellipseName:"Walbeck"},
- "WGS60": {a:6378165.0, rf:298.3, ellipseName:"WGS 60"},
- "WGS66": {a:6378145.0, rf:298.25, ellipseName:"WGS 66"},
- "WGS72": {a:6378135.0, rf:298.26, ellipseName:"WGS 72"},
- "WGS84": {a:6378137.0, rf:298.257223563, ellipseName:"WGS 84"},
- "sphere": {a:6370997.0, b:6370997.0, ellipseName:"Normal Sphere (r=6370997)"}
- };
- Proj4js.Datum = {
- "WGS84": {towgs84: "0,0,0", ellipse: "WGS84", datumName: "WGS84"},
- "GGRS87": {towgs84: "-199.87,74.79,246.62", ellipse: "GRS80", datumName: "Greek_Geodetic_Reference_System_1987"},
- "NAD83": {towgs84: "0,0,0", ellipse: "GRS80", datumName: "North_American_Datum_1983"},
- "NAD27": {nadgrids: "@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat", ellipse: "clrk66", datumName: "North_American_Datum_1927"},
- "potsdam": {towgs84: "606.0,23.0,413.0", ellipse: "bessel", datumName: "Potsdam Rauenberg 1950 DHDN"},
- "carthage": {towgs84: "-263.0,6.0,431.0", ellipse: "clark80", datumName: "Carthage 1934 Tunisia"},
- "hermannskogel": {towgs84: "653.0,-212.0,449.0", ellipse: "bessel", datumName: "Hermannskogel"},
- "ire65": {towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15", ellipse: "mod_airy", datumName: "Ireland 1965"},
- "nzgd49": {towgs84: "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993", ellipse: "intl", datumName: "New Zealand Geodetic Datum 1949"},
- "OSGB36": {towgs84: "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894", ellipse: "airy", datumName: "Airy 1830"}
- };
- Proj4js.WGS84 = new Proj4js.Proj('WGS84');
- Proj4js.Datum['OSB36'] = Proj4js.Datum['OSGB36']; //as returned from spatialreference.org
- //lookup table to go from the projection name in WKT to the Proj4js projection name
- //build this out as required
- Proj4js.wktProjections = {
- "Lambert Tangential Conformal Conic Projection": "lcc",
- "Mercator": "merc",
- "Popular Visualisation Pseudo Mercator": "merc",
- "Mercator_1SP": "merc",
- "Transverse_Mercator": "tmerc",
- "Transverse Mercator": "tmerc",
- "Lambert Azimuthal Equal Area": "laea",
- "Universal Transverse Mercator System": "utm"
- };
- Proj4js.defs['EPSG:3857'] = Proj4js.defs['EPSG:3785'];
- /* ======================================================================
- projCode/aea.js
- ====================================================================== */
- /*******************************************************************************
- NAME ALBERS CONICAL EQUAL AREA
- PURPOSE: Transforms input longitude and latitude to Easting and Northing
- for the Albers Conical Equal Area projection. The longitude
- and latitude must be in radians. The Easting and Northing
- values will be returned in meters.
- PROGRAMMER DATE
- ---------- ----
- T. Mittan, Feb, 1992
- ALGORITHM REFERENCES
- 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
- U.S. Geological Survey Professional Paper 1453 , United State Government
- Printing Office, Washington D.C., 1989.
- *******************************************************************************/
- Proj4js.Proj.aea = {
- init : function() {
- if (Math.abs(this.lat1 + this.lat2) < Proj4js.common.EPSLN) {
- Proj4js.reportError("aeaInitEqualLatitudes");
- return;
- }
- this.temp = this.b / this.a;
- this.es = 1.0 - Math.pow(this.temp,2);
- this.e3 = Math.sqrt(this.es);
- this.sin_po=Math.sin(this.lat1);
- this.cos_po=Math.cos(this.lat1);
- this.t1=this.sin_po;
- this.con = this.sin_po;
- this.ms1 = Proj4js.common.msfnz(this.e3,this.sin_po,this.cos_po);
- this.qs1 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po);
- this.sin_po=Math.sin(this.lat2);
- this.cos_po=Math.cos(this.lat2);
- this.t2=this.sin_po;
- this.ms2 = Proj4js.common.msfnz(this.e3,this.sin_po,this.cos_po);
- this.qs2 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po);
- this.sin_po=Math.sin(this.lat0);
- this.cos_po=Math.cos(this.lat0);
- this.t3=this.sin_po;
- this.qs0 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po);
- if (Math.abs(this.lat1 - this.lat2) > Proj4js.common.EPSLN) {
- this.ns0 = (this.ms1 * this.ms1 - this.ms2 *this.ms2)/ (this.qs2 - this.qs1);
- } else {
- this.ns0 = this.con;
- }
- this.c = this.ms1 * this.ms1 + this.ns0 * this.qs1;
- this.rh = this.a * Math.sqrt(this.c - this.ns0 * this.qs0)/this.ns0;
- },
- /* Albers Conical Equal Area forward equations--mapping lat,long to x,y
- -------------------------------------------------------------------*/
- forward: function(p){
- var lon=p.x;
- var lat=p.y;
- this.sin_phi=Math.sin(lat);
- this.cos_phi=Math.cos(lat);
- var qs = Proj4js.common.qsfnz(this.e3,this.sin_phi,this.cos_phi);
- var rh1 =this.a * Math.sqrt(this.c - this.ns0 * qs)/this.ns0;
- var theta = this.ns0 * Proj4js.common.adjust_lon(lon - this.long0);
- var x = rh1 * Math.sin(theta) + this.x0;
- var y = this.rh - rh1 * Math.cos(theta) + this.y0;
- p.x = x;
- p.y = y;
- return p;
- },
- inverse: function(p) {
- var rh1,qs,con,theta,lon,lat;
- p.x -= this.x0;
- p.y = this.rh - p.y + this.y0;
- if (this.ns0 >= 0) {
- rh1 = Math.sqrt(p.x *p.x + p.y * p.y);
- con = 1.0;
- } else {
- rh1 = -Math.sqrt(p.x * p.x + p.y *p.y);
- con = -1.0;
- }
- theta = 0.0;
- if (rh1 != 0.0) {
- theta = Math.atan2(con * p.x, con * p.y);
- }
- con = rh1 * this.ns0 / this.a;
- qs = (this.c - con * con) / this.ns0;
- if (this.e3 >= 1e-10) {
- con = 1 - .5 * (1.0 -this.es) * Math.log((1.0 - this.e3) / (1.0 + this.e3))/this.e3;
- if (Math.abs(Math.abs(con) - Math.abs(qs)) > .0000000001 ) {
- lat = this.phi1z(this.e3,qs);
- } else {
- if (qs >= 0) {
- lat = .5 * Proj4js.common.PI;
- } else {
- lat = -.5 * Proj4js.common.PI;
- }
- }
- } else {
- lat = this.phi1z(this.e3,qs);
- }
- lon = Proj4js.common.adjust_lon(theta/this.ns0 + this.long0);
- p.x = lon;
- p.y = lat;
- return p;
- },
-
- /* Function to compute phi1, the latitude for the inverse of the
- Albers Conical Equal-Area projection.
- -------------------------------------------*/
- phi1z: function (eccent,qs) {
- var sinphi, cosphi, con, com, dphi;
- var phi = Proj4js.common.asinz(.5 * qs);
- if (eccent < Proj4js.common.EPSLN) return phi;
-
- var eccnts = eccent * eccent;
- for (var i = 1; i <= 25; i++) {
- sinphi = Math.sin(phi);
- cosphi = Math.cos(phi);
- con = eccent * sinphi;
- com = 1.0 - con * con;
- dphi = .5 * com * com / cosphi * (qs / (1.0 - eccnts) - sinphi / com + .5 / eccent * Math.log((1.0 - con) / (1.0 + con)));
- phi = phi + dphi;
- if (Math.abs(dphi) <= 1e-7) return phi;
- }
- Proj4js.reportError("aea:phi1z:Convergence error");
- return null;
- }
-
- };
- /* ======================================================================
- projCode/sterea.js
- ====================================================================== */
- Proj4js.Proj.sterea = {
- dependsOn : 'gauss',
- init : function() {
- Proj4js.Proj['gauss'].init.apply(this);
- if (!this.rc) {
- Proj4js.reportError("sterea:init:E_ERROR_0");
- return;
- }
- this.sinc0 = Math.sin(this.phic0);
- this.cosc0 = Math.cos(this.phic0);
- this.R2 = 2.0 * this.rc;
- if (!this.title) this.title = "Oblique Stereographic Alternative";
- },
- forward : function(p) {
- var sinc, cosc, cosl, k;
- p.x = Proj4js.common.adjust_lon(p.x-this.long0); /* adjust del longitude */
- Proj4js.Proj['gauss'].forward.apply(this, [p]);
- sinc = Math.sin(p.y);
- cosc = Math.cos(p.y);
- cosl = Math.cos(p.x);
- k = this.k0 * this.R2 / (1.0 + this.sinc0 * sinc + this.cosc0 * cosc * cosl);
- p.x = k * cosc * Math.sin(p.x);
- p.y = k * (this.cosc0 * sinc - this.sinc0 * cosc * cosl);
- p.x = this.a * p.x + this.x0;
- p.y = this.a * p.y + this.y0;
- return p;
- },
- inverse : function(p) {
- var sinc, cosc, lon, lat, rho;
- p.x = (p.x - this.x0) / this.a; /* descale and de-offset */
- p.y = (p.y - this.y0) / this.a;
- p.x /= this.k0;
- p.y /= this.k0;
- if ( (rho = Math.sqrt(p.x*p.x + p.y*p.y)) ) {
- var c = 2.0 * Math.atan2(rho, this.R2);
- sinc = Math.sin(c);
- cosc = Math.cos(c);
- lat = Math.asin(cosc * this.sinc0 + p.y * sinc * this.cosc0 / rho);
- lon = Math.atan2(p.x * sinc, rho * this.cosc0 * cosc - p.y * this.sinc0 * sinc);
- } else {
- lat = this.phic0;
- lon = 0.;
- }
- p.x = lon;
- p.y = lat;
- Proj4js.Proj['gauss'].inverse.apply(this,[p]);
- p.x = Proj4js.common.adjust_lon(p.x + this.long0); /* adjust longitude to CM */
- return p;
- }
- };
- /* ======================================================================
- projCode/poly.js
- ====================================================================== */
- /* Function to compute, phi4, the latitude for the inverse of the
- Polyconic projection.
- ------------------------------------------------------------*/
- function phi4z (eccent,e0,e1,e2,e3,a,b,c,phi) {
- var sinphi, sin2ph, tanphi, ml, mlp, con1, con2, con3, dphi, i;
- phi = a;
- for (i = 1; i <= 15; i++) {
- sinphi = Math.sin(phi);
- tanphi = Math.tan(phi);
- c = tanphi * Math.sqrt (1.0 - eccent * sinphi * sinphi);
- sin2ph = Math.sin (2.0 * phi);
- /*
- ml = e0 * *phi - e1 * sin2ph + e2 * sin (4.0 * *phi);
- mlp = e0 - 2.0 * e1 * cos (2.0 * *phi) + 4.0 * e2 * cos (4.0 * *phi);
- */
- ml = e0 * phi - e1 * sin2ph + e2 * Math.sin (4.0 * phi) - e3 * Math.sin (6.0 * phi);
- mlp = e0 - 2.0 * e1 * Math.cos (2.0 * phi) + 4.0 * e2 * Math.cos (4.0 * phi) - 6.0 * e3 * Math.cos (6.0 * phi);
- con1 = 2.0 * ml + c * (ml * ml + b) - 2.0 * a * (c * ml + 1.0);
- con2 = eccent * sin2ph * (ml * ml + b - 2.0 * a * ml) / (2.0 *c);
- con3 = 2.0 * (a - ml) * (c * mlp - 2.0 / sin2ph) - 2.0 * mlp;
- dphi = con1 / (con2 + con3);
- phi += dphi;
- if (Math.abs(dphi) <= .0000000001 ) return(phi);
- }
- Proj4js.reportError("phi4z: No convergence");
- return null;
- }
- /* Function to compute the constant e4 from the input of the eccentricity
- of the spheroid, x. This constant is used in the Polar Stereographic
- projection.
- --------------------------------------------------------------------*/
- function e4fn(x) {
- var con, com;
- con = 1.0 + x;
- com = 1.0 - x;
- return (Math.sqrt((Math.pow(con,con))*(Math.pow(com,com))));
- }
- /*******************************************************************************
- NAME POLYCONIC
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the Polyconic projection. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- PROGRAMMER DATE
- ---------- ----
- T. Mittan Mar, 1993
- ALGORITHM REFERENCES
- 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
- U.S. Geological Survey Professional Paper 1453 , United State Government
- Printing Office, Washington D.C., 1989.
- *******************************************************************************/
- Proj4js.Proj.poly = {
- /* Initialize the POLYCONIC projection
- ----------------------------------*/
- init: function() {
- var temp; /* temporary variable */
- if (this.lat0 == 0) this.lat0 = 90;//this.lat0 ca
- /* Place parameters in static storage for common use
- -------------------------------------------------*/
- this.temp = this.b / this.a;
- this.es = 1.0 - Math.pow(this.temp,2);// devait etre dans tmerc.js mais n y est pas donc je commente sinon retour de valeurs nulles
- this.e = Math.sqrt(this.es);
- this.e0 = Proj4js.common.e0fn(this.es);
- this.e1 = Proj4js.common.e1fn(this.es);
- this.e2 = Proj4js.common.e2fn(this.es);
- this.e3 = Proj4js.common.e3fn(this.es);
- this.ml0 = Proj4js.common.mlfn(this.e0, this.e1,this.e2, this.e3, this.lat0);//si que des zeros le calcul ne se fait pas
- //if (!this.ml0) {this.ml0=0;}
- },
- /* Polyconic forward equations--mapping lat,long to x,y
- ---------------------------------------------------*/
- forward: function(p) {
- var sinphi, cosphi; /* sin and cos value */
- var al; /* temporary values */
- var c; /* temporary values */
- var con, ml; /* cone constant, small m */
- var ms; /* small m */
- var x,y;
- var lon=p.x;
- var lat=p.y;
- con = Proj4js.common.adjust_lon(lon - this.long0);
- if (Math.abs(lat) <= .0000001) {
- x = this.x0 + this.a * con;
- y = this.y0 - this.a * this.ml0;
- } else {
- sinphi = Math.sin(lat);
- cosphi = Math.cos(lat);
- ml = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat);
- ms = Proj4js.common.msfnz(this.e,sinphi,cosphi);
- con = sinphi;
- x = this.x0 + this.a * ms * Math.sin(con)/sinphi;
- y = this.y0 + this.a * (ml - this.ml0 + ms * (1.0 - Math.cos(con))/sinphi);
- }
- p.x=x;
- p.y=y;
- return p;
- },
- /* Inverse equations
- -----------------*/
- inverse: function(p) {
- var sin_phi, cos_phi; /* sin and cos value */
- var al; /* temporary values */
- var b; /* temporary values */
- var c; /* temporary values */
- var con, ml; /* cone constant, small m */
- var iflg; /* error flag */
- var lon,lat;
- p.x -= this.x0;
- p.y -= this.y0;
- al = this.ml0 + p.y/this.a;
- iflg = 0;
- if (Math.abs(al) <= .0000001) {
- lon = p.x/this.a + this.long0;
- lat = 0.0;
- } else {
- b = al * al + (p.x/this.a) * (p.x/this.a);
- iflg = phi4z(this.es,this.e0,this.e1,this.e2,this.e3,this.al,b,c,lat);
- if (iflg != 1) return(iflg);
- lon = Proj4js.common.adjust_lon((Proj4js.common.asinz(p.x * c / this.a) / Math.sin(lat)) + this.long0);
- }
- p.x=lon;
- p.y=lat;
- return p;
- }
- };
- /* ======================================================================
- projCode/equi.js
- ====================================================================== */
- /*******************************************************************************
- NAME EQUIRECTANGULAR
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the Equirectangular projection. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- PROGRAMMER DATE
- ---------- ----
- T. Mittan Mar, 1993
- ALGORITHM REFERENCES
- 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
- U.S. Geological Survey Professional Paper 1453 , United State Government
- Printing Office, Washington D.C., 1989.
- *******************************************************************************/
- Proj4js.Proj.equi = {
- init: function() {
- if(!this.x0) this.x0=0;
- if(!this.y0) this.y0=0;
- if(!this.lat0) this.lat0=0;
- if(!this.long0) this.long0=0;
- ///this.t2;
- },
- /* Equirectangular forward equations--mapping lat,long to x,y
- ---------------------------------------------------------*/
- forward: function(p) {
- var lon=p.x;
- var lat=p.y;
- var dlon = Proj4js.common.adjust_lon(lon - this.long0);
- var x = this.x0 +this. a * dlon *Math.cos(this.lat0);
- var y = this.y0 + this.a * lat;
- this.t1=x;
- this.t2=Math.cos(this.lat0);
- p.x=x;
- p.y=y;
- return p;
- }, //equiFwd()
- /* Equirectangular inverse equations--mapping x,y to lat/long
- ---------------------------------------------------------*/
- inverse: function(p) {
- p.x -= this.x0;
- p.y -= this.y0;
- var lat = p.y /this. a;
- if ( Math.abs(lat) > Proj4js.common.HALF_PI) {
- Proj4js.reportError("equi:Inv:DataError");
- }
- var lon = Proj4js.common.adjust_lon(this.long0 + p.x / (this.a * Math.cos(this.lat0)));
- p.x=lon;
- p.y=lat;
- }//equiInv()
- };
- /* ======================================================================
- projCode/merc.js
- ====================================================================== */
- /*******************************************************************************
- NAME MERCATOR
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the Mercator projection. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- PROGRAMMER DATE
- ---------- ----
- D. Steinwand, EROS Nov, 1991
- T. Mittan Mar, 1993
- ALGORITHM REFERENCES
- 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
- U.S. Geological Survey Professional Paper 1453 , United State Government
- Printing Office, Washington D.C., 1989.
- *******************************************************************************/
- //static double r_major = a; /* major axis */
- //static double r_minor = b; /* minor axis */
- //static double lon_center = long0; /* Center longitude (projection center) */
- //static double lat_origin = lat0; /* center latitude */
- //static double e,es; /* eccentricity constants */
- //static double m1; /* small value m */
- //static double false_northing = y0; /* y offset in meters */
- //static double false_easting = x0; /* x offset in meters */
- //scale_fact = k0
- Proj4js.Proj.merc = {
- init : function() {
- //?this.temp = this.r_minor / this.r_major;
- //this.temp = this.b / this.a;
- //this.es = 1.0 - Math.sqrt(this.temp);
- //this.e = Math.sqrt( this.es );
- //?this.m1 = Math.cos(this.lat_origin) / (Math.sqrt( 1.0 - this.es * Math.sin(this.lat_origin) * Math.sin(this.lat_origin)));
- //this.m1 = Math.cos(0.0) / (Math.sqrt( 1.0 - this.es * Math.sin(0.0) * Math.sin(0.0)));
- if (this.lat_ts) {
- if (this.sphere) {
- this.k0 = Math.cos(this.lat_ts);
- } else {
- this.k0 = Proj4js.common.msfnz(this.es, Math.sin(this.lat_ts), Math.cos(this.lat_ts));
- }
- }
- },
- /* Mercator forward equations--mapping lat,long to x,y
- --------------------------------------------------*/
- forward : function(p) {
- //alert("ll2m coords : "+coords);
- var lon = p.x;
- var lat = p.y;
- // convert to radians
- if ( lat*Proj4js.common.R2D > 90.0 &&
- lat*Proj4js.common.R2D < -90.0 &&
- lon*Proj4js.common.R2D > 180.0 &&
- lon*Proj4js.common.R2D < -180.0) {
- Proj4js.reportError("merc:forward: llInputOutOfRange: "+ lon +" : " + lat);
- return null;
- }
- var x,y;
- if(Math.abs( Math.abs(lat) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN) {
- Proj4js.reportError("merc:forward: ll2mAtPoles");
- return null;
- } else {
- if (this.sphere) {
- x = this.x0 + this.a * this.k0 * Proj4js.common.adjust_lon(lon - this.long0);
- y = this.y0 + this.a * this.k0 * Math.log(Math.tan(Proj4js.common.FORTPI + 0.5*lat));
- } else {
- var sinphi = Math.sin(lat);
- var ts = Proj4js.common.tsfnz(this.e,lat,sinphi);
- x = this.x0 + this.a * this.k0 * Proj4js.common.adjust_lon(lon - this.long0);
- y = this.y0 - this.a * this.k0 * Math.log(ts);
- }
- p.x = x;
- p.y = y;
- return p;
- }
- },
- /* Mercator inverse equations--mapping x,y to lat/long
- --------------------------------------------------*/
- inverse : function(p) {
- var x = p.x - this.x0;
- var y = p.y - this.y0;
- var lon,lat;
- if (this.sphere) {
- lat = Proj4js.common.HALF_PI - 2.0 * Math.atan(Math.exp(-y / this.a * this.k0));
- } else {
- var ts = Math.exp(-y / (this.a * this.k0));
- lat = Proj4js.common.phi2z(this.e,ts);
- if(lat == -9999) {
- Proj4js.reportError("merc:inverse: lat = -9999");
- return null;
- }
- }
- lon = Proj4js.common.adjust_lon(this.long0+ x / (this.a * this.k0));
- p.x = lon;
- p.y = lat;
- return p;
- }
- };
- /* ======================================================================
- projCode/utm.js
- ====================================================================== */
- /*******************************************************************************
- NAME TRANSVERSE MERCATOR
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the Transverse Mercator projection. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- ALGORITHM REFERENCES
- 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
- U.S. Geological Survey Professional Paper 1453 , United State Government
- Printing Office, Washington D.C., 1989.
- *******************************************************************************/
- /**
- Initialize Transverse Mercator projection
- */
- Proj4js.Proj.utm = {
- dependsOn : 'tmerc',
- init : function() {
- if (!this.zone) {
- Proj4js.reportError("utm:init: zone must be specified for UTM");
- return;
- }
- this.lat0 = 0.0;
- this.long0 = ((6 * Math.abs(this.zone)) - 183) * Proj4js.common.D2R;
- this.x0 = 500000.0;
- this.y0 = this.utmSouth ? 10000000.0 : 0.0;
- this.k0 = 0.9996;
- Proj4js.Proj['tmerc'].init.apply(this);
- this.forward = Proj4js.Proj['tmerc'].forward;
- this.inverse = Proj4js.Proj['tmerc'].inverse;
- }
- };
- /* ======================================================================
- projCode/eqdc.js
- ====================================================================== */
- /*******************************************************************************
- NAME EQUIDISTANT CONIC
- PURPOSE: Transforms input longitude and latitude to Easting and Northing
- for the Equidistant Conic projection. The longitude and
- latitude must be in radians. The Easting and Northing values
- will be returned in meters.
- PROGRAMMER DATE
- ---------- ----
- T. Mittan Mar, 1993
- ALGORITHM REFERENCES
- 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
- U.S. Geological Survey Professional Paper 1453 , United State Government
- Printing Office, Washington D.C., 1989.
- *******************************************************************************/
- /* Variables common to all subroutines in this code file
- -----------------------------------------------------*/
- Proj4js.Proj.eqdc = {
- /* Initialize the Equidistant Conic projection
- ------------------------------------------*/
- init: function() {
- /* Place parameters in static storage for common use
- -------------------------------------------------*/
- if(!this.mode) this.mode=0;//chosen default mode
- this.temp = this.b / this.a;
- this.es = 1.0 - Math.pow(this.temp,2);
- this.e = Math.sqrt(this.es);
- this.e0 = Proj4js.common.e0fn(this.es);
- this.e1 = Proj4js.common.e1fn(this.es);
- this.e2 = Proj4js.common.e2fn(this.es);
- this.e3 = Proj4js.common.e3fn(this.es);
- this.sinphi=Math.sin(this.lat1);
- this.cosphi=Math.cos(this.lat1);
- this.ms1 = Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi);
- this.ml1 = Proj4js.common.mlfn(this.e0, this.e1, this.e2,this.e3, this.lat1);
- /* format B
- ---------*/
- if (this.mode != 0) {
- if (Math.abs(this.lat1 + this.lat2) < Proj4js.common.EPSLN) {
- Proj4js.reportError("eqdc:Init:EqualLatitudes");
- //return(81);
- }
- this.sinphi=Math.sin(this.lat2);
- this.cosphi=Math.cos(this.lat2);
- this.ms2 = Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi);
- this.ml2 = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat2);
- if (Math.abs(this.lat1 - this.lat2) >= Proj4js.common.EPSLN) {
- this.ns = (this.ms1 - this.ms2) / (this.ml2 - this.ml1);
- } else {
- this.ns = this.sinphi;
- }
- } else {
- this.ns = this.sinphi;
- }
- this.g = this.ml1 + this.ms1/this.ns;
- this.ml0 = Proj4js.common.mlfn(this.e0, this.e1,this. e2, this.e3, this.lat0);
- this.rh = this.a * (this.g - this.ml0);
- },
- /* Equidistant Conic forward equations--mapping lat,long to x,y
- -----------------------------------------------------------*/
- forward: function(p) {
- var lon=p.x;
- var lat=p.y;
- /* Forward equations
- -----------------*/
- var ml = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat);
- var rh1 = this.a * (this.g - ml);
- var theta = this.ns * Proj4js.common.adjust_lon(lon - this.long0);
- var x = this.x0 + rh1 * Math.sin(theta);
- var y = this.y0 + this.rh - rh1 * Math.cos(theta);
- p.x=x;
- p.y=y;
- return p;
- },
- /* Inverse equations
- -----------------*/
- inverse: function(p) {
- p.x -= this.x0;
- p.y = this.rh - p.y + this.y0;
- var con, rh1;
- if (this.ns >= 0) {
- rh1 = Math.sqrt(p.x *p.x + p.y * p.y);
- con = 1.0;
- } else {
- rh1 = -Math.sqrt(p.x *p. x +p. y * p.y);
- con = -1.0;
- }
- var theta = 0.0;
- if (rh1 != 0.0) theta = Math.atan2(con *p.x, con *p.y);
- var ml = this.g - rh1 /this.a;
- var lat = this.phi3z(ml,this.e0,this.e1,this.e2,this.e3);
- var lon = Proj4js.common.adjust_lon(this.long0 + theta / this.ns);
- p.x=lon;
- p.y=lat;
- return p;
- },
-
- /* Function to compute latitude, phi3, for the inverse of the Equidistant
- Conic projection.
- -----------------------------------------------------------------*/
- phi3z: function(ml,e0,e1,e2,e3) {
- var phi;
- var dphi;
- phi = ml;
- for (var i = 0; i < 15; i++) {
- dphi = (ml + e1 * Math.sin(2.0 * phi) - e2 * Math.sin(4.0 * phi) + e3 * Math.sin(6.0 * phi))/ e0 - phi;
- phi += dphi;
- if (Math.abs(dphi) <= .0000000001) {
- return phi;
- }
- }
- Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations");
- return null;
- }
-
- };
- /* ======================================================================
- projCode/tmerc.js
- ====================================================================== */
- /*******************************************************************************
- NAME TRANSVERSE MERCATOR
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the Transverse Mercator projection. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- ALGORITHM REFERENCES
- 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
- U.S. Geological Survey Professional Paper 1453 , United State Government
- Printing Office, Washington D.C., 1989.
- *******************************************************************************/
- /**
- Initialize Transverse Mercator projection
- */
- Proj4js.Proj.tmerc = {
- init : function() {
- this.e0 = Proj4js.common.e0fn(this.es);
- this.e1 = Proj4js.common.e1fn(this.es);
- this.e2 = Proj4js.common.e2fn(this.es);
- this.e3 = Proj4js.common.e3fn(this.es);
- this.ml0 = this.a * Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0);
- },
- /**
- Transverse Mercator Forward - long/lat to x/y
- long/lat in radians
- */
- forward : function(p) {
- var lon = p.x;
- var lat = p.y;
- var delta_lon = Proj4js.common.adjust_lon(lon - this.long0); // Delta longitude
- var con; // cone constant
- var x, y;
- var sin_phi=Math.sin(lat);
- var cos_phi=Math.cos(lat);
- if (this.sphere) { /* spherical form */
- var b = cos_phi * Math.sin(delta_lon);
- if ((Math.abs(Math.abs(b) - 1.0)) < .0000000001) {
- Proj4js.reportError("tmerc:forward: Point projects into infinity");
- return(93);
- } else {
- x = .5 * this.a * this.k0 * Math.log((1.0 + b)/(1.0 - b));
- con = Math.acos(cos_phi * Math.cos(delta_lon)/Math.sqrt(1.0 - b*b));
- if (lat < 0) con = - con;
- y = this.a * this.k0 * (con - this.lat0);
- }
- } else {
- var al = cos_phi * delta_lon;
- var als = Math.pow(al,2);
- var c = this.ep2 * Math.pow(cos_phi,2);
- var tq = Math.tan(lat);
- var t = Math.pow(tq,2);
- con = 1.0 - this.es * Math.pow(sin_phi,2);
- var n = this.a / Math.sqrt(con);
- var ml = this.a * Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat);
- x = this.k0 * n * al * (1.0 + als / 6.0 * (1.0 - t + c + als / 20.0 * (5.0 - 18.0 * t + Math.pow(t,2) + 72.0 * c - 58.0 * this.ep2))) + this.x0;
- y = this.k0 * (ml - this.ml0 + n * tq * (als * (0.5 + als / 24.0 * (5.0 - t + 9.0 * c + 4.0 * Math.pow(c,2) + als / 30.0 * (61.0 - 58.0 * t + Math.pow(t,2) + 600.0 * c - 330.0 * this.ep2))))) + this.y0;
- }
- p.x = x; p.y = y;
- return p;
- }, // tmercFwd()
- /**
- Transverse Mercator Inverse - x/y to long/lat
- */
- inverse : function(p) {
- var con, phi; /* temporary angles */
- var delta_phi; /* difference between longitudes */
- var i;
- var max_iter = 6; /* maximun number of iterations */
- var lat, lon;
- if (this.sphere) { /* spherical form */
- var f = Math.exp(p.x/(this.a * this.k0));
- var g = .5 * (f - 1/f);
- var temp = this.lat0 + p.y/(this.a * this.k0);
- var h = Math.cos(temp);
- con = Math.sqrt((1.0 - h * h)/(1.0 + g * g));
- lat = Proj4js.common.asinz(con);
- if (temp < 0)
- lat = -lat;
- if ((g == 0) && (h == 0)) {
- lon = this.long0;
- } else {
- lon = Proj4js.common.adjust_lon(Math.atan2(g,h) + this.long0);
- }
- } else { // ellipsoidal form
- var x = p.x - this.x0;
- var y = p.y - this.y0;
- con = (this.ml0 + y / this.k0) / this.a;
- phi = con;
- for (i=0;true;i++) {
- delta_phi=((con + this.e1 * Math.sin(2.0*phi) - this.e2 * Math.sin(4.0*phi) + this.e3 * Math.sin(6.0*phi)) / this.e0) - phi;
- phi += delta_phi;
- if (Math.abs(delta_phi) <= Proj4js.common.EPSLN) break;
- if (i >= max_iter) {
- Proj4js.reportError("tmerc:inverse: Latitude failed to converge");
- return(95);
- }
- } // for()
- if (Math.abs(phi) < Proj4js.common.HALF_PI) {
- // sincos(phi, &sin_phi, &cos_phi);
- var sin_phi=Math.sin(phi);
- var cos_phi=Math.cos(phi);
- var tan_phi = Math.tan(phi);
- var c = this.ep2 * Math.pow(cos_phi,2);
- var cs = Math.pow(c,2);
- var t = Math.pow(tan_phi,2);
- var ts = Math.pow(t,2);
- con = 1.0 - this.es * Math.pow(sin_phi,2);
- var n = this.a / Math.sqrt(con);
- var r = n * (1.0 - this.es) / con;
- var d = x / (n * this.k0);
- var ds = Math.pow(d,2);
- lat = phi - (n * tan_phi * ds / r) * (0.5 - ds / 24.0 * (5.0 + 3.0 * t + 10.0 * c - 4.0 * cs - 9.0 * this.ep2 - ds / 30.0 * (61.0 + 90.0 * t + 298.0 * c + 45.0 * ts - 252.0 * this.ep2 - 3.0 * cs)));
- lon = Proj4js.common.adjust_lon(this.long0 + (d * (1.0 - ds / 6.0 * (1.0 + 2.0 * t + c - ds / 20.0 * (5.0 - 2.0 * c + 28.0 * t - 3.0 * cs + 8.0 * this.ep2 + 24.0 * ts))) / cos_phi));
- } else {
- lat = Proj4js.common.HALF_PI * Proj4js.common.sign(y);
- lon = this.long0;
- }
- }
- p.x = lon;
- p.y = lat;
- return p;
- } // tmercInv()
- };
- /* ======================================================================
- defs/GOOGLE.js
- ====================================================================== */
- Proj4js.defs["GOOGLE"]="+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";
- Proj4js.defs["EPSG:900913"]=Proj4js.defs["GOOGLE"];
- /* ======================================================================
- projCode/gstmerc.js
- ====================================================================== */
- Proj4js.Proj.gstmerc = {
- init : function() {
- // array of: a, b, lon0, lat0, k0, x0, y0
- var temp= this.b / this.a;
- this.e= Math.sqrt(1.0 - temp*temp);
- this.lc= this.long0;
- this.rs= Math.sqrt(1.0+this.e*this.e*Math.pow(Math.cos(this.lat0),4.0)/(1.0-this.e*this.e));
- var sinz= Math.sin(this.lat0);
- var pc= Math.asin(sinz/this.rs);
- var sinzpc= Math.sin(pc);
- this.cp= Proj4js.common.latiso(0.0,pc,sinzpc)-this.rs*Proj4js.common.latiso(this.e,this.lat0,sinz);
- this.n2= this.k0*this.a*Math.sqrt(1.0-this.e*this.e)/(1.0-this.e*this.e*sinz*sinz);
- this.xs= this.x0;
- this.ys= this.y0-this.n2*pc;
- if (!this.title) this.title = "Gauss Schreiber transverse mercator";
- },
- // forward equations--mapping lat,long to x,y
- // -----------------------------------------------------------------
- forward : function(p) {
- var lon= p.x;
- var lat= p.y;
- var L= this.rs*(lon-this.lc);
- var Ls= this.cp+(this.rs*Proj4js.common.latiso(this.e,lat,Math.sin(lat)));
- var lat1= Math.asin(Math.sin(L)/Proj4js.common.cosh(Ls));
- var Ls1= Proj4js.common.latiso(0.0,lat1,Math.sin(lat1));
- p.x= this.xs+(this.n2*Ls1);
- p.y= this.ys+(this.n2*Math.atan(Proj4js.common.sinh(Ls)/Math.cos(L)));
- return p;
- },
- // inverse equations--mapping x,y to lat/long
- // -----------------------------------------------------------------
- inverse : function(p) {
- var x= p.x;
- var y= p.y;
- var L= Math.atan(Proj4js.common.sinh((x-this.xs)/this.n2)/Math.cos((y-this.ys)/this.n2));
- var lat1= Math.asin(Math.sin((y-this.ys)/this.n2)/Proj4js.common.cosh((x-this.xs)/this.n2));
- var LC= Proj4js.common.latiso(0.0,lat1,Math.sin(lat1));
- p.x= this.lc+L/this.rs;
- p.y= Proj4js.common.invlatiso(this.e,(LC-this.cp)/this.rs);
- return p;
- }
- };
- /* ======================================================================
- projCode/ortho.js
- ====================================================================== */
- /*******************************************************************************
- NAME ORTHOGRAPHIC
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the Orthographic projection. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- PROGRAMMER DATE
- ---------- ----
- T. Mittan Mar, 1993
- ALGORITHM REFERENCES
- 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
- U.S. Geological Survey Professional Paper 1453 , United State Government
- Printing Office, Washington D.C., 1989.
- *******************************************************************************/
- Proj4js.Proj.ortho = {
- /* Initialize the Orthographic projection
- -------------------------------------*/
- init: function(def) {
- //double temp; /* temporary variable */
- /* Place parameters in static storage for common use
- -------------------------------------------------*/;
- this.sin_p14=Math.sin(this.lat0);
- this.cos_p14=Math.cos(this.lat0);
- },
- /* Orthographic forward equations--mapping lat,long to x,y
- ---------------------------------------------------*/
- forward: function(p) {
- var sinphi, cosphi; /* sin and cos value */
- var dlon; /* delta longitude value */
- var coslon; /* cos of longitude */
- var ksp; /* scale factor */
- var g;
- var lon=p.x;
- var lat=p.y;
- /* Forward equations
- -----------------*/
- dlon = Proj4js.common.adjust_lon(lon - this.long0);
- sinphi=Math.sin(lat);
- cosphi=Math.cos(lat);
- coslon = Math.cos(dlon);
- g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon;
- ksp = 1.0;
- if ((g > 0) || (Math.abs(g) <= Proj4js.common.EPSLN)) {
- var x = this.a * ksp * cosphi * Math.sin(dlon);
- var y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon);
- } else {
- Proj4js.reportError("orthoFwdPointError");
- }
- p.x=x;
- p.y=y;
- return p;
- },
- inverse: function(p) {
- var rh; /* height above ellipsoid */
- var z; /* angle */
- var sinz,cosz; /* sin of z and cos of z */
- var temp;
- var con;
- var lon , lat;
- /* Inverse equations
- -----------------*/
- p.x -= this.x0;
- p.y -= this.y0;
- rh = Math.sqrt(p.x * p.x + p.y * p.y);
- if (rh > this.a + .0000001) {
- Proj4js.reportError("orthoInvDataError");
- }
- z = Proj4js.common.asinz(rh / this.a);
- sinz=Math.sin(z);
- cosz=Math.cos(z);
- lon = this.long0;
- if (Math.abs(rh) <= Proj4js.common.EPSLN) {
- lat = this.lat0;
- }
- lat = Proj4js.common.asinz(cosz * this.sin_p14 + (p.y * sinz * this.cos_p14)/rh);
- con = Math.abs(this.lat0) - Proj4js.common.HALF_PI;
- if (Math.abs(con) <= Proj4js.common.EPSLN) {
- if (this.lat0 >= 0) {
- lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x, -p.y));
- } else {
- lon = Proj4js.common.adjust_lon(this.long0 -Math.atan2(-p.x, p.y));
- }
- }
- con = cosz - this.sin_p14 * Math.sin(lat);
- p.x=lon;
- p.y=lat;
- return p;
- }
- };
- /* ======================================================================
- projCode/krovak.js
- ====================================================================== */
- /**
- NOTES: According to EPSG the full Krovak projection method should have
- the following parameters. Within PROJ.4 the azimuth, and pseudo
- standard parallel are hardcoded in the algorithm and can't be
- altered from outside. The others all have defaults to match the
- common usage with Krovak projection.
- lat_0 = latitude of centre of the projection
-
- lon_0 = longitude of centre of the projection
-
- ** = azimuth (true) of the centre line passing through the centre of the projection
- ** = latitude of pseudo standard parallel
-
- k = scale factor on the pseudo standard parallel
-
- x_0 = False Easting of the centre of the projection at the apex of the cone
-
- y_0 = False Northing of the centre of the projection at the apex of the cone
- **/
- Proj4js.Proj.krovak = {
- init: function() {
- /* we want Bessel as fixed ellipsoid */
- this.a = 6377397.155;
- this.es = 0.006674372230614;
- this.e = Math.sqrt(this.es);
- /* if latitude of projection center is not set, use 49d30'N */
- if (!this.lat0) {
- this.lat0 = 0.863937979737193;
- }
- if (!this.long0) {
- this.long0 = 0.7417649320975901 - 0.308341501185665;
- }
- /* if scale not set default to 0.9999 */
- if (!this.k0) {
- this.k0 = 0.9999;
- }
- this.s45 = 0.785398163397448; /* 45� */
- this.s90 = 2 * this.s45;
- this.fi0 = this.lat0; /* Latitude of projection centre 49� 30' */
- /* Ellipsoid Bessel 1841 a = 6377397.155m 1/f = 299.1528128,
- e2=0.006674372230614;
- */
- this.e2 = this.es; /* 0.006674372230614; */
- this.e = Math.sqrt(this.e2);
- this.alfa = Math.sqrt(1. + (this.e2 * Math.pow(Math.cos(this.fi0), 4)) / (1. - this.e2));
- this.uq = 1.04216856380474; /* DU(2, 59, 42, 42.69689) */
- this.u0 = Math.asin(Math.sin(this.fi0) / this.alfa);
- this.g = Math.pow( (1. + this.e * Math.sin(this.fi0)) / (1. - this.e * Math.sin(this.fi0)) , this.alfa * this.e / 2. );
- this.k = Math.tan( this.u0 / 2. + this.s45) / Math.pow (Math.tan(this.fi0 / 2. + this.s45) , this.alfa) * this.g;
- this.k1 = this.k0;
- this.n0 = this.a * Math.sqrt(1. - this.e2) / (1. - this.e2 * Math.pow(Math.sin(this.fi0), 2));
- this.s0 = 1.37008346281555; /* Latitude of pseudo standard parallel 78� 30'00" N */
- this.n = Math.sin(this.s0);
- this.ro0 = this.k1 * this.n0 / Math.tan(this.s0);
- this.ad = this.s90 - this.uq;
- },
-
- /* ellipsoid */
- /* calculate xy from lat/lon */
- /* Constants, identical to inverse transform function */
- forward: function(p) {
- var gfi, u, deltav, s, d, eps, ro;
- var lon = p.x;
- var lat = p.y;
- var delta_lon = Proj4js.common.adjust_lon(lon - this.long0); // Delta longitude
- /* Transformation */
- gfi = Math.pow ( ((1. + this.e * Math.sin(lat)) / (1. - this.e * Math.sin(lat))) , (this.alfa * this.e / 2.));
- u= 2. * (Math.atan(this.k * Math.pow( Math.tan(lat / 2. + this.s45), this.alfa) / gfi)-this.s45);
- deltav = - delta_lon * this.alfa;
- s = Math.asin(Math.cos(this.ad) * Math.sin(u) + Math.sin(this.ad) * Math.cos(u) * Math.cos(deltav));
- d = Math.asin(Math.cos(u) * Math.sin(deltav) / Math.cos(s));
- eps = this.n * d;
- ro = this.ro0 * Math.pow(Math.tan(this.s0 / 2. + this.s45) , this.n) / Math.pow(Math.tan(s / 2. + this.s45) , this.n);
- /* x and y are reverted! */
- //p.y = ro * Math.cos(eps) / a;
- //p.x = ro * Math.sin(eps) / a;
- p.y = ro * Math.cos(eps) / 1.0;
- p.x = ro * Math.sin(eps) / 1.0;
- if(this.czech) {
- p.y *= -1.0;
- p.x *= -1.0;
- }
- return (p);
- },
- /* calculate lat/lon from xy */
- inverse: function(p) {
- /* Constants, identisch wie in der Umkehrfunktion */
- var u, deltav, s, d, eps, ro, fi1;
- var ok;
- /* Transformation */
- /* revert y, x*/
- var tmp = p.x;
- p.x=p.y;
- p.y=tmp;
- if(this.czech) {
- p.y *= -1.0;
- p.x *= -1.0;
- }
- ro = Math.sqrt(p.x * p.x + p.y * p.y);
- eps = Math.atan2(p.y, p.x);
- d = eps / Math.sin(this.s0);
- s = 2. * (Math.atan( Math.pow(this.ro0 / ro, 1. / this.n) * Math.tan(this.s0 / 2. + this.s45)) - this.s45);
- u = Math.asin(Math.cos(this.ad) * Math.sin(s) - Math.sin(this.ad) * Math.cos(s) * Math.cos(d));
- deltav = Math.asin(Math.cos(s) * Math.sin(d) / Math.cos(u));
- p.x = this.long0 - deltav / this.alfa;
- /* ITERATION FOR lat */
- fi1 = u;
- ok = 0;
- var iter = 0;
- do {
- 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);
- if (Math.abs(fi1 - p.y) < 0.0000000001) ok=1;
- fi1 = p.y;
- iter += 1;
- } while (ok==0 && iter < 15);
- if (iter >= 15) {
- Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations");
- //console.log('iter:', iter);
- return null;
- }
-
- return (p);
- }
- };
- /* ======================================================================
- projCode/somerc.js
- ====================================================================== */
- /*******************************************************************************
- NAME SWISS OBLIQUE MERCATOR
- PURPOSE: Swiss projection.
- WARNING: X and Y are inverted (weird) in the swiss coordinate system. Not
- here, since we want X to be horizontal and Y vertical.
- ALGORITHM REFERENCES
- 1. "Formules et constantes pour le Calcul pour la
- projection cylindrique conforme à axe oblique et pour la transformation entre
- des systèmes de référence".
- http://www.swisstopo.admin.ch/internet/swisstopo/fr/home/topics/survey/sys/refsys/switzerland.parsysrelated1.31216.downloadList.77004.DownloadFile.tmp/swissprojectionfr.pdf
- *******************************************************************************/
- Proj4js.Proj.somerc = {
- init: function() {
- var phy0 = this.lat0;
- this.lambda0 = this.long0;
- var sinPhy0 = Math.sin(phy0);
- var semiMajorAxis = this.a;
- var invF = this.rf;
- var flattening = 1 / invF;
- var e2 = 2 * flattening - Math.pow(flattening, 2);
- var e = this.e = Math.sqrt(e2);
- this.R = this.k0 * semiMajorAxis * Math.sqrt(1 - e2) / (1 - e2 * Math.pow(sinPhy0, 2.0));
- this.alpha = Math.sqrt(1 + e2 / (1 - e2) * Math.pow(Math.cos(phy0), 4.0));
- this.b0 = Math.asin(sinPhy0 / this.alpha);
- this.K = Math.log(Math.tan(Math.PI / 4.0 + this.b0 / 2.0))
- - this.alpha
- * Math.log(Math.tan(Math.PI / 4.0 + phy0 / 2.0))
- + this.alpha
- * e / 2
- * Math.log((1 + e * sinPhy0)
- / (1 - e * sinPhy0));
- },
- forward: function(p) {
- var Sa1 = Math.log(Math.tan(Math.PI / 4.0 - p.y / 2.0));
- var Sa2 = this.e / 2.0
- * Math.log((1 + this.e * Math.sin(p.y))
- / (1 - this.e * Math.sin(p.y)));
- var S = -this.alpha * (Sa1 + Sa2) + this.K;
- // spheric latitude
- var b = 2.0 * (Math.atan(Math.exp(S)) - Math.PI / 4.0);
- // spheric longitude
- var I = this.alpha * (p.x - this.lambda0);
- // psoeudo equatorial rotation
- var rotI = Math.atan(Math.sin(I)
- / (Math.sin(this.b0) * Math.tan(b) +
- Math.cos(this.b0) * Math.cos(I)));
- var rotB = Math.asin(Math.cos(this.b0) * Math.sin(b) -
- Math.sin(this.b0) * Math.cos(b) * Math.cos(I));
- p.y = this.R / 2.0
- * Math.log((1 + Math.sin(rotB)) / (1 - Math.sin(rotB)))
- + this.y0;
- p.x = this.R * rotI + this.x0;
- return p;
- },
- inverse: function(p) {
- var Y = p.x - this.x0;
- var X = p.y - this.y0;
- var rotI = Y / this.R;
- var rotB = 2 * (Math.atan(Math.exp(X / this.R)) - Math.PI / 4.0);
- var b = Math.asin(Math.cos(this.b0) * Math.sin(rotB)
- + Math.sin(this.b0) * Math.cos(rotB) * Math.cos(rotI));
- var I = Math.atan(Math.sin(rotI)
- / (Math.cos(this.b0) * Math.cos(rotI) - Math.sin(this.b0)
- * Math.tan(rotB)));
- var lambda = this.lambda0 + I / this.alpha;
- var S = 0.0;
- var phy = b;
- var prevPhy = -1000.0;
- var iteration = 0;
- while (Math.abs(phy - prevPhy) > 0.0000001)
- {
- if (++iteration > 20)
- {
- Proj4js.reportError("omercFwdInfinity");
- return;
- }
- //S = Math.log(Math.tan(Math.PI / 4.0 + phy / 2.0));
- S = 1.0
- / this.alpha
- * (Math.log(Math.tan(Math.PI / 4.0 + b / 2.0)) - this.K)
- + this.e
- * Math.log(Math.tan(Math.PI / 4.0
- + Math.asin(this.e * Math.sin(phy))
- / 2.0));
- prevPhy = phy;
- phy = 2.0 * Math.atan(Math.exp(S)) - Math.PI / 2.0;
- }
- p.x = lambda;
- p.y = phy;
- return p;
- }
- };
- /* ======================================================================
- projCode/stere.js
- ====================================================================== */
- // Initialize the Stereographic projection
- Proj4js.Proj.stere = {
- ssfn_: function(phit, sinphi, eccen) {
- sinphi *= eccen;
- return (Math.tan (.5 * (Proj4js.common.HALF_PI + phit)) * Math.pow((1. - sinphi) / (1. + sinphi), .5 * eccen));
- },
- TOL: 1.e-8,
- NITER: 8,
- CONV: 1.e-10,
- S_POLE: 0,
- N_POLE: 1,
- OBLIQ: 2,
- EQUIT: 3,
- init: function() {
- this.phits = this.lat_ts ? this.lat_ts : Proj4js.common.HALF_PI;
- var t = Math.abs(this.lat0);
- if ((Math.abs(t) - Proj4js.common.HALF_PI) < Proj4js.common.EPSLN) {
- this.mode = this.lat0 < 0. ? this.S_POLE : this.N_POLE;
- } else {
- this.mode = t > Proj4js.common.EPSLN ? this.OBLIQ : this.EQUIT;
- }
- this.phits = Math.abs(this.phits);
- if (this.es) {
- var X;
- switch (this.mode) {
- case this.N_POLE:
- case this.S_POLE:
- if (Math.abs(this.phits - Proj4js.common.HALF_PI) < Proj4js.common.EPSLN) {
- this.akm1 = 2. * this.k0 / Math.sqrt(Math.pow(1+this.e,1+this.e)*Math.pow(1-this.e,1-this.e));
- } else {
- t = Math.sin(this.phits);
- this.akm1 = Math.cos(this.phits) / Proj4js.common.tsfnz(this.e, this.phits, t);
- t *= this.e;
- this.akm1 /= Math.sqrt(1. - t * t);
- }
- break;
- case this.EQUIT:
- this.akm1 = 2. * this.k0;
- break;
- case this.OBLIQ:
- t = Math.sin(this.lat0);
- X = 2. * Math.atan(this.ssfn_(this.lat0, t, this.e)) - Proj4js.common.HALF_PI;
- t *= this.e;
- this.akm1 = 2. * this.k0 * Math.cos(this.lat0) / Math.sqrt(1. - t * t);
- this.sinX1 = Math.sin(X);
- this.cosX1 = Math.cos(X);
- break;
- }
- } else {
- switch (this.mode) {
- case this.OBLIQ:
- this.sinph0 = Math.sin(this.lat0);
- this.cosph0 = Math.cos(this.lat0);
- case this.EQUIT:
- this.akm1 = 2. * this.k0;
- break;
- case this.S_POLE:
- case this.N_POLE:
- this.akm1 = Math.abs(this.phits - Proj4js.common.HALF_PI) >= Proj4js.common.EPSLN ?
- Math.cos(this.phits) / Math.tan(Proj4js.common.FORTPI - .5 * this.phits) :
- 2. * this.k0 ;
- break;
- }
- }
- },
- // Stereographic forward equations--mapping lat,long to x,y
- forward: function(p) {
- var lon = p.x;
- lon = Proj4js.common.adjust_lon(lon - this.long0);
- var lat = p.y;
- var x, y;
-
- if (this.sphere) {
- var sinphi, cosphi, coslam, sinlam;
- sinphi = Math.sin(lat);
- cosphi = Math.cos(lat);
- coslam = Math.cos(lon);
- sinlam = Math.sin(lon);
- switch (this.mode) {
- case this.EQUIT:
- y = 1. + cosphi * coslam;
- if (y <= Proj4js.common.EPSLN) {
- Proj4js.reportError("stere:forward:Equit");
- }
- y = this.akm1 / y;
- x = y * cosphi * sinlam;
- y *= sinphi;
- break;
- case this.OBLIQ:
- y = 1. + this.sinph0 * sinphi + this.cosph0 * cosphi * coslam;
- if (y <= Proj4js.common.EPSLN) {
- Proj4js.reportError("stere:forward:Obliq");
- }
- y = this.akm1 / y;
- x = y * cosphi * sinlam;
- y *= this.cosph0 * sinphi - this.sinph0 * cosphi * coslam;
- break;
- case this.N_POLE:
- coslam = -coslam;
- lat = -lat;
- //Note no break here so it conitnues through S_POLE
- case this.S_POLE:
- if (Math.abs(lat - Proj4js.common.HALF_PI) < this.TOL) {
- Proj4js.reportError("stere:forward:S_POLE");
- }
- y = this.akm1 * Math.tan(Proj4js.common.FORTPI + .5 * lat);
- x = sinlam * y;
- y *= coslam;
- break;
- }
- } else {
- coslam = Math.cos(lon);
- sinlam = Math.sin(lon);
- sinphi = Math.sin(lat);
- var sinX, cosX;
- if (this.mode == this.OBLIQ || this.mode == this.EQUIT) {
- var Xt = 2. * Math.atan(this.ssfn_(lat, sinphi, this.e));
- sinX = Math.sin(Xt - Proj4js.common.HALF_PI);
- cosX = Math.cos(Xt);
- }
- switch (this.mode) {
- case this.OBLIQ:
- var A = this.akm1 / (this.cosX1 * (1. + this.sinX1 * sinX + this.cosX1 * cosX * coslam));
- y = A * (this.cosX1 * sinX - this.sinX1 * cosX * coslam);
- x = A * cosX;
- break;
- case this.EQUIT:
- var A = 2. * this.akm1 / (1. + cosX * coslam);
- y = A * sinX;
- x = A * cosX;
- break;
- case this.S_POLE:
- lat = -lat;
- coslam = - coslam;
- sinphi = -sinphi;
- case this.N_POLE:
- x = this.akm1 * Proj4js.common.tsfnz(this.e, lat, sinphi);
- y = - x * coslam;
- break;
- }
- x = x * sinlam;
- }
- p.x = x*this.a + this.x0;
- p.y = y*this.a + this.y0;
- return p;
- },
- //* Stereographic inverse equations--mapping x,y to lat/long
- inverse: function(p) {
- var x = (p.x - this.x0)/this.a; /* descale and de-offset */
- var y = (p.y - this.y0)/this.a;
- var lon, lat;
- var cosphi, sinphi, tp=0.0, phi_l=0.0, rho, halfe=0.0, pi2=0.0;
- var i;
- if (this.sphere) {
- var c, rh, sinc, cosc;
- rh = Math.sqrt(x*x + y*y);
- c = 2. * Math.atan(rh / this.akm1);
- sinc = Math.sin(c);
- cosc = Math.cos(c);
- lon = 0.;
- switch (this.mode) {
- case this.EQUIT:
- if (Math.abs(rh) <= Proj4js.common.EPSLN) {
- lat = 0.;
- } else {
- lat = Math.asin(y * sinc / rh);
- }
- if (cosc != 0. || x != 0.) lon = Math.atan2(x * sinc, cosc * rh);
- break;
- case this.OBLIQ:
- if (Math.abs(rh) <= Proj4js.common.EPSLN) {
- lat = this.phi0;
- } else {
- lat = Math.asin(cosc * this.sinph0 + y * sinc * this.cosph0 / rh);
- }
- c = cosc - this.sinph0 * Math.sin(lat);
- if (c != 0. || x != 0.) {
- lon = Math.atan2(x * sinc * this.cosph0, c * rh);
- }
- break;
- case this.N_POLE:
- y = -y;
- case this.S_POLE:
- if (Math.abs(rh) <= Proj4js.common.EPSLN) {
- lat = this.phi0;
- } else {
- lat = Math.asin(this.mode == this.S_POLE ? -cosc : cosc);
- }
- lon = (x == 0. && y == 0.) ? 0. : Math.atan2(x, y);
- break;
- }
- p.x = Proj4js.common.adjust_lon(lon + this.long0);
- p.y = lat;
- } else {
- rho = Math.sqrt(x*x + y*y);
- switch (this.mode) {
- case this.OBLIQ:
- case this.EQUIT:
- tp = 2. * Math.atan2(rho * this.cosX1 , this.akm1);
- cosphi = Math.cos(tp);
- sinphi = Math.sin(tp);
- if( rho == 0.0 ) {
- phi_l = Math.asin(cosphi * this.sinX1);
- } else {
- phi_l = Math.asin(cosphi * this.sinX1 + (y * sinphi * this.cosX1 / rho));
- }
- tp = Math.tan(.5 * (Proj4js.common.HALF_PI + phi_l));
- x *= sinphi;
- y = rho * this.cosX1 * cosphi - y * this.sinX1* sinphi;
- pi2 = Proj4js.common.HALF_PI;
- halfe = .5 * this.e;
- break;
- case this.N_POLE:
- y = -y;
- case this.S_POLE:
- tp = - rho / this.akm1;
- phi_l = Proj4js.common.HALF_PI - 2. * Math.atan(tp);
- pi2 = -Proj4js.common.HALF_PI;
- halfe = -.5 * this.e;
- break;
- }
- for (i = this.NITER; i--; phi_l = lat) { //check this
- sinphi = this.e * Math.sin(phi_l);
- lat = 2. * Math.atan(tp * Math.pow((1.+sinphi)/(1.-sinphi), halfe)) - pi2;
- if (Math.abs(phi_l - lat) < this.CONV) {
- if (this.mode == this.S_POLE) lat = -lat;
- lon = (x == 0. && y == 0.) ? 0. : Math.atan2(x, y);
- p.x = Proj4js.common.adjust_lon(lon + this.long0);
- p.y = lat;
- return p;
- }
- }
- }
- }
- };
- /* ======================================================================
- projCode/nzmg.js
- ====================================================================== */
- /*******************************************************************************
- NAME NEW ZEALAND MAP GRID
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the New Zealand Map Grid projection. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- ALGORITHM REFERENCES
- 1. Department of Land and Survey Technical Circular 1973/32
- http://www.linz.govt.nz/docs/miscellaneous/nz-map-definition.pdf
- 2. OSG Technical Report 4.1
- http://www.linz.govt.nz/docs/miscellaneous/nzmg.pdf
- IMPLEMENTATION NOTES
- The two references use different symbols for the calculated values. This
- implementation uses the variable names similar to the symbols in reference [1].
- The alogrithm uses different units for delta latitude and delta longitude.
- The delta latitude is assumed to be in units of seconds of arc x 10^-5.
- The delta longitude is the usual radians. Look out for these conversions.
- The algorithm is described using complex arithmetic. There were three
- options:
- * find and use a Javascript library for complex arithmetic
- * write my own complex library
- * expand the complex arithmetic by hand to simple arithmetic
- This implementation has expanded the complex multiplication operations
- into parallel simple arithmetic operations for the real and imaginary parts.
- The imaginary part is way over to the right of the display; this probably
- violates every coding standard in the world, but, to me, it makes it much
- more obvious what is going on.
- The following complex operations are used:
- - addition
- - multiplication
- - division
- - complex number raised to integer power
- - summation
- A summary of complex arithmetic operations:
- (from http://en.wikipedia.org/wiki/Complex_arithmetic)
- addition: (a + bi) + (c + di) = (a + c) + (b + d)i
- subtraction: (a + bi) - (c + di) = (a - c) + (b - d)i
- multiplication: (a + bi) x (c + di) = (ac - bd) + (bc + ad)i
- division: (a + bi) / (c + di) = [(ac + bd)/(cc + dd)] + [(bc - ad)/(cc + dd)]i
- The algorithm needs to calculate summations of simple and complex numbers. This is
- implemented using a for-loop, pre-loading the summed value to zero.
- The algorithm needs to calculate theta^2, theta^3, etc while doing a summation.
- There are three possible implementations:
- - use Math.pow in the summation loop - except for complex numbers
- - precalculate the values before running the loop
- - calculate theta^n = theta^(n-1) * theta during the loop
- This implementation uses the third option for both real and complex arithmetic.
- For example
- psi_n = 1;
- sum = 0;
- for (n = 1; n <=6; n++) {
- psi_n1 = psi_n * psi; // calculate psi^(n+1)
- psi_n = psi_n1;
- sum = sum + A[n] * psi_n;
- }
- TEST VECTORS
- NZMG E, N: 2487100.638 6751049.719 metres
- NZGD49 long, lat: 172.739194 -34.444066 degrees
- NZMG E, N: 2486533.395 6077263.661 metres
- NZGD49 long, lat: 172.723106 -40.512409 degrees
- NZMG E, N: 2216746.425 5388508.765 metres
- NZGD49 long, lat: 169.172062 -46.651295 degrees
- Note that these test vectors convert from NZMG metres to lat/long referenced
- to NZGD49, not the more usual WGS84. The difference is about 70m N/S and about
- 10m E/W.
- These test vectors are provided in reference [1]. Many more test
- vectors are available in
- http://www.linz.govt.nz/docs/topography/topographicdata/placenamesdatabase/nznamesmar08.zip
- which is a catalog of names on the 260-series maps.
- EPSG CODES
- NZMG EPSG:27200
- NZGD49 EPSG:4272
- http://spatialreference.org/ defines these as
- Proj4js.defs["EPSG:4272"] = "+proj=longlat +ellps=intl +datum=nzgd49 +no_defs ";
- Proj4js.defs["EPSG:27200"] = "+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000 +y_0=6023150 +ellps=intl +datum=nzgd49 +units=m +no_defs ";
- LICENSE
- Copyright: Stephen Irons 2008
- Released under terms of the LGPL as per: http://www.gnu.org/copyleft/lesser.html
- *******************************************************************************/
- /**
- Initialize New Zealand Map Grip projection
- */
- Proj4js.Proj.nzmg = {
- /**
- * iterations: Number of iterations to refine inverse transform.
- * 0 -> km accuracy
- * 1 -> m accuracy -- suitable for most mapping applications
- * 2 -> mm accuracy
- */
- iterations: 1,
- init : function() {
- this.A = new Array();
- this.A[1] = +0.6399175073;
- this.A[2] = -0.1358797613;
- this.A[3] = +0.063294409;
- this.A[4] = -0.02526853;
- this.A[5] = +0.0117879;
- this.A[6] = -0.0055161;
- this.A[7] = +0.0026906;
- this.A[8] = -0.001333;
- this.A[9] = +0.00067;
- this.A[10] = -0.00034;
- this.B_re = new Array(); this.B_im = new Array();
- this.B_re[1] = +0.7557853228; this.B_im[1] = 0.0;
- this.B_re[2] = +0.249204646; this.B_im[2] = +0.003371507;
- this.B_re[3] = -0.001541739; this.B_im[3] = +0.041058560;
- this.B_re[4] = -0.10162907; this.B_im[4] = +0.01727609;
- this.B_re[5] = -0.26623489; this.B_im[5] = -0.36249218;
- this.B_re[6] = -0.6870983; this.B_im[6] = -1.1651967;
- this.C_re = new Array(); this.C_im = new Array();
- this.C_re[1] = +1.3231270439; this.C_im[1] = 0.0;
- this.C_re[2] = -0.577245789; this.C_im[2] = -0.007809598;
- this.C_re[3] = +0.508307513; this.C_im[3] = -0.112208952;
- this.C_re[4] = -0.15094762; this.C_im[4] = +0.18200602;
- this.C_re[5] = +1.01418179; this.C_im[5] = +1.64497696;
- this.C_re[6] = +1.9660549; this.C_im[6] = +2.5127645;
- this.D = new Array();
- this.D[1] = +1.5627014243;
- this.D[2] = +0.5185406398;
- this.D[3] = -0.03333098;
- this.D[4] = -0.1052906;
- this.D[5] = -0.0368594;
- this.D[6] = +0.007317;
- this.D[7] = +0.01220;
- this.D[8] = +0.00394;
- this.D[9] = -0.0013;
- },
- /**
- New Zealand Map Grid Forward - long/lat to x/y
- long/lat in radians
- */
- forward : function(p) {
- var lon = p.x;
- var lat = p.y;
- var delta_lat = lat - this.lat0;
- var delta_lon = lon - this.long0;
- // 1. Calculate d_phi and d_psi ... // and d_lambda
- // For this algorithm, delta_latitude is in seconds of arc x 10-5, so we need to scale to those units. Longitude is radians.
- var d_phi = delta_lat / Proj4js.common.SEC_TO_RAD * 1E-5; var d_lambda = delta_lon;
- var d_phi_n = 1; // d_phi^0
- var d_psi = 0;
- for (var n = 1; n <= 10; n++) {
- d_phi_n = d_phi_n * d_phi;
- d_psi = d_psi + this.A[n] * d_phi_n;
- }
- // 2. Calculate theta
- var th_re = d_psi; var th_im = d_lambda;
- // 3. Calculate z
- var th_n_re = 1; var th_n_im = 0; // theta^0
- var th_n_re1; var th_n_im1;
- var z_re = 0; var z_im = 0;
- for (var n = 1; n <= 6; n++) {
- th_n_re1 = th_n_re*th_re - th_n_im*th_im; th_n_im1 = th_n_im*th_re + th_n_re*th_im;
- th_n_re = th_n_re1; th_n_im = th_n_im1;
- z_re = z_re + this.B_re[n]*th_n_re - this.B_im[n]*th_n_im; z_im = z_im + this.B_im[n]*th_n_re + this.B_re[n]*th_n_im;
- }
- // 4. Calculate easting and northing
- p.x = (z_im * this.a) + this.x0;
- p.y = (z_re * this.a) + this.y0;
- return p;
- },
- /**
- New Zealand Map Grid Inverse - x/y to long/lat
- */
- inverse : function(p) {
- var x = p.x;
- var y = p.y;
- var delta_x = x - this.x0;
- var delta_y = y - this.y0;
- // 1. Calculate z
- var z_re = delta_y / this.a; var z_im = delta_x / this.a;
- // 2a. Calculate theta - first approximation gives km accuracy
- var z_n_re = 1; var z_n_im = 0; // z^0
- var z_n_re1; var z_n_im1;
- var th_re = 0; var th_im = 0;
- for (var n = 1; n <= 6; n++) {
- z_n_re1 = z_n_re*z_re - z_n_im*z_im; z_n_im1 = z_n_im*z_re + z_n_re*z_im;
- z_n_re = z_n_re1; z_n_im = z_n_im1;
- th_re = th_re + this.C_re[n]*z_n_re - this.C_im[n]*z_n_im; th_im = th_im + this.C_im[n]*z_n_re + this.C_re[n]*z_n_im;
- }
- // 2b. Iterate to refine the accuracy of the calculation
- // 0 iterations gives km accuracy
- // 1 iteration gives m accuracy -- good enough for most mapping applications
- // 2 iterations bives mm accuracy
- for (var i = 0; i < this.iterations; i++) {
- var th_n_re = th_re; var th_n_im = th_im;
- var th_n_re1; var th_n_im1;
- var num_re = z_re; var num_im = z_im;
- for (var n = 2; n <= 6; n++) {
- th_n_re1 = th_n_re*th_re - th_n_im*th_im; th_n_im1 = th_n_im*th_re + th_n_re*th_im;
- th_n_re = th_n_re1; th_n_im = th_n_im1;
- num_re = num_re + (n-1)*(this.B_re[n]*th_n_re - this.B_im[n]*th_n_im); num_im = num_im + (n-1)*(this.B_im[n]*th_n_re + this.B_re[n]*th_n_im);
- }
- th_n_re = 1; th_n_im = 0;
- var den_re = this.B_re[1]; var den_im = this.B_im[1];
- for (var n = 2; n <= 6; n++) {
- th_n_re1 = th_n_re*th_re - th_n_im*th_im; th_n_im1 = th_n_im*th_re + th_n_re*th_im;
- th_n_re = th_n_re1; th_n_im = th_n_im1;
- den_re = den_re + n * (this.B_re[n]*th_n_re - this.B_im[n]*th_n_im); den_im = den_im + n * (this.B_im[n]*th_n_re + this.B_re[n]*th_n_im);
- }
- // Complex division
- var den2 = den_re*den_re + den_im*den_im;
- th_re = (num_re*den_re + num_im*den_im) / den2; th_im = (num_im*den_re - num_re*den_im) / den2;
- }
- // 3. Calculate d_phi ... // and d_lambda
- var d_psi = th_re; var d_lambda = th_im;
- var d_psi_n = 1; // d_psi^0
- var d_phi = 0;
- for (var n = 1; n <= 9; n++) {
- d_psi_n = d_psi_n * d_psi;
- d_phi = d_phi + this.D[n] * d_psi_n;
- }
- // 4. Calculate latitude and longitude
- // d_phi is calcuated in second of arc * 10^-5, so we need to scale back to radians. d_lambda is in radians.
- var lat = this.lat0 + (d_phi * Proj4js.common.SEC_TO_RAD * 1E5);
- var lon = this.long0 + d_lambda;
- p.x = lon;
- p.y = lat;
- return p;
- }
- };
- /* ======================================================================
- projCode/mill.js
- ====================================================================== */
- /*******************************************************************************
- NAME MILLER CYLINDRICAL
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the Miller Cylindrical projection. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- PROGRAMMER DATE
- ---------- ----
- T. Mittan March, 1993
- This function was adapted from the Lambert Azimuthal Equal Area projection
- code (FORTRAN) in the General Cartographic Transformation Package software
- which is available from the U.S. Geological Survey National Mapping Division.
-
- ALGORITHM REFERENCES
- 1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder,
- The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355.
- 2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 3. "Software Documentation for GCTP General Cartographic Transformation
- Package", U.S. Geological Survey National Mapping Division, May 1982.
- *******************************************************************************/
- Proj4js.Proj.mill = {
- /* Initialize the Miller Cylindrical projection
- -------------------------------------------*/
- init: function() {
- //no-op
- },
- /* Miller Cylindrical forward equations--mapping lat,long to x,y
- ------------------------------------------------------------*/
- forward: function(p) {
- var lon=p.x;
- var lat=p.y;
- /* Forward equations
- -----------------*/
- var dlon = Proj4js.common.adjust_lon(lon -this.long0);
- var x = this.x0 + this.a * dlon;
- var y = this.y0 + this.a * Math.log(Math.tan((Proj4js.common.PI / 4.0) + (lat / 2.5))) * 1.25;
- p.x=x;
- p.y=y;
- return p;
- },//millFwd()
- /* Miller Cylindrical inverse equations--mapping x,y to lat/long
- ------------------------------------------------------------*/
- inverse: function(p) {
- p.x -= this.x0;
- p.y -= this.y0;
- var lon = Proj4js.common.adjust_lon(this.long0 + p.x /this.a);
- var lat = 2.5 * (Math.atan(Math.exp(0.8*p.y/this.a)) - Proj4js.common.PI / 4.0);
- p.x=lon;
- p.y=lat;
- return p;
- }//millInv()
- };
- /* ======================================================================
- projCode/gnom.js
- ====================================================================== */
- /*****************************************************************************
- NAME GNOMONIC
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the Gnomonic Projection.
- Implementation based on the existing sterea and ortho
- implementations.
- PROGRAMMER DATE
- ---------- ----
- Richard Marsden November 2009
- ALGORITHM REFERENCES
- 1. Snyder, John P., "Flattening the Earth - Two Thousand Years of Map
- Projections", University of Chicago Press 1993
- 2. Wolfram Mathworld "Gnomonic Projection"
- http://mathworld.wolfram.com/GnomonicProjection.html
- Accessed: 12th November 2009
- ******************************************************************************/
- Proj4js.Proj.gnom = {
- /* Initialize the Gnomonic projection
- -------------------------------------*/
- init: function(def) {
- /* Place parameters in static storage for common use
- -------------------------------------------------*/
- this.sin_p14=Math.sin(this.lat0);
- this.cos_p14=Math.cos(this.lat0);
- // Approximation for projecting points to the horizon (infinity)
- this.infinity_dist = 1000 * this.a;
- this.rc = 1;
- },
- /* Gnomonic forward equations--mapping lat,long to x,y
- ---------------------------------------------------*/
- forward: function(p) {
- var sinphi, cosphi; /* sin and cos value */
- var dlon; /* delta longitude value */
- var coslon; /* cos of longitude */
- var ksp; /* scale factor */
- var g;
- var x, y;
- var lon=p.x;
- var lat=p.y;
- /* Forward equations
- -----------------*/
- dlon = Proj4js.common.adjust_lon(lon - this.long0);
- sinphi=Math.sin(lat);
- cosphi=Math.cos(lat);
- coslon = Math.cos(dlon);
- g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon;
- ksp = 1.0;
- if ((g > 0) || (Math.abs(g) <= Proj4js.common.EPSLN)) {
- x = this.x0 + this.a * ksp * cosphi * Math.sin(dlon) / g;
- y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon) / g;
- } else {
- Proj4js.reportError("orthoFwdPointError");
- // Point is in the opposing hemisphere and is unprojectable
- // We still need to return a reasonable point, so we project
- // to infinity, on a bearing
- // equivalent to the northern hemisphere equivalent
- // This is a reasonable approximation for short shapes and lines that
- // straddle the horizon.
- x = this.x0 + this.infinity_dist * cosphi * Math.sin(dlon);
- y = this.y0 + this.infinity_dist * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon);
- }
- p.x=x;
- p.y=y;
- return p;
- },
- inverse: function(p) {
- var rh; /* Rho */
- var z; /* angle */
- var sinc, cosc;
- var c;
- var lon , lat;
- /* Inverse equations
- -----------------*/
- p.x = (p.x - this.x0) / this.a;
- p.y = (p.y - this.y0) / this.a;
- p.x /= this.k0;
- p.y /= this.k0;
- if ( (rh = Math.sqrt(p.x * p.x + p.y * p.y)) ) {
- c = Math.atan2(rh, this.rc);
- sinc = Math.sin(c);
- cosc = Math.cos(c);
- lat = Proj4js.common.asinz(cosc*this.sin_p14 + (p.y*sinc*this.cos_p14) / rh);
- lon = Math.atan2(p.x*sinc, rh*this.cos_p14*cosc - p.y*this.sin_p14*sinc);
- lon = Proj4js.common.adjust_lon(this.long0+lon);
- } else {
- lat = this.phic0;
- lon = 0.0;
- }
-
- p.x=lon;
- p.y=lat;
- return p;
- }
- };
- /* ======================================================================
- projCode/sinu.js
- ====================================================================== */
- /*******************************************************************************
- NAME SINUSOIDAL
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the Sinusoidal projection. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- PROGRAMMER DATE
- ---------- ----
- D. Steinwand, EROS May, 1991
- This function was adapted from the Sinusoidal projection code (FORTRAN) in the
- General Cartographic Transformation Package software which is available from
- the U.S. Geological Survey National Mapping Division.
-
- ALGORITHM REFERENCES
- 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 2. "Software Documentation for GCTP General Cartographic Transformation
- Package", U.S. Geological Survey National Mapping Division, May 1982.
- *******************************************************************************/
- Proj4js.Proj.sinu = {
- /* Initialize the Sinusoidal projection
- ------------------------------------*/
- init: function() {
- /* Place parameters in static storage for common use
- -------------------------------------------------*/
-
- if (!this.sphere) {
- this.en = Proj4js.common.pj_enfn(this.es);
- } else {
- this.n = 1.;
- this.m = 0.;
- this.es = 0;
- this.C_y = Math.sqrt((this.m + 1.) / this.n);
- this.C_x = this.C_y/(this.m + 1.);
- }
-
- },
- /* Sinusoidal forward equations--mapping lat,long to x,y
- -----------------------------------------------------*/
- forward: function(p) {
- var x,y,delta_lon;
- var lon=p.x;
- var lat=p.y;
- /* Forward equations
- -----------------*/
- lon = Proj4js.common.adjust_lon(lon - this.long0);
-
- if (this.sphere) {
- if (!this.m) {
- lat = this.n != 1. ? Math.asin(this.n * Math.sin(lat)): lat;
- } else {
- var k = this.n * Math.sin(lat);
- for (var i = Proj4js.common.MAX_ITER; i ; --i) {
- var V = (this.m * lat + Math.sin(lat) - k) / (this.m + Math.cos(lat));
- lat -= V;
- if (Math.abs(V) < Proj4js.common.EPSLN) break;
- }
- }
- x = this.a * this.C_x * lon * (this.m + Math.cos(lat));
- y = this.a * this.C_y * lat;
- } else {
-
- var s = Math.sin(lat);
- var c = Math.cos(lat);
- y = this.a * Proj4js.common.pj_mlfn(lat, s, c, this.en);
- x = this.a * lon * c / Math.sqrt(1. - this.es * s * s);
- }
- p.x=x;
- p.y=y;
- return p;
- },
- inverse: function(p) {
- var lat,temp,lon;
-
- /* Inverse equations
- -----------------*/
- p.x -= this.x0;
- p.y -= this.y0;
- lat = p.y / this.a;
-
- if (this.sphere) {
-
- p.y /= this.C_y;
- lat = this.m ? Math.asin((this.m * p.y + Math.sin(p.y)) / this.n) :
- ( this.n != 1. ? Math.asin(Math.sin(p.y) / this.n) : p.y );
- lon = p.x / (this.C_x * (this.m + Math.cos(p.y)));
-
- } else {
- lat = Proj4js.common.pj_inv_mlfn(p.y/this.a, this.es, this.en)
- var s = Math.abs(lat);
- if (s < Proj4js.common.HALF_PI) {
- s = Math.sin(lat);
- temp = this.long0 + p.x * Math.sqrt(1. - this.es * s * s) /(this.a * Math.cos(lat));
- //temp = this.long0 + p.x / (this.a * Math.cos(lat));
- lon = Proj4js.common.adjust_lon(temp);
- } else if ((s - Proj4js.common.EPSLN) < Proj4js.common.HALF_PI) {
- lon = this.long0;
- }
-
- }
-
- p.x=lon;
- p.y=lat;
- return p;
- }
- };
- /* ======================================================================
- projCode/vandg.js
- ====================================================================== */
- /*******************************************************************************
- NAME VAN DER GRINTEN
- PURPOSE: Transforms input Easting and Northing to longitude and
- latitude for the Van der Grinten projection. The
- Easting and Northing must be in meters. The longitude
- and latitude values will be returned in radians.
- PROGRAMMER DATE
- ---------- ----
- T. Mittan March, 1993
- This function was adapted from the Van Der Grinten projection code
- (FORTRAN) in the General Cartographic Transformation Package software
- which is available from the U.S. Geological Survey National Mapping Division.
-
- ALGORITHM REFERENCES
- 1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder,
- The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355.
- 2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 3. "Software Documentation for GCTP General Cartographic Transformation
- Package", U.S. Geological Survey National Mapping Division, May 1982.
- *******************************************************************************/
- Proj4js.Proj.vandg = {
- /* Initialize the Van Der Grinten projection
- ----------------------------------------*/
- init: function() {
- this.R = 6370997.0; //Radius of earth
- },
- forward: function(p) {
- var lon=p.x;
- var lat=p.y;
- /* Forward equations
- -----------------*/
- var dlon = Proj4js.common.adjust_lon(lon - this.long0);
- var x,y;
- if (Math.abs(lat) <= Proj4js.common.EPSLN) {
- x = this.x0 + this.R * dlon;
- y = this.y0;
- }
- var theta = Proj4js.common.asinz(2.0 * Math.abs(lat / Proj4js.common.PI));
- if ((Math.abs(dlon) <= Proj4js.common.EPSLN) || (Math.abs(Math.abs(lat) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN)) {
- x = this.x0;
- if (lat >= 0) {
- y = this.y0 + Proj4js.common.PI * this.R * Math.tan(.5 * theta);
- } else {
- y = this.y0 + Proj4js.common.PI * this.R * - Math.tan(.5 * theta);
- }
- // return(OK);
- }
- var al = .5 * Math.abs((Proj4js.common.PI / dlon) - (dlon / Proj4js.common.PI));
- var asq = al * al;
- var sinth = Math.sin(theta);
- var costh = Math.cos(theta);
- var g = costh / (sinth + costh - 1.0);
- var gsq = g * g;
- var m = g * (2.0 / sinth - 1.0);
- var msq = m * m;
- var con = Proj4js.common.PI * this.R * (al * (g - msq) + Math.sqrt(asq * (g - msq) * (g - msq) - (msq + asq) * (gsq - msq))) / (msq + asq);
- if (dlon < 0) {
- con = -con;
- }
- x = this.x0 + con;
- con = Math.abs(con / (Proj4js.common.PI * this.R));
- if (lat >= 0) {
- y = this.y0 + Proj4js.common.PI * this.R * Math.sqrt(1.0 - con * con - 2.0 * al * con);
- } else {
- y = this.y0 - Proj4js.common.PI * this.R * Math.sqrt(1.0 - con * con - 2.0 * al * con);
- }
- p.x = x;
- p.y = y;
- return p;
- },
- /* Van Der Grinten inverse equations--mapping x,y to lat/long
- ---------------------------------------------------------*/
- inverse: function(p) {
- var lon, lat;
- var xx,yy,xys,c1,c2,c3;
- var al,asq;
- var a1;
- var m1;
- var con;
- var th1;
- var d;
- /* inverse equations
- -----------------*/
- p.x -= this.x0;
- p.y -= this.y0;
- con = Proj4js.common.PI * this.R;
- xx = p.x / con;
- yy =p.y / con;
- xys = xx * xx + yy * yy;
- c1 = -Math.abs(yy) * (1.0 + xys);
- c2 = c1 - 2.0 * yy * yy + xx * xx;
- c3 = -2.0 * c1 + 1.0 + 2.0 * yy * yy + xys * xys;
- d = yy * yy / c3 + (2.0 * c2 * c2 * c2 / c3 / c3 / c3 - 9.0 * c1 * c2 / c3 /c3) / 27.0;
- a1 = (c1 - c2 * c2 / 3.0 / c3) / c3;
- m1 = 2.0 * Math.sqrt( -a1 / 3.0);
- con = ((3.0 * d) / a1) / m1;
- if (Math.abs(con) > 1.0) {
- if (con >= 0.0) {
- con = 1.0;
- } else {
- con = -1.0;
- }
- }
- th1 = Math.acos(con) / 3.0;
- if (p.y >= 0) {
- lat = (-m1 *Math.cos(th1 + Proj4js.common.PI / 3.0) - c2 / 3.0 / c3) * Proj4js.common.PI;
- } else {
- lat = -(-m1 * Math.cos(th1 + Proj4js.common.PI / 3.0) - c2 / 3.0 / c3) * Proj4js.common.PI;
- }
- if (Math.abs(xx) < Proj4js.common.EPSLN) {
- lon = this.long0;
- }
- lon = Proj4js.common.adjust_lon(this.long0 + Proj4js.common.PI * (xys - 1.0 + Math.sqrt(1.0 + 2.0 * (xx * xx - yy * yy) + xys * xys)) / 2.0 / xx);
- p.x=lon;
- p.y=lat;
- return p;
- }
- };
- /* ======================================================================
- projCode/cea.js
- ====================================================================== */
- /*******************************************************************************
- NAME LAMBERT CYLINDRICAL EQUAL AREA
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the Lambert Cylindrical Equal Area projection.
- This class of projection includes the Behrmann and
- Gall-Peters Projections. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- PROGRAMMER DATE
- ---------- ----
- R. Marsden August 2009
- Winwaed Software Tech LLC, http://www.winwaed.com
- This function was adapted from the Miller Cylindrical Projection in the Proj4JS
- library.
- Note: This implementation assumes a Spherical Earth. The (commented) code
- has been included for the ellipsoidal forward transform, but derivation of
- the ellispoidal inverse transform is beyond me. Note that most of the
- Proj4JS implementations do NOT currently support ellipsoidal figures.
- Therefore this is not seen as a problem - especially this lack of support
- is explicitly stated here.
-
- ALGORITHM REFERENCES
- 1. "Cartographic Projection Procedures for the UNIX Environment -
- A User's Manual" by Gerald I. Evenden, USGS Open File Report 90-284
- and Release 4 Interim Reports (2003)
- 2. Snyder, John P., "Flattening the Earth - Two Thousand Years of Map
- Projections", Univ. Chicago Press, 1993
- *******************************************************************************/
- Proj4js.Proj.cea = {
- /* Initialize the Cylindrical Equal Area projection
- -------------------------------------------*/
- init: function() {
- //no-op
- },
- /* Cylindrical Equal Area forward equations--mapping lat,long to x,y
- ------------------------------------------------------------*/
- forward: function(p) {
- var lon=p.x;
- var lat=p.y;
- /* Forward equations
- -----------------*/
- var dlon = Proj4js.common.adjust_lon(lon -this.long0);
- var x = this.x0 + this.a * dlon * Math.cos(this.lat_ts);
- var y = this.y0 + this.a * Math.sin(lat) / Math.cos(this.lat_ts);
- /* Elliptical Forward Transform
- Not implemented due to a lack of a matchign inverse function
- {
- var Sin_Lat = Math.sin(lat);
- var Rn = this.a * (Math.sqrt(1.0e0 - this.es * Sin_Lat * Sin_Lat ));
- x = this.x0 + this.a * dlon * Math.cos(this.lat_ts);
- y = this.y0 + Rn * Math.sin(lat) / Math.cos(this.lat_ts);
- }
- */
- p.x=x;
- p.y=y;
- return p;
- },//ceaFwd()
- /* Cylindrical Equal Area inverse equations--mapping x,y to lat/long
- ------------------------------------------------------------*/
- inverse: function(p) {
- p.x -= this.x0;
- p.y -= this.y0;
- var lon = Proj4js.common.adjust_lon( this.long0 + (p.x / this.a) / Math.cos(this.lat_ts) );
- var lat = Math.asin( (p.y/this.a) * Math.cos(this.lat_ts) );
- p.x=lon;
- p.y=lat;
- return p;
- }//ceaInv()
- };
- /* ======================================================================
- projCode/eqc.js
- ====================================================================== */
- /* similar to equi.js FIXME proj4 uses eqc */
- Proj4js.Proj.eqc = {
- init : function() {
- if(!this.x0) this.x0=0;
- if(!this.y0) this.y0=0;
- if(!this.lat0) this.lat0=0;
- if(!this.long0) this.long0=0;
- if(!this.lat_ts) this.lat_ts=0;
- if (!this.title) this.title = "Equidistant Cylindrical (Plate Carre)";
- this.rc= Math.cos(this.lat_ts);
- },
- // forward equations--mapping lat,long to x,y
- // -----------------------------------------------------------------
- forward : function(p) {
- var lon= p.x;
- var lat= p.y;
- var dlon = Proj4js.common.adjust_lon(lon - this.long0);
- var dlat = Proj4js.common.adjust_lat(lat - this.lat0 );
- p.x= this.x0 + (this.a*dlon*this.rc);
- p.y= this.y0 + (this.a*dlat );
- return p;
- },
- // inverse equations--mapping x,y to lat/long
- // -----------------------------------------------------------------
- inverse : function(p) {
- var x= p.x;
- var y= p.y;
- p.x= Proj4js.common.adjust_lon(this.long0 + ((x - this.x0)/(this.a*this.rc)));
- p.y= Proj4js.common.adjust_lat(this.lat0 + ((y - this.y0)/(this.a )));
- return p;
- }
- };
- /* ======================================================================
- projCode/cass.js
- ====================================================================== */
- /*******************************************************************************
- NAME CASSINI
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the Cassini projection. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- Ported from PROJ.4.
- ALGORITHM REFERENCES
- 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
- U.S. Geological Survey Professional Paper 1453 , United State Government
- *******************************************************************************/
- //Proj4js.defs["EPSG:28191"] = "+proj=cass +lat_0=31.73409694444445 +lon_0=35.21208055555556 +x_0=170251.555 +y_0=126867.909 +a=6378300.789 +b=6356566.435 +towgs84=-275.722,94.7824,340.894,-8.001,-4.42,-11.821,1 +units=m +no_defs";
- // Initialize the Cassini projection
- // -----------------------------------------------------------------
- Proj4js.Proj.cass = {
- init : function() {
- if (!this.sphere) {
- this.en = Proj4js.common.pj_enfn(this.es)
- this.m0 = Proj4js.common.pj_mlfn(this.lat0, Math.sin(this.lat0), Math.cos(this.lat0), this.en);
- }
- },
- C1: .16666666666666666666,
- C2: .00833333333333333333,
- C3: .04166666666666666666,
- C4: .33333333333333333333,
- C5: .06666666666666666666,
- /* Cassini forward equations--mapping lat,long to x,y
- -----------------------------------------------------------------------*/
- forward: function(p) {
- /* Forward equations
- -----------------*/
- var x,y;
- var lam=p.x;
- var phi=p.y;
- lam = Proj4js.common.adjust_lon(lam - this.long0);
-
- if (this.sphere) {
- x = Math.asin(Math.cos(phi) * Math.sin(lam));
- y = Math.atan2(Math.tan(phi) , Math.cos(lam)) - this.phi0;
- } else {
- //ellipsoid
- this.n = Math.sin(phi);
- this.c = Math.cos(phi);
- y = Proj4js.common.pj_mlfn(phi, this.n, this.c, this.en);
- this.n = 1./Math.sqrt(1. - this.es * this.n * this.n);
- this.tn = Math.tan(phi);
- this.t = this.tn * this.tn;
- this.a1 = lam * this.c;
- this.c *= this.es * this.c / (1 - this.es);
- this.a2 = this.a1 * this.a1;
- x = this.n * this.a1 * (1. - this.a2 * this.t * (this.C1 - (8. - this.t + 8. * this.c) * this.a2 * this.C2));
- y -= this.m0 - this.n * this.tn * this.a2 * (.5 + (5. - this.t + 6. * this.c) * this.a2 * this.C3);
- }
-
- p.x = this.a*x + this.x0;
- p.y = this.a*y + this.y0;
- return p;
- },//cassFwd()
- /* Inverse equations
- -----------------*/
- inverse: function(p) {
- p.x -= this.x0;
- p.y -= this.y0;
- var x = p.x/this.a;
- var y = p.y/this.a;
- var phi, lam;
- if (this.sphere) {
- this.dd = y + this.lat0;
- phi = Math.asin(Math.sin(this.dd) * Math.cos(x));
- lam = Math.atan2(Math.tan(x), Math.cos(this.dd));
- } else {
- /* ellipsoid */
- var ph1 = Proj4js.common.pj_inv_mlfn(this.m0 + y, this.es, this.en);
- this.tn = Math.tan(ph1);
- this.t = this.tn * this.tn;
- this.n = Math.sin(ph1);
- this.r = 1. / (1. - this.es * this.n * this.n);
- this.n = Math.sqrt(this.r);
- this.r *= (1. - this.es) * this.n;
- this.dd = x / this.n;
- this.d2 = this.dd * this.dd;
- phi = ph1 - (this.n * this.tn / this.r) * this.d2 * (.5 - (1. + 3. * this.t) * this.d2 * this.C3);
- lam = this.dd * (1. + this.t * this.d2 * (-this.C4 + (1. + 3. * this.t) * this.d2 * this.C5)) / Math.cos(ph1);
- }
- p.x = Proj4js.common.adjust_lon(this.long0+lam);
- p.y = phi;
- return p;
- }//cassInv()
- }
- /* ======================================================================
- projCode/gauss.js
- ====================================================================== */
- Proj4js.Proj.gauss = {
- init : function() {
- var sphi = Math.sin(this.lat0);
- var cphi = Math.cos(this.lat0);
- cphi *= cphi;
- this.rc = Math.sqrt(1.0 - this.es) / (1.0 - this.es * sphi * sphi);
- this.C = Math.sqrt(1.0 + this.es * cphi * cphi / (1.0 - this.es));
- this.phic0 = Math.asin(sphi / this.C);
- this.ratexp = 0.5 * this.C * this.e;
- this.K = Math.tan(0.5 * this.phic0 + Proj4js.common.FORTPI) / (Math.pow(Math.tan(0.5*this.lat0 + Proj4js.common.FORTPI), this.C) * Proj4js.common.srat(this.e*sphi, this.ratexp));
- },
- forward : function(p) {
- var lon = p.x;
- var lat = p.y;
- p.y = 2.0 * Math.atan( this.K * Math.pow(Math.tan(0.5 * lat + Proj4js.common.FORTPI), this.C) * Proj4js.common.srat(this.e * Math.sin(lat), this.ratexp) ) - Proj4js.common.HALF_PI;
- p.x = this.C * lon;
- return p;
- },
- inverse : function(p) {
- var DEL_TOL = 1e-14;
- var lon = p.x / this.C;
- var lat = p.y;
- var num = Math.pow(Math.tan(0.5 * lat + Proj4js.common.FORTPI)/this.K, 1./this.C);
- for (var i = Proj4js.common.MAX_ITER; i>0; --i) {
- lat = 2.0 * Math.atan(num * Proj4js.common.srat(this.e * Math.sin(p.y), -0.5 * this.e)) - Proj4js.common.HALF_PI;
- if (Math.abs(lat - p.y) < DEL_TOL) break;
- p.y = lat;
- }
- /* convergence failed */
- if (!i) {
- Proj4js.reportError("gauss:inverse:convergence failed");
- return null;
- }
- p.x = lon;
- p.y = lat;
- return p;
- }
- };
- /* ======================================================================
- projCode/omerc.js
- ====================================================================== */
- /*******************************************************************************
- NAME OBLIQUE MERCATOR (HOTINE)
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the Oblique Mercator projection. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- PROGRAMMER DATE
- ---------- ----
- T. Mittan Mar, 1993
- ALGORITHM REFERENCES
- 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
- U.S. Geological Survey Professional Paper 1453 , United State Government
- Printing Office, Washington D.C., 1989.
- *******************************************************************************/
- Proj4js.Proj.omerc = {
- /* Initialize the Oblique Mercator projection
- ------------------------------------------*/
- init: function() {
- if (!this.mode) this.mode=0;
- if (!this.lon1) {this.lon1=0;this.mode=1;}
- if (!this.lon2) this.lon2=0;
- if (!this.lat2) this.lat2=0;
- /* Place parameters in static storage for common use
- -------------------------------------------------*/
- var temp = this.b/ this.a;
- var es = 1.0 - Math.pow(temp,2);
- var e = Math.sqrt(es);
- this.sin_p20=Math.sin(this.lat0);
- this.cos_p20=Math.cos(this.lat0);
- this.con = 1.0 - this.es * this.sin_p20 * this.sin_p20;
- this.com = Math.sqrt(1.0 - es);
- this.bl = Math.sqrt(1.0 + this.es * Math.pow(this.cos_p20,4.0)/(1.0 - es));
- this.al = this.a * this.bl * this.k0 * this.com / this.con;
- if (Math.abs(this.lat0) < Proj4js.common.EPSLN) {
- this.ts = 1.0;
- this.d = 1.0;
- this.el = 1.0;
- } else {
- this.ts = Proj4js.common.tsfnz(this.e,this.lat0,this.sin_p20);
- this.con = Math.sqrt(this.con);
- this.d = this.bl * this.com / (this.cos_p20 * this.con);
- if ((this.d * this.d - 1.0) > 0.0) {
- if (this.lat0 >= 0.0) {
- this.f = this.d + Math.sqrt(this.d * this.d - 1.0);
- } else {
- this.f = this.d - Math.sqrt(this.d * this.d - 1.0);
- }
- } else {
- this.f = this.d;
- }
- this.el = this.f * Math.pow(this.ts,this.bl);
- }
- //this.longc=52.60353916666667;
- if (this.mode != 0) {
- this.g = .5 * (this.f - 1.0/this.f);
- this.gama = Proj4js.common.asinz(Math.sin(this.alpha) / this.d);
- this.longc= this.longc - Proj4js.common.asinz(this.g * Math.tan(this.gama))/this.bl;
- /* Report parameters common to format B
- -------------------------------------*/
- //genrpt(azimuth * R2D,"Azimuth of Central Line: ");
- //cenlon(lon_origin);
- // cenlat(lat_origin);
- this.con = Math.abs(this.lat0);
- if ((this.con > Proj4js.common.EPSLN) && (Math.abs(this.con - Proj4js.common.HALF_PI) > Proj4js.common.EPSLN)) {
- this.singam=Math.sin(this.gama);
- this.cosgam=Math.cos(this.gama);
- this.sinaz=Math.sin(this.alpha);
- this.cosaz=Math.cos(this.alpha);
- if (this.lat0>= 0) {
- this.u = (this.al / this.bl) * Math.atan(Math.sqrt(this.d*this.d - 1.0)/this.cosaz);
- } else {
- this.u = -(this.al / this.bl) *Math.atan(Math.sqrt(this.d*this.d - 1.0)/this.cosaz);
- }
- } else {
- Proj4js.reportError("omerc:Init:DataError");
- }
- } else {
- this.sinphi =Math. sin(this.at1);
- this.ts1 = Proj4js.common.tsfnz(this.e,this.lat1,this.sinphi);
- this.sinphi = Math.sin(this.lat2);
- this.ts2 = Proj4js.common.tsfnz(this.e,this.lat2,this.sinphi);
- this.h = Math.pow(this.ts1,this.bl);
- this.l = Math.pow(this.ts2,this.bl);
- this.f = this.el/this.h;
- this.g = .5 * (this.f - 1.0/this.f);
- this.j = (this.el * this.el - this.l * this.h)/(this.el * this.el + this.l * this.h);
- this.p = (this.l - this.h) / (this.l + this.h);
- this.dlon = this.lon1 - this.lon2;
- if (this.dlon < -Proj4js.common.PI) this.lon2 = this.lon2 - 2.0 * Proj4js.common.PI;
- if (this.dlon > Proj4js.common.PI) this.lon2 = this.lon2 + 2.0 * Proj4js.common.PI;
- this.dlon = this.lon1 - this.lon2;
- this.longc = .5 * (this.lon1 + this.lon2) -Math.atan(this.j * Math.tan(.5 * this.bl * this.dlon)/this.p)/this.bl;
- this.dlon = Proj4js.common.adjust_lon(this.lon1 - this.longc);
- this.gama = Math.atan(Math.sin(this.bl * this.dlon)/this.g);
- this.alpha = Proj4js.common.asinz(this.d * Math.sin(this.gama));
- /* Report parameters common to format A
- -------------------------------------*/
- if (Math.abs(this.lat1 - this.lat2) <= Proj4js.common.EPSLN) {
- Proj4js.reportError("omercInitDataError");
- //return(202);
- } else {
- this.con = Math.abs(this.lat1);
- }
- if ((this.con <= Proj4js.common.EPSLN) || (Math.abs(this.con - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN)) {
- Proj4js.reportError("omercInitDataError");
- //return(202);
- } else {
- if (Math.abs(Math.abs(this.lat0) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN) {
- Proj4js.reportError("omercInitDataError");
- //return(202);
- }
- }
- this.singam=Math.sin(this.gam);
- this.cosgam=Math.cos(this.gam);
- this.sinaz=Math.sin(this.alpha);
- this.cosaz=Math.cos(this.alpha);
- if (this.lat0 >= 0) {
- this.u = (this.al/this.bl) * Math.atan(Math.sqrt(this.d * this.d - 1.0)/this.cosaz);
- } else {
- this.u = -(this.al/this.bl) * Math.atan(Math.sqrt(this.d * this.d - 1.0)/this.cosaz);
- }
- }
- },
- /* Oblique Mercator forward equations--mapping lat,long to x,y
- ----------------------------------------------------------*/
- forward: function(p) {
- var theta; /* angle */
- var sin_phi, cos_phi;/* sin and cos value */
- var b; /* temporary values */
- var c, t, tq; /* temporary values */
- var con, n, ml; /* cone constant, small m */
- var q,us,vl;
- var ul,vs;
- var s;
- var dlon;
- var ts1;
- var lon=p.x;
- var lat=p.y;
- /* Forward equations
- -----------------*/
- sin_phi = Math.sin(lat);
- dlon = Proj4js.common.adjust_lon(lon - this.longc);
- vl = Math.sin(this.bl * dlon);
- if (Math.abs(Math.abs(lat) - Proj4js.common.HALF_PI) > Proj4js.common.EPSLN) {
- ts1 = Proj4js.common.tsfnz(this.e,lat,sin_phi);
- q = this.el / (Math.pow(ts1,this.bl));
- s = .5 * (q - 1.0 / q);
- t = .5 * (q + 1.0/ q);
- ul = (s * this.singam - vl * this.cosgam) / t;
- con = Math.cos(this.bl * dlon);
- if (Math.abs(con) < .0000001) {
- us = this.al * this.bl * dlon;
- } else {
- us = this.al * Math.atan((s * this.cosgam + vl * this.singam) / con)/this.bl;
- if (con < 0) us = us + Proj4js.common.PI * this.al / this.bl;
- }
- } else {
- if (lat >= 0) {
- ul = this.singam;
- } else {
- ul = -this.singam;
- }
- us = this.al * lat / this.bl;
- }
- if (Math.abs(Math.abs(ul) - 1.0) <= Proj4js.common.EPSLN) {
- //alert("Point projects into infinity","omer-for");
- Proj4js.reportError("omercFwdInfinity");
- //return(205);
- }
- vs = .5 * this.al * Math.log((1.0 - ul)/(1.0 + ul)) / this.bl;
- us = us - this.u;
- var x = this.x0 + vs * this.cosaz + us * this.sinaz;
- var y = this.y0 + us * this.cosaz - vs * this.sinaz;
- p.x=x;
- p.y=y;
- return p;
- },
- inverse: function(p) {
- var delta_lon; /* Delta longitude (Given longitude - center */
- var theta; /* angle */
- var delta_theta; /* adjusted longitude */
- var sin_phi, cos_phi;/* sin and cos value */
- var b; /* temporary values */
- var c, t, tq; /* temporary values */
- var con, n, ml; /* cone constant, small m */
- var vs,us,q,s,ts1;
- var vl,ul,bs;
- var lon, lat;
- var flag;
- /* Inverse equations
- -----------------*/
- p.x -= this.x0;
- p.y -= this.y0;
- flag = 0;
- vs = p.x * this.cosaz - p.y * this.sinaz;
- us = p.y * this.cosaz + p.x * this.sinaz;
- us = us + this.u;
- q = Math.exp(-this.bl * vs / this.al);
- s = .5 * (q - 1.0/q);
- t = .5 * (q + 1.0/q);
- vl = Math.sin(this.bl * us / this.al);
- ul = (vl * this.cosgam + s * this.singam)/t;
- if (Math.abs(Math.abs(ul) - 1.0) <= Proj4js.common.EPSLN)
- {
- lon = this.longc;
- if (ul >= 0.0) {
- lat = Proj4js.common.HALF_PI;
- } else {
- lat = -Proj4js.common.HALF_PI;
- }
- } else {
- con = 1.0 / this.bl;
- ts1 =Math.pow((this.el / Math.sqrt((1.0 + ul) / (1.0 - ul))),con);
- lat = Proj4js.common.phi2z(this.e,ts1);
- //if (flag != 0)
- //return(flag);
- //~ con = Math.cos(this.bl * us /al);
- theta = this.longc - Math.atan2((s * this.cosgam - vl * this.singam) , con)/this.bl;
- lon = Proj4js.common.adjust_lon(theta);
- }
- p.x=lon;
- p.y=lat;
- return p;
- }
- };
- /* ======================================================================
- projCode/lcc.js
- ====================================================================== */
- /*******************************************************************************
- NAME LAMBERT CONFORMAL CONIC
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the Lambert Conformal Conic projection. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- ALGORITHM REFERENCES
- 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
- U.S. Geological Survey Professional Paper 1453 , United State Government
- *******************************************************************************/
- //<2104> +proj=lcc +lat_1=10.16666666666667 +lat_0=10.16666666666667 +lon_0=-71.60561777777777 +k_0=1 +x0=-17044 +x0=-23139.97 +ellps=intl +units=m +no_defs no_defs
- // Initialize the Lambert Conformal conic projection
- // -----------------------------------------------------------------
- //Proj4js.Proj.lcc = Class.create();
- Proj4js.Proj.lcc = {
- init : function() {
- // array of: r_maj,r_min,lat1,lat2,c_lon,c_lat,false_east,false_north
- //double c_lat; /* center latitude */
- //double c_lon; /* center longitude */
- //double lat1; /* first standard parallel */
- //double lat2; /* second standard parallel */
- //double r_maj; /* major axis */
- //double r_min; /* minor axis */
- //double false_east; /* x offset in meters */
- //double false_north; /* y offset in meters */
- if (!this.lat2){this.lat2=this.lat0;}//if lat2 is not defined
- if (!this.k0) this.k0 = 1.0;
- // Standard Parallels cannot be equal and on opposite sides of the equator
- if (Math.abs(this.lat1+this.lat2) < Proj4js.common.EPSLN) {
- Proj4js.reportError("lcc:init: Equal Latitudes");
- return;
- }
- var temp = this.b / this.a;
- this.e = Math.sqrt(1.0 - temp*temp);
- var sin1 = Math.sin(this.lat1);
- var cos1 = Math.cos(this.lat1);
- var ms1 = Proj4js.common.msfnz(this.e, sin1, cos1);
- var ts1 = Proj4js.common.tsfnz(this.e, this.lat1, sin1);
- var sin2 = Math.sin(this.lat2);
- var cos2 = Math.cos(this.lat2);
- var ms2 = Proj4js.common.msfnz(this.e, sin2, cos2);
- var ts2 = Proj4js.common.tsfnz(this.e, this.lat2, sin2);
- var ts0 = Proj4js.common.tsfnz(this.e, this.lat0, Math.sin(this.lat0));
- if (Math.abs(this.lat1 - this.lat2) > Proj4js.common.EPSLN) {
- this.ns = Math.log(ms1/ms2)/Math.log(ts1/ts2);
- } else {
- this.ns = sin1;
- }
- this.f0 = ms1 / (this.ns * Math.pow(ts1, this.ns));
- this.rh = this.a * this.f0 * Math.pow(ts0, this.ns);
- if (!this.title) this.title = "Lambert Conformal Conic";
- },
- // Lambert Conformal conic forward equations--mapping lat,long to x,y
- // -----------------------------------------------------------------
- forward : function(p) {
- var lon = p.x;
- var lat = p.y;
- // convert to radians
- if ( lat <= 90.0 && lat >= -90.0 && lon <= 180.0 && lon >= -180.0) {
- //lon = lon * Proj4js.common.D2R;
- //lat = lat * Proj4js.common.D2R;
- } else {
- Proj4js.reportError("lcc:forward: llInputOutOfRange: "+ lon +" : " + lat);
- return null;
- }
- var con = Math.abs( Math.abs(lat) - Proj4js.common.HALF_PI);
- var ts, rh1;
- if (con > Proj4js.common.EPSLN) {
- ts = Proj4js.common.tsfnz(this.e, lat, Math.sin(lat) );
- rh1 = this.a * this.f0 * Math.pow(ts, this.ns);
- } else {
- con = lat * this.ns;
- if (con <= 0) {
- Proj4js.reportError("lcc:forward: No Projection");
- return null;
- }
- rh1 = 0;
- }
- var theta = this.ns * Proj4js.common.adjust_lon(lon - this.long0);
- p.x = this.k0 * (rh1 * Math.sin(theta)) + this.x0;
- p.y = this.k0 * (this.rh - rh1 * Math.cos(theta)) + this.y0;
- return p;
- },
- // Lambert Conformal Conic inverse equations--mapping x,y to lat/long
- // -----------------------------------------------------------------
- inverse : function(p) {
- var rh1, con, ts;
- var lat, lon;
- var x = (p.x - this.x0)/this.k0;
- var y = (this.rh - (p.y - this.y0)/this.k0);
- if (this.ns > 0) {
- rh1 = Math.sqrt (x * x + y * y);
- con = 1.0;
- } else {
- rh1 = -Math.sqrt (x * x + y * y);
- con = -1.0;
- }
- var theta = 0.0;
- if (rh1 != 0) {
- theta = Math.atan2((con * x),(con * y));
- }
- if ((rh1 != 0) || (this.ns > 0.0)) {
- con = 1.0/this.ns;
- ts = Math.pow((rh1/(this.a * this.f0)), con);
- lat = Proj4js.common.phi2z(this.e, ts);
- if (lat == -9999) return null;
- } else {
- lat = -Proj4js.common.HALF_PI;
- }
- lon = Proj4js.common.adjust_lon(theta/this.ns + this.long0);
- p.x = lon;
- p.y = lat;
- return p;
- }
- };
- /* ======================================================================
- projCode/laea.js
- ====================================================================== */
- /*******************************************************************************
- NAME LAMBERT AZIMUTHAL EQUAL-AREA
-
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the Lambert Azimuthal Equal-Area projection. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- PROGRAMMER DATE
- ---------- ----
- D. Steinwand, EROS March, 1991
- This function was adapted from the Lambert Azimuthal Equal Area projection
- code (FORTRAN) in the General Cartographic Transformation Package software
- which is available from the U.S. Geological Survey National Mapping Division.
-
- ALGORITHM REFERENCES
- 1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder,
- The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355.
- 2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- 3. "Software Documentation for GCTP General Cartographic Transformation
- Package", U.S. Geological Survey National Mapping Division, May 1982.
- *******************************************************************************/
- Proj4js.Proj.laea = {
- S_POLE: 1,
- N_POLE: 2,
- EQUIT: 3,
- OBLIQ: 4,
- /* Initialize the Lambert Azimuthal Equal Area projection
- ------------------------------------------------------*/
- init: function() {
- var t = Math.abs(this.lat0);
- if (Math.abs(t - Proj4js.common.HALF_PI) < Proj4js.common.EPSLN) {
- this.mode = this.lat0 < 0. ? this.S_POLE : this.N_POLE;
- } else if (Math.abs(t) < Proj4js.common.EPSLN) {
- this.mode = this.EQUIT;
- } else {
- this.mode = this.OBLIQ;
- }
- if (this.es > 0) {
- var sinphi;
-
- this.qp = Proj4js.common.qsfnz(this.e, 1.0);
- this.mmf = .5 / (1. - this.es);
- this.apa = this.authset(this.es);
- switch (this.mode) {
- case this.N_POLE:
- case this.S_POLE:
- this.dd = 1.;
- break;
- case this.EQUIT:
- this.rq = Math.sqrt(.5 * this.qp);
- this.dd = 1. / this.rq;
- this.xmf = 1.;
- this.ymf = .5 * this.qp;
- break;
- case this.OBLIQ:
- this.rq = Math.sqrt(.5 * this.qp);
- sinphi = Math.sin(this.lat0);
- this.sinb1 = Proj4js.common.qsfnz(this.e, sinphi) / this.qp;
- this.cosb1 = Math.sqrt(1. - this.sinb1 * this.sinb1);
- this.dd = Math.cos(this.lat0) / (Math.sqrt(1. - this.es * sinphi * sinphi) * this.rq * this.cosb1);
- this.ymf = (this.xmf = this.rq) / this.dd;
- this.xmf *= this.dd;
- break;
- }
- } else {
- if (this.mode == this.OBLIQ) {
- this.sinph0 = Math.sin(this.lat0);
- this.cosph0 = Math.cos(this.lat0);
- }
- }
- },
- /* Lambert Azimuthal Equal Area forward equations--mapping lat,long to x,y
- -----------------------------------------------------------------------*/
- forward: function(p) {
- /* Forward equations
- -----------------*/
- var x,y;
- var lam=p.x;
- var phi=p.y;
- lam = Proj4js.common.adjust_lon(lam - this.long0);
-
- if (this.sphere) {
- var coslam, cosphi, sinphi;
-
- sinphi = Math.sin(phi);
- cosphi = Math.cos(phi);
- coslam = Math.cos(lam);
- switch (this.mode) {
- case this.OBLIQ:
- case this.EQUIT:
- y = (this.mode == this.EQUIT) ? 1. + cosphi * coslam : 1. + this.sinph0 * sinphi + this.cosph0 * cosphi * coslam;
- if (y <= Proj4js.common.EPSLN) {
- Proj4js.reportError("laea:fwd:y less than eps");
- return null;
- }
- y = Math.sqrt(2. / y);
- x = y * cosphi * Math.sin(lam);
- y *= (this.mode == this.EQUIT) ? sinphi : this.cosph0 * sinphi - this.sinph0 * cosphi * coslam;
- break;
- case this.N_POLE:
- coslam = -coslam;
- case this.S_POLE:
- if (Math.abs(phi + this.phi0) < Proj4js.common.EPSLN) {
- Proj4js.reportError("laea:fwd:phi < eps");
- return null;
- }
- y = Proj4js.common.FORTPI - phi * .5;
- y = 2. * ((this.mode == this.S_POLE) ? Math.cos(y) : Math.sin(y));
- x = y * Math.sin(lam);
- y *= coslam;
- break;
- }
- } else {
- var coslam, sinlam, sinphi, q, sinb=0.0, cosb=0.0, b=0.0;
-
- coslam = Math.cos(lam);
- sinlam = Math.sin(lam);
- sinphi = Math.sin(phi);
- q = Proj4js.common.qsfnz(this.e, sinphi);
- if (this.mode == this.OBLIQ || this.mode == this.EQUIT) {
- sinb = q / this.qp;
- cosb = Math.sqrt(1. - sinb * sinb);
- }
- switch (this.mode) {
- case this.OBLIQ:
- b = 1. + this.sinb1 * sinb + this.cosb1 * cosb * coslam;
- break;
- case this.EQUIT:
- b = 1. + cosb * coslam;
- break;
- case this.N_POLE:
- b = Proj4js.common.HALF_PI + phi;
- q = this.qp - q;
- break;
- case this.S_POLE:
- b = phi - Proj4js.common.HALF_PI;
- q = this.qp + q;
- break;
- }
- if (Math.abs(b) < Proj4js.common.EPSLN) {
- Proj4js.reportError("laea:fwd:b < eps");
- return null;
- }
- switch (this.mode) {
- case this.OBLIQ:
- case this.EQUIT:
- b = Math.sqrt(2. / b);
- if (this.mode == this.OBLIQ) {
- y = this.ymf * b * (this.cosb1 * sinb - this.sinb1 * cosb * coslam);
- } else {
- y = (b = Math.sqrt(2. / (1. + cosb * coslam))) * sinb * this.ymf;
- }
- x = this.xmf * b * cosb * sinlam;
- break;
- case this.N_POLE:
- case this.S_POLE:
- if (q >= 0.) {
- x = (b = Math.sqrt(q)) * sinlam;
- y = coslam * ((this.mode == this.S_POLE) ? b : -b);
- } else {
- x = y = 0.;
- }
- break;
- }
- }
- //v 1.0
- /*
- var sin_lat=Math.sin(lat);
- var cos_lat=Math.cos(lat);
- var sin_delta_lon=Math.sin(delta_lon);
- var cos_delta_lon=Math.cos(delta_lon);
- var g =this.sin_lat_o * sin_lat +this.cos_lat_o * cos_lat * cos_delta_lon;
- if (g == -1.0) {
- Proj4js.reportError("laea:fwd:Point projects to a circle of radius "+ 2.0 * R);
- return null;
- }
- var ksp = this.a * Math.sqrt(2.0 / (1.0 + g));
- var x = ksp * cos_lat * sin_delta_lon + this.x0;
- var y = ksp * (this.cos_lat_o * sin_lat - this.sin_lat_o * cos_lat * cos_delta_lon) + this.y0;
- */
- p.x = this.a*x + this.x0;
- p.y = this.a*y + this.y0;
- return p;
- },//lamazFwd()
- /* Inverse equations
- -----------------*/
- inverse: function(p) {
- p.x -= this.x0;
- p.y -= this.y0;
- var x = p.x/this.a;
- var y = p.y/this.a;
- var lam, phi;
- if (this.sphere) {
- var cosz=0.0, rh, sinz=0.0;
-
- rh = Math.sqrt(x*x + y*y);
- phi = rh * .5;
- if (phi > 1.) {
- Proj4js.reportError("laea:Inv:DataError");
- return null;
- }
- phi = 2. * Math.asin(phi);
- if (this.mode == this.OBLIQ || this.mode == this.EQUIT) {
- sinz = Math.sin(phi);
- cosz = Math.cos(phi);
- }
- switch (this.mode) {
- case this.EQUIT:
- phi = (Math.abs(rh) <= Proj4js.common.EPSLN) ? 0. : Math.asin(y * sinz / rh);
- x *= sinz;
- y = cosz * rh;
- break;
- case this.OBLIQ:
- phi = (Math.abs(rh) <= Proj4js.common.EPSLN) ? this.phi0 : Math.asin(cosz * this.sinph0 + y * sinz * this.cosph0 / rh);
- x *= sinz * this.cosph0;
- y = (cosz - Math.sin(phi) * this.sinph0) * rh;
- break;
- case this.N_POLE:
- y = -y;
- phi = Proj4js.common.HALF_PI - phi;
- break;
- case this.S_POLE:
- phi -= Proj4js.common.HALF_PI;
- break;
- }
- lam = (y == 0. && (this.mode == this.EQUIT || this.mode == this.OBLIQ)) ? 0. : Math.atan2(x, y);
- } else {
- var cCe, sCe, q, rho, ab=0.0;
-
- switch (this.mode) {
- case this.EQUIT:
- case this.OBLIQ:
- x /= this.dd;
- y *= this.dd;
- rho = Math.sqrt(x*x + y*y);
- if (rho < Proj4js.common.EPSLN) {
- p.x = 0.;
- p.y = this.phi0;
- return p;
- }
- sCe = 2. * Math.asin(.5 * rho / this.rq);
- cCe = Math.cos(sCe);
- x *= (sCe = Math.sin(sCe));
- if (this.mode == this.OBLIQ) {
- ab = cCe * this.sinb1 + y * sCe * this.cosb1 / rho
- q = this.qp * ab;
- y = rho * this.cosb1 * cCe - y * this.sinb1 * sCe;
- } else {
- ab = y * sCe / rho;
- q = this.qp * ab;
- y = rho * cCe;
- }
- break;
- case this.N_POLE:
- y = -y;
- case this.S_POLE:
- q = (x * x + y * y);
- if (!q ) {
- p.x = 0.;
- p.y = this.phi0;
- return p;
- }
- /*
- q = this.qp - q;
- */
- ab = 1. - q / this.qp;
- if (this.mode == this.S_POLE) {
- ab = - ab;
- }
- break;
- }
- lam = Math.atan2(x, y);
- phi = this.authlat(Math.asin(ab), this.apa);
- }
- /*
- var Rh = Math.Math.sqrt(p.x *p.x +p.y * p.y);
- var temp = Rh / (2.0 * this.a);
- if (temp > 1) {
- Proj4js.reportError("laea:Inv:DataError");
- return null;
- }
- var z = 2.0 * Proj4js.common.asinz(temp);
- var sin_z=Math.sin(z);
- var cos_z=Math.cos(z);
- var lon =this.long0;
- if (Math.abs(Rh) > Proj4js.common.EPSLN) {
- var lat = Proj4js.common.asinz(this.sin_lat_o * cos_z +this. cos_lat_o * sin_z *p.y / Rh);
- var temp =Math.abs(this.lat0) - Proj4js.common.HALF_PI;
- if (Math.abs(temp) > Proj4js.common.EPSLN) {
- temp = cos_z -this.sin_lat_o * Math.sin(lat);
- if(temp!=0.0) lon=Proj4js.common.adjust_lon(this.long0+Math.atan2(p.x*sin_z*this.cos_lat_o,temp*Rh));
- } else if (this.lat0 < 0.0) {
- lon = Proj4js.common.adjust_lon(this.long0 - Math.atan2(-p.x,p.y));
- } else {
- lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x, -p.y));
- }
- } else {
- lat = this.lat0;
- }
- */
- //return(OK);
- p.x = Proj4js.common.adjust_lon(this.long0+lam);
- p.y = phi;
- return p;
- },//lamazInv()
-
- /* determine latitude from authalic latitude */
- P00: .33333333333333333333,
- P01: .17222222222222222222,
- P02: .10257936507936507936,
- P10: .06388888888888888888,
- P11: .06640211640211640211,
- P20: .01641501294219154443,
-
- authset: function(es) {
- var t;
- var APA = new Array();
- APA[0] = es * this.P00;
- t = es * es;
- APA[0] += t * this.P01;
- APA[1] = t * this.P10;
- t *= es;
- APA[0] += t * this.P02;
- APA[1] += t * this.P11;
- APA[2] = t * this.P20;
- return APA;
- },
-
- authlat: function(beta, APA) {
- var t = beta+beta;
- return(beta + APA[0] * Math.sin(t) + APA[1] * Math.sin(t+t) + APA[2] * Math.sin(t+t+t));
- }
-
- };
- /* ======================================================================
- projCode/aeqd.js
- ====================================================================== */
- Proj4js.Proj.aeqd = {
- init : function() {
- this.sin_p12=Math.sin(this.lat0);
- this.cos_p12=Math.cos(this.lat0);
- },
- forward: function(p) {
- var lon=p.x;
- var lat=p.y;
- var ksp;
- var sinphi=Math.sin(p.y);
- var cosphi=Math.cos(p.y);
- var dlon = Proj4js.common.adjust_lon(lon - this.long0);
- var coslon = Math.cos(dlon);
- var g = this.sin_p12 * sinphi + this.cos_p12 * cosphi * coslon;
- if (Math.abs(Math.abs(g) - 1.0) < Proj4js.common.EPSLN) {
- ksp = 1.0;
- if (g < 0.0) {
- Proj4js.reportError("aeqd:Fwd:PointError");
- return;
- }
- } else {
- var z = Math.acos(g);
- ksp = z/Math.sin(z);
- }
- p.x = this.x0 + this.a * ksp * cosphi * Math.sin(dlon);
- p.y = this.y0 + this.a * ksp * (this.cos_p12 * sinphi - this.sin_p12 * cosphi * coslon);
- return p;
- },
- inverse: function(p){
- p.x -= this.x0;
- p.y -= this.y0;
- var rh = Math.sqrt(p.x * p.x + p.y *p.y);
- if (rh > (2.0 * Proj4js.common.HALF_PI * this.a)) {
- Proj4js.reportError("aeqdInvDataError");
- return;
- }
- var z = rh / this.a;
- var sinz=Math.sin(z);
- var cosz=Math.cos(z);
- var lon = this.long0;
- var lat;
- if (Math.abs(rh) <= Proj4js.common.EPSLN) {
- lat = this.lat0;
- } else {
- lat = Proj4js.common.asinz(cosz * this.sin_p12 + (p.y * sinz * this.cos_p12) / rh);
- var con = Math.abs(this.lat0) - Proj4js.common.HALF_PI;
- if (Math.abs(con) <= Proj4js.common.EPSLN) {
- if (this.lat0 >= 0.0) {
- lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x , -p.y));
- } else {
- lon = Proj4js.common.adjust_lon(this.long0 - Math.atan2(-p.x , p.y));
- }
- } else {
- con = cosz - this.sin_p12 * Math.sin(lat);
- if ((Math.abs(con) < Proj4js.common.EPSLN) && (Math.abs(p.x) < Proj4js.common.EPSLN)) {
- //no-op, just keep the lon value as is
- } else {
- var temp = Math.atan2((p.x * sinz * this.cos_p12), (con * rh));
- lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2((p.x * sinz * this.cos_p12), (con * rh)));
- }
- }
- }
- p.x = lon;
- p.y = lat;
- return p;
- }
- };
- /* ======================================================================
- projCode/moll.js
- ====================================================================== */
- /*******************************************************************************
- NAME MOLLWEIDE
- PURPOSE: Transforms input longitude and latitude to Easting and
- Northing for the MOllweide projection. The
- longitude and latitude must be in radians. The Easting
- and Northing values will be returned in meters.
- PROGRAMMER DATE
- ---------- ----
- D. Steinwand, EROS May, 1991; Updated Sept, 1992; Updated Feb, 1993
- S. Nelson, EDC Jun, 2993; Made corrections in precision and
- number of iterations.
- ALGORITHM REFERENCES
- 1. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
- U.S. Geological Survey Professional Paper 1453 , United State Government
- Printing Office, Washington D.C., 1989.
- 2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
- Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
- State Government Printing Office, Washington D.C., 1987.
- *******************************************************************************/
- Proj4js.Proj.moll = {
- /* Initialize the Mollweide projection
- ------------------------------------*/
- init: function(){
- //no-op
- },
- /* Mollweide forward equations--mapping lat,long to x,y
- ----------------------------------------------------*/
- forward: function(p) {
- /* Forward equations
- -----------------*/
- var lon=p.x;
- var lat=p.y;
- var delta_lon = Proj4js.common.adjust_lon(lon - this.long0);
- var theta = lat;
- var con = Proj4js.common.PI * Math.sin(lat);
- /* Iterate using the Newton-Raphson method to find theta
- -----------------------------------------------------*/
- for (var i=0;true;i++) {
- var delta_theta = -(theta + Math.sin(theta) - con)/ (1.0 + Math.cos(theta));
- theta += delta_theta;
- if (Math.abs(delta_theta) < Proj4js.common.EPSLN) break;
- if (i >= 50) {
- Proj4js.reportError("moll:Fwd:IterationError");
- //return(241);
- }
- }
- theta /= 2.0;
- /* If the latitude is 90 deg, force the x coordinate to be "0 + false easting"
- this is done here because of precision problems with "cos(theta)"
- --------------------------------------------------------------------------*/
- if (Proj4js.common.PI/2 - Math.abs(lat) < Proj4js.common.EPSLN) delta_lon =0;
- var x = 0.900316316158 * this.a * delta_lon * Math.cos(theta) + this.x0;
- var y = 1.4142135623731 * this.a * Math.sin(theta) + this.y0;
- p.x=x;
- p.y=y;
- return p;
- },
- inverse: function(p){
- var theta;
- var arg;
- /* Inverse equations
- -----------------*/
- p.x-= this.x0;
- //~ p.y -= this.y0;
- var arg = p.y / (1.4142135623731 * this.a);
- /* Because of division by zero problems, 'arg' can not be 1.0. Therefore
- a number very close to one is used instead.
- -------------------------------------------------------------------*/
- if(Math.abs(arg) > 0.999999999999) arg=0.999999999999;
- var theta =Math.asin(arg);
- var lon = Proj4js.common.adjust_lon(this.long0 + (p.x / (0.900316316158 * this.a * Math.cos(theta))));
- if(lon < (-Proj4js.common.PI)) lon= -Proj4js.common.PI;
- if(lon > Proj4js.common.PI) lon= Proj4js.common.PI;
- arg = (2.0 * theta + Math.sin(2.0 * theta)) / Proj4js.common.PI;
- if(Math.abs(arg) > 1.0)arg=1.0;
- var lat = Math.asin(arg);
- //return(OK);
- p.x=lon;
- p.y=lat;
- return p;
- }
- };
|