proj4js-combined.js 182 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440
  1. /*
  2. proj4js.js -- Javascript reprojection library.
  3. Authors: Mike Adair madairATdmsolutions.ca
  4. Richard Greenwood richATgreenwoodmap.com
  5. Didier Richard didier.richardATign.fr
  6. Stephen Irons stephen.ironsATclear.net.nz
  7. Olivier Terral oterralATgmail.com
  8. License:
  9. Copyright (c) 2012, Mike Adair, Richard Greenwood, Didier Richard,
  10. Stephen Irons and Olivier Terral
  11. Permission is hereby granted, free of charge, to any person obtaining a
  12. copy of this software and associated documentation files (the "Software"),
  13. to deal in the Software without restriction, including without limitation
  14. the rights to use, copy, modify, merge, publish, distribute, sublicense,
  15. and/or sell copies of the Software, and to permit persons to whom the
  16. Software is furnished to do so, subject to the following conditions:
  17. The above copyright notice and this permission notice shall be included
  18. in all copies or substantial portions of the Software.
  19. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22. THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  24. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  25. DEALINGS IN THE SOFTWARE.
  26. Note: This program is an almost direct port of the C library PROJ.4.
  27. */
  28. /* ======================================================================
  29. proj4js.js
  30. ====================================================================== */
  31. /*
  32. Author: Mike Adair madairATdmsolutions.ca
  33. Richard Greenwood rich@greenwoodmap.com
  34. License: LGPL as per: http://www.gnu.org/copyleft/lesser.html
  35. $Id: Proj.js 2956 2007-07-09 12:17:52Z steven $
  36. */
  37. /**
  38. * Namespace: Proj4js
  39. *
  40. * Proj4js is a JavaScript library to transform point coordinates from one
  41. * coordinate system to another, including datum transformations.
  42. *
  43. * This library is a port of both the Proj.4 and GCTCP C libraries to JavaScript.
  44. * Enabling these transformations in the browser allows geographic data stored
  45. * in different projections to be combined in browser-based web mapping
  46. * applications.
  47. *
  48. * Proj4js must have access to coordinate system initialization strings (which
  49. * are the same as for PROJ.4 command line). Thes can be included in your
  50. * application using a <script> tag or Proj4js can load CS initialization
  51. * strings from a local directory or a web service such as spatialreference.org.
  52. *
  53. * Similarly, Proj4js must have access to projection transform code. These can
  54. * be included individually using a <script> tag in your page, built into a
  55. * custom build of Proj4js or loaded dynamically at run-time. Using the
  56. * -combined and -compressed versions of Proj4js includes all projection class
  57. * code by default.
  58. *
  59. * Note that dynamic loading of defs and code happens ascynchrously, check the
  60. * Proj.readyToUse flag before using the Proj object. If the defs and code
  61. * required by your application are loaded through script tags, dynamic loading
  62. * is not required and the Proj object will be readyToUse on return from the
  63. * constructor.
  64. *
  65. * All coordinates are handled as points which have a .x and a .y property
  66. * which will be modified in place.
  67. *
  68. * Override Proj4js.reportError for output of alerts and warnings.
  69. *
  70. * See http://trac.osgeo.org/proj4js/wiki/UserGuide for full details.
  71. */
  72. /**
  73. * Global namespace object for Proj4js library
  74. */
  75. var Proj4js = {
  76. /**
  77. * Property: defaultDatum
  78. * The datum to use when no others a specified
  79. */
  80. defaultDatum: 'WGS84', //default datum
  81. /**
  82. * Method: transform(source, dest, point)
  83. * Transform a point coordinate from one map projection to another. This is
  84. * really the only public method you should need to use.
  85. *
  86. * Parameters:
  87. * source - {Proj4js.Proj} source map projection for the transformation
  88. * dest - {Proj4js.Proj} destination map projection for the transformation
  89. * point - {Object} point to transform, may be geodetic (long, lat) or
  90. * projected Cartesian (x,y), but should always have x,y properties.
  91. */
  92. transform: function(source, dest, point) {
  93. if (!source.readyToUse) {
  94. this.reportError("Proj4js initialization for:"+source.srsCode+" not yet complete");
  95. return point;
  96. }
  97. if (!dest.readyToUse) {
  98. this.reportError("Proj4js initialization for:"+dest.srsCode+" not yet complete");
  99. return point;
  100. }
  101. // Workaround for datum shifts towgs84, if either source or destination projection is not wgs84
  102. if (source.datum && dest.datum && (
  103. ((source.datum.datum_type == Proj4js.common.PJD_3PARAM || source.datum.datum_type == Proj4js.common.PJD_7PARAM) && dest.datumCode != "WGS84") ||
  104. ((dest.datum.datum_type == Proj4js.common.PJD_3PARAM || dest.datum.datum_type == Proj4js.common.PJD_7PARAM) && source.datumCode != "WGS84"))) {
  105. var wgs84 = Proj4js.WGS84;
  106. this.transform(source, wgs84, point);
  107. source = wgs84;
  108. }
  109. // DGR, 2010/11/12
  110. if (source.axis!="enu") {
  111. this.adjust_axis(source,false,point);
  112. }
  113. // Transform source points to long/lat, if they aren't already.
  114. if ( source.projName=="longlat") {
  115. point.x *= Proj4js.common.D2R; // convert degrees to radians
  116. point.y *= Proj4js.common.D2R;
  117. } else {
  118. if (source.to_meter) {
  119. point.x *= source.to_meter;
  120. point.y *= source.to_meter;
  121. }
  122. source.inverse(point); // Convert Cartesian to longlat
  123. }
  124. // Adjust for the prime meridian if necessary
  125. if (source.from_greenwich) {
  126. point.x += source.from_greenwich;
  127. }
  128. // Convert datums if needed, and if possible.
  129. point = this.datum_transform( source.datum, dest.datum, point );
  130. // Adjust for the prime meridian if necessary
  131. if (dest.from_greenwich) {
  132. point.x -= dest.from_greenwich;
  133. }
  134. if( dest.projName=="longlat" ) {
  135. // convert radians to decimal degrees
  136. point.x *= Proj4js.common.R2D;
  137. point.y *= Proj4js.common.R2D;
  138. } else { // else project
  139. dest.forward(point);
  140. if (dest.to_meter) {
  141. point.x /= dest.to_meter;
  142. point.y /= dest.to_meter;
  143. }
  144. }
  145. // DGR, 2010/11/12
  146. if (dest.axis!="enu") {
  147. this.adjust_axis(dest,true,point);
  148. }
  149. return point;
  150. }, // transform()
  151. /** datum_transform()
  152. source coordinate system definition,
  153. destination coordinate system definition,
  154. point to transform in geodetic coordinates (long, lat, height)
  155. */
  156. datum_transform : function( source, dest, point ) {
  157. // Short cut if the datums are identical.
  158. if( source.compare_datums( dest ) ) {
  159. return point; // in this case, zero is sucess,
  160. // whereas cs_compare_datums returns 1 to indicate TRUE
  161. // confusing, should fix this
  162. }
  163. // Explicitly skip datum transform by setting 'datum=none' as parameter for either source or dest
  164. if( source.datum_type == Proj4js.common.PJD_NODATUM
  165. || dest.datum_type == Proj4js.common.PJD_NODATUM) {
  166. return point;
  167. }
  168. // Do we need to go through geocentric coordinates?
  169. if( source.es != dest.es || source.a != dest.a
  170. || source.datum_type == Proj4js.common.PJD_3PARAM
  171. || source.datum_type == Proj4js.common.PJD_7PARAM
  172. || dest.datum_type == Proj4js.common.PJD_3PARAM
  173. || dest.datum_type == Proj4js.common.PJD_7PARAM)
  174. {
  175. // Convert to geocentric coordinates.
  176. source.geodetic_to_geocentric( point );
  177. // CHECK_RETURN;
  178. // Convert between datums
  179. if( source.datum_type == Proj4js.common.PJD_3PARAM || source.datum_type == Proj4js.common.PJD_7PARAM ) {
  180. source.geocentric_to_wgs84(point);
  181. // CHECK_RETURN;
  182. }
  183. if( dest.datum_type == Proj4js.common.PJD_3PARAM || dest.datum_type == Proj4js.common.PJD_7PARAM ) {
  184. dest.geocentric_from_wgs84(point);
  185. // CHECK_RETURN;
  186. }
  187. // Convert back to geodetic coordinates
  188. dest.geocentric_to_geodetic( point );
  189. // CHECK_RETURN;
  190. }
  191. return point;
  192. }, // cs_datum_transform
  193. /**
  194. * Function: adjust_axis
  195. * Normalize or de-normalized the x/y/z axes. The normal form is "enu"
  196. * (easting, northing, up).
  197. * Parameters:
  198. * crs {Proj4js.Proj} the coordinate reference system
  199. * denorm {Boolean} when false, normalize
  200. * point {Object} the coordinates to adjust
  201. */
  202. adjust_axis: function(crs, denorm, point) {
  203. var xin= point.x, yin= point.y, zin= point.z || 0.0;
  204. var v, t;
  205. for (var i= 0; i<3; i++) {
  206. if (denorm && i==2 && point.z===undefined) { continue; }
  207. if (i==0) { v= xin; t= 'x'; }
  208. else if (i==1) { v= yin; t= 'y'; }
  209. else { v= zin; t= 'z'; }
  210. switch(crs.axis[i]) {
  211. case 'e':
  212. point[t]= v;
  213. break;
  214. case 'w':
  215. point[t]= -v;
  216. break;
  217. case 'n':
  218. point[t]= v;
  219. break;
  220. case 's':
  221. point[t]= -v;
  222. break;
  223. case 'u':
  224. if (point[t]!==undefined) { point.z= v; }
  225. break;
  226. case 'd':
  227. if (point[t]!==undefined) { point.z= -v; }
  228. break;
  229. default :
  230. alert("ERROR: unknow axis ("+crs.axis[i]+") - check definition of "+crs.projName);
  231. return null;
  232. }
  233. }
  234. return point;
  235. },
  236. /**
  237. * Function: reportError
  238. * An internal method to report errors back to user.
  239. * Override this in applications to report error messages or throw exceptions.
  240. */
  241. reportError: function(msg) {
  242. //console.log(msg);
  243. },
  244. /**
  245. *
  246. * Title: Private Methods
  247. * The following properties and methods are intended for internal use only.
  248. *
  249. * This is a minimal implementation of JavaScript inheritance methods so that
  250. * Proj4js can be used as a stand-alone library.
  251. * These are copies of the equivalent OpenLayers methods at v2.7
  252. */
  253. /**
  254. * Function: extend
  255. * Copy all properties of a source object to a destination object. Modifies
  256. * the passed in destination object. Any properties on the source object
  257. * that are set to undefined will not be (re)set on the destination object.
  258. *
  259. * Parameters:
  260. * destination - {Object} The object that will be modified
  261. * source - {Object} The object with properties to be set on the destination
  262. *
  263. * Returns:
  264. * {Object} The destination object.
  265. */
  266. extend: function(destination, source) {
  267. destination = destination || {};
  268. if(source) {
  269. for(var property in source) {
  270. var value = source[property];
  271. if(value !== undefined) {
  272. destination[property] = value;
  273. }
  274. }
  275. }
  276. return destination;
  277. },
  278. /**
  279. * Constructor: Class
  280. * Base class used to construct all other classes. Includes support for
  281. * multiple inheritance.
  282. *
  283. */
  284. Class: function() {
  285. var Class = function() {
  286. this.initialize.apply(this, arguments);
  287. };
  288. var extended = {};
  289. var parent;
  290. for(var i=0; i<arguments.length; ++i) {
  291. if(typeof arguments[i] == "function") {
  292. // get the prototype of the superclass
  293. parent = arguments[i].prototype;
  294. } else {
  295. // in this case we're extending with the prototype
  296. parent = arguments[i];
  297. }
  298. Proj4js.extend(extended, parent);
  299. }
  300. Class.prototype = extended;
  301. return Class;
  302. },
  303. /**
  304. * Function: bind
  305. * Bind a function to an object. Method to easily create closures with
  306. * 'this' altered.
  307. *
  308. * Parameters:
  309. * func - {Function} Input function.
  310. * object - {Object} The object to bind to the input function (as this).
  311. *
  312. * Returns:
  313. * {Function} A closure with 'this' set to the passed in object.
  314. */
  315. bind: function(func, object) {
  316. // create a reference to all arguments past the second one
  317. var args = Array.prototype.slice.apply(arguments, [2]);
  318. return function() {
  319. // Push on any additional arguments from the actual function call.
  320. // These will come after those sent to the bind call.
  321. var newArgs = args.concat(
  322. Array.prototype.slice.apply(arguments, [0])
  323. );
  324. return func.apply(object, newArgs);
  325. };
  326. },
  327. /**
  328. * The following properties and methods handle dynamic loading of JSON objects.
  329. */
  330. /**
  331. * Property: scriptName
  332. * {String} The filename of this script without any path.
  333. */
  334. scriptName: "proj4js-combined.js",
  335. /**
  336. * Property: defsLookupService
  337. * AJAX service to retreive projection definition parameters from
  338. */
  339. defsLookupService: 'http://spatialreference.org/ref',
  340. /**
  341. * Property: libPath
  342. * internal: http server path to library code.
  343. */
  344. libPath: null,
  345. /**
  346. * Function: getScriptLocation
  347. * Return the path to this script.
  348. *
  349. * Returns:
  350. * Path to this script
  351. */
  352. getScriptLocation: function () {
  353. if (this.libPath) return this.libPath;
  354. var scriptName = this.scriptName;
  355. var scriptNameLen = scriptName.length;
  356. var scripts = document.getElementsByTagName('script');
  357. for (var i = 0; i < scripts.length; i++) {
  358. var src = scripts[i].getAttribute('src');
  359. if (src) {
  360. var index = src.lastIndexOf(scriptName);
  361. // is it found, at the end of the URL?
  362. if ((index > -1) && (index + scriptNameLen == src.length)) {
  363. this.libPath = src.slice(0, -scriptNameLen);
  364. break;
  365. }
  366. }
  367. }
  368. return this.libPath||"";
  369. },
  370. /**
  371. * Function: loadScript
  372. * Load a JS file from a URL into a <script> tag in the page.
  373. *
  374. * Parameters:
  375. * url - {String} The URL containing the script to load
  376. * onload - {Function} A method to be executed when the script loads successfully
  377. * onfail - {Function} A method to be executed when there is an error loading the script
  378. * loadCheck - {Function} A boolean method that checks to see if the script
  379. * has loaded. Typically this just checks for the existance of
  380. * an object in the file just loaded.
  381. */
  382. loadScript: function(url, onload, onfail, loadCheck) {
  383. var script = document.createElement('script');
  384. script.defer = false;
  385. script.type = "text/javascript";
  386. script.id = url;
  387. script.src = url;
  388. script.onload = onload;
  389. script.onerror = onfail;
  390. script.loadCheck = loadCheck;
  391. if (/MSIE/.test(navigator.userAgent)) {
  392. script.onreadystatechange = this.checkReadyState;
  393. }
  394. document.getElementsByTagName('head')[0].appendChild(script);
  395. },
  396. /**
  397. * Function: checkReadyState
  398. * IE workaround since there is no onerror handler. Calls the user defined
  399. * loadCheck method to determine if the script is loaded.
  400. *
  401. */
  402. checkReadyState: function() {
  403. if (this.readyState == 'loaded') {
  404. if (!this.loadCheck()) {
  405. this.onerror();
  406. } else {
  407. this.onload();
  408. }
  409. }
  410. }
  411. };
  412. /**
  413. * Class: Proj4js.Proj
  414. *
  415. * Proj objects provide transformation methods for point coordinates
  416. * between geodetic latitude/longitude and a projected coordinate system.
  417. * once they have been initialized with a projection code.
  418. *
  419. * Initialization of Proj objects is with a projection code, usually EPSG codes,
  420. * which is the key that will be used with the Proj4js.defs array.
  421. *
  422. * The code passed in will be stripped of colons and converted to uppercase
  423. * to locate projection definition files.
  424. *
  425. * A projection object has properties for units and title strings.
  426. */
  427. Proj4js.Proj = Proj4js.Class({
  428. /**
  429. * Property: readyToUse
  430. * Flag to indicate if initialization is complete for this Proj object
  431. */
  432. readyToUse: false,
  433. /**
  434. * Property: title
  435. * The title to describe the projection
  436. */
  437. title: null,
  438. /**
  439. * Property: projName
  440. * The projection class for this projection, e.g. lcc (lambert conformal conic,
  441. * or merc for mercator). These are exactly equivalent to their Proj4
  442. * counterparts.
  443. */
  444. projName: null,
  445. /**
  446. * Property: units
  447. * The units of the projection. Values include 'm' and 'degrees'
  448. */
  449. units: null,
  450. /**
  451. * Property: datum
  452. * The datum specified for the projection
  453. */
  454. datum: null,
  455. /**
  456. * Property: x0
  457. * The x coordinate origin
  458. */
  459. x0: 0,
  460. /**
  461. * Property: y0
  462. * The y coordinate origin
  463. */
  464. y0: 0,
  465. /**
  466. * Property: localCS
  467. * Flag to indicate if the projection is a local one in which no transforms
  468. * are required.
  469. */
  470. localCS: false,
  471. /**
  472. * Property: queue
  473. * Buffer (FIFO) to hold callbacks waiting to be called when projection loaded.
  474. */
  475. queue: null,
  476. /**
  477. * Constructor: initialize
  478. * Constructor for Proj4js.Proj objects
  479. *
  480. * Parameters:
  481. * srsCode - a code for map projection definition parameters. These are usually
  482. * (but not always) EPSG codes.
  483. */
  484. initialize: function(srsCode, callback) {
  485. this.srsCodeInput = srsCode;
  486. //Register callbacks prior to attempting to process definition
  487. this.queue = [];
  488. if( callback ){
  489. this.queue.push( callback );
  490. }
  491. //check to see if this is a WKT string
  492. if ((srsCode.indexOf('GEOGCS') >= 0) ||
  493. (srsCode.indexOf('GEOCCS') >= 0) ||
  494. (srsCode.indexOf('PROJCS') >= 0) ||
  495. (srsCode.indexOf('LOCAL_CS') >= 0)) {
  496. this.parseWKT(srsCode);
  497. this.deriveConstants();
  498. this.loadProjCode(this.projName);
  499. return;
  500. }
  501. // DGR 2008-08-03 : support urn and url
  502. if (srsCode.indexOf('urn:') == 0) {
  503. //urn:ORIGINATOR:def:crs:CODESPACE:VERSION:ID
  504. var urn = srsCode.split(':');
  505. if ((urn[1] == 'ogc' || urn[1] =='x-ogc') &&
  506. (urn[2] =='def') &&
  507. (urn[3] =='crs')) {
  508. srsCode = urn[4]+':'+urn[urn.length-1];
  509. }
  510. } else if (srsCode.indexOf('http://') == 0) {
  511. //url#ID
  512. var url = srsCode.split('#');
  513. if (url[0].match(/epsg.org/)) {
  514. // http://www.epsg.org/#
  515. srsCode = 'EPSG:'+url[1];
  516. } else if (url[0].match(/RIG.xml/)) {
  517. //http://librairies.ign.fr/geoportail/resources/RIG.xml#
  518. //http://interop.ign.fr/registers/ign/RIG.xml#
  519. srsCode = 'IGNF:'+url[1];
  520. }
  521. }
  522. this.srsCode = srsCode.toUpperCase();
  523. if (this.srsCode.indexOf("EPSG") == 0) {
  524. this.srsCode = this.srsCode;
  525. this.srsAuth = 'epsg';
  526. this.srsProjNumber = this.srsCode.substring(5);
  527. // DGR 2007-11-20 : authority IGNF
  528. } else if (this.srsCode.indexOf("IGNF") == 0) {
  529. this.srsCode = this.srsCode;
  530. this.srsAuth = 'IGNF';
  531. this.srsProjNumber = this.srsCode.substring(5);
  532. // DGR 2008-06-19 : pseudo-authority CRS for WMS
  533. } else if (this.srsCode.indexOf("CRS") == 0) {
  534. this.srsCode = this.srsCode;
  535. this.srsAuth = 'CRS';
  536. this.srsProjNumber = this.srsCode.substring(4);
  537. } else {
  538. this.srsAuth = '';
  539. this.srsProjNumber = this.srsCode;
  540. }
  541. this.loadProjDefinition();
  542. },
  543. /**
  544. * Function: loadProjDefinition
  545. * Loads the coordinate system initialization string if required.
  546. * Note that dynamic loading happens asynchronously so an application must
  547. * wait for the readyToUse property is set to true.
  548. * To prevent dynamic loading, include the defs through a script tag in
  549. * your application.
  550. *
  551. */
  552. loadProjDefinition: function() {
  553. //check in memory
  554. if (Proj4js.defs[this.srsCode]) {
  555. this.defsLoaded();
  556. return;
  557. }
  558. //else check for def on the server
  559. var url = Proj4js.getScriptLocation() + 'defs/' + this.srsAuth.toUpperCase() + this.srsProjNumber + '.js';
  560. Proj4js.loadScript(url,
  561. Proj4js.bind(this.defsLoaded, this),
  562. Proj4js.bind(this.loadFromService, this),
  563. Proj4js.bind(this.checkDefsLoaded, this) );
  564. },
  565. /**
  566. * Function: loadFromService
  567. * Creates the REST URL for loading the definition from a web service and
  568. * loads it.
  569. *
  570. */
  571. loadFromService: function() {
  572. //else load from web service
  573. var url = Proj4js.defsLookupService +'/' + this.srsAuth +'/'+ this.srsProjNumber + '/proj4js/';
  574. Proj4js.loadScript(url,
  575. Proj4js.bind(this.defsLoaded, this),
  576. Proj4js.bind(this.defsFailed, this),
  577. Proj4js.bind(this.checkDefsLoaded, this) );
  578. },
  579. /**
  580. * Function: defsLoaded
  581. * Continues the Proj object initilization once the def file is loaded
  582. *
  583. */
  584. defsLoaded: function() {
  585. this.parseDefs();
  586. this.loadProjCode(this.projName);
  587. },
  588. /**
  589. * Function: checkDefsLoaded
  590. * This is the loadCheck method to see if the def object exists
  591. *
  592. */
  593. checkDefsLoaded: function() {
  594. if (Proj4js.defs[this.srsCode]) {
  595. return true;
  596. } else {
  597. return false;
  598. }
  599. },
  600. /**
  601. * Function: defsFailed
  602. * Report an error in loading the defs file, but continue on using WGS84
  603. *
  604. */
  605. defsFailed: function() {
  606. Proj4js.reportError('failed to load projection definition for: '+this.srsCode);
  607. Proj4js.defs[this.srsCode] = Proj4js.defs['WGS84']; //set it to something so it can at least continue
  608. this.defsLoaded();
  609. },
  610. /**
  611. * Function: loadProjCode
  612. * Loads projection class code dynamically if required.
  613. * Projection code may be included either through a script tag or in
  614. * a built version of proj4js
  615. *
  616. */
  617. loadProjCode: function(projName) {
  618. if (Proj4js.Proj[projName]) {
  619. this.initTransforms();
  620. return;
  621. }
  622. //the URL for the projection code
  623. var url = Proj4js.getScriptLocation() + 'projCode/' + projName + '.js';
  624. Proj4js.loadScript(url,
  625. Proj4js.bind(this.loadProjCodeSuccess, this, projName),
  626. Proj4js.bind(this.loadProjCodeFailure, this, projName),
  627. Proj4js.bind(this.checkCodeLoaded, this, projName) );
  628. },
  629. /**
  630. * Function: loadProjCodeSuccess
  631. * Loads any proj dependencies or continue on to final initialization.
  632. *
  633. */
  634. loadProjCodeSuccess: function(projName) {
  635. if (Proj4js.Proj[projName].dependsOn){
  636. this.loadProjCode(Proj4js.Proj[projName].dependsOn);
  637. } else {
  638. this.initTransforms();
  639. }
  640. },
  641. /**
  642. * Function: defsFailed
  643. * Report an error in loading the proj file. Initialization of the Proj
  644. * object has failed and the readyToUse flag will never be set.
  645. *
  646. */
  647. loadProjCodeFailure: function(projName) {
  648. Proj4js.reportError("failed to find projection file for: " + projName);
  649. //TBD initialize with identity transforms so proj will still work?
  650. },
  651. /**
  652. * Function: checkCodeLoaded
  653. * This is the loadCheck method to see if the projection code is loaded
  654. *
  655. */
  656. checkCodeLoaded: function(projName) {
  657. if (Proj4js.Proj[projName]) {
  658. return true;
  659. } else {
  660. return false;
  661. }
  662. },
  663. /**
  664. * Function: initTransforms
  665. * Finalize the initialization of the Proj object
  666. *
  667. */
  668. initTransforms: function() {
  669. Proj4js.extend(this, Proj4js.Proj[this.projName]);
  670. this.init();
  671. this.readyToUse = true;
  672. if( this.queue ) {
  673. var item;
  674. while( (item = this.queue.shift()) ) {
  675. item.call( this, this );
  676. }
  677. }
  678. },
  679. /**
  680. * Function: parseWKT
  681. * Parses a WKT string to get initialization parameters
  682. *
  683. */
  684. wktRE: /^(\w+)\[(.*)\]$/,
  685. parseWKT: function(wkt) {
  686. var wktMatch = wkt.match(this.wktRE);
  687. if (!wktMatch) return;
  688. var wktObject = wktMatch[1];
  689. var wktContent = wktMatch[2];
  690. var wktTemp = wktContent.split(",");
  691. var wktName;
  692. if (wktObject.toUpperCase() == "TOWGS84") {
  693. wktName = wktObject; //no name supplied for the TOWGS84 array
  694. } else {
  695. wktName = wktTemp.shift();
  696. }
  697. wktName = wktName.replace(/^\"/,"");
  698. wktName = wktName.replace(/\"$/,"");
  699. /*
  700. wktContent = wktTemp.join(",");
  701. var wktArray = wktContent.split("],");
  702. for (var i=0; i<wktArray.length-1; ++i) {
  703. wktArray[i] += "]";
  704. }
  705. */
  706. var wktArray = new Array();
  707. var bkCount = 0;
  708. var obj = "";
  709. for (var i=0; i<wktTemp.length; ++i) {
  710. var token = wktTemp[i];
  711. for (var j=0; j<token.length; ++j) {
  712. if (token.charAt(j) == "[") ++bkCount;
  713. if (token.charAt(j) == "]") --bkCount;
  714. }
  715. obj += token;
  716. if (bkCount === 0) {
  717. wktArray.push(obj);
  718. obj = "";
  719. } else {
  720. obj += ",";
  721. }
  722. }
  723. //do something based on the type of the wktObject being parsed
  724. //add in variations in the spelling as required
  725. switch (wktObject) {
  726. case 'LOCAL_CS':
  727. this.projName = 'identity'
  728. this.localCS = true;
  729. this.srsCode = wktName;
  730. break;
  731. case 'GEOGCS':
  732. this.projName = 'longlat'
  733. this.geocsCode = wktName;
  734. if (!this.srsCode) this.srsCode = wktName;
  735. break;
  736. case 'PROJCS':
  737. this.srsCode = wktName;
  738. break;
  739. case 'GEOCCS':
  740. break;
  741. case 'PROJECTION':
  742. this.projName = Proj4js.wktProjections[wktName]
  743. break;
  744. case 'DATUM':
  745. this.datumName = wktName;
  746. break;
  747. case 'LOCAL_DATUM':
  748. this.datumCode = 'none';
  749. break;
  750. case 'SPHEROID':
  751. this.ellps = wktName;
  752. this.a = parseFloat(wktArray.shift());
  753. this.rf = parseFloat(wktArray.shift());
  754. break;
  755. case 'PRIMEM':
  756. this.from_greenwich = parseFloat(wktArray.shift()); //to radians?
  757. break;
  758. case 'UNIT':
  759. this.units = wktName;
  760. this.unitsPerMeter = parseFloat(wktArray.shift());
  761. break;
  762. case 'PARAMETER':
  763. var name = wktName.toLowerCase();
  764. var value = parseFloat(wktArray.shift());
  765. //there may be many variations on the wktName values, add in case
  766. //statements as required
  767. switch (name) {
  768. case 'false_easting':
  769. this.x0 = value;
  770. break;
  771. case 'false_northing':
  772. this.y0 = value;
  773. break;
  774. case 'scale_factor':
  775. this.k0 = value;
  776. break;
  777. case 'central_meridian':
  778. this.long0 = value*Proj4js.common.D2R;
  779. break;
  780. case 'latitude_of_origin':
  781. this.lat0 = value*Proj4js.common.D2R;
  782. break;
  783. case 'more_here':
  784. break;
  785. default:
  786. break;
  787. }
  788. break;
  789. case 'TOWGS84':
  790. this.datum_params = wktArray;
  791. break;
  792. //DGR 2010-11-12: AXIS
  793. case 'AXIS':
  794. var name= wktName.toLowerCase();
  795. var value= wktArray.shift();
  796. switch (value) {
  797. case 'EAST' : value= 'e'; break;
  798. case 'WEST' : value= 'w'; break;
  799. case 'NORTH': value= 'n'; break;
  800. case 'SOUTH': value= 's'; break;
  801. case 'UP' : value= 'u'; break;
  802. case 'DOWN' : value= 'd'; break;
  803. case 'OTHER':
  804. default : value= ' '; break;//FIXME
  805. }
  806. if (!this.axis) { this.axis= "enu"; }
  807. switch(name) {
  808. case 'x': this.axis= value + this.axis.substr(1,2); break;
  809. case 'y': this.axis= this.axis.substr(0,1) + value + this.axis.substr(2,1); break;
  810. case 'z': this.axis= this.axis.substr(0,2) + value ; break;
  811. default : break;
  812. }
  813. case 'MORE_HERE':
  814. break;
  815. default:
  816. break;
  817. }
  818. for (var i=0; i<wktArray.length; ++i) {
  819. this.parseWKT(wktArray[i]);
  820. }
  821. },
  822. /**
  823. * Function: parseDefs
  824. * Parses the PROJ.4 initialization string and sets the associated properties.
  825. *
  826. */
  827. parseDefs: function() {
  828. this.defData = Proj4js.defs[this.srsCode];
  829. var paramName, paramVal;
  830. if (!this.defData) {
  831. return;
  832. }
  833. var paramArray=this.defData.split("+");
  834. for (var prop=0; prop<paramArray.length; prop++) {
  835. var property = paramArray[prop].split("=");
  836. paramName = property[0].toLowerCase();
  837. paramVal = property[1];
  838. switch (paramName.replace(/\s/gi,"")) { // trim out spaces
  839. case "": break; // throw away nameless parameter
  840. case "title": this.title = paramVal; break;
  841. case "proj": this.projName = paramVal.replace(/\s/gi,""); break;
  842. case "units": this.units = paramVal.replace(/\s/gi,""); break;
  843. case "datum": this.datumCode = paramVal.replace(/\s/gi,""); break;
  844. case "nadgrids": this.nagrids = paramVal.replace(/\s/gi,""); break;
  845. case "ellps": this.ellps = paramVal.replace(/\s/gi,""); break;
  846. case "a": this.a = parseFloat(paramVal); break; // semi-major radius
  847. case "b": this.b = parseFloat(paramVal); break; // semi-minor radius
  848. // DGR 2007-11-20
  849. case "rf": this.rf = parseFloat(paramVal); break; // inverse flattening rf= a/(a-b)
  850. case "lat_0": this.lat0 = paramVal*Proj4js.common.D2R; break; // phi0, central latitude
  851. case "lat_1": this.lat1 = paramVal*Proj4js.common.D2R; break; //standard parallel 1
  852. case "lat_2": this.lat2 = paramVal*Proj4js.common.D2R; break; //standard parallel 2
  853. case "lat_ts": this.lat_ts = paramVal*Proj4js.common.D2R; break; // used in merc and eqc
  854. case "lon_0": this.long0 = paramVal*Proj4js.common.D2R; break; // lam0, central longitude
  855. case "alpha": this.alpha = parseFloat(paramVal)*Proj4js.common.D2R; break; //for somerc projection
  856. case "lonc": this.longc = paramVal*Proj4js.common.D2R; break; //for somerc projection
  857. case "x_0": this.x0 = parseFloat(paramVal); break; // false easting
  858. case "y_0": this.y0 = parseFloat(paramVal); break; // false northing
  859. case "k_0": this.k0 = parseFloat(paramVal); break; // projection scale factor
  860. case "k": this.k0 = parseFloat(paramVal); break; // both forms returned
  861. case "r_a": this.R_A = true; break; // sphere--area of ellipsoid
  862. case "zone": this.zone = parseInt(paramVal,10); break; // UTM Zone
  863. case "south": this.utmSouth = true; break; // UTM north/south
  864. case "towgs84":this.datum_params = paramVal.split(","); break;
  865. case "to_meter": this.to_meter = parseFloat(paramVal); break; // cartesian scaling
  866. case "from_greenwich": this.from_greenwich = paramVal*Proj4js.common.D2R; break;
  867. // DGR 2008-07-09 : if pm is not a well-known prime meridian take
  868. // the value instead of 0.0, then convert to radians
  869. case "pm": paramVal = paramVal.replace(/\s/gi,"");
  870. this.from_greenwich = Proj4js.PrimeMeridian[paramVal] ?
  871. Proj4js.PrimeMeridian[paramVal] : parseFloat(paramVal);
  872. this.from_greenwich *= Proj4js.common.D2R;
  873. break;
  874. // DGR 2010-11-12: axis
  875. case "axis": paramVal = paramVal.replace(/\s/gi,"");
  876. var legalAxis= "ewnsud";
  877. if (paramVal.length==3 &&
  878. legalAxis.indexOf(paramVal.substr(0,1))!=-1 &&
  879. legalAxis.indexOf(paramVal.substr(1,1))!=-1 &&
  880. legalAxis.indexOf(paramVal.substr(2,1))!=-1) {
  881. this.axis= paramVal;
  882. } //FIXME: be silent ?
  883. break
  884. case "no_defs": break;
  885. default: //alert("Unrecognized parameter: " + paramName);
  886. } // switch()
  887. } // for paramArray
  888. this.deriveConstants();
  889. },
  890. /**
  891. * Function: deriveConstants
  892. * Sets several derived constant values and initialization of datum and ellipse
  893. * parameters.
  894. *
  895. */
  896. deriveConstants: function() {
  897. if (this.nagrids == '@null') this.datumCode = 'none';
  898. if (this.datumCode && this.datumCode != 'none') {
  899. var datumDef = Proj4js.Datum[this.datumCode];
  900. if (datumDef) {
  901. this.datum_params = datumDef.towgs84 ? datumDef.towgs84.split(',') : null;
  902. this.ellps = datumDef.ellipse;
  903. this.datumName = datumDef.datumName ? datumDef.datumName : this.datumCode;
  904. }
  905. }
  906. if (!this.a) { // do we have an ellipsoid?
  907. var ellipse = Proj4js.Ellipsoid[this.ellps] ? Proj4js.Ellipsoid[this.ellps] : Proj4js.Ellipsoid['WGS84'];
  908. Proj4js.extend(this, ellipse);
  909. }
  910. if (this.rf && !this.b) this.b = (1.0 - 1.0/this.rf) * this.a;
  911. if (this.rf === 0 || Math.abs(this.a - this.b)<Proj4js.common.EPSLN) {
  912. this.sphere = true;
  913. this.b= this.a;
  914. }
  915. this.a2 = this.a * this.a; // used in geocentric
  916. this.b2 = this.b * this.b; // used in geocentric
  917. this.es = (this.a2-this.b2)/this.a2; // e ^ 2
  918. this.e = Math.sqrt(this.es); // eccentricity
  919. if (this.R_A) {
  920. this.a *= 1. - this.es * (Proj4js.common.SIXTH + this.es * (Proj4js.common.RA4 + this.es * Proj4js.common.RA6));
  921. this.a2 = this.a * this.a;
  922. this.b2 = this.b * this.b;
  923. this.es = 0.;
  924. }
  925. this.ep2=(this.a2-this.b2)/this.b2; // used in geocentric
  926. if (!this.k0) this.k0 = 1.0; //default value
  927. //DGR 2010-11-12: axis
  928. if (!this.axis) { this.axis= "enu"; }
  929. this.datum = new Proj4js.datum(this);
  930. }
  931. });
  932. Proj4js.Proj.longlat = {
  933. init: function() {
  934. //no-op for longlat
  935. },
  936. forward: function(pt) {
  937. //identity transform
  938. return pt;
  939. },
  940. inverse: function(pt) {
  941. //identity transform
  942. return pt;
  943. }
  944. };
  945. Proj4js.Proj.identity = Proj4js.Proj.longlat;
  946. /**
  947. Proj4js.defs is a collection of coordinate system definition objects in the
  948. PROJ.4 command line format.
  949. Generally a def is added by means of a separate .js file for example:
  950. <SCRIPT type="text/javascript" src="defs/EPSG26912.js"></SCRIPT>
  951. def is a CS definition in PROJ.4 WKT format, for example:
  952. +proj="tmerc" //longlat, etc.
  953. +a=majorRadius
  954. +b=minorRadius
  955. +lat0=somenumber
  956. +long=somenumber
  957. */
  958. Proj4js.defs = {
  959. // These are so widely used, we'll go ahead and throw them in
  960. // without requiring a separate .js file
  961. 'WGS84': "+title=long/lat:WGS84 +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees",
  962. 'EPSG:4326': "+title=long/lat:WGS84 +proj=longlat +a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84 +units=degrees",
  963. 'EPSG:4269': "+title=long/lat:NAD83 +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees",
  964. '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"
  965. };
  966. Proj4js.defs['EPSG:3785'] = Proj4js.defs['EPSG:3875']; //maintain backward compat, official code is 3875
  967. Proj4js.defs['GOOGLE'] = Proj4js.defs['EPSG:3875'];
  968. Proj4js.defs['EPSG:900913'] = Proj4js.defs['EPSG:3875'];
  969. Proj4js.defs['EPSG:102113'] = Proj4js.defs['EPSG:3875'];
  970. Proj4js.common = {
  971. PI : 3.141592653589793238, //Math.PI,
  972. HALF_PI : 1.570796326794896619, //Math.PI*0.5,
  973. TWO_PI : 6.283185307179586477, //Math.PI*2,
  974. FORTPI : 0.78539816339744833,
  975. R2D : 57.29577951308232088,
  976. D2R : 0.01745329251994329577,
  977. SEC_TO_RAD : 4.84813681109535993589914102357e-6, /* SEC_TO_RAD = Pi/180/3600 */
  978. EPSLN : 1.0e-10,
  979. MAX_ITER : 20,
  980. // following constants from geocent.c
  981. COS_67P5 : 0.38268343236508977, /* cosine of 67.5 degrees */
  982. AD_C : 1.0026000, /* Toms region 1 constant */
  983. /* datum_type values */
  984. PJD_UNKNOWN : 0,
  985. PJD_3PARAM : 1,
  986. PJD_7PARAM : 2,
  987. PJD_GRIDSHIFT: 3,
  988. PJD_WGS84 : 4, // WGS84 or equivalent
  989. PJD_NODATUM : 5, // WGS84 or equivalent
  990. SRS_WGS84_SEMIMAJOR : 6378137.0, // only used in grid shift transforms
  991. // ellipoid pj_set_ell.c
  992. SIXTH : .1666666666666666667, /* 1/6 */
  993. RA4 : .04722222222222222222, /* 17/360 */
  994. RA6 : .02215608465608465608, /* 67/3024 */
  995. RV4 : .06944444444444444444, /* 5/72 */
  996. RV6 : .04243827160493827160, /* 55/1296 */
  997. // Function to compute the constant small m which is the radius of
  998. // a parallel of latitude, phi, divided by the semimajor axis.
  999. // -----------------------------------------------------------------
  1000. msfnz : function(eccent, sinphi, cosphi) {
  1001. var con = eccent * sinphi;
  1002. return cosphi/(Math.sqrt(1.0 - con * con));
  1003. },
  1004. // Function to compute the constant small t for use in the forward
  1005. // computations in the Lambert Conformal Conic and the Polar
  1006. // Stereographic projections.
  1007. // -----------------------------------------------------------------
  1008. tsfnz : function(eccent, phi, sinphi) {
  1009. var con = eccent * sinphi;
  1010. var com = .5 * eccent;
  1011. con = Math.pow(((1.0 - con) / (1.0 + con)), com);
  1012. return (Math.tan(.5 * (this.HALF_PI - phi))/con);
  1013. },
  1014. // Function to compute the latitude angle, phi2, for the inverse of the
  1015. // Lambert Conformal Conic and Polar Stereographic projections.
  1016. // ----------------------------------------------------------------
  1017. phi2z : function(eccent, ts) {
  1018. var eccnth = .5 * eccent;
  1019. var con, dphi;
  1020. var phi = this.HALF_PI - 2 * Math.atan(ts);
  1021. for (var i = 0; i <= 15; i++) {
  1022. con = eccent * Math.sin(phi);
  1023. dphi = this.HALF_PI - 2 * Math.atan(ts *(Math.pow(((1.0 - con)/(1.0 + con)),eccnth))) - phi;
  1024. phi += dphi;
  1025. if (Math.abs(dphi) <= .0000000001) return phi;
  1026. }
  1027. alert("phi2z has NoConvergence");
  1028. return (-9999);
  1029. },
  1030. /* Function to compute constant small q which is the radius of a
  1031. parallel of latitude, phi, divided by the semimajor axis.
  1032. ------------------------------------------------------------*/
  1033. qsfnz : function(eccent,sinphi) {
  1034. var con;
  1035. if (eccent > 1.0e-7) {
  1036. con = eccent * sinphi;
  1037. return (( 1.0- eccent * eccent) * (sinphi /(1.0 - con * con) - (.5/eccent)*Math.log((1.0 - con)/(1.0 + con))));
  1038. } else {
  1039. return(2.0 * sinphi);
  1040. }
  1041. },
  1042. /* Function to eliminate roundoff errors in asin
  1043. ----------------------------------------------*/
  1044. asinz : function(x) {
  1045. if (Math.abs(x)>1.0) {
  1046. x=(x>1.0)?1.0:-1.0;
  1047. }
  1048. return Math.asin(x);
  1049. },
  1050. // following functions from gctpc cproj.c for transverse mercator projections
  1051. e0fn : function(x) {return(1.0-0.25*x*(1.0+x/16.0*(3.0+1.25*x)));},
  1052. e1fn : function(x) {return(0.375*x*(1.0+0.25*x*(1.0+0.46875*x)));},
  1053. e2fn : function(x) {return(0.05859375*x*x*(1.0+0.75*x));},
  1054. e3fn : function(x) {return(x*x*x*(35.0/3072.0));},
  1055. 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));},
  1056. srat : function(esinp, exp) {
  1057. return(Math.pow((1.0-esinp)/(1.0+esinp), exp));
  1058. },
  1059. // Function to return the sign of an argument
  1060. sign : function(x) { if (x < 0.0) return(-1); else return(1);},
  1061. // Function to adjust longitude to -180 to 180; input in radians
  1062. adjust_lon : function(x) {
  1063. x = (Math.abs(x) < this.PI) ? x: (x - (this.sign(x)*this.TWO_PI) );
  1064. return x;
  1065. },
  1066. // IGNF - DGR : algorithms used by IGN France
  1067. // Function to adjust latitude to -90 to 90; input in radians
  1068. adjust_lat : function(x) {
  1069. x= (Math.abs(x) < this.HALF_PI) ? x: (x - (this.sign(x)*this.PI) );
  1070. return x;
  1071. },
  1072. // Latitude Isometrique - close to tsfnz ...
  1073. latiso : function(eccent, phi, sinphi) {
  1074. if (Math.abs(phi) > this.HALF_PI) return +Number.NaN;
  1075. if (phi==this.HALF_PI) return Number.POSITIVE_INFINITY;
  1076. if (phi==-1.0*this.HALF_PI) return -1.0*Number.POSITIVE_INFINITY;
  1077. var con= eccent*sinphi;
  1078. return Math.log(Math.tan((this.HALF_PI+phi)/2.0))+eccent*Math.log((1.0-con)/(1.0+con))/2.0;
  1079. },
  1080. fL : function(x,L) {
  1081. return 2.0*Math.atan(x*Math.exp(L)) - this.HALF_PI;
  1082. },
  1083. // Inverse Latitude Isometrique - close to ph2z
  1084. invlatiso : function(eccent, ts) {
  1085. var phi= this.fL(1.0,ts);
  1086. var Iphi= 0.0;
  1087. var con= 0.0;
  1088. do {
  1089. Iphi= phi;
  1090. con= eccent*Math.sin(Iphi);
  1091. phi= this.fL(Math.exp(eccent*Math.log((1.0+con)/(1.0-con))/2.0),ts)
  1092. } while (Math.abs(phi-Iphi)>1.0e-12);
  1093. return phi;
  1094. },
  1095. // Needed for Gauss Schreiber
  1096. // Original: Denis Makarov (info@binarythings.com)
  1097. // Web Site: http://www.binarythings.com
  1098. sinh : function(x)
  1099. {
  1100. var r= Math.exp(x);
  1101. r= (r-1.0/r)/2.0;
  1102. return r;
  1103. },
  1104. cosh : function(x)
  1105. {
  1106. var r= Math.exp(x);
  1107. r= (r+1.0/r)/2.0;
  1108. return r;
  1109. },
  1110. tanh : function(x)
  1111. {
  1112. var r= Math.exp(x);
  1113. r= (r-1.0/r)/(r+1.0/r);
  1114. return r;
  1115. },
  1116. asinh : function(x)
  1117. {
  1118. var s= (x>= 0? 1.0:-1.0);
  1119. return s*(Math.log( Math.abs(x) + Math.sqrt(x*x+1.0) ));
  1120. },
  1121. acosh : function(x)
  1122. {
  1123. return 2.0*Math.log(Math.sqrt((x+1.0)/2.0) + Math.sqrt((x-1.0)/2.0));
  1124. },
  1125. atanh : function(x)
  1126. {
  1127. return Math.log((x-1.0)/(x+1.0))/2.0;
  1128. },
  1129. // Grande Normale
  1130. gN : function(a,e,sinphi)
  1131. {
  1132. var temp= e*sinphi;
  1133. return a/Math.sqrt(1.0 - temp*temp);
  1134. },
  1135. //code from the PROJ.4 pj_mlfn.c file; this may be useful for other projections
  1136. pj_enfn: function(es) {
  1137. var en = new Array();
  1138. en[0] = this.C00 - es * (this.C02 + es * (this.C04 + es * (this.C06 + es * this.C08)));
  1139. en[1] = es * (this.C22 - es * (this.C04 + es * (this.C06 + es * this.C08)));
  1140. var t = es * es;
  1141. en[2] = t * (this.C44 - es * (this.C46 + es * this.C48));
  1142. t *= es;
  1143. en[3] = t * (this.C66 - es * this.C68);
  1144. en[4] = t * es * this.C88;
  1145. return en;
  1146. },
  1147. pj_mlfn: function(phi, sphi, cphi, en) {
  1148. cphi *= sphi;
  1149. sphi *= sphi;
  1150. return(en[0] * phi - cphi * (en[1] + sphi*(en[2]+ sphi*(en[3] + sphi*en[4]))));
  1151. },
  1152. pj_inv_mlfn: function(arg, es, en) {
  1153. var k = 1./(1.-es);
  1154. var phi = arg;
  1155. for (var i = Proj4js.common.MAX_ITER; i ; --i) { /* rarely goes over 2 iterations */
  1156. var s = Math.sin(phi);
  1157. var t = 1. - es * s * s;
  1158. //t = this.pj_mlfn(phi, s, Math.cos(phi), en) - arg;
  1159. //phi -= t * (t * Math.sqrt(t)) * k;
  1160. t = (this.pj_mlfn(phi, s, Math.cos(phi), en) - arg) * (t * Math.sqrt(t)) * k;
  1161. phi -= t;
  1162. if (Math.abs(t) < Proj4js.common.EPSLN)
  1163. return phi;
  1164. }
  1165. Proj4js.reportError("cass:pj_inv_mlfn: Convergence error");
  1166. return phi;
  1167. },
  1168. /* meridinal distance for ellipsoid and inverse
  1169. ** 8th degree - accurate to < 1e-5 meters when used in conjuction
  1170. ** with typical major axis values.
  1171. ** Inverse determines phi to EPS (1e-11) radians, about 1e-6 seconds.
  1172. */
  1173. C00: 1.0,
  1174. C02: .25,
  1175. C04: .046875,
  1176. C06: .01953125,
  1177. C08: .01068115234375,
  1178. C22: .75,
  1179. C44: .46875,
  1180. C46: .01302083333333333333,
  1181. C48: .00712076822916666666,
  1182. C66: .36458333333333333333,
  1183. C68: .00569661458333333333,
  1184. C88: .3076171875
  1185. };
  1186. /** datum object
  1187. */
  1188. Proj4js.datum = Proj4js.Class({
  1189. initialize : function(proj) {
  1190. this.datum_type = Proj4js.common.PJD_WGS84; //default setting
  1191. if (proj.datumCode && proj.datumCode == 'none') {
  1192. this.datum_type = Proj4js.common.PJD_NODATUM;
  1193. }
  1194. if (proj && proj.datum_params) {
  1195. for (var i=0; i<proj.datum_params.length; i++) {
  1196. proj.datum_params[i]=parseFloat(proj.datum_params[i]);
  1197. }
  1198. if (proj.datum_params[0] != 0 || proj.datum_params[1] != 0 || proj.datum_params[2] != 0 ) {
  1199. this.datum_type = Proj4js.common.PJD_3PARAM;
  1200. }
  1201. if (proj.datum_params.length > 3) {
  1202. if (proj.datum_params[3] != 0 || proj.datum_params[4] != 0 ||
  1203. proj.datum_params[5] != 0 || proj.datum_params[6] != 0 ) {
  1204. this.datum_type = Proj4js.common.PJD_7PARAM;
  1205. proj.datum_params[3] *= Proj4js.common.SEC_TO_RAD;
  1206. proj.datum_params[4] *= Proj4js.common.SEC_TO_RAD;
  1207. proj.datum_params[5] *= Proj4js.common.SEC_TO_RAD;
  1208. proj.datum_params[6] = (proj.datum_params[6]/1000000.0) + 1.0;
  1209. }
  1210. }
  1211. }
  1212. if (proj) {
  1213. this.a = proj.a; //datum object also uses these values
  1214. this.b = proj.b;
  1215. this.es = proj.es;
  1216. this.ep2 = proj.ep2;
  1217. this.datum_params = proj.datum_params;
  1218. }
  1219. },
  1220. /****************************************************************/
  1221. // cs_compare_datums()
  1222. // Returns TRUE if the two datums match, otherwise FALSE.
  1223. compare_datums : function( dest ) {
  1224. if( this.datum_type != dest.datum_type ) {
  1225. return false; // false, datums are not equal
  1226. } else if( this.a != dest.a || Math.abs(this.es-dest.es) > 0.000000000050 ) {
  1227. // the tolerence for es is to ensure that GRS80 and WGS84
  1228. // are considered identical
  1229. return false;
  1230. } else if( this.datum_type == Proj4js.common.PJD_3PARAM ) {
  1231. return (this.datum_params[0] == dest.datum_params[0]
  1232. && this.datum_params[1] == dest.datum_params[1]
  1233. && this.datum_params[2] == dest.datum_params[2]);
  1234. } else if( this.datum_type == Proj4js.common.PJD_7PARAM ) {
  1235. return (this.datum_params[0] == dest.datum_params[0]
  1236. && this.datum_params[1] == dest.datum_params[1]
  1237. && this.datum_params[2] == dest.datum_params[2]
  1238. && this.datum_params[3] == dest.datum_params[3]
  1239. && this.datum_params[4] == dest.datum_params[4]
  1240. && this.datum_params[5] == dest.datum_params[5]
  1241. && this.datum_params[6] == dest.datum_params[6]);
  1242. } else if ( this.datum_type == Proj4js.common.PJD_GRIDSHIFT ||
  1243. dest.datum_type == Proj4js.common.PJD_GRIDSHIFT ) {
  1244. alert("ERROR: Grid shift transformations are not implemented.");
  1245. return false
  1246. } else {
  1247. return true; // datums are equal
  1248. }
  1249. }, // cs_compare_datums()
  1250. /*
  1251. * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates
  1252. * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z),
  1253. * according to the current ellipsoid parameters.
  1254. *
  1255. * Latitude : Geodetic latitude in radians (input)
  1256. * Longitude : Geodetic longitude in radians (input)
  1257. * Height : Geodetic height, in meters (input)
  1258. * X : Calculated Geocentric X coordinate, in meters (output)
  1259. * Y : Calculated Geocentric Y coordinate, in meters (output)
  1260. * Z : Calculated Geocentric Z coordinate, in meters (output)
  1261. *
  1262. */
  1263. geodetic_to_geocentric : function(p) {
  1264. var Longitude = p.x;
  1265. var Latitude = p.y;
  1266. var Height = p.z ? p.z : 0; //Z value not always supplied
  1267. var X; // output
  1268. var Y;
  1269. var Z;
  1270. var Error_Code=0; // GEOCENT_NO_ERROR;
  1271. var Rn; /* Earth radius at location */
  1272. var Sin_Lat; /* Math.sin(Latitude) */
  1273. var Sin2_Lat; /* Square of Math.sin(Latitude) */
  1274. var Cos_Lat; /* Math.cos(Latitude) */
  1275. /*
  1276. ** Don't blow up if Latitude is just a little out of the value
  1277. ** range as it may just be a rounding issue. Also removed longitude
  1278. ** test, it should be wrapped by Math.cos() and Math.sin(). NFW for PROJ.4, Sep/2001.
  1279. */
  1280. if( Latitude < -Proj4js.common.HALF_PI && Latitude > -1.001 * Proj4js.common.HALF_PI ) {
  1281. Latitude = -Proj4js.common.HALF_PI;
  1282. } else if( Latitude > Proj4js.common.HALF_PI && Latitude < 1.001 * Proj4js.common.HALF_PI ) {
  1283. Latitude = Proj4js.common.HALF_PI;
  1284. } else if ((Latitude < -Proj4js.common.HALF_PI) || (Latitude > Proj4js.common.HALF_PI)) {
  1285. /* Latitude out of range */
  1286. Proj4js.reportError('geocent:lat out of range:'+Latitude);
  1287. return null;
  1288. }
  1289. if (Longitude > Proj4js.common.PI) Longitude -= (2*Proj4js.common.PI);
  1290. Sin_Lat = Math.sin(Latitude);
  1291. Cos_Lat = Math.cos(Latitude);
  1292. Sin2_Lat = Sin_Lat * Sin_Lat;
  1293. Rn = this.a / (Math.sqrt(1.0e0 - this.es * Sin2_Lat));
  1294. X = (Rn + Height) * Cos_Lat * Math.cos(Longitude);
  1295. Y = (Rn + Height) * Cos_Lat * Math.sin(Longitude);
  1296. Z = ((Rn * (1 - this.es)) + Height) * Sin_Lat;
  1297. p.x = X;
  1298. p.y = Y;
  1299. p.z = Z;
  1300. return Error_Code;
  1301. }, // cs_geodetic_to_geocentric()
  1302. geocentric_to_geodetic : function (p) {
  1303. /* local defintions and variables */
  1304. /* end-criterium of loop, accuracy of sin(Latitude) */
  1305. var genau = 1.E-12;
  1306. var genau2 = (genau*genau);
  1307. var maxiter = 30;
  1308. var P; /* distance between semi-minor axis and location */
  1309. var RR; /* distance between center and location */
  1310. var CT; /* sin of geocentric latitude */
  1311. var ST; /* cos of geocentric latitude */
  1312. var RX;
  1313. var RK;
  1314. var RN; /* Earth radius at location */
  1315. var CPHI0; /* cos of start or old geodetic latitude in iterations */
  1316. var SPHI0; /* sin of start or old geodetic latitude in iterations */
  1317. var CPHI; /* cos of searched geodetic latitude */
  1318. var SPHI; /* sin of searched geodetic latitude */
  1319. var SDPHI; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */
  1320. var At_Pole; /* indicates location is in polar region */
  1321. var iter; /* # of continous iteration, max. 30 is always enough (s.a.) */
  1322. var X = p.x;
  1323. var Y = p.y;
  1324. var Z = p.z ? p.z : 0.0; //Z value not always supplied
  1325. var Longitude;
  1326. var Latitude;
  1327. var Height;
  1328. At_Pole = false;
  1329. P = Math.sqrt(X*X+Y*Y);
  1330. RR = Math.sqrt(X*X+Y*Y+Z*Z);
  1331. /* special cases for latitude and longitude */
  1332. if (P/this.a < genau) {
  1333. /* special case, if P=0. (X=0., Y=0.) */
  1334. At_Pole = true;
  1335. Longitude = 0.0;
  1336. /* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis
  1337. * of ellipsoid (=center of mass), Latitude becomes PI/2 */
  1338. if (RR/this.a < genau) {
  1339. Latitude = Proj4js.common.HALF_PI;
  1340. Height = -this.b;
  1341. return;
  1342. }
  1343. } else {
  1344. /* ellipsoidal (geodetic) longitude
  1345. * interval: -PI < Longitude <= +PI */
  1346. Longitude=Math.atan2(Y,X);
  1347. }
  1348. /* --------------------------------------------------------------
  1349. * Following iterative algorithm was developped by
  1350. * "Institut f�r Erdmessung", University of Hannover, July 1988.
  1351. * Internet: www.ife.uni-hannover.de
  1352. * Iterative computation of CPHI,SPHI and Height.
  1353. * Iteration of CPHI and SPHI to 10**-12 radian resp.
  1354. * 2*10**-7 arcsec.
  1355. * --------------------------------------------------------------
  1356. */
  1357. CT = Z/RR;
  1358. ST = P/RR;
  1359. RX = 1.0/Math.sqrt(1.0-this.es*(2.0-this.es)*ST*ST);
  1360. CPHI0 = ST*(1.0-this.es)*RX;
  1361. SPHI0 = CT*RX;
  1362. iter = 0;
  1363. /* loop to find sin(Latitude) resp. Latitude
  1364. * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */
  1365. do
  1366. {
  1367. iter++;
  1368. RN = this.a/Math.sqrt(1.0-this.es*SPHI0*SPHI0);
  1369. /* ellipsoidal (geodetic) height */
  1370. Height = P*CPHI0+Z*SPHI0-RN*(1.0-this.es*SPHI0*SPHI0);
  1371. RK = this.es*RN/(RN+Height);
  1372. RX = 1.0/Math.sqrt(1.0-RK*(2.0-RK)*ST*ST);
  1373. CPHI = ST*(1.0-RK)*RX;
  1374. SPHI = CT*RX;
  1375. SDPHI = SPHI*CPHI0-CPHI*SPHI0;
  1376. CPHI0 = CPHI;
  1377. SPHI0 = SPHI;
  1378. }
  1379. while (SDPHI*SDPHI > genau2 && iter < maxiter);
  1380. /* ellipsoidal (geodetic) latitude */
  1381. Latitude=Math.atan(SPHI/Math.abs(CPHI));
  1382. p.x = Longitude;
  1383. p.y = Latitude;
  1384. p.z = Height;
  1385. return p;
  1386. }, // cs_geocentric_to_geodetic()
  1387. /** Convert_Geocentric_To_Geodetic
  1388. * The method used here is derived from 'An Improved Algorithm for
  1389. * Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996
  1390. */
  1391. geocentric_to_geodetic_noniter : function (p) {
  1392. var X = p.x;
  1393. var Y = p.y;
  1394. var Z = p.z ? p.z : 0; //Z value not always supplied
  1395. var Longitude;
  1396. var Latitude;
  1397. var Height;
  1398. var W; /* distance from Z axis */
  1399. var W2; /* square of distance from Z axis */
  1400. var T0; /* initial estimate of vertical component */
  1401. var T1; /* corrected estimate of vertical component */
  1402. var S0; /* initial estimate of horizontal component */
  1403. var S1; /* corrected estimate of horizontal component */
  1404. var Sin_B0; /* Math.sin(B0), B0 is estimate of Bowring aux variable */
  1405. var Sin3_B0; /* cube of Math.sin(B0) */
  1406. var Cos_B0; /* Math.cos(B0) */
  1407. var Sin_p1; /* Math.sin(phi1), phi1 is estimated latitude */
  1408. var Cos_p1; /* Math.cos(phi1) */
  1409. var Rn; /* Earth radius at location */
  1410. var Sum; /* numerator of Math.cos(phi1) */
  1411. var At_Pole; /* indicates location is in polar region */
  1412. X = parseFloat(X); // cast from string to float
  1413. Y = parseFloat(Y);
  1414. Z = parseFloat(Z);
  1415. At_Pole = false;
  1416. if (X != 0.0)
  1417. {
  1418. Longitude = Math.atan2(Y,X);
  1419. }
  1420. else
  1421. {
  1422. if (Y > 0)
  1423. {
  1424. Longitude = Proj4js.common.HALF_PI;
  1425. }
  1426. else if (Y < 0)
  1427. {
  1428. Longitude = -Proj4js.common.HALF_PI;
  1429. }
  1430. else
  1431. {
  1432. At_Pole = true;
  1433. Longitude = 0.0;
  1434. if (Z > 0.0)
  1435. { /* north pole */
  1436. Latitude = Proj4js.common.HALF_PI;
  1437. }
  1438. else if (Z < 0.0)
  1439. { /* south pole */
  1440. Latitude = -Proj4js.common.HALF_PI;
  1441. }
  1442. else
  1443. { /* center of earth */
  1444. Latitude = Proj4js.common.HALF_PI;
  1445. Height = -this.b;
  1446. return;
  1447. }
  1448. }
  1449. }
  1450. W2 = X*X + Y*Y;
  1451. W = Math.sqrt(W2);
  1452. T0 = Z * Proj4js.common.AD_C;
  1453. S0 = Math.sqrt(T0 * T0 + W2);
  1454. Sin_B0 = T0 / S0;
  1455. Cos_B0 = W / S0;
  1456. Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
  1457. T1 = Z + this.b * this.ep2 * Sin3_B0;
  1458. Sum = W - this.a * this.es * Cos_B0 * Cos_B0 * Cos_B0;
  1459. S1 = Math.sqrt(T1*T1 + Sum * Sum);
  1460. Sin_p1 = T1 / S1;
  1461. Cos_p1 = Sum / S1;
  1462. Rn = this.a / Math.sqrt(1.0 - this.es * Sin_p1 * Sin_p1);
  1463. if (Cos_p1 >= Proj4js.common.COS_67P5)
  1464. {
  1465. Height = W / Cos_p1 - Rn;
  1466. }
  1467. else if (Cos_p1 <= -Proj4js.common.COS_67P5)
  1468. {
  1469. Height = W / -Cos_p1 - Rn;
  1470. }
  1471. else
  1472. {
  1473. Height = Z / Sin_p1 + Rn * (this.es - 1.0);
  1474. }
  1475. if (At_Pole == false)
  1476. {
  1477. Latitude = Math.atan(Sin_p1 / Cos_p1);
  1478. }
  1479. p.x = Longitude;
  1480. p.y = Latitude;
  1481. p.z = Height;
  1482. return p;
  1483. }, // geocentric_to_geodetic_noniter()
  1484. /****************************************************************/
  1485. // pj_geocentic_to_wgs84( p )
  1486. // p = point to transform in geocentric coordinates (x,y,z)
  1487. geocentric_to_wgs84 : function ( p ) {
  1488. if( this.datum_type == Proj4js.common.PJD_3PARAM )
  1489. {
  1490. // if( x[io] == HUGE_VAL )
  1491. // continue;
  1492. p.x += this.datum_params[0];
  1493. p.y += this.datum_params[1];
  1494. p.z += this.datum_params[2];
  1495. }
  1496. else if (this.datum_type == Proj4js.common.PJD_7PARAM)
  1497. {
  1498. var Dx_BF =this.datum_params[0];
  1499. var Dy_BF =this.datum_params[1];
  1500. var Dz_BF =this.datum_params[2];
  1501. var Rx_BF =this.datum_params[3];
  1502. var Ry_BF =this.datum_params[4];
  1503. var Rz_BF =this.datum_params[5];
  1504. var M_BF =this.datum_params[6];
  1505. // if( x[io] == HUGE_VAL )
  1506. // continue;
  1507. var x_out = M_BF*( p.x - Rz_BF*p.y + Ry_BF*p.z) + Dx_BF;
  1508. var y_out = M_BF*( Rz_BF*p.x + p.y - Rx_BF*p.z) + Dy_BF;
  1509. var z_out = M_BF*(-Ry_BF*p.x + Rx_BF*p.y + p.z) + Dz_BF;
  1510. p.x = x_out;
  1511. p.y = y_out;
  1512. p.z = z_out;
  1513. }
  1514. }, // cs_geocentric_to_wgs84
  1515. /****************************************************************/
  1516. // pj_geocentic_from_wgs84()
  1517. // coordinate system definition,
  1518. // point to transform in geocentric coordinates (x,y,z)
  1519. geocentric_from_wgs84 : function( p ) {
  1520. if( this.datum_type == Proj4js.common.PJD_3PARAM )
  1521. {
  1522. //if( x[io] == HUGE_VAL )
  1523. // continue;
  1524. p.x -= this.datum_params[0];
  1525. p.y -= this.datum_params[1];
  1526. p.z -= this.datum_params[2];
  1527. }
  1528. else if (this.datum_type == Proj4js.common.PJD_7PARAM)
  1529. {
  1530. var Dx_BF =this.datum_params[0];
  1531. var Dy_BF =this.datum_params[1];
  1532. var Dz_BF =this.datum_params[2];
  1533. var Rx_BF =this.datum_params[3];
  1534. var Ry_BF =this.datum_params[4];
  1535. var Rz_BF =this.datum_params[5];
  1536. var M_BF =this.datum_params[6];
  1537. var x_tmp = (p.x - Dx_BF) / M_BF;
  1538. var y_tmp = (p.y - Dy_BF) / M_BF;
  1539. var z_tmp = (p.z - Dz_BF) / M_BF;
  1540. //if( x[io] == HUGE_VAL )
  1541. // continue;
  1542. p.x = x_tmp + Rz_BF*y_tmp - Ry_BF*z_tmp;
  1543. p.y = -Rz_BF*x_tmp + y_tmp + Rx_BF*z_tmp;
  1544. p.z = Ry_BF*x_tmp - Rx_BF*y_tmp + z_tmp;
  1545. } //cs_geocentric_from_wgs84()
  1546. }
  1547. });
  1548. /** point object, nothing fancy, just allows values to be
  1549. passed back and forth by reference rather than by value.
  1550. Other point classes may be used as long as they have
  1551. x and y properties, which will get modified in the transform method.
  1552. */
  1553. Proj4js.Point = Proj4js.Class({
  1554. /**
  1555. * Constructor: Proj4js.Point
  1556. *
  1557. * Parameters:
  1558. * - x {float} or {Array} either the first coordinates component or
  1559. * the full coordinates
  1560. * - y {float} the second component
  1561. * - z {float} the third component, optional.
  1562. */
  1563. initialize : function(x,y,z) {
  1564. if (typeof x == 'object') {
  1565. this.x = x[0];
  1566. this.y = x[1];
  1567. this.z = x[2] || 0.0;
  1568. } else if (typeof x == 'string' && typeof y == 'undefined') {
  1569. var coords = x.split(',');
  1570. this.x = parseFloat(coords[0]);
  1571. this.y = parseFloat(coords[1]);
  1572. this.z = parseFloat(coords[2]) || 0.0;
  1573. } else {
  1574. this.x = x;
  1575. this.y = y;
  1576. this.z = z || 0.0;
  1577. }
  1578. },
  1579. /**
  1580. * APIMethod: clone
  1581. * Build a copy of a Proj4js.Point object.
  1582. *
  1583. * Return:
  1584. * {Proj4js}.Point the cloned point.
  1585. */
  1586. clone : function() {
  1587. return new Proj4js.Point(this.x, this.y, this.z);
  1588. },
  1589. /**
  1590. * APIMethod: toString
  1591. * Return a readable string version of the point
  1592. *
  1593. * Return:
  1594. * {String} String representation of Proj4js.Point object.
  1595. * (ex. <i>"x=5,y=42"</i>)
  1596. */
  1597. toString : function() {
  1598. return ("x=" + this.x + ",y=" + this.y);
  1599. },
  1600. /**
  1601. * APIMethod: toShortString
  1602. * Return a short string version of the point.
  1603. *
  1604. * Return:
  1605. * {String} Shortened String representation of Proj4js.Point object.
  1606. * (ex. <i>"5, 42"</i>)
  1607. */
  1608. toShortString : function() {
  1609. return (this.x + ", " + this.y);
  1610. }
  1611. });
  1612. Proj4js.PrimeMeridian = {
  1613. "greenwich": 0.0, //"0dE",
  1614. "lisbon": -9.131906111111, //"9d07'54.862\"W",
  1615. "paris": 2.337229166667, //"2d20'14.025\"E",
  1616. "bogota": -74.080916666667, //"74d04'51.3\"W",
  1617. "madrid": -3.687938888889, //"3d41'16.58\"W",
  1618. "rome": 12.452333333333, //"12d27'8.4\"E",
  1619. "bern": 7.439583333333, //"7d26'22.5\"E",
  1620. "jakarta": 106.807719444444, //"106d48'27.79\"E",
  1621. "ferro": -17.666666666667, //"17d40'W",
  1622. "brussels": 4.367975, //"4d22'4.71\"E",
  1623. "stockholm": 18.058277777778, //"18d3'29.8\"E",
  1624. "athens": 23.7163375, //"23d42'58.815\"E",
  1625. "oslo": 10.722916666667 //"10d43'22.5\"E"
  1626. };
  1627. Proj4js.Ellipsoid = {
  1628. "MERIT": {a:6378137.0, rf:298.257, ellipseName:"MERIT 1983"},
  1629. "SGS85": {a:6378136.0, rf:298.257, ellipseName:"Soviet Geodetic System 85"},
  1630. "GRS80": {a:6378137.0, rf:298.257222101, ellipseName:"GRS 1980(IUGG, 1980)"},
  1631. "IAU76": {a:6378140.0, rf:298.257, ellipseName:"IAU 1976"},
  1632. "airy": {a:6377563.396, b:6356256.910, ellipseName:"Airy 1830"},
  1633. "APL4.": {a:6378137, rf:298.25, ellipseName:"Appl. Physics. 1965"},
  1634. "NWL9D": {a:6378145.0, rf:298.25, ellipseName:"Naval Weapons Lab., 1965"},
  1635. "mod_airy": {a:6377340.189, b:6356034.446, ellipseName:"Modified Airy"},
  1636. "andrae": {a:6377104.43, rf:300.0, ellipseName:"Andrae 1876 (Den., Iclnd.)"},
  1637. "aust_SA": {a:6378160.0, rf:298.25, ellipseName:"Australian Natl & S. Amer. 1969"},
  1638. "GRS67": {a:6378160.0, rf:298.2471674270, ellipseName:"GRS 67(IUGG 1967)"},
  1639. "bessel": {a:6377397.155, rf:299.1528128, ellipseName:"Bessel 1841"},
  1640. "bess_nam": {a:6377483.865, rf:299.1528128, ellipseName:"Bessel 1841 (Namibia)"},
  1641. "clrk66": {a:6378206.4, b:6356583.8, ellipseName:"Clarke 1866"},
  1642. "clrk80": {a:6378249.145, rf:293.4663, ellipseName:"Clarke 1880 mod."},
  1643. "CPM": {a:6375738.7, rf:334.29, ellipseName:"Comm. des Poids et Mesures 1799"},
  1644. "delmbr": {a:6376428.0, rf:311.5, ellipseName:"Delambre 1810 (Belgium)"},
  1645. "engelis": {a:6378136.05, rf:298.2566, ellipseName:"Engelis 1985"},
  1646. "evrst30": {a:6377276.345, rf:300.8017, ellipseName:"Everest 1830"},
  1647. "evrst48": {a:6377304.063, rf:300.8017, ellipseName:"Everest 1948"},
  1648. "evrst56": {a:6377301.243, rf:300.8017, ellipseName:"Everest 1956"},
  1649. "evrst69": {a:6377295.664, rf:300.8017, ellipseName:"Everest 1969"},
  1650. "evrstSS": {a:6377298.556, rf:300.8017, ellipseName:"Everest (Sabah & Sarawak)"},
  1651. "fschr60": {a:6378166.0, rf:298.3, ellipseName:"Fischer (Mercury Datum) 1960"},
  1652. "fschr60m": {a:6378155.0, rf:298.3, ellipseName:"Fischer 1960"},
  1653. "fschr68": {a:6378150.0, rf:298.3, ellipseName:"Fischer 1968"},
  1654. "helmert": {a:6378200.0, rf:298.3, ellipseName:"Helmert 1906"},
  1655. "hough": {a:6378270.0, rf:297.0, ellipseName:"Hough"},
  1656. "intl": {a:6378388.0, rf:297.0, ellipseName:"International 1909 (Hayford)"},
  1657. "kaula": {a:6378163.0, rf:298.24, ellipseName:"Kaula 1961"},
  1658. "lerch": {a:6378139.0, rf:298.257, ellipseName:"Lerch 1979"},
  1659. "mprts": {a:6397300.0, rf:191.0, ellipseName:"Maupertius 1738"},
  1660. "new_intl": {a:6378157.5, b:6356772.2, ellipseName:"New International 1967"},
  1661. "plessis": {a:6376523.0, rf:6355863.0, ellipseName:"Plessis 1817 (France)"},
  1662. "krass": {a:6378245.0, rf:298.3, ellipseName:"Krassovsky, 1942"},
  1663. "SEasia": {a:6378155.0, b:6356773.3205, ellipseName:"Southeast Asia"},
  1664. "walbeck": {a:6376896.0, b:6355834.8467, ellipseName:"Walbeck"},
  1665. "WGS60": {a:6378165.0, rf:298.3, ellipseName:"WGS 60"},
  1666. "WGS66": {a:6378145.0, rf:298.25, ellipseName:"WGS 66"},
  1667. "WGS72": {a:6378135.0, rf:298.26, ellipseName:"WGS 72"},
  1668. "WGS84": {a:6378137.0, rf:298.257223563, ellipseName:"WGS 84"},
  1669. "sphere": {a:6370997.0, b:6370997.0, ellipseName:"Normal Sphere (r=6370997)"}
  1670. };
  1671. Proj4js.Datum = {
  1672. "WGS84": {towgs84: "0,0,0", ellipse: "WGS84", datumName: "WGS84"},
  1673. "GGRS87": {towgs84: "-199.87,74.79,246.62", ellipse: "GRS80", datumName: "Greek_Geodetic_Reference_System_1987"},
  1674. "NAD83": {towgs84: "0,0,0", ellipse: "GRS80", datumName: "North_American_Datum_1983"},
  1675. "NAD27": {nadgrids: "@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat", ellipse: "clrk66", datumName: "North_American_Datum_1927"},
  1676. "potsdam": {towgs84: "606.0,23.0,413.0", ellipse: "bessel", datumName: "Potsdam Rauenberg 1950 DHDN"},
  1677. "carthage": {towgs84: "-263.0,6.0,431.0", ellipse: "clark80", datumName: "Carthage 1934 Tunisia"},
  1678. "hermannskogel": {towgs84: "653.0,-212.0,449.0", ellipse: "bessel", datumName: "Hermannskogel"},
  1679. "ire65": {towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15", ellipse: "mod_airy", datumName: "Ireland 1965"},
  1680. "nzgd49": {towgs84: "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993", ellipse: "intl", datumName: "New Zealand Geodetic Datum 1949"},
  1681. "OSGB36": {towgs84: "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894", ellipse: "airy", datumName: "Airy 1830"}
  1682. };
  1683. Proj4js.WGS84 = new Proj4js.Proj('WGS84');
  1684. Proj4js.Datum['OSB36'] = Proj4js.Datum['OSGB36']; //as returned from spatialreference.org
  1685. //lookup table to go from the projection name in WKT to the Proj4js projection name
  1686. //build this out as required
  1687. Proj4js.wktProjections = {
  1688. "Lambert Tangential Conformal Conic Projection": "lcc",
  1689. "Mercator": "merc",
  1690. "Popular Visualisation Pseudo Mercator": "merc",
  1691. "Mercator_1SP": "merc",
  1692. "Transverse_Mercator": "tmerc",
  1693. "Transverse Mercator": "tmerc",
  1694. "Lambert Azimuthal Equal Area": "laea",
  1695. "Universal Transverse Mercator System": "utm"
  1696. };
  1697. Proj4js.defs['EPSG:3857'] = Proj4js.defs['EPSG:3785'];
  1698. /* ======================================================================
  1699. projCode/aea.js
  1700. ====================================================================== */
  1701. /*******************************************************************************
  1702. NAME ALBERS CONICAL EQUAL AREA
  1703. PURPOSE: Transforms input longitude and latitude to Easting and Northing
  1704. for the Albers Conical Equal Area projection. The longitude
  1705. and latitude must be in radians. The Easting and Northing
  1706. values will be returned in meters.
  1707. PROGRAMMER DATE
  1708. ---------- ----
  1709. T. Mittan, Feb, 1992
  1710. ALGORITHM REFERENCES
  1711. 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  1712. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  1713. State Government Printing Office, Washington D.C., 1987.
  1714. 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
  1715. U.S. Geological Survey Professional Paper 1453 , United State Government
  1716. Printing Office, Washington D.C., 1989.
  1717. *******************************************************************************/
  1718. Proj4js.Proj.aea = {
  1719. init : function() {
  1720. if (Math.abs(this.lat1 + this.lat2) < Proj4js.common.EPSLN) {
  1721. Proj4js.reportError("aeaInitEqualLatitudes");
  1722. return;
  1723. }
  1724. this.temp = this.b / this.a;
  1725. this.es = 1.0 - Math.pow(this.temp,2);
  1726. this.e3 = Math.sqrt(this.es);
  1727. this.sin_po=Math.sin(this.lat1);
  1728. this.cos_po=Math.cos(this.lat1);
  1729. this.t1=this.sin_po;
  1730. this.con = this.sin_po;
  1731. this.ms1 = Proj4js.common.msfnz(this.e3,this.sin_po,this.cos_po);
  1732. this.qs1 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po);
  1733. this.sin_po=Math.sin(this.lat2);
  1734. this.cos_po=Math.cos(this.lat2);
  1735. this.t2=this.sin_po;
  1736. this.ms2 = Proj4js.common.msfnz(this.e3,this.sin_po,this.cos_po);
  1737. this.qs2 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po);
  1738. this.sin_po=Math.sin(this.lat0);
  1739. this.cos_po=Math.cos(this.lat0);
  1740. this.t3=this.sin_po;
  1741. this.qs0 = Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po);
  1742. if (Math.abs(this.lat1 - this.lat2) > Proj4js.common.EPSLN) {
  1743. this.ns0 = (this.ms1 * this.ms1 - this.ms2 *this.ms2)/ (this.qs2 - this.qs1);
  1744. } else {
  1745. this.ns0 = this.con;
  1746. }
  1747. this.c = this.ms1 * this.ms1 + this.ns0 * this.qs1;
  1748. this.rh = this.a * Math.sqrt(this.c - this.ns0 * this.qs0)/this.ns0;
  1749. },
  1750. /* Albers Conical Equal Area forward equations--mapping lat,long to x,y
  1751. -------------------------------------------------------------------*/
  1752. forward: function(p){
  1753. var lon=p.x;
  1754. var lat=p.y;
  1755. this.sin_phi=Math.sin(lat);
  1756. this.cos_phi=Math.cos(lat);
  1757. var qs = Proj4js.common.qsfnz(this.e3,this.sin_phi,this.cos_phi);
  1758. var rh1 =this.a * Math.sqrt(this.c - this.ns0 * qs)/this.ns0;
  1759. var theta = this.ns0 * Proj4js.common.adjust_lon(lon - this.long0);
  1760. var x = rh1 * Math.sin(theta) + this.x0;
  1761. var y = this.rh - rh1 * Math.cos(theta) + this.y0;
  1762. p.x = x;
  1763. p.y = y;
  1764. return p;
  1765. },
  1766. inverse: function(p) {
  1767. var rh1,qs,con,theta,lon,lat;
  1768. p.x -= this.x0;
  1769. p.y = this.rh - p.y + this.y0;
  1770. if (this.ns0 >= 0) {
  1771. rh1 = Math.sqrt(p.x *p.x + p.y * p.y);
  1772. con = 1.0;
  1773. } else {
  1774. rh1 = -Math.sqrt(p.x * p.x + p.y *p.y);
  1775. con = -1.0;
  1776. }
  1777. theta = 0.0;
  1778. if (rh1 != 0.0) {
  1779. theta = Math.atan2(con * p.x, con * p.y);
  1780. }
  1781. con = rh1 * this.ns0 / this.a;
  1782. qs = (this.c - con * con) / this.ns0;
  1783. if (this.e3 >= 1e-10) {
  1784. con = 1 - .5 * (1.0 -this.es) * Math.log((1.0 - this.e3) / (1.0 + this.e3))/this.e3;
  1785. if (Math.abs(Math.abs(con) - Math.abs(qs)) > .0000000001 ) {
  1786. lat = this.phi1z(this.e3,qs);
  1787. } else {
  1788. if (qs >= 0) {
  1789. lat = .5 * Proj4js.common.PI;
  1790. } else {
  1791. lat = -.5 * Proj4js.common.PI;
  1792. }
  1793. }
  1794. } else {
  1795. lat = this.phi1z(this.e3,qs);
  1796. }
  1797. lon = Proj4js.common.adjust_lon(theta/this.ns0 + this.long0);
  1798. p.x = lon;
  1799. p.y = lat;
  1800. return p;
  1801. },
  1802. /* Function to compute phi1, the latitude for the inverse of the
  1803. Albers Conical Equal-Area projection.
  1804. -------------------------------------------*/
  1805. phi1z: function (eccent,qs) {
  1806. var sinphi, cosphi, con, com, dphi;
  1807. var phi = Proj4js.common.asinz(.5 * qs);
  1808. if (eccent < Proj4js.common.EPSLN) return phi;
  1809. var eccnts = eccent * eccent;
  1810. for (var i = 1; i <= 25; i++) {
  1811. sinphi = Math.sin(phi);
  1812. cosphi = Math.cos(phi);
  1813. con = eccent * sinphi;
  1814. com = 1.0 - con * con;
  1815. dphi = .5 * com * com / cosphi * (qs / (1.0 - eccnts) - sinphi / com + .5 / eccent * Math.log((1.0 - con) / (1.0 + con)));
  1816. phi = phi + dphi;
  1817. if (Math.abs(dphi) <= 1e-7) return phi;
  1818. }
  1819. Proj4js.reportError("aea:phi1z:Convergence error");
  1820. return null;
  1821. }
  1822. };
  1823. /* ======================================================================
  1824. projCode/sterea.js
  1825. ====================================================================== */
  1826. Proj4js.Proj.sterea = {
  1827. dependsOn : 'gauss',
  1828. init : function() {
  1829. Proj4js.Proj['gauss'].init.apply(this);
  1830. if (!this.rc) {
  1831. Proj4js.reportError("sterea:init:E_ERROR_0");
  1832. return;
  1833. }
  1834. this.sinc0 = Math.sin(this.phic0);
  1835. this.cosc0 = Math.cos(this.phic0);
  1836. this.R2 = 2.0 * this.rc;
  1837. if (!this.title) this.title = "Oblique Stereographic Alternative";
  1838. },
  1839. forward : function(p) {
  1840. var sinc, cosc, cosl, k;
  1841. p.x = Proj4js.common.adjust_lon(p.x-this.long0); /* adjust del longitude */
  1842. Proj4js.Proj['gauss'].forward.apply(this, [p]);
  1843. sinc = Math.sin(p.y);
  1844. cosc = Math.cos(p.y);
  1845. cosl = Math.cos(p.x);
  1846. k = this.k0 * this.R2 / (1.0 + this.sinc0 * sinc + this.cosc0 * cosc * cosl);
  1847. p.x = k * cosc * Math.sin(p.x);
  1848. p.y = k * (this.cosc0 * sinc - this.sinc0 * cosc * cosl);
  1849. p.x = this.a * p.x + this.x0;
  1850. p.y = this.a * p.y + this.y0;
  1851. return p;
  1852. },
  1853. inverse : function(p) {
  1854. var sinc, cosc, lon, lat, rho;
  1855. p.x = (p.x - this.x0) / this.a; /* descale and de-offset */
  1856. p.y = (p.y - this.y0) / this.a;
  1857. p.x /= this.k0;
  1858. p.y /= this.k0;
  1859. if ( (rho = Math.sqrt(p.x*p.x + p.y*p.y)) ) {
  1860. var c = 2.0 * Math.atan2(rho, this.R2);
  1861. sinc = Math.sin(c);
  1862. cosc = Math.cos(c);
  1863. lat = Math.asin(cosc * this.sinc0 + p.y * sinc * this.cosc0 / rho);
  1864. lon = Math.atan2(p.x * sinc, rho * this.cosc0 * cosc - p.y * this.sinc0 * sinc);
  1865. } else {
  1866. lat = this.phic0;
  1867. lon = 0.;
  1868. }
  1869. p.x = lon;
  1870. p.y = lat;
  1871. Proj4js.Proj['gauss'].inverse.apply(this,[p]);
  1872. p.x = Proj4js.common.adjust_lon(p.x + this.long0); /* adjust longitude to CM */
  1873. return p;
  1874. }
  1875. };
  1876. /* ======================================================================
  1877. projCode/poly.js
  1878. ====================================================================== */
  1879. /* Function to compute, phi4, the latitude for the inverse of the
  1880. Polyconic projection.
  1881. ------------------------------------------------------------*/
  1882. function phi4z (eccent,e0,e1,e2,e3,a,b,c,phi) {
  1883. var sinphi, sin2ph, tanphi, ml, mlp, con1, con2, con3, dphi, i;
  1884. phi = a;
  1885. for (i = 1; i <= 15; i++) {
  1886. sinphi = Math.sin(phi);
  1887. tanphi = Math.tan(phi);
  1888. c = tanphi * Math.sqrt (1.0 - eccent * sinphi * sinphi);
  1889. sin2ph = Math.sin (2.0 * phi);
  1890. /*
  1891. ml = e0 * *phi - e1 * sin2ph + e2 * sin (4.0 * *phi);
  1892. mlp = e0 - 2.0 * e1 * cos (2.0 * *phi) + 4.0 * e2 * cos (4.0 * *phi);
  1893. */
  1894. ml = e0 * phi - e1 * sin2ph + e2 * Math.sin (4.0 * phi) - e3 * Math.sin (6.0 * phi);
  1895. 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);
  1896. con1 = 2.0 * ml + c * (ml * ml + b) - 2.0 * a * (c * ml + 1.0);
  1897. con2 = eccent * sin2ph * (ml * ml + b - 2.0 * a * ml) / (2.0 *c);
  1898. con3 = 2.0 * (a - ml) * (c * mlp - 2.0 / sin2ph) - 2.0 * mlp;
  1899. dphi = con1 / (con2 + con3);
  1900. phi += dphi;
  1901. if (Math.abs(dphi) <= .0000000001 ) return(phi);
  1902. }
  1903. Proj4js.reportError("phi4z: No convergence");
  1904. return null;
  1905. }
  1906. /* Function to compute the constant e4 from the input of the eccentricity
  1907. of the spheroid, x. This constant is used in the Polar Stereographic
  1908. projection.
  1909. --------------------------------------------------------------------*/
  1910. function e4fn(x) {
  1911. var con, com;
  1912. con = 1.0 + x;
  1913. com = 1.0 - x;
  1914. return (Math.sqrt((Math.pow(con,con))*(Math.pow(com,com))));
  1915. }
  1916. /*******************************************************************************
  1917. NAME POLYCONIC
  1918. PURPOSE: Transforms input longitude and latitude to Easting and
  1919. Northing for the Polyconic projection. The
  1920. longitude and latitude must be in radians. The Easting
  1921. and Northing values will be returned in meters.
  1922. PROGRAMMER DATE
  1923. ---------- ----
  1924. T. Mittan Mar, 1993
  1925. ALGORITHM REFERENCES
  1926. 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  1927. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  1928. State Government Printing Office, Washington D.C., 1987.
  1929. 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
  1930. U.S. Geological Survey Professional Paper 1453 , United State Government
  1931. Printing Office, Washington D.C., 1989.
  1932. *******************************************************************************/
  1933. Proj4js.Proj.poly = {
  1934. /* Initialize the POLYCONIC projection
  1935. ----------------------------------*/
  1936. init: function() {
  1937. var temp; /* temporary variable */
  1938. if (this.lat0 == 0) this.lat0 = 90;//this.lat0 ca
  1939. /* Place parameters in static storage for common use
  1940. -------------------------------------------------*/
  1941. this.temp = this.b / this.a;
  1942. 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
  1943. this.e = Math.sqrt(this.es);
  1944. this.e0 = Proj4js.common.e0fn(this.es);
  1945. this.e1 = Proj4js.common.e1fn(this.es);
  1946. this.e2 = Proj4js.common.e2fn(this.es);
  1947. this.e3 = Proj4js.common.e3fn(this.es);
  1948. 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
  1949. //if (!this.ml0) {this.ml0=0;}
  1950. },
  1951. /* Polyconic forward equations--mapping lat,long to x,y
  1952. ---------------------------------------------------*/
  1953. forward: function(p) {
  1954. var sinphi, cosphi; /* sin and cos value */
  1955. var al; /* temporary values */
  1956. var c; /* temporary values */
  1957. var con, ml; /* cone constant, small m */
  1958. var ms; /* small m */
  1959. var x,y;
  1960. var lon=p.x;
  1961. var lat=p.y;
  1962. con = Proj4js.common.adjust_lon(lon - this.long0);
  1963. if (Math.abs(lat) <= .0000001) {
  1964. x = this.x0 + this.a * con;
  1965. y = this.y0 - this.a * this.ml0;
  1966. } else {
  1967. sinphi = Math.sin(lat);
  1968. cosphi = Math.cos(lat);
  1969. ml = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat);
  1970. ms = Proj4js.common.msfnz(this.e,sinphi,cosphi);
  1971. con = sinphi;
  1972. x = this.x0 + this.a * ms * Math.sin(con)/sinphi;
  1973. y = this.y0 + this.a * (ml - this.ml0 + ms * (1.0 - Math.cos(con))/sinphi);
  1974. }
  1975. p.x=x;
  1976. p.y=y;
  1977. return p;
  1978. },
  1979. /* Inverse equations
  1980. -----------------*/
  1981. inverse: function(p) {
  1982. var sin_phi, cos_phi; /* sin and cos value */
  1983. var al; /* temporary values */
  1984. var b; /* temporary values */
  1985. var c; /* temporary values */
  1986. var con, ml; /* cone constant, small m */
  1987. var iflg; /* error flag */
  1988. var lon,lat;
  1989. p.x -= this.x0;
  1990. p.y -= this.y0;
  1991. al = this.ml0 + p.y/this.a;
  1992. iflg = 0;
  1993. if (Math.abs(al) <= .0000001) {
  1994. lon = p.x/this.a + this.long0;
  1995. lat = 0.0;
  1996. } else {
  1997. b = al * al + (p.x/this.a) * (p.x/this.a);
  1998. iflg = phi4z(this.es,this.e0,this.e1,this.e2,this.e3,this.al,b,c,lat);
  1999. if (iflg != 1) return(iflg);
  2000. lon = Proj4js.common.adjust_lon((Proj4js.common.asinz(p.x * c / this.a) / Math.sin(lat)) + this.long0);
  2001. }
  2002. p.x=lon;
  2003. p.y=lat;
  2004. return p;
  2005. }
  2006. };
  2007. /* ======================================================================
  2008. projCode/equi.js
  2009. ====================================================================== */
  2010. /*******************************************************************************
  2011. NAME EQUIRECTANGULAR
  2012. PURPOSE: Transforms input longitude and latitude to Easting and
  2013. Northing for the Equirectangular projection. The
  2014. longitude and latitude must be in radians. The Easting
  2015. and Northing values will be returned in meters.
  2016. PROGRAMMER DATE
  2017. ---------- ----
  2018. T. Mittan Mar, 1993
  2019. ALGORITHM REFERENCES
  2020. 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  2021. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  2022. State Government Printing Office, Washington D.C., 1987.
  2023. 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
  2024. U.S. Geological Survey Professional Paper 1453 , United State Government
  2025. Printing Office, Washington D.C., 1989.
  2026. *******************************************************************************/
  2027. Proj4js.Proj.equi = {
  2028. init: function() {
  2029. if(!this.x0) this.x0=0;
  2030. if(!this.y0) this.y0=0;
  2031. if(!this.lat0) this.lat0=0;
  2032. if(!this.long0) this.long0=0;
  2033. ///this.t2;
  2034. },
  2035. /* Equirectangular forward equations--mapping lat,long to x,y
  2036. ---------------------------------------------------------*/
  2037. forward: function(p) {
  2038. var lon=p.x;
  2039. var lat=p.y;
  2040. var dlon = Proj4js.common.adjust_lon(lon - this.long0);
  2041. var x = this.x0 +this. a * dlon *Math.cos(this.lat0);
  2042. var y = this.y0 + this.a * lat;
  2043. this.t1=x;
  2044. this.t2=Math.cos(this.lat0);
  2045. p.x=x;
  2046. p.y=y;
  2047. return p;
  2048. }, //equiFwd()
  2049. /* Equirectangular inverse equations--mapping x,y to lat/long
  2050. ---------------------------------------------------------*/
  2051. inverse: function(p) {
  2052. p.x -= this.x0;
  2053. p.y -= this.y0;
  2054. var lat = p.y /this. a;
  2055. if ( Math.abs(lat) > Proj4js.common.HALF_PI) {
  2056. Proj4js.reportError("equi:Inv:DataError");
  2057. }
  2058. var lon = Proj4js.common.adjust_lon(this.long0 + p.x / (this.a * Math.cos(this.lat0)));
  2059. p.x=lon;
  2060. p.y=lat;
  2061. }//equiInv()
  2062. };
  2063. /* ======================================================================
  2064. projCode/merc.js
  2065. ====================================================================== */
  2066. /*******************************************************************************
  2067. NAME MERCATOR
  2068. PURPOSE: Transforms input longitude and latitude to Easting and
  2069. Northing for the Mercator projection. The
  2070. longitude and latitude must be in radians. The Easting
  2071. and Northing values will be returned in meters.
  2072. PROGRAMMER DATE
  2073. ---------- ----
  2074. D. Steinwand, EROS Nov, 1991
  2075. T. Mittan Mar, 1993
  2076. ALGORITHM REFERENCES
  2077. 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  2078. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  2079. State Government Printing Office, Washington D.C., 1987.
  2080. 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
  2081. U.S. Geological Survey Professional Paper 1453 , United State Government
  2082. Printing Office, Washington D.C., 1989.
  2083. *******************************************************************************/
  2084. //static double r_major = a; /* major axis */
  2085. //static double r_minor = b; /* minor axis */
  2086. //static double lon_center = long0; /* Center longitude (projection center) */
  2087. //static double lat_origin = lat0; /* center latitude */
  2088. //static double e,es; /* eccentricity constants */
  2089. //static double m1; /* small value m */
  2090. //static double false_northing = y0; /* y offset in meters */
  2091. //static double false_easting = x0; /* x offset in meters */
  2092. //scale_fact = k0
  2093. Proj4js.Proj.merc = {
  2094. init : function() {
  2095. //?this.temp = this.r_minor / this.r_major;
  2096. //this.temp = this.b / this.a;
  2097. //this.es = 1.0 - Math.sqrt(this.temp);
  2098. //this.e = Math.sqrt( this.es );
  2099. //?this.m1 = Math.cos(this.lat_origin) / (Math.sqrt( 1.0 - this.es * Math.sin(this.lat_origin) * Math.sin(this.lat_origin)));
  2100. //this.m1 = Math.cos(0.0) / (Math.sqrt( 1.0 - this.es * Math.sin(0.0) * Math.sin(0.0)));
  2101. if (this.lat_ts) {
  2102. if (this.sphere) {
  2103. this.k0 = Math.cos(this.lat_ts);
  2104. } else {
  2105. this.k0 = Proj4js.common.msfnz(this.es, Math.sin(this.lat_ts), Math.cos(this.lat_ts));
  2106. }
  2107. }
  2108. },
  2109. /* Mercator forward equations--mapping lat,long to x,y
  2110. --------------------------------------------------*/
  2111. forward : function(p) {
  2112. //alert("ll2m coords : "+coords);
  2113. var lon = p.x;
  2114. var lat = p.y;
  2115. // convert to radians
  2116. if ( lat*Proj4js.common.R2D > 90.0 &&
  2117. lat*Proj4js.common.R2D < -90.0 &&
  2118. lon*Proj4js.common.R2D > 180.0 &&
  2119. lon*Proj4js.common.R2D < -180.0) {
  2120. Proj4js.reportError("merc:forward: llInputOutOfRange: "+ lon +" : " + lat);
  2121. return null;
  2122. }
  2123. var x,y;
  2124. if(Math.abs( Math.abs(lat) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN) {
  2125. Proj4js.reportError("merc:forward: ll2mAtPoles");
  2126. return null;
  2127. } else {
  2128. if (this.sphere) {
  2129. x = this.x0 + this.a * this.k0 * Proj4js.common.adjust_lon(lon - this.long0);
  2130. y = this.y0 + this.a * this.k0 * Math.log(Math.tan(Proj4js.common.FORTPI + 0.5*lat));
  2131. } else {
  2132. var sinphi = Math.sin(lat);
  2133. var ts = Proj4js.common.tsfnz(this.e,lat,sinphi);
  2134. x = this.x0 + this.a * this.k0 * Proj4js.common.adjust_lon(lon - this.long0);
  2135. y = this.y0 - this.a * this.k0 * Math.log(ts);
  2136. }
  2137. p.x = x;
  2138. p.y = y;
  2139. return p;
  2140. }
  2141. },
  2142. /* Mercator inverse equations--mapping x,y to lat/long
  2143. --------------------------------------------------*/
  2144. inverse : function(p) {
  2145. var x = p.x - this.x0;
  2146. var y = p.y - this.y0;
  2147. var lon,lat;
  2148. if (this.sphere) {
  2149. lat = Proj4js.common.HALF_PI - 2.0 * Math.atan(Math.exp(-y / this.a * this.k0));
  2150. } else {
  2151. var ts = Math.exp(-y / (this.a * this.k0));
  2152. lat = Proj4js.common.phi2z(this.e,ts);
  2153. if(lat == -9999) {
  2154. Proj4js.reportError("merc:inverse: lat = -9999");
  2155. return null;
  2156. }
  2157. }
  2158. lon = Proj4js.common.adjust_lon(this.long0+ x / (this.a * this.k0));
  2159. p.x = lon;
  2160. p.y = lat;
  2161. return p;
  2162. }
  2163. };
  2164. /* ======================================================================
  2165. projCode/utm.js
  2166. ====================================================================== */
  2167. /*******************************************************************************
  2168. NAME TRANSVERSE MERCATOR
  2169. PURPOSE: Transforms input longitude and latitude to Easting and
  2170. Northing for the Transverse Mercator projection. The
  2171. longitude and latitude must be in radians. The Easting
  2172. and Northing values will be returned in meters.
  2173. ALGORITHM REFERENCES
  2174. 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  2175. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  2176. State Government Printing Office, Washington D.C., 1987.
  2177. 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
  2178. U.S. Geological Survey Professional Paper 1453 , United State Government
  2179. Printing Office, Washington D.C., 1989.
  2180. *******************************************************************************/
  2181. /**
  2182. Initialize Transverse Mercator projection
  2183. */
  2184. Proj4js.Proj.utm = {
  2185. dependsOn : 'tmerc',
  2186. init : function() {
  2187. if (!this.zone) {
  2188. Proj4js.reportError("utm:init: zone must be specified for UTM");
  2189. return;
  2190. }
  2191. this.lat0 = 0.0;
  2192. this.long0 = ((6 * Math.abs(this.zone)) - 183) * Proj4js.common.D2R;
  2193. this.x0 = 500000.0;
  2194. this.y0 = this.utmSouth ? 10000000.0 : 0.0;
  2195. this.k0 = 0.9996;
  2196. Proj4js.Proj['tmerc'].init.apply(this);
  2197. this.forward = Proj4js.Proj['tmerc'].forward;
  2198. this.inverse = Proj4js.Proj['tmerc'].inverse;
  2199. }
  2200. };
  2201. /* ======================================================================
  2202. projCode/eqdc.js
  2203. ====================================================================== */
  2204. /*******************************************************************************
  2205. NAME EQUIDISTANT CONIC
  2206. PURPOSE: Transforms input longitude and latitude to Easting and Northing
  2207. for the Equidistant Conic projection. The longitude and
  2208. latitude must be in radians. The Easting and Northing values
  2209. will be returned in meters.
  2210. PROGRAMMER DATE
  2211. ---------- ----
  2212. T. Mittan Mar, 1993
  2213. ALGORITHM REFERENCES
  2214. 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  2215. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  2216. State Government Printing Office, Washington D.C., 1987.
  2217. 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
  2218. U.S. Geological Survey Professional Paper 1453 , United State Government
  2219. Printing Office, Washington D.C., 1989.
  2220. *******************************************************************************/
  2221. /* Variables common to all subroutines in this code file
  2222. -----------------------------------------------------*/
  2223. Proj4js.Proj.eqdc = {
  2224. /* Initialize the Equidistant Conic projection
  2225. ------------------------------------------*/
  2226. init: function() {
  2227. /* Place parameters in static storage for common use
  2228. -------------------------------------------------*/
  2229. if(!this.mode) this.mode=0;//chosen default mode
  2230. this.temp = this.b / this.a;
  2231. this.es = 1.0 - Math.pow(this.temp,2);
  2232. this.e = Math.sqrt(this.es);
  2233. this.e0 = Proj4js.common.e0fn(this.es);
  2234. this.e1 = Proj4js.common.e1fn(this.es);
  2235. this.e2 = Proj4js.common.e2fn(this.es);
  2236. this.e3 = Proj4js.common.e3fn(this.es);
  2237. this.sinphi=Math.sin(this.lat1);
  2238. this.cosphi=Math.cos(this.lat1);
  2239. this.ms1 = Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi);
  2240. this.ml1 = Proj4js.common.mlfn(this.e0, this.e1, this.e2,this.e3, this.lat1);
  2241. /* format B
  2242. ---------*/
  2243. if (this.mode != 0) {
  2244. if (Math.abs(this.lat1 + this.lat2) < Proj4js.common.EPSLN) {
  2245. Proj4js.reportError("eqdc:Init:EqualLatitudes");
  2246. //return(81);
  2247. }
  2248. this.sinphi=Math.sin(this.lat2);
  2249. this.cosphi=Math.cos(this.lat2);
  2250. this.ms2 = Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi);
  2251. this.ml2 = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat2);
  2252. if (Math.abs(this.lat1 - this.lat2) >= Proj4js.common.EPSLN) {
  2253. this.ns = (this.ms1 - this.ms2) / (this.ml2 - this.ml1);
  2254. } else {
  2255. this.ns = this.sinphi;
  2256. }
  2257. } else {
  2258. this.ns = this.sinphi;
  2259. }
  2260. this.g = this.ml1 + this.ms1/this.ns;
  2261. this.ml0 = Proj4js.common.mlfn(this.e0, this.e1,this. e2, this.e3, this.lat0);
  2262. this.rh = this.a * (this.g - this.ml0);
  2263. },
  2264. /* Equidistant Conic forward equations--mapping lat,long to x,y
  2265. -----------------------------------------------------------*/
  2266. forward: function(p) {
  2267. var lon=p.x;
  2268. var lat=p.y;
  2269. /* Forward equations
  2270. -----------------*/
  2271. var ml = Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat);
  2272. var rh1 = this.a * (this.g - ml);
  2273. var theta = this.ns * Proj4js.common.adjust_lon(lon - this.long0);
  2274. var x = this.x0 + rh1 * Math.sin(theta);
  2275. var y = this.y0 + this.rh - rh1 * Math.cos(theta);
  2276. p.x=x;
  2277. p.y=y;
  2278. return p;
  2279. },
  2280. /* Inverse equations
  2281. -----------------*/
  2282. inverse: function(p) {
  2283. p.x -= this.x0;
  2284. p.y = this.rh - p.y + this.y0;
  2285. var con, rh1;
  2286. if (this.ns >= 0) {
  2287. rh1 = Math.sqrt(p.x *p.x + p.y * p.y);
  2288. con = 1.0;
  2289. } else {
  2290. rh1 = -Math.sqrt(p.x *p. x +p. y * p.y);
  2291. con = -1.0;
  2292. }
  2293. var theta = 0.0;
  2294. if (rh1 != 0.0) theta = Math.atan2(con *p.x, con *p.y);
  2295. var ml = this.g - rh1 /this.a;
  2296. var lat = this.phi3z(ml,this.e0,this.e1,this.e2,this.e3);
  2297. var lon = Proj4js.common.adjust_lon(this.long0 + theta / this.ns);
  2298. p.x=lon;
  2299. p.y=lat;
  2300. return p;
  2301. },
  2302. /* Function to compute latitude, phi3, for the inverse of the Equidistant
  2303. Conic projection.
  2304. -----------------------------------------------------------------*/
  2305. phi3z: function(ml,e0,e1,e2,e3) {
  2306. var phi;
  2307. var dphi;
  2308. phi = ml;
  2309. for (var i = 0; i < 15; i++) {
  2310. dphi = (ml + e1 * Math.sin(2.0 * phi) - e2 * Math.sin(4.0 * phi) + e3 * Math.sin(6.0 * phi))/ e0 - phi;
  2311. phi += dphi;
  2312. if (Math.abs(dphi) <= .0000000001) {
  2313. return phi;
  2314. }
  2315. }
  2316. Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations");
  2317. return null;
  2318. }
  2319. };
  2320. /* ======================================================================
  2321. projCode/tmerc.js
  2322. ====================================================================== */
  2323. /*******************************************************************************
  2324. NAME TRANSVERSE MERCATOR
  2325. PURPOSE: Transforms input longitude and latitude to Easting and
  2326. Northing for the Transverse Mercator projection. The
  2327. longitude and latitude must be in radians. The Easting
  2328. and Northing values will be returned in meters.
  2329. ALGORITHM REFERENCES
  2330. 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  2331. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  2332. State Government Printing Office, Washington D.C., 1987.
  2333. 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
  2334. U.S. Geological Survey Professional Paper 1453 , United State Government
  2335. Printing Office, Washington D.C., 1989.
  2336. *******************************************************************************/
  2337. /**
  2338. Initialize Transverse Mercator projection
  2339. */
  2340. Proj4js.Proj.tmerc = {
  2341. init : function() {
  2342. this.e0 = Proj4js.common.e0fn(this.es);
  2343. this.e1 = Proj4js.common.e1fn(this.es);
  2344. this.e2 = Proj4js.common.e2fn(this.es);
  2345. this.e3 = Proj4js.common.e3fn(this.es);
  2346. this.ml0 = this.a * Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0);
  2347. },
  2348. /**
  2349. Transverse Mercator Forward - long/lat to x/y
  2350. long/lat in radians
  2351. */
  2352. forward : function(p) {
  2353. var lon = p.x;
  2354. var lat = p.y;
  2355. var delta_lon = Proj4js.common.adjust_lon(lon - this.long0); // Delta longitude
  2356. var con; // cone constant
  2357. var x, y;
  2358. var sin_phi=Math.sin(lat);
  2359. var cos_phi=Math.cos(lat);
  2360. if (this.sphere) { /* spherical form */
  2361. var b = cos_phi * Math.sin(delta_lon);
  2362. if ((Math.abs(Math.abs(b) - 1.0)) < .0000000001) {
  2363. Proj4js.reportError("tmerc:forward: Point projects into infinity");
  2364. return(93);
  2365. } else {
  2366. x = .5 * this.a * this.k0 * Math.log((1.0 + b)/(1.0 - b));
  2367. con = Math.acos(cos_phi * Math.cos(delta_lon)/Math.sqrt(1.0 - b*b));
  2368. if (lat < 0) con = - con;
  2369. y = this.a * this.k0 * (con - this.lat0);
  2370. }
  2371. } else {
  2372. var al = cos_phi * delta_lon;
  2373. var als = Math.pow(al,2);
  2374. var c = this.ep2 * Math.pow(cos_phi,2);
  2375. var tq = Math.tan(lat);
  2376. var t = Math.pow(tq,2);
  2377. con = 1.0 - this.es * Math.pow(sin_phi,2);
  2378. var n = this.a / Math.sqrt(con);
  2379. var ml = this.a * Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat);
  2380. 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;
  2381. 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;
  2382. }
  2383. p.x = x; p.y = y;
  2384. return p;
  2385. }, // tmercFwd()
  2386. /**
  2387. Transverse Mercator Inverse - x/y to long/lat
  2388. */
  2389. inverse : function(p) {
  2390. var con, phi; /* temporary angles */
  2391. var delta_phi; /* difference between longitudes */
  2392. var i;
  2393. var max_iter = 6; /* maximun number of iterations */
  2394. var lat, lon;
  2395. if (this.sphere) { /* spherical form */
  2396. var f = Math.exp(p.x/(this.a * this.k0));
  2397. var g = .5 * (f - 1/f);
  2398. var temp = this.lat0 + p.y/(this.a * this.k0);
  2399. var h = Math.cos(temp);
  2400. con = Math.sqrt((1.0 - h * h)/(1.0 + g * g));
  2401. lat = Proj4js.common.asinz(con);
  2402. if (temp < 0)
  2403. lat = -lat;
  2404. if ((g == 0) && (h == 0)) {
  2405. lon = this.long0;
  2406. } else {
  2407. lon = Proj4js.common.adjust_lon(Math.atan2(g,h) + this.long0);
  2408. }
  2409. } else { // ellipsoidal form
  2410. var x = p.x - this.x0;
  2411. var y = p.y - this.y0;
  2412. con = (this.ml0 + y / this.k0) / this.a;
  2413. phi = con;
  2414. for (i=0;true;i++) {
  2415. 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;
  2416. phi += delta_phi;
  2417. if (Math.abs(delta_phi) <= Proj4js.common.EPSLN) break;
  2418. if (i >= max_iter) {
  2419. Proj4js.reportError("tmerc:inverse: Latitude failed to converge");
  2420. return(95);
  2421. }
  2422. } // for()
  2423. if (Math.abs(phi) < Proj4js.common.HALF_PI) {
  2424. // sincos(phi, &sin_phi, &cos_phi);
  2425. var sin_phi=Math.sin(phi);
  2426. var cos_phi=Math.cos(phi);
  2427. var tan_phi = Math.tan(phi);
  2428. var c = this.ep2 * Math.pow(cos_phi,2);
  2429. var cs = Math.pow(c,2);
  2430. var t = Math.pow(tan_phi,2);
  2431. var ts = Math.pow(t,2);
  2432. con = 1.0 - this.es * Math.pow(sin_phi,2);
  2433. var n = this.a / Math.sqrt(con);
  2434. var r = n * (1.0 - this.es) / con;
  2435. var d = x / (n * this.k0);
  2436. var ds = Math.pow(d,2);
  2437. 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)));
  2438. 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));
  2439. } else {
  2440. lat = Proj4js.common.HALF_PI * Proj4js.common.sign(y);
  2441. lon = this.long0;
  2442. }
  2443. }
  2444. p.x = lon;
  2445. p.y = lat;
  2446. return p;
  2447. } // tmercInv()
  2448. };
  2449. /* ======================================================================
  2450. defs/GOOGLE.js
  2451. ====================================================================== */
  2452. 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";
  2453. Proj4js.defs["EPSG:900913"]=Proj4js.defs["GOOGLE"];
  2454. /* ======================================================================
  2455. projCode/gstmerc.js
  2456. ====================================================================== */
  2457. Proj4js.Proj.gstmerc = {
  2458. init : function() {
  2459. // array of: a, b, lon0, lat0, k0, x0, y0
  2460. var temp= this.b / this.a;
  2461. this.e= Math.sqrt(1.0 - temp*temp);
  2462. this.lc= this.long0;
  2463. this.rs= Math.sqrt(1.0+this.e*this.e*Math.pow(Math.cos(this.lat0),4.0)/(1.0-this.e*this.e));
  2464. var sinz= Math.sin(this.lat0);
  2465. var pc= Math.asin(sinz/this.rs);
  2466. var sinzpc= Math.sin(pc);
  2467. this.cp= Proj4js.common.latiso(0.0,pc,sinzpc)-this.rs*Proj4js.common.latiso(this.e,this.lat0,sinz);
  2468. this.n2= this.k0*this.a*Math.sqrt(1.0-this.e*this.e)/(1.0-this.e*this.e*sinz*sinz);
  2469. this.xs= this.x0;
  2470. this.ys= this.y0-this.n2*pc;
  2471. if (!this.title) this.title = "Gauss Schreiber transverse mercator";
  2472. },
  2473. // forward equations--mapping lat,long to x,y
  2474. // -----------------------------------------------------------------
  2475. forward : function(p) {
  2476. var lon= p.x;
  2477. var lat= p.y;
  2478. var L= this.rs*(lon-this.lc);
  2479. var Ls= this.cp+(this.rs*Proj4js.common.latiso(this.e,lat,Math.sin(lat)));
  2480. var lat1= Math.asin(Math.sin(L)/Proj4js.common.cosh(Ls));
  2481. var Ls1= Proj4js.common.latiso(0.0,lat1,Math.sin(lat1));
  2482. p.x= this.xs+(this.n2*Ls1);
  2483. p.y= this.ys+(this.n2*Math.atan(Proj4js.common.sinh(Ls)/Math.cos(L)));
  2484. return p;
  2485. },
  2486. // inverse equations--mapping x,y to lat/long
  2487. // -----------------------------------------------------------------
  2488. inverse : function(p) {
  2489. var x= p.x;
  2490. var y= p.y;
  2491. var L= Math.atan(Proj4js.common.sinh((x-this.xs)/this.n2)/Math.cos((y-this.ys)/this.n2));
  2492. var lat1= Math.asin(Math.sin((y-this.ys)/this.n2)/Proj4js.common.cosh((x-this.xs)/this.n2));
  2493. var LC= Proj4js.common.latiso(0.0,lat1,Math.sin(lat1));
  2494. p.x= this.lc+L/this.rs;
  2495. p.y= Proj4js.common.invlatiso(this.e,(LC-this.cp)/this.rs);
  2496. return p;
  2497. }
  2498. };
  2499. /* ======================================================================
  2500. projCode/ortho.js
  2501. ====================================================================== */
  2502. /*******************************************************************************
  2503. NAME ORTHOGRAPHIC
  2504. PURPOSE: Transforms input longitude and latitude to Easting and
  2505. Northing for the Orthographic projection. The
  2506. longitude and latitude must be in radians. The Easting
  2507. and Northing values will be returned in meters.
  2508. PROGRAMMER DATE
  2509. ---------- ----
  2510. T. Mittan Mar, 1993
  2511. ALGORITHM REFERENCES
  2512. 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  2513. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  2514. State Government Printing Office, Washington D.C., 1987.
  2515. 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
  2516. U.S. Geological Survey Professional Paper 1453 , United State Government
  2517. Printing Office, Washington D.C., 1989.
  2518. *******************************************************************************/
  2519. Proj4js.Proj.ortho = {
  2520. /* Initialize the Orthographic projection
  2521. -------------------------------------*/
  2522. init: function(def) {
  2523. //double temp; /* temporary variable */
  2524. /* Place parameters in static storage for common use
  2525. -------------------------------------------------*/;
  2526. this.sin_p14=Math.sin(this.lat0);
  2527. this.cos_p14=Math.cos(this.lat0);
  2528. },
  2529. /* Orthographic forward equations--mapping lat,long to x,y
  2530. ---------------------------------------------------*/
  2531. forward: function(p) {
  2532. var sinphi, cosphi; /* sin and cos value */
  2533. var dlon; /* delta longitude value */
  2534. var coslon; /* cos of longitude */
  2535. var ksp; /* scale factor */
  2536. var g;
  2537. var lon=p.x;
  2538. var lat=p.y;
  2539. /* Forward equations
  2540. -----------------*/
  2541. dlon = Proj4js.common.adjust_lon(lon - this.long0);
  2542. sinphi=Math.sin(lat);
  2543. cosphi=Math.cos(lat);
  2544. coslon = Math.cos(dlon);
  2545. g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon;
  2546. ksp = 1.0;
  2547. if ((g > 0) || (Math.abs(g) <= Proj4js.common.EPSLN)) {
  2548. var x = this.a * ksp * cosphi * Math.sin(dlon);
  2549. var y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon);
  2550. } else {
  2551. Proj4js.reportError("orthoFwdPointError");
  2552. }
  2553. p.x=x;
  2554. p.y=y;
  2555. return p;
  2556. },
  2557. inverse: function(p) {
  2558. var rh; /* height above ellipsoid */
  2559. var z; /* angle */
  2560. var sinz,cosz; /* sin of z and cos of z */
  2561. var temp;
  2562. var con;
  2563. var lon , lat;
  2564. /* Inverse equations
  2565. -----------------*/
  2566. p.x -= this.x0;
  2567. p.y -= this.y0;
  2568. rh = Math.sqrt(p.x * p.x + p.y * p.y);
  2569. if (rh > this.a + .0000001) {
  2570. Proj4js.reportError("orthoInvDataError");
  2571. }
  2572. z = Proj4js.common.asinz(rh / this.a);
  2573. sinz=Math.sin(z);
  2574. cosz=Math.cos(z);
  2575. lon = this.long0;
  2576. if (Math.abs(rh) <= Proj4js.common.EPSLN) {
  2577. lat = this.lat0;
  2578. }
  2579. lat = Proj4js.common.asinz(cosz * this.sin_p14 + (p.y * sinz * this.cos_p14)/rh);
  2580. con = Math.abs(this.lat0) - Proj4js.common.HALF_PI;
  2581. if (Math.abs(con) <= Proj4js.common.EPSLN) {
  2582. if (this.lat0 >= 0) {
  2583. lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x, -p.y));
  2584. } else {
  2585. lon = Proj4js.common.adjust_lon(this.long0 -Math.atan2(-p.x, p.y));
  2586. }
  2587. }
  2588. con = cosz - this.sin_p14 * Math.sin(lat);
  2589. p.x=lon;
  2590. p.y=lat;
  2591. return p;
  2592. }
  2593. };
  2594. /* ======================================================================
  2595. projCode/krovak.js
  2596. ====================================================================== */
  2597. /**
  2598. NOTES: According to EPSG the full Krovak projection method should have
  2599. the following parameters. Within PROJ.4 the azimuth, and pseudo
  2600. standard parallel are hardcoded in the algorithm and can't be
  2601. altered from outside. The others all have defaults to match the
  2602. common usage with Krovak projection.
  2603. lat_0 = latitude of centre of the projection
  2604. lon_0 = longitude of centre of the projection
  2605. ** = azimuth (true) of the centre line passing through the centre of the projection
  2606. ** = latitude of pseudo standard parallel
  2607. k = scale factor on the pseudo standard parallel
  2608. x_0 = False Easting of the centre of the projection at the apex of the cone
  2609. y_0 = False Northing of the centre of the projection at the apex of the cone
  2610. **/
  2611. Proj4js.Proj.krovak = {
  2612. init: function() {
  2613. /* we want Bessel as fixed ellipsoid */
  2614. this.a = 6377397.155;
  2615. this.es = 0.006674372230614;
  2616. this.e = Math.sqrt(this.es);
  2617. /* if latitude of projection center is not set, use 49d30'N */
  2618. if (!this.lat0) {
  2619. this.lat0 = 0.863937979737193;
  2620. }
  2621. if (!this.long0) {
  2622. this.long0 = 0.7417649320975901 - 0.308341501185665;
  2623. }
  2624. /* if scale not set default to 0.9999 */
  2625. if (!this.k0) {
  2626. this.k0 = 0.9999;
  2627. }
  2628. this.s45 = 0.785398163397448; /* 45� */
  2629. this.s90 = 2 * this.s45;
  2630. this.fi0 = this.lat0; /* Latitude of projection centre 49� 30' */
  2631. /* Ellipsoid Bessel 1841 a = 6377397.155m 1/f = 299.1528128,
  2632. e2=0.006674372230614;
  2633. */
  2634. this.e2 = this.es; /* 0.006674372230614; */
  2635. this.e = Math.sqrt(this.e2);
  2636. this.alfa = Math.sqrt(1. + (this.e2 * Math.pow(Math.cos(this.fi0), 4)) / (1. - this.e2));
  2637. this.uq = 1.04216856380474; /* DU(2, 59, 42, 42.69689) */
  2638. this.u0 = Math.asin(Math.sin(this.fi0) / this.alfa);
  2639. this.g = Math.pow( (1. + this.e * Math.sin(this.fi0)) / (1. - this.e * Math.sin(this.fi0)) , this.alfa * this.e / 2. );
  2640. this.k = Math.tan( this.u0 / 2. + this.s45) / Math.pow (Math.tan(this.fi0 / 2. + this.s45) , this.alfa) * this.g;
  2641. this.k1 = this.k0;
  2642. this.n0 = this.a * Math.sqrt(1. - this.e2) / (1. - this.e2 * Math.pow(Math.sin(this.fi0), 2));
  2643. this.s0 = 1.37008346281555; /* Latitude of pseudo standard parallel 78� 30'00" N */
  2644. this.n = Math.sin(this.s0);
  2645. this.ro0 = this.k1 * this.n0 / Math.tan(this.s0);
  2646. this.ad = this.s90 - this.uq;
  2647. },
  2648. /* ellipsoid */
  2649. /* calculate xy from lat/lon */
  2650. /* Constants, identical to inverse transform function */
  2651. forward: function(p) {
  2652. var gfi, u, deltav, s, d, eps, ro;
  2653. var lon = p.x;
  2654. var lat = p.y;
  2655. var delta_lon = Proj4js.common.adjust_lon(lon - this.long0); // Delta longitude
  2656. /* Transformation */
  2657. gfi = Math.pow ( ((1. + this.e * Math.sin(lat)) / (1. - this.e * Math.sin(lat))) , (this.alfa * this.e / 2.));
  2658. u= 2. * (Math.atan(this.k * Math.pow( Math.tan(lat / 2. + this.s45), this.alfa) / gfi)-this.s45);
  2659. deltav = - delta_lon * this.alfa;
  2660. s = Math.asin(Math.cos(this.ad) * Math.sin(u) + Math.sin(this.ad) * Math.cos(u) * Math.cos(deltav));
  2661. d = Math.asin(Math.cos(u) * Math.sin(deltav) / Math.cos(s));
  2662. eps = this.n * d;
  2663. ro = this.ro0 * Math.pow(Math.tan(this.s0 / 2. + this.s45) , this.n) / Math.pow(Math.tan(s / 2. + this.s45) , this.n);
  2664. /* x and y are reverted! */
  2665. //p.y = ro * Math.cos(eps) / a;
  2666. //p.x = ro * Math.sin(eps) / a;
  2667. p.y = ro * Math.cos(eps) / 1.0;
  2668. p.x = ro * Math.sin(eps) / 1.0;
  2669. if(this.czech) {
  2670. p.y *= -1.0;
  2671. p.x *= -1.0;
  2672. }
  2673. return (p);
  2674. },
  2675. /* calculate lat/lon from xy */
  2676. inverse: function(p) {
  2677. /* Constants, identisch wie in der Umkehrfunktion */
  2678. var u, deltav, s, d, eps, ro, fi1;
  2679. var ok;
  2680. /* Transformation */
  2681. /* revert y, x*/
  2682. var tmp = p.x;
  2683. p.x=p.y;
  2684. p.y=tmp;
  2685. if(this.czech) {
  2686. p.y *= -1.0;
  2687. p.x *= -1.0;
  2688. }
  2689. ro = Math.sqrt(p.x * p.x + p.y * p.y);
  2690. eps = Math.atan2(p.y, p.x);
  2691. d = eps / Math.sin(this.s0);
  2692. s = 2. * (Math.atan( Math.pow(this.ro0 / ro, 1. / this.n) * Math.tan(this.s0 / 2. + this.s45)) - this.s45);
  2693. u = Math.asin(Math.cos(this.ad) * Math.sin(s) - Math.sin(this.ad) * Math.cos(s) * Math.cos(d));
  2694. deltav = Math.asin(Math.cos(s) * Math.sin(d) / Math.cos(u));
  2695. p.x = this.long0 - deltav / this.alfa;
  2696. /* ITERATION FOR lat */
  2697. fi1 = u;
  2698. ok = 0;
  2699. var iter = 0;
  2700. do {
  2701. p.y = 2. * ( Math.atan( Math.pow( this.k, -1. / this.alfa) *
  2702. Math.pow( Math.tan(u / 2. + this.s45) , 1. / this.alfa) *
  2703. Math.pow( (1. + this.e * Math.sin(fi1)) / (1. - this.e * Math.sin(fi1)) , this.e / 2.)
  2704. ) - this.s45);
  2705. if (Math.abs(fi1 - p.y) < 0.0000000001) ok=1;
  2706. fi1 = p.y;
  2707. iter += 1;
  2708. } while (ok==0 && iter < 15);
  2709. if (iter >= 15) {
  2710. Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations");
  2711. //console.log('iter:', iter);
  2712. return null;
  2713. }
  2714. return (p);
  2715. }
  2716. };
  2717. /* ======================================================================
  2718. projCode/somerc.js
  2719. ====================================================================== */
  2720. /*******************************************************************************
  2721. NAME SWISS OBLIQUE MERCATOR
  2722. PURPOSE: Swiss projection.
  2723. WARNING: X and Y are inverted (weird) in the swiss coordinate system. Not
  2724. here, since we want X to be horizontal and Y vertical.
  2725. ALGORITHM REFERENCES
  2726. 1. "Formules et constantes pour le Calcul pour la
  2727. projection cylindrique conforme à axe oblique et pour la transformation entre
  2728. des systèmes de référence".
  2729. http://www.swisstopo.admin.ch/internet/swisstopo/fr/home/topics/survey/sys/refsys/switzerland.parsysrelated1.31216.downloadList.77004.DownloadFile.tmp/swissprojectionfr.pdf
  2730. *******************************************************************************/
  2731. Proj4js.Proj.somerc = {
  2732. init: function() {
  2733. var phy0 = this.lat0;
  2734. this.lambda0 = this.long0;
  2735. var sinPhy0 = Math.sin(phy0);
  2736. var semiMajorAxis = this.a;
  2737. var invF = this.rf;
  2738. var flattening = 1 / invF;
  2739. var e2 = 2 * flattening - Math.pow(flattening, 2);
  2740. var e = this.e = Math.sqrt(e2);
  2741. this.R = this.k0 * semiMajorAxis * Math.sqrt(1 - e2) / (1 - e2 * Math.pow(sinPhy0, 2.0));
  2742. this.alpha = Math.sqrt(1 + e2 / (1 - e2) * Math.pow(Math.cos(phy0), 4.0));
  2743. this.b0 = Math.asin(sinPhy0 / this.alpha);
  2744. this.K = Math.log(Math.tan(Math.PI / 4.0 + this.b0 / 2.0))
  2745. - this.alpha
  2746. * Math.log(Math.tan(Math.PI / 4.0 + phy0 / 2.0))
  2747. + this.alpha
  2748. * e / 2
  2749. * Math.log((1 + e * sinPhy0)
  2750. / (1 - e * sinPhy0));
  2751. },
  2752. forward: function(p) {
  2753. var Sa1 = Math.log(Math.tan(Math.PI / 4.0 - p.y / 2.0));
  2754. var Sa2 = this.e / 2.0
  2755. * Math.log((1 + this.e * Math.sin(p.y))
  2756. / (1 - this.e * Math.sin(p.y)));
  2757. var S = -this.alpha * (Sa1 + Sa2) + this.K;
  2758. // spheric latitude
  2759. var b = 2.0 * (Math.atan(Math.exp(S)) - Math.PI / 4.0);
  2760. // spheric longitude
  2761. var I = this.alpha * (p.x - this.lambda0);
  2762. // psoeudo equatorial rotation
  2763. var rotI = Math.atan(Math.sin(I)
  2764. / (Math.sin(this.b0) * Math.tan(b) +
  2765. Math.cos(this.b0) * Math.cos(I)));
  2766. var rotB = Math.asin(Math.cos(this.b0) * Math.sin(b) -
  2767. Math.sin(this.b0) * Math.cos(b) * Math.cos(I));
  2768. p.y = this.R / 2.0
  2769. * Math.log((1 + Math.sin(rotB)) / (1 - Math.sin(rotB)))
  2770. + this.y0;
  2771. p.x = this.R * rotI + this.x0;
  2772. return p;
  2773. },
  2774. inverse: function(p) {
  2775. var Y = p.x - this.x0;
  2776. var X = p.y - this.y0;
  2777. var rotI = Y / this.R;
  2778. var rotB = 2 * (Math.atan(Math.exp(X / this.R)) - Math.PI / 4.0);
  2779. var b = Math.asin(Math.cos(this.b0) * Math.sin(rotB)
  2780. + Math.sin(this.b0) * Math.cos(rotB) * Math.cos(rotI));
  2781. var I = Math.atan(Math.sin(rotI)
  2782. / (Math.cos(this.b0) * Math.cos(rotI) - Math.sin(this.b0)
  2783. * Math.tan(rotB)));
  2784. var lambda = this.lambda0 + I / this.alpha;
  2785. var S = 0.0;
  2786. var phy = b;
  2787. var prevPhy = -1000.0;
  2788. var iteration = 0;
  2789. while (Math.abs(phy - prevPhy) > 0.0000001)
  2790. {
  2791. if (++iteration > 20)
  2792. {
  2793. Proj4js.reportError("omercFwdInfinity");
  2794. return;
  2795. }
  2796. //S = Math.log(Math.tan(Math.PI / 4.0 + phy / 2.0));
  2797. S = 1.0
  2798. / this.alpha
  2799. * (Math.log(Math.tan(Math.PI / 4.0 + b / 2.0)) - this.K)
  2800. + this.e
  2801. * Math.log(Math.tan(Math.PI / 4.0
  2802. + Math.asin(this.e * Math.sin(phy))
  2803. / 2.0));
  2804. prevPhy = phy;
  2805. phy = 2.0 * Math.atan(Math.exp(S)) - Math.PI / 2.0;
  2806. }
  2807. p.x = lambda;
  2808. p.y = phy;
  2809. return p;
  2810. }
  2811. };
  2812. /* ======================================================================
  2813. projCode/stere.js
  2814. ====================================================================== */
  2815. // Initialize the Stereographic projection
  2816. Proj4js.Proj.stere = {
  2817. ssfn_: function(phit, sinphi, eccen) {
  2818. sinphi *= eccen;
  2819. return (Math.tan (.5 * (Proj4js.common.HALF_PI + phit)) * Math.pow((1. - sinphi) / (1. + sinphi), .5 * eccen));
  2820. },
  2821. TOL: 1.e-8,
  2822. NITER: 8,
  2823. CONV: 1.e-10,
  2824. S_POLE: 0,
  2825. N_POLE: 1,
  2826. OBLIQ: 2,
  2827. EQUIT: 3,
  2828. init: function() {
  2829. this.phits = this.lat_ts ? this.lat_ts : Proj4js.common.HALF_PI;
  2830. var t = Math.abs(this.lat0);
  2831. if ((Math.abs(t) - Proj4js.common.HALF_PI) < Proj4js.common.EPSLN) {
  2832. this.mode = this.lat0 < 0. ? this.S_POLE : this.N_POLE;
  2833. } else {
  2834. this.mode = t > Proj4js.common.EPSLN ? this.OBLIQ : this.EQUIT;
  2835. }
  2836. this.phits = Math.abs(this.phits);
  2837. if (this.es) {
  2838. var X;
  2839. switch (this.mode) {
  2840. case this.N_POLE:
  2841. case this.S_POLE:
  2842. if (Math.abs(this.phits - Proj4js.common.HALF_PI) < Proj4js.common.EPSLN) {
  2843. this.akm1 = 2. * this.k0 / Math.sqrt(Math.pow(1+this.e,1+this.e)*Math.pow(1-this.e,1-this.e));
  2844. } else {
  2845. t = Math.sin(this.phits);
  2846. this.akm1 = Math.cos(this.phits) / Proj4js.common.tsfnz(this.e, this.phits, t);
  2847. t *= this.e;
  2848. this.akm1 /= Math.sqrt(1. - t * t);
  2849. }
  2850. break;
  2851. case this.EQUIT:
  2852. this.akm1 = 2. * this.k0;
  2853. break;
  2854. case this.OBLIQ:
  2855. t = Math.sin(this.lat0);
  2856. X = 2. * Math.atan(this.ssfn_(this.lat0, t, this.e)) - Proj4js.common.HALF_PI;
  2857. t *= this.e;
  2858. this.akm1 = 2. * this.k0 * Math.cos(this.lat0) / Math.sqrt(1. - t * t);
  2859. this.sinX1 = Math.sin(X);
  2860. this.cosX1 = Math.cos(X);
  2861. break;
  2862. }
  2863. } else {
  2864. switch (this.mode) {
  2865. case this.OBLIQ:
  2866. this.sinph0 = Math.sin(this.lat0);
  2867. this.cosph0 = Math.cos(this.lat0);
  2868. case this.EQUIT:
  2869. this.akm1 = 2. * this.k0;
  2870. break;
  2871. case this.S_POLE:
  2872. case this.N_POLE:
  2873. this.akm1 = Math.abs(this.phits - Proj4js.common.HALF_PI) >= Proj4js.common.EPSLN ?
  2874. Math.cos(this.phits) / Math.tan(Proj4js.common.FORTPI - .5 * this.phits) :
  2875. 2. * this.k0 ;
  2876. break;
  2877. }
  2878. }
  2879. },
  2880. // Stereographic forward equations--mapping lat,long to x,y
  2881. forward: function(p) {
  2882. var lon = p.x;
  2883. lon = Proj4js.common.adjust_lon(lon - this.long0);
  2884. var lat = p.y;
  2885. var x, y;
  2886. if (this.sphere) {
  2887. var sinphi, cosphi, coslam, sinlam;
  2888. sinphi = Math.sin(lat);
  2889. cosphi = Math.cos(lat);
  2890. coslam = Math.cos(lon);
  2891. sinlam = Math.sin(lon);
  2892. switch (this.mode) {
  2893. case this.EQUIT:
  2894. y = 1. + cosphi * coslam;
  2895. if (y <= Proj4js.common.EPSLN) {
  2896. Proj4js.reportError("stere:forward:Equit");
  2897. }
  2898. y = this.akm1 / y;
  2899. x = y * cosphi * sinlam;
  2900. y *= sinphi;
  2901. break;
  2902. case this.OBLIQ:
  2903. y = 1. + this.sinph0 * sinphi + this.cosph0 * cosphi * coslam;
  2904. if (y <= Proj4js.common.EPSLN) {
  2905. Proj4js.reportError("stere:forward:Obliq");
  2906. }
  2907. y = this.akm1 / y;
  2908. x = y * cosphi * sinlam;
  2909. y *= this.cosph0 * sinphi - this.sinph0 * cosphi * coslam;
  2910. break;
  2911. case this.N_POLE:
  2912. coslam = -coslam;
  2913. lat = -lat;
  2914. //Note no break here so it conitnues through S_POLE
  2915. case this.S_POLE:
  2916. if (Math.abs(lat - Proj4js.common.HALF_PI) < this.TOL) {
  2917. Proj4js.reportError("stere:forward:S_POLE");
  2918. }
  2919. y = this.akm1 * Math.tan(Proj4js.common.FORTPI + .5 * lat);
  2920. x = sinlam * y;
  2921. y *= coslam;
  2922. break;
  2923. }
  2924. } else {
  2925. coslam = Math.cos(lon);
  2926. sinlam = Math.sin(lon);
  2927. sinphi = Math.sin(lat);
  2928. var sinX, cosX;
  2929. if (this.mode == this.OBLIQ || this.mode == this.EQUIT) {
  2930. var Xt = 2. * Math.atan(this.ssfn_(lat, sinphi, this.e));
  2931. sinX = Math.sin(Xt - Proj4js.common.HALF_PI);
  2932. cosX = Math.cos(Xt);
  2933. }
  2934. switch (this.mode) {
  2935. case this.OBLIQ:
  2936. var A = this.akm1 / (this.cosX1 * (1. + this.sinX1 * sinX + this.cosX1 * cosX * coslam));
  2937. y = A * (this.cosX1 * sinX - this.sinX1 * cosX * coslam);
  2938. x = A * cosX;
  2939. break;
  2940. case this.EQUIT:
  2941. var A = 2. * this.akm1 / (1. + cosX * coslam);
  2942. y = A * sinX;
  2943. x = A * cosX;
  2944. break;
  2945. case this.S_POLE:
  2946. lat = -lat;
  2947. coslam = - coslam;
  2948. sinphi = -sinphi;
  2949. case this.N_POLE:
  2950. x = this.akm1 * Proj4js.common.tsfnz(this.e, lat, sinphi);
  2951. y = - x * coslam;
  2952. break;
  2953. }
  2954. x = x * sinlam;
  2955. }
  2956. p.x = x*this.a + this.x0;
  2957. p.y = y*this.a + this.y0;
  2958. return p;
  2959. },
  2960. //* Stereographic inverse equations--mapping x,y to lat/long
  2961. inverse: function(p) {
  2962. var x = (p.x - this.x0)/this.a; /* descale and de-offset */
  2963. var y = (p.y - this.y0)/this.a;
  2964. var lon, lat;
  2965. var cosphi, sinphi, tp=0.0, phi_l=0.0, rho, halfe=0.0, pi2=0.0;
  2966. var i;
  2967. if (this.sphere) {
  2968. var c, rh, sinc, cosc;
  2969. rh = Math.sqrt(x*x + y*y);
  2970. c = 2. * Math.atan(rh / this.akm1);
  2971. sinc = Math.sin(c);
  2972. cosc = Math.cos(c);
  2973. lon = 0.;
  2974. switch (this.mode) {
  2975. case this.EQUIT:
  2976. if (Math.abs(rh) <= Proj4js.common.EPSLN) {
  2977. lat = 0.;
  2978. } else {
  2979. lat = Math.asin(y * sinc / rh);
  2980. }
  2981. if (cosc != 0. || x != 0.) lon = Math.atan2(x * sinc, cosc * rh);
  2982. break;
  2983. case this.OBLIQ:
  2984. if (Math.abs(rh) <= Proj4js.common.EPSLN) {
  2985. lat = this.phi0;
  2986. } else {
  2987. lat = Math.asin(cosc * this.sinph0 + y * sinc * this.cosph0 / rh);
  2988. }
  2989. c = cosc - this.sinph0 * Math.sin(lat);
  2990. if (c != 0. || x != 0.) {
  2991. lon = Math.atan2(x * sinc * this.cosph0, c * rh);
  2992. }
  2993. break;
  2994. case this.N_POLE:
  2995. y = -y;
  2996. case this.S_POLE:
  2997. if (Math.abs(rh) <= Proj4js.common.EPSLN) {
  2998. lat = this.phi0;
  2999. } else {
  3000. lat = Math.asin(this.mode == this.S_POLE ? -cosc : cosc);
  3001. }
  3002. lon = (x == 0. && y == 0.) ? 0. : Math.atan2(x, y);
  3003. break;
  3004. }
  3005. p.x = Proj4js.common.adjust_lon(lon + this.long0);
  3006. p.y = lat;
  3007. } else {
  3008. rho = Math.sqrt(x*x + y*y);
  3009. switch (this.mode) {
  3010. case this.OBLIQ:
  3011. case this.EQUIT:
  3012. tp = 2. * Math.atan2(rho * this.cosX1 , this.akm1);
  3013. cosphi = Math.cos(tp);
  3014. sinphi = Math.sin(tp);
  3015. if( rho == 0.0 ) {
  3016. phi_l = Math.asin(cosphi * this.sinX1);
  3017. } else {
  3018. phi_l = Math.asin(cosphi * this.sinX1 + (y * sinphi * this.cosX1 / rho));
  3019. }
  3020. tp = Math.tan(.5 * (Proj4js.common.HALF_PI + phi_l));
  3021. x *= sinphi;
  3022. y = rho * this.cosX1 * cosphi - y * this.sinX1* sinphi;
  3023. pi2 = Proj4js.common.HALF_PI;
  3024. halfe = .5 * this.e;
  3025. break;
  3026. case this.N_POLE:
  3027. y = -y;
  3028. case this.S_POLE:
  3029. tp = - rho / this.akm1;
  3030. phi_l = Proj4js.common.HALF_PI - 2. * Math.atan(tp);
  3031. pi2 = -Proj4js.common.HALF_PI;
  3032. halfe = -.5 * this.e;
  3033. break;
  3034. }
  3035. for (i = this.NITER; i--; phi_l = lat) { //check this
  3036. sinphi = this.e * Math.sin(phi_l);
  3037. lat = 2. * Math.atan(tp * Math.pow((1.+sinphi)/(1.-sinphi), halfe)) - pi2;
  3038. if (Math.abs(phi_l - lat) < this.CONV) {
  3039. if (this.mode == this.S_POLE) lat = -lat;
  3040. lon = (x == 0. && y == 0.) ? 0. : Math.atan2(x, y);
  3041. p.x = Proj4js.common.adjust_lon(lon + this.long0);
  3042. p.y = lat;
  3043. return p;
  3044. }
  3045. }
  3046. }
  3047. }
  3048. };
  3049. /* ======================================================================
  3050. projCode/nzmg.js
  3051. ====================================================================== */
  3052. /*******************************************************************************
  3053. NAME NEW ZEALAND MAP GRID
  3054. PURPOSE: Transforms input longitude and latitude to Easting and
  3055. Northing for the New Zealand Map Grid projection. The
  3056. longitude and latitude must be in radians. The Easting
  3057. and Northing values will be returned in meters.
  3058. ALGORITHM REFERENCES
  3059. 1. Department of Land and Survey Technical Circular 1973/32
  3060. http://www.linz.govt.nz/docs/miscellaneous/nz-map-definition.pdf
  3061. 2. OSG Technical Report 4.1
  3062. http://www.linz.govt.nz/docs/miscellaneous/nzmg.pdf
  3063. IMPLEMENTATION NOTES
  3064. The two references use different symbols for the calculated values. This
  3065. implementation uses the variable names similar to the symbols in reference [1].
  3066. The alogrithm uses different units for delta latitude and delta longitude.
  3067. The delta latitude is assumed to be in units of seconds of arc x 10^-5.
  3068. The delta longitude is the usual radians. Look out for these conversions.
  3069. The algorithm is described using complex arithmetic. There were three
  3070. options:
  3071. * find and use a Javascript library for complex arithmetic
  3072. * write my own complex library
  3073. * expand the complex arithmetic by hand to simple arithmetic
  3074. This implementation has expanded the complex multiplication operations
  3075. into parallel simple arithmetic operations for the real and imaginary parts.
  3076. The imaginary part is way over to the right of the display; this probably
  3077. violates every coding standard in the world, but, to me, it makes it much
  3078. more obvious what is going on.
  3079. The following complex operations are used:
  3080. - addition
  3081. - multiplication
  3082. - division
  3083. - complex number raised to integer power
  3084. - summation
  3085. A summary of complex arithmetic operations:
  3086. (from http://en.wikipedia.org/wiki/Complex_arithmetic)
  3087. addition: (a + bi) + (c + di) = (a + c) + (b + d)i
  3088. subtraction: (a + bi) - (c + di) = (a - c) + (b - d)i
  3089. multiplication: (a + bi) x (c + di) = (ac - bd) + (bc + ad)i
  3090. division: (a + bi) / (c + di) = [(ac + bd)/(cc + dd)] + [(bc - ad)/(cc + dd)]i
  3091. The algorithm needs to calculate summations of simple and complex numbers. This is
  3092. implemented using a for-loop, pre-loading the summed value to zero.
  3093. The algorithm needs to calculate theta^2, theta^3, etc while doing a summation.
  3094. There are three possible implementations:
  3095. - use Math.pow in the summation loop - except for complex numbers
  3096. - precalculate the values before running the loop
  3097. - calculate theta^n = theta^(n-1) * theta during the loop
  3098. This implementation uses the third option for both real and complex arithmetic.
  3099. For example
  3100. psi_n = 1;
  3101. sum = 0;
  3102. for (n = 1; n <=6; n++) {
  3103. psi_n1 = psi_n * psi; // calculate psi^(n+1)
  3104. psi_n = psi_n1;
  3105. sum = sum + A[n] * psi_n;
  3106. }
  3107. TEST VECTORS
  3108. NZMG E, N: 2487100.638 6751049.719 metres
  3109. NZGD49 long, lat: 172.739194 -34.444066 degrees
  3110. NZMG E, N: 2486533.395 6077263.661 metres
  3111. NZGD49 long, lat: 172.723106 -40.512409 degrees
  3112. NZMG E, N: 2216746.425 5388508.765 metres
  3113. NZGD49 long, lat: 169.172062 -46.651295 degrees
  3114. Note that these test vectors convert from NZMG metres to lat/long referenced
  3115. to NZGD49, not the more usual WGS84. The difference is about 70m N/S and about
  3116. 10m E/W.
  3117. These test vectors are provided in reference [1]. Many more test
  3118. vectors are available in
  3119. http://www.linz.govt.nz/docs/topography/topographicdata/placenamesdatabase/nznamesmar08.zip
  3120. which is a catalog of names on the 260-series maps.
  3121. EPSG CODES
  3122. NZMG EPSG:27200
  3123. NZGD49 EPSG:4272
  3124. http://spatialreference.org/ defines these as
  3125. Proj4js.defs["EPSG:4272"] = "+proj=longlat +ellps=intl +datum=nzgd49 +no_defs ";
  3126. 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 ";
  3127. LICENSE
  3128. Copyright: Stephen Irons 2008
  3129. Released under terms of the LGPL as per: http://www.gnu.org/copyleft/lesser.html
  3130. *******************************************************************************/
  3131. /**
  3132. Initialize New Zealand Map Grip projection
  3133. */
  3134. Proj4js.Proj.nzmg = {
  3135. /**
  3136. * iterations: Number of iterations to refine inverse transform.
  3137. * 0 -> km accuracy
  3138. * 1 -> m accuracy -- suitable for most mapping applications
  3139. * 2 -> mm accuracy
  3140. */
  3141. iterations: 1,
  3142. init : function() {
  3143. this.A = new Array();
  3144. this.A[1] = +0.6399175073;
  3145. this.A[2] = -0.1358797613;
  3146. this.A[3] = +0.063294409;
  3147. this.A[4] = -0.02526853;
  3148. this.A[5] = +0.0117879;
  3149. this.A[6] = -0.0055161;
  3150. this.A[7] = +0.0026906;
  3151. this.A[8] = -0.001333;
  3152. this.A[9] = +0.00067;
  3153. this.A[10] = -0.00034;
  3154. this.B_re = new Array(); this.B_im = new Array();
  3155. this.B_re[1] = +0.7557853228; this.B_im[1] = 0.0;
  3156. this.B_re[2] = +0.249204646; this.B_im[2] = +0.003371507;
  3157. this.B_re[3] = -0.001541739; this.B_im[3] = +0.041058560;
  3158. this.B_re[4] = -0.10162907; this.B_im[4] = +0.01727609;
  3159. this.B_re[5] = -0.26623489; this.B_im[5] = -0.36249218;
  3160. this.B_re[6] = -0.6870983; this.B_im[6] = -1.1651967;
  3161. this.C_re = new Array(); this.C_im = new Array();
  3162. this.C_re[1] = +1.3231270439; this.C_im[1] = 0.0;
  3163. this.C_re[2] = -0.577245789; this.C_im[2] = -0.007809598;
  3164. this.C_re[3] = +0.508307513; this.C_im[3] = -0.112208952;
  3165. this.C_re[4] = -0.15094762; this.C_im[4] = +0.18200602;
  3166. this.C_re[5] = +1.01418179; this.C_im[5] = +1.64497696;
  3167. this.C_re[6] = +1.9660549; this.C_im[6] = +2.5127645;
  3168. this.D = new Array();
  3169. this.D[1] = +1.5627014243;
  3170. this.D[2] = +0.5185406398;
  3171. this.D[3] = -0.03333098;
  3172. this.D[4] = -0.1052906;
  3173. this.D[5] = -0.0368594;
  3174. this.D[6] = +0.007317;
  3175. this.D[7] = +0.01220;
  3176. this.D[8] = +0.00394;
  3177. this.D[9] = -0.0013;
  3178. },
  3179. /**
  3180. New Zealand Map Grid Forward - long/lat to x/y
  3181. long/lat in radians
  3182. */
  3183. forward : function(p) {
  3184. var lon = p.x;
  3185. var lat = p.y;
  3186. var delta_lat = lat - this.lat0;
  3187. var delta_lon = lon - this.long0;
  3188. // 1. Calculate d_phi and d_psi ... // and d_lambda
  3189. // For this algorithm, delta_latitude is in seconds of arc x 10-5, so we need to scale to those units. Longitude is radians.
  3190. var d_phi = delta_lat / Proj4js.common.SEC_TO_RAD * 1E-5; var d_lambda = delta_lon;
  3191. var d_phi_n = 1; // d_phi^0
  3192. var d_psi = 0;
  3193. for (var n = 1; n <= 10; n++) {
  3194. d_phi_n = d_phi_n * d_phi;
  3195. d_psi = d_psi + this.A[n] * d_phi_n;
  3196. }
  3197. // 2. Calculate theta
  3198. var th_re = d_psi; var th_im = d_lambda;
  3199. // 3. Calculate z
  3200. var th_n_re = 1; var th_n_im = 0; // theta^0
  3201. var th_n_re1; var th_n_im1;
  3202. var z_re = 0; var z_im = 0;
  3203. for (var n = 1; n <= 6; n++) {
  3204. 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;
  3205. th_n_re = th_n_re1; th_n_im = th_n_im1;
  3206. 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;
  3207. }
  3208. // 4. Calculate easting and northing
  3209. p.x = (z_im * this.a) + this.x0;
  3210. p.y = (z_re * this.a) + this.y0;
  3211. return p;
  3212. },
  3213. /**
  3214. New Zealand Map Grid Inverse - x/y to long/lat
  3215. */
  3216. inverse : function(p) {
  3217. var x = p.x;
  3218. var y = p.y;
  3219. var delta_x = x - this.x0;
  3220. var delta_y = y - this.y0;
  3221. // 1. Calculate z
  3222. var z_re = delta_y / this.a; var z_im = delta_x / this.a;
  3223. // 2a. Calculate theta - first approximation gives km accuracy
  3224. var z_n_re = 1; var z_n_im = 0; // z^0
  3225. var z_n_re1; var z_n_im1;
  3226. var th_re = 0; var th_im = 0;
  3227. for (var n = 1; n <= 6; n++) {
  3228. 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;
  3229. z_n_re = z_n_re1; z_n_im = z_n_im1;
  3230. 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;
  3231. }
  3232. // 2b. Iterate to refine the accuracy of the calculation
  3233. // 0 iterations gives km accuracy
  3234. // 1 iteration gives m accuracy -- good enough for most mapping applications
  3235. // 2 iterations bives mm accuracy
  3236. for (var i = 0; i < this.iterations; i++) {
  3237. var th_n_re = th_re; var th_n_im = th_im;
  3238. var th_n_re1; var th_n_im1;
  3239. var num_re = z_re; var num_im = z_im;
  3240. for (var n = 2; n <= 6; n++) {
  3241. 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;
  3242. th_n_re = th_n_re1; th_n_im = th_n_im1;
  3243. 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);
  3244. }
  3245. th_n_re = 1; th_n_im = 0;
  3246. var den_re = this.B_re[1]; var den_im = this.B_im[1];
  3247. for (var n = 2; n <= 6; n++) {
  3248. 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;
  3249. th_n_re = th_n_re1; th_n_im = th_n_im1;
  3250. 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);
  3251. }
  3252. // Complex division
  3253. var den2 = den_re*den_re + den_im*den_im;
  3254. th_re = (num_re*den_re + num_im*den_im) / den2; th_im = (num_im*den_re - num_re*den_im) / den2;
  3255. }
  3256. // 3. Calculate d_phi ... // and d_lambda
  3257. var d_psi = th_re; var d_lambda = th_im;
  3258. var d_psi_n = 1; // d_psi^0
  3259. var d_phi = 0;
  3260. for (var n = 1; n <= 9; n++) {
  3261. d_psi_n = d_psi_n * d_psi;
  3262. d_phi = d_phi + this.D[n] * d_psi_n;
  3263. }
  3264. // 4. Calculate latitude and longitude
  3265. // d_phi is calcuated in second of arc * 10^-5, so we need to scale back to radians. d_lambda is in radians.
  3266. var lat = this.lat0 + (d_phi * Proj4js.common.SEC_TO_RAD * 1E5);
  3267. var lon = this.long0 + d_lambda;
  3268. p.x = lon;
  3269. p.y = lat;
  3270. return p;
  3271. }
  3272. };
  3273. /* ======================================================================
  3274. projCode/mill.js
  3275. ====================================================================== */
  3276. /*******************************************************************************
  3277. NAME MILLER CYLINDRICAL
  3278. PURPOSE: Transforms input longitude and latitude to Easting and
  3279. Northing for the Miller Cylindrical projection. The
  3280. longitude and latitude must be in radians. The Easting
  3281. and Northing values will be returned in meters.
  3282. PROGRAMMER DATE
  3283. ---------- ----
  3284. T. Mittan March, 1993
  3285. This function was adapted from the Lambert Azimuthal Equal Area projection
  3286. code (FORTRAN) in the General Cartographic Transformation Package software
  3287. which is available from the U.S. Geological Survey National Mapping Division.
  3288. ALGORITHM REFERENCES
  3289. 1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder,
  3290. The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355.
  3291. 2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  3292. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  3293. State Government Printing Office, Washington D.C., 1987.
  3294. 3. "Software Documentation for GCTP General Cartographic Transformation
  3295. Package", U.S. Geological Survey National Mapping Division, May 1982.
  3296. *******************************************************************************/
  3297. Proj4js.Proj.mill = {
  3298. /* Initialize the Miller Cylindrical projection
  3299. -------------------------------------------*/
  3300. init: function() {
  3301. //no-op
  3302. },
  3303. /* Miller Cylindrical forward equations--mapping lat,long to x,y
  3304. ------------------------------------------------------------*/
  3305. forward: function(p) {
  3306. var lon=p.x;
  3307. var lat=p.y;
  3308. /* Forward equations
  3309. -----------------*/
  3310. var dlon = Proj4js.common.adjust_lon(lon -this.long0);
  3311. var x = this.x0 + this.a * dlon;
  3312. var y = this.y0 + this.a * Math.log(Math.tan((Proj4js.common.PI / 4.0) + (lat / 2.5))) * 1.25;
  3313. p.x=x;
  3314. p.y=y;
  3315. return p;
  3316. },//millFwd()
  3317. /* Miller Cylindrical inverse equations--mapping x,y to lat/long
  3318. ------------------------------------------------------------*/
  3319. inverse: function(p) {
  3320. p.x -= this.x0;
  3321. p.y -= this.y0;
  3322. var lon = Proj4js.common.adjust_lon(this.long0 + p.x /this.a);
  3323. var lat = 2.5 * (Math.atan(Math.exp(0.8*p.y/this.a)) - Proj4js.common.PI / 4.0);
  3324. p.x=lon;
  3325. p.y=lat;
  3326. return p;
  3327. }//millInv()
  3328. };
  3329. /* ======================================================================
  3330. projCode/gnom.js
  3331. ====================================================================== */
  3332. /*****************************************************************************
  3333. NAME GNOMONIC
  3334. PURPOSE: Transforms input longitude and latitude to Easting and
  3335. Northing for the Gnomonic Projection.
  3336. Implementation based on the existing sterea and ortho
  3337. implementations.
  3338. PROGRAMMER DATE
  3339. ---------- ----
  3340. Richard Marsden November 2009
  3341. ALGORITHM REFERENCES
  3342. 1. Snyder, John P., "Flattening the Earth - Two Thousand Years of Map
  3343. Projections", University of Chicago Press 1993
  3344. 2. Wolfram Mathworld "Gnomonic Projection"
  3345. http://mathworld.wolfram.com/GnomonicProjection.html
  3346. Accessed: 12th November 2009
  3347. ******************************************************************************/
  3348. Proj4js.Proj.gnom = {
  3349. /* Initialize the Gnomonic projection
  3350. -------------------------------------*/
  3351. init: function(def) {
  3352. /* Place parameters in static storage for common use
  3353. -------------------------------------------------*/
  3354. this.sin_p14=Math.sin(this.lat0);
  3355. this.cos_p14=Math.cos(this.lat0);
  3356. // Approximation for projecting points to the horizon (infinity)
  3357. this.infinity_dist = 1000 * this.a;
  3358. this.rc = 1;
  3359. },
  3360. /* Gnomonic forward equations--mapping lat,long to x,y
  3361. ---------------------------------------------------*/
  3362. forward: function(p) {
  3363. var sinphi, cosphi; /* sin and cos value */
  3364. var dlon; /* delta longitude value */
  3365. var coslon; /* cos of longitude */
  3366. var ksp; /* scale factor */
  3367. var g;
  3368. var x, y;
  3369. var lon=p.x;
  3370. var lat=p.y;
  3371. /* Forward equations
  3372. -----------------*/
  3373. dlon = Proj4js.common.adjust_lon(lon - this.long0);
  3374. sinphi=Math.sin(lat);
  3375. cosphi=Math.cos(lat);
  3376. coslon = Math.cos(dlon);
  3377. g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon;
  3378. ksp = 1.0;
  3379. if ((g > 0) || (Math.abs(g) <= Proj4js.common.EPSLN)) {
  3380. x = this.x0 + this.a * ksp * cosphi * Math.sin(dlon) / g;
  3381. y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon) / g;
  3382. } else {
  3383. Proj4js.reportError("orthoFwdPointError");
  3384. // Point is in the opposing hemisphere and is unprojectable
  3385. // We still need to return a reasonable point, so we project
  3386. // to infinity, on a bearing
  3387. // equivalent to the northern hemisphere equivalent
  3388. // This is a reasonable approximation for short shapes and lines that
  3389. // straddle the horizon.
  3390. x = this.x0 + this.infinity_dist * cosphi * Math.sin(dlon);
  3391. y = this.y0 + this.infinity_dist * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon);
  3392. }
  3393. p.x=x;
  3394. p.y=y;
  3395. return p;
  3396. },
  3397. inverse: function(p) {
  3398. var rh; /* Rho */
  3399. var z; /* angle */
  3400. var sinc, cosc;
  3401. var c;
  3402. var lon , lat;
  3403. /* Inverse equations
  3404. -----------------*/
  3405. p.x = (p.x - this.x0) / this.a;
  3406. p.y = (p.y - this.y0) / this.a;
  3407. p.x /= this.k0;
  3408. p.y /= this.k0;
  3409. if ( (rh = Math.sqrt(p.x * p.x + p.y * p.y)) ) {
  3410. c = Math.atan2(rh, this.rc);
  3411. sinc = Math.sin(c);
  3412. cosc = Math.cos(c);
  3413. lat = Proj4js.common.asinz(cosc*this.sin_p14 + (p.y*sinc*this.cos_p14) / rh);
  3414. lon = Math.atan2(p.x*sinc, rh*this.cos_p14*cosc - p.y*this.sin_p14*sinc);
  3415. lon = Proj4js.common.adjust_lon(this.long0+lon);
  3416. } else {
  3417. lat = this.phic0;
  3418. lon = 0.0;
  3419. }
  3420. p.x=lon;
  3421. p.y=lat;
  3422. return p;
  3423. }
  3424. };
  3425. /* ======================================================================
  3426. projCode/sinu.js
  3427. ====================================================================== */
  3428. /*******************************************************************************
  3429. NAME SINUSOIDAL
  3430. PURPOSE: Transforms input longitude and latitude to Easting and
  3431. Northing for the Sinusoidal projection. The
  3432. longitude and latitude must be in radians. The Easting
  3433. and Northing values will be returned in meters.
  3434. PROGRAMMER DATE
  3435. ---------- ----
  3436. D. Steinwand, EROS May, 1991
  3437. This function was adapted from the Sinusoidal projection code (FORTRAN) in the
  3438. General Cartographic Transformation Package software which is available from
  3439. the U.S. Geological Survey National Mapping Division.
  3440. ALGORITHM REFERENCES
  3441. 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  3442. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  3443. State Government Printing Office, Washington D.C., 1987.
  3444. 2. "Software Documentation for GCTP General Cartographic Transformation
  3445. Package", U.S. Geological Survey National Mapping Division, May 1982.
  3446. *******************************************************************************/
  3447. Proj4js.Proj.sinu = {
  3448. /* Initialize the Sinusoidal projection
  3449. ------------------------------------*/
  3450. init: function() {
  3451. /* Place parameters in static storage for common use
  3452. -------------------------------------------------*/
  3453. if (!this.sphere) {
  3454. this.en = Proj4js.common.pj_enfn(this.es);
  3455. } else {
  3456. this.n = 1.;
  3457. this.m = 0.;
  3458. this.es = 0;
  3459. this.C_y = Math.sqrt((this.m + 1.) / this.n);
  3460. this.C_x = this.C_y/(this.m + 1.);
  3461. }
  3462. },
  3463. /* Sinusoidal forward equations--mapping lat,long to x,y
  3464. -----------------------------------------------------*/
  3465. forward: function(p) {
  3466. var x,y,delta_lon;
  3467. var lon=p.x;
  3468. var lat=p.y;
  3469. /* Forward equations
  3470. -----------------*/
  3471. lon = Proj4js.common.adjust_lon(lon - this.long0);
  3472. if (this.sphere) {
  3473. if (!this.m) {
  3474. lat = this.n != 1. ? Math.asin(this.n * Math.sin(lat)): lat;
  3475. } else {
  3476. var k = this.n * Math.sin(lat);
  3477. for (var i = Proj4js.common.MAX_ITER; i ; --i) {
  3478. var V = (this.m * lat + Math.sin(lat) - k) / (this.m + Math.cos(lat));
  3479. lat -= V;
  3480. if (Math.abs(V) < Proj4js.common.EPSLN) break;
  3481. }
  3482. }
  3483. x = this.a * this.C_x * lon * (this.m + Math.cos(lat));
  3484. y = this.a * this.C_y * lat;
  3485. } else {
  3486. var s = Math.sin(lat);
  3487. var c = Math.cos(lat);
  3488. y = this.a * Proj4js.common.pj_mlfn(lat, s, c, this.en);
  3489. x = this.a * lon * c / Math.sqrt(1. - this.es * s * s);
  3490. }
  3491. p.x=x;
  3492. p.y=y;
  3493. return p;
  3494. },
  3495. inverse: function(p) {
  3496. var lat,temp,lon;
  3497. /* Inverse equations
  3498. -----------------*/
  3499. p.x -= this.x0;
  3500. p.y -= this.y0;
  3501. lat = p.y / this.a;
  3502. if (this.sphere) {
  3503. p.y /= this.C_y;
  3504. lat = this.m ? Math.asin((this.m * p.y + Math.sin(p.y)) / this.n) :
  3505. ( this.n != 1. ? Math.asin(Math.sin(p.y) / this.n) : p.y );
  3506. lon = p.x / (this.C_x * (this.m + Math.cos(p.y)));
  3507. } else {
  3508. lat = Proj4js.common.pj_inv_mlfn(p.y/this.a, this.es, this.en)
  3509. var s = Math.abs(lat);
  3510. if (s < Proj4js.common.HALF_PI) {
  3511. s = Math.sin(lat);
  3512. temp = this.long0 + p.x * Math.sqrt(1. - this.es * s * s) /(this.a * Math.cos(lat));
  3513. //temp = this.long0 + p.x / (this.a * Math.cos(lat));
  3514. lon = Proj4js.common.adjust_lon(temp);
  3515. } else if ((s - Proj4js.common.EPSLN) < Proj4js.common.HALF_PI) {
  3516. lon = this.long0;
  3517. }
  3518. }
  3519. p.x=lon;
  3520. p.y=lat;
  3521. return p;
  3522. }
  3523. };
  3524. /* ======================================================================
  3525. projCode/vandg.js
  3526. ====================================================================== */
  3527. /*******************************************************************************
  3528. NAME VAN DER GRINTEN
  3529. PURPOSE: Transforms input Easting and Northing to longitude and
  3530. latitude for the Van der Grinten projection. The
  3531. Easting and Northing must be in meters. The longitude
  3532. and latitude values will be returned in radians.
  3533. PROGRAMMER DATE
  3534. ---------- ----
  3535. T. Mittan March, 1993
  3536. This function was adapted from the Van Der Grinten projection code
  3537. (FORTRAN) in the General Cartographic Transformation Package software
  3538. which is available from the U.S. Geological Survey National Mapping Division.
  3539. ALGORITHM REFERENCES
  3540. 1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder,
  3541. The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355.
  3542. 2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  3543. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  3544. State Government Printing Office, Washington D.C., 1987.
  3545. 3. "Software Documentation for GCTP General Cartographic Transformation
  3546. Package", U.S. Geological Survey National Mapping Division, May 1982.
  3547. *******************************************************************************/
  3548. Proj4js.Proj.vandg = {
  3549. /* Initialize the Van Der Grinten projection
  3550. ----------------------------------------*/
  3551. init: function() {
  3552. this.R = 6370997.0; //Radius of earth
  3553. },
  3554. forward: function(p) {
  3555. var lon=p.x;
  3556. var lat=p.y;
  3557. /* Forward equations
  3558. -----------------*/
  3559. var dlon = Proj4js.common.adjust_lon(lon - this.long0);
  3560. var x,y;
  3561. if (Math.abs(lat) <= Proj4js.common.EPSLN) {
  3562. x = this.x0 + this.R * dlon;
  3563. y = this.y0;
  3564. }
  3565. var theta = Proj4js.common.asinz(2.0 * Math.abs(lat / Proj4js.common.PI));
  3566. if ((Math.abs(dlon) <= Proj4js.common.EPSLN) || (Math.abs(Math.abs(lat) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN)) {
  3567. x = this.x0;
  3568. if (lat >= 0) {
  3569. y = this.y0 + Proj4js.common.PI * this.R * Math.tan(.5 * theta);
  3570. } else {
  3571. y = this.y0 + Proj4js.common.PI * this.R * - Math.tan(.5 * theta);
  3572. }
  3573. // return(OK);
  3574. }
  3575. var al = .5 * Math.abs((Proj4js.common.PI / dlon) - (dlon / Proj4js.common.PI));
  3576. var asq = al * al;
  3577. var sinth = Math.sin(theta);
  3578. var costh = Math.cos(theta);
  3579. var g = costh / (sinth + costh - 1.0);
  3580. var gsq = g * g;
  3581. var m = g * (2.0 / sinth - 1.0);
  3582. var msq = m * m;
  3583. var con = Proj4js.common.PI * this.R * (al * (g - msq) + Math.sqrt(asq * (g - msq) * (g - msq) - (msq + asq) * (gsq - msq))) / (msq + asq);
  3584. if (dlon < 0) {
  3585. con = -con;
  3586. }
  3587. x = this.x0 + con;
  3588. con = Math.abs(con / (Proj4js.common.PI * this.R));
  3589. if (lat >= 0) {
  3590. y = this.y0 + Proj4js.common.PI * this.R * Math.sqrt(1.0 - con * con - 2.0 * al * con);
  3591. } else {
  3592. y = this.y0 - Proj4js.common.PI * this.R * Math.sqrt(1.0 - con * con - 2.0 * al * con);
  3593. }
  3594. p.x = x;
  3595. p.y = y;
  3596. return p;
  3597. },
  3598. /* Van Der Grinten inverse equations--mapping x,y to lat/long
  3599. ---------------------------------------------------------*/
  3600. inverse: function(p) {
  3601. var lon, lat;
  3602. var xx,yy,xys,c1,c2,c3;
  3603. var al,asq;
  3604. var a1;
  3605. var m1;
  3606. var con;
  3607. var th1;
  3608. var d;
  3609. /* inverse equations
  3610. -----------------*/
  3611. p.x -= this.x0;
  3612. p.y -= this.y0;
  3613. con = Proj4js.common.PI * this.R;
  3614. xx = p.x / con;
  3615. yy =p.y / con;
  3616. xys = xx * xx + yy * yy;
  3617. c1 = -Math.abs(yy) * (1.0 + xys);
  3618. c2 = c1 - 2.0 * yy * yy + xx * xx;
  3619. c3 = -2.0 * c1 + 1.0 + 2.0 * yy * yy + xys * xys;
  3620. d = yy * yy / c3 + (2.0 * c2 * c2 * c2 / c3 / c3 / c3 - 9.0 * c1 * c2 / c3 /c3) / 27.0;
  3621. a1 = (c1 - c2 * c2 / 3.0 / c3) / c3;
  3622. m1 = 2.0 * Math.sqrt( -a1 / 3.0);
  3623. con = ((3.0 * d) / a1) / m1;
  3624. if (Math.abs(con) > 1.0) {
  3625. if (con >= 0.0) {
  3626. con = 1.0;
  3627. } else {
  3628. con = -1.0;
  3629. }
  3630. }
  3631. th1 = Math.acos(con) / 3.0;
  3632. if (p.y >= 0) {
  3633. lat = (-m1 *Math.cos(th1 + Proj4js.common.PI / 3.0) - c2 / 3.0 / c3) * Proj4js.common.PI;
  3634. } else {
  3635. lat = -(-m1 * Math.cos(th1 + Proj4js.common.PI / 3.0) - c2 / 3.0 / c3) * Proj4js.common.PI;
  3636. }
  3637. if (Math.abs(xx) < Proj4js.common.EPSLN) {
  3638. lon = this.long0;
  3639. }
  3640. 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);
  3641. p.x=lon;
  3642. p.y=lat;
  3643. return p;
  3644. }
  3645. };
  3646. /* ======================================================================
  3647. projCode/cea.js
  3648. ====================================================================== */
  3649. /*******************************************************************************
  3650. NAME LAMBERT CYLINDRICAL EQUAL AREA
  3651. PURPOSE: Transforms input longitude and latitude to Easting and
  3652. Northing for the Lambert Cylindrical Equal Area projection.
  3653. This class of projection includes the Behrmann and
  3654. Gall-Peters Projections. The
  3655. longitude and latitude must be in radians. The Easting
  3656. and Northing values will be returned in meters.
  3657. PROGRAMMER DATE
  3658. ---------- ----
  3659. R. Marsden August 2009
  3660. Winwaed Software Tech LLC, http://www.winwaed.com
  3661. This function was adapted from the Miller Cylindrical Projection in the Proj4JS
  3662. library.
  3663. Note: This implementation assumes a Spherical Earth. The (commented) code
  3664. has been included for the ellipsoidal forward transform, but derivation of
  3665. the ellispoidal inverse transform is beyond me. Note that most of the
  3666. Proj4JS implementations do NOT currently support ellipsoidal figures.
  3667. Therefore this is not seen as a problem - especially this lack of support
  3668. is explicitly stated here.
  3669. ALGORITHM REFERENCES
  3670. 1. "Cartographic Projection Procedures for the UNIX Environment -
  3671. A User's Manual" by Gerald I. Evenden, USGS Open File Report 90-284
  3672. and Release 4 Interim Reports (2003)
  3673. 2. Snyder, John P., "Flattening the Earth - Two Thousand Years of Map
  3674. Projections", Univ. Chicago Press, 1993
  3675. *******************************************************************************/
  3676. Proj4js.Proj.cea = {
  3677. /* Initialize the Cylindrical Equal Area projection
  3678. -------------------------------------------*/
  3679. init: function() {
  3680. //no-op
  3681. },
  3682. /* Cylindrical Equal Area forward equations--mapping lat,long to x,y
  3683. ------------------------------------------------------------*/
  3684. forward: function(p) {
  3685. var lon=p.x;
  3686. var lat=p.y;
  3687. /* Forward equations
  3688. -----------------*/
  3689. var dlon = Proj4js.common.adjust_lon(lon -this.long0);
  3690. var x = this.x0 + this.a * dlon * Math.cos(this.lat_ts);
  3691. var y = this.y0 + this.a * Math.sin(lat) / Math.cos(this.lat_ts);
  3692. /* Elliptical Forward Transform
  3693. Not implemented due to a lack of a matchign inverse function
  3694. {
  3695. var Sin_Lat = Math.sin(lat);
  3696. var Rn = this.a * (Math.sqrt(1.0e0 - this.es * Sin_Lat * Sin_Lat ));
  3697. x = this.x0 + this.a * dlon * Math.cos(this.lat_ts);
  3698. y = this.y0 + Rn * Math.sin(lat) / Math.cos(this.lat_ts);
  3699. }
  3700. */
  3701. p.x=x;
  3702. p.y=y;
  3703. return p;
  3704. },//ceaFwd()
  3705. /* Cylindrical Equal Area inverse equations--mapping x,y to lat/long
  3706. ------------------------------------------------------------*/
  3707. inverse: function(p) {
  3708. p.x -= this.x0;
  3709. p.y -= this.y0;
  3710. var lon = Proj4js.common.adjust_lon( this.long0 + (p.x / this.a) / Math.cos(this.lat_ts) );
  3711. var lat = Math.asin( (p.y/this.a) * Math.cos(this.lat_ts) );
  3712. p.x=lon;
  3713. p.y=lat;
  3714. return p;
  3715. }//ceaInv()
  3716. };
  3717. /* ======================================================================
  3718. projCode/eqc.js
  3719. ====================================================================== */
  3720. /* similar to equi.js FIXME proj4 uses eqc */
  3721. Proj4js.Proj.eqc = {
  3722. init : function() {
  3723. if(!this.x0) this.x0=0;
  3724. if(!this.y0) this.y0=0;
  3725. if(!this.lat0) this.lat0=0;
  3726. if(!this.long0) this.long0=0;
  3727. if(!this.lat_ts) this.lat_ts=0;
  3728. if (!this.title) this.title = "Equidistant Cylindrical (Plate Carre)";
  3729. this.rc= Math.cos(this.lat_ts);
  3730. },
  3731. // forward equations--mapping lat,long to x,y
  3732. // -----------------------------------------------------------------
  3733. forward : function(p) {
  3734. var lon= p.x;
  3735. var lat= p.y;
  3736. var dlon = Proj4js.common.adjust_lon(lon - this.long0);
  3737. var dlat = Proj4js.common.adjust_lat(lat - this.lat0 );
  3738. p.x= this.x0 + (this.a*dlon*this.rc);
  3739. p.y= this.y0 + (this.a*dlat );
  3740. return p;
  3741. },
  3742. // inverse equations--mapping x,y to lat/long
  3743. // -----------------------------------------------------------------
  3744. inverse : function(p) {
  3745. var x= p.x;
  3746. var y= p.y;
  3747. p.x= Proj4js.common.adjust_lon(this.long0 + ((x - this.x0)/(this.a*this.rc)));
  3748. p.y= Proj4js.common.adjust_lat(this.lat0 + ((y - this.y0)/(this.a )));
  3749. return p;
  3750. }
  3751. };
  3752. /* ======================================================================
  3753. projCode/cass.js
  3754. ====================================================================== */
  3755. /*******************************************************************************
  3756. NAME CASSINI
  3757. PURPOSE: Transforms input longitude and latitude to Easting and
  3758. Northing for the Cassini projection. The
  3759. longitude and latitude must be in radians. The Easting
  3760. and Northing values will be returned in meters.
  3761. Ported from PROJ.4.
  3762. ALGORITHM REFERENCES
  3763. 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  3764. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  3765. State Government Printing Office, Washington D.C., 1987.
  3766. 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
  3767. U.S. Geological Survey Professional Paper 1453 , United State Government
  3768. *******************************************************************************/
  3769. //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";
  3770. // Initialize the Cassini projection
  3771. // -----------------------------------------------------------------
  3772. Proj4js.Proj.cass = {
  3773. init : function() {
  3774. if (!this.sphere) {
  3775. this.en = Proj4js.common.pj_enfn(this.es)
  3776. this.m0 = Proj4js.common.pj_mlfn(this.lat0, Math.sin(this.lat0), Math.cos(this.lat0), this.en);
  3777. }
  3778. },
  3779. C1: .16666666666666666666,
  3780. C2: .00833333333333333333,
  3781. C3: .04166666666666666666,
  3782. C4: .33333333333333333333,
  3783. C5: .06666666666666666666,
  3784. /* Cassini forward equations--mapping lat,long to x,y
  3785. -----------------------------------------------------------------------*/
  3786. forward: function(p) {
  3787. /* Forward equations
  3788. -----------------*/
  3789. var x,y;
  3790. var lam=p.x;
  3791. var phi=p.y;
  3792. lam = Proj4js.common.adjust_lon(lam - this.long0);
  3793. if (this.sphere) {
  3794. x = Math.asin(Math.cos(phi) * Math.sin(lam));
  3795. y = Math.atan2(Math.tan(phi) , Math.cos(lam)) - this.phi0;
  3796. } else {
  3797. //ellipsoid
  3798. this.n = Math.sin(phi);
  3799. this.c = Math.cos(phi);
  3800. y = Proj4js.common.pj_mlfn(phi, this.n, this.c, this.en);
  3801. this.n = 1./Math.sqrt(1. - this.es * this.n * this.n);
  3802. this.tn = Math.tan(phi);
  3803. this.t = this.tn * this.tn;
  3804. this.a1 = lam * this.c;
  3805. this.c *= this.es * this.c / (1 - this.es);
  3806. this.a2 = this.a1 * this.a1;
  3807. x = this.n * this.a1 * (1. - this.a2 * this.t * (this.C1 - (8. - this.t + 8. * this.c) * this.a2 * this.C2));
  3808. y -= this.m0 - this.n * this.tn * this.a2 * (.5 + (5. - this.t + 6. * this.c) * this.a2 * this.C3);
  3809. }
  3810. p.x = this.a*x + this.x0;
  3811. p.y = this.a*y + this.y0;
  3812. return p;
  3813. },//cassFwd()
  3814. /* Inverse equations
  3815. -----------------*/
  3816. inverse: function(p) {
  3817. p.x -= this.x0;
  3818. p.y -= this.y0;
  3819. var x = p.x/this.a;
  3820. var y = p.y/this.a;
  3821. var phi, lam;
  3822. if (this.sphere) {
  3823. this.dd = y + this.lat0;
  3824. phi = Math.asin(Math.sin(this.dd) * Math.cos(x));
  3825. lam = Math.atan2(Math.tan(x), Math.cos(this.dd));
  3826. } else {
  3827. /* ellipsoid */
  3828. var ph1 = Proj4js.common.pj_inv_mlfn(this.m0 + y, this.es, this.en);
  3829. this.tn = Math.tan(ph1);
  3830. this.t = this.tn * this.tn;
  3831. this.n = Math.sin(ph1);
  3832. this.r = 1. / (1. - this.es * this.n * this.n);
  3833. this.n = Math.sqrt(this.r);
  3834. this.r *= (1. - this.es) * this.n;
  3835. this.dd = x / this.n;
  3836. this.d2 = this.dd * this.dd;
  3837. phi = ph1 - (this.n * this.tn / this.r) * this.d2 * (.5 - (1. + 3. * this.t) * this.d2 * this.C3);
  3838. lam = this.dd * (1. + this.t * this.d2 * (-this.C4 + (1. + 3. * this.t) * this.d2 * this.C5)) / Math.cos(ph1);
  3839. }
  3840. p.x = Proj4js.common.adjust_lon(this.long0+lam);
  3841. p.y = phi;
  3842. return p;
  3843. }//cassInv()
  3844. }
  3845. /* ======================================================================
  3846. projCode/gauss.js
  3847. ====================================================================== */
  3848. Proj4js.Proj.gauss = {
  3849. init : function() {
  3850. var sphi = Math.sin(this.lat0);
  3851. var cphi = Math.cos(this.lat0);
  3852. cphi *= cphi;
  3853. this.rc = Math.sqrt(1.0 - this.es) / (1.0 - this.es * sphi * sphi);
  3854. this.C = Math.sqrt(1.0 + this.es * cphi * cphi / (1.0 - this.es));
  3855. this.phic0 = Math.asin(sphi / this.C);
  3856. this.ratexp = 0.5 * this.C * this.e;
  3857. 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));
  3858. },
  3859. forward : function(p) {
  3860. var lon = p.x;
  3861. var lat = p.y;
  3862. 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;
  3863. p.x = this.C * lon;
  3864. return p;
  3865. },
  3866. inverse : function(p) {
  3867. var DEL_TOL = 1e-14;
  3868. var lon = p.x / this.C;
  3869. var lat = p.y;
  3870. var num = Math.pow(Math.tan(0.5 * lat + Proj4js.common.FORTPI)/this.K, 1./this.C);
  3871. for (var i = Proj4js.common.MAX_ITER; i>0; --i) {
  3872. lat = 2.0 * Math.atan(num * Proj4js.common.srat(this.e * Math.sin(p.y), -0.5 * this.e)) - Proj4js.common.HALF_PI;
  3873. if (Math.abs(lat - p.y) < DEL_TOL) break;
  3874. p.y = lat;
  3875. }
  3876. /* convergence failed */
  3877. if (!i) {
  3878. Proj4js.reportError("gauss:inverse:convergence failed");
  3879. return null;
  3880. }
  3881. p.x = lon;
  3882. p.y = lat;
  3883. return p;
  3884. }
  3885. };
  3886. /* ======================================================================
  3887. projCode/omerc.js
  3888. ====================================================================== */
  3889. /*******************************************************************************
  3890. NAME OBLIQUE MERCATOR (HOTINE)
  3891. PURPOSE: Transforms input longitude and latitude to Easting and
  3892. Northing for the Oblique Mercator projection. The
  3893. longitude and latitude must be in radians. The Easting
  3894. and Northing values will be returned in meters.
  3895. PROGRAMMER DATE
  3896. ---------- ----
  3897. T. Mittan Mar, 1993
  3898. ALGORITHM REFERENCES
  3899. 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  3900. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  3901. State Government Printing Office, Washington D.C., 1987.
  3902. 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
  3903. U.S. Geological Survey Professional Paper 1453 , United State Government
  3904. Printing Office, Washington D.C., 1989.
  3905. *******************************************************************************/
  3906. Proj4js.Proj.omerc = {
  3907. /* Initialize the Oblique Mercator projection
  3908. ------------------------------------------*/
  3909. init: function() {
  3910. if (!this.mode) this.mode=0;
  3911. if (!this.lon1) {this.lon1=0;this.mode=1;}
  3912. if (!this.lon2) this.lon2=0;
  3913. if (!this.lat2) this.lat2=0;
  3914. /* Place parameters in static storage for common use
  3915. -------------------------------------------------*/
  3916. var temp = this.b/ this.a;
  3917. var es = 1.0 - Math.pow(temp,2);
  3918. var e = Math.sqrt(es);
  3919. this.sin_p20=Math.sin(this.lat0);
  3920. this.cos_p20=Math.cos(this.lat0);
  3921. this.con = 1.0 - this.es * this.sin_p20 * this.sin_p20;
  3922. this.com = Math.sqrt(1.0 - es);
  3923. this.bl = Math.sqrt(1.0 + this.es * Math.pow(this.cos_p20,4.0)/(1.0 - es));
  3924. this.al = this.a * this.bl * this.k0 * this.com / this.con;
  3925. if (Math.abs(this.lat0) < Proj4js.common.EPSLN) {
  3926. this.ts = 1.0;
  3927. this.d = 1.0;
  3928. this.el = 1.0;
  3929. } else {
  3930. this.ts = Proj4js.common.tsfnz(this.e,this.lat0,this.sin_p20);
  3931. this.con = Math.sqrt(this.con);
  3932. this.d = this.bl * this.com / (this.cos_p20 * this.con);
  3933. if ((this.d * this.d - 1.0) > 0.0) {
  3934. if (this.lat0 >= 0.0) {
  3935. this.f = this.d + Math.sqrt(this.d * this.d - 1.0);
  3936. } else {
  3937. this.f = this.d - Math.sqrt(this.d * this.d - 1.0);
  3938. }
  3939. } else {
  3940. this.f = this.d;
  3941. }
  3942. this.el = this.f * Math.pow(this.ts,this.bl);
  3943. }
  3944. //this.longc=52.60353916666667;
  3945. if (this.mode != 0) {
  3946. this.g = .5 * (this.f - 1.0/this.f);
  3947. this.gama = Proj4js.common.asinz(Math.sin(this.alpha) / this.d);
  3948. this.longc= this.longc - Proj4js.common.asinz(this.g * Math.tan(this.gama))/this.bl;
  3949. /* Report parameters common to format B
  3950. -------------------------------------*/
  3951. //genrpt(azimuth * R2D,"Azimuth of Central Line: ");
  3952. //cenlon(lon_origin);
  3953. // cenlat(lat_origin);
  3954. this.con = Math.abs(this.lat0);
  3955. if ((this.con > Proj4js.common.EPSLN) && (Math.abs(this.con - Proj4js.common.HALF_PI) > Proj4js.common.EPSLN)) {
  3956. this.singam=Math.sin(this.gama);
  3957. this.cosgam=Math.cos(this.gama);
  3958. this.sinaz=Math.sin(this.alpha);
  3959. this.cosaz=Math.cos(this.alpha);
  3960. if (this.lat0>= 0) {
  3961. this.u = (this.al / this.bl) * Math.atan(Math.sqrt(this.d*this.d - 1.0)/this.cosaz);
  3962. } else {
  3963. this.u = -(this.al / this.bl) *Math.atan(Math.sqrt(this.d*this.d - 1.0)/this.cosaz);
  3964. }
  3965. } else {
  3966. Proj4js.reportError("omerc:Init:DataError");
  3967. }
  3968. } else {
  3969. this.sinphi =Math. sin(this.at1);
  3970. this.ts1 = Proj4js.common.tsfnz(this.e,this.lat1,this.sinphi);
  3971. this.sinphi = Math.sin(this.lat2);
  3972. this.ts2 = Proj4js.common.tsfnz(this.e,this.lat2,this.sinphi);
  3973. this.h = Math.pow(this.ts1,this.bl);
  3974. this.l = Math.pow(this.ts2,this.bl);
  3975. this.f = this.el/this.h;
  3976. this.g = .5 * (this.f - 1.0/this.f);
  3977. this.j = (this.el * this.el - this.l * this.h)/(this.el * this.el + this.l * this.h);
  3978. this.p = (this.l - this.h) / (this.l + this.h);
  3979. this.dlon = this.lon1 - this.lon2;
  3980. if (this.dlon < -Proj4js.common.PI) this.lon2 = this.lon2 - 2.0 * Proj4js.common.PI;
  3981. if (this.dlon > Proj4js.common.PI) this.lon2 = this.lon2 + 2.0 * Proj4js.common.PI;
  3982. this.dlon = this.lon1 - this.lon2;
  3983. this.longc = .5 * (this.lon1 + this.lon2) -Math.atan(this.j * Math.tan(.5 * this.bl * this.dlon)/this.p)/this.bl;
  3984. this.dlon = Proj4js.common.adjust_lon(this.lon1 - this.longc);
  3985. this.gama = Math.atan(Math.sin(this.bl * this.dlon)/this.g);
  3986. this.alpha = Proj4js.common.asinz(this.d * Math.sin(this.gama));
  3987. /* Report parameters common to format A
  3988. -------------------------------------*/
  3989. if (Math.abs(this.lat1 - this.lat2) <= Proj4js.common.EPSLN) {
  3990. Proj4js.reportError("omercInitDataError");
  3991. //return(202);
  3992. } else {
  3993. this.con = Math.abs(this.lat1);
  3994. }
  3995. if ((this.con <= Proj4js.common.EPSLN) || (Math.abs(this.con - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN)) {
  3996. Proj4js.reportError("omercInitDataError");
  3997. //return(202);
  3998. } else {
  3999. if (Math.abs(Math.abs(this.lat0) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN) {
  4000. Proj4js.reportError("omercInitDataError");
  4001. //return(202);
  4002. }
  4003. }
  4004. this.singam=Math.sin(this.gam);
  4005. this.cosgam=Math.cos(this.gam);
  4006. this.sinaz=Math.sin(this.alpha);
  4007. this.cosaz=Math.cos(this.alpha);
  4008. if (this.lat0 >= 0) {
  4009. this.u = (this.al/this.bl) * Math.atan(Math.sqrt(this.d * this.d - 1.0)/this.cosaz);
  4010. } else {
  4011. this.u = -(this.al/this.bl) * Math.atan(Math.sqrt(this.d * this.d - 1.0)/this.cosaz);
  4012. }
  4013. }
  4014. },
  4015. /* Oblique Mercator forward equations--mapping lat,long to x,y
  4016. ----------------------------------------------------------*/
  4017. forward: function(p) {
  4018. var theta; /* angle */
  4019. var sin_phi, cos_phi;/* sin and cos value */
  4020. var b; /* temporary values */
  4021. var c, t, tq; /* temporary values */
  4022. var con, n, ml; /* cone constant, small m */
  4023. var q,us,vl;
  4024. var ul,vs;
  4025. var s;
  4026. var dlon;
  4027. var ts1;
  4028. var lon=p.x;
  4029. var lat=p.y;
  4030. /* Forward equations
  4031. -----------------*/
  4032. sin_phi = Math.sin(lat);
  4033. dlon = Proj4js.common.adjust_lon(lon - this.longc);
  4034. vl = Math.sin(this.bl * dlon);
  4035. if (Math.abs(Math.abs(lat) - Proj4js.common.HALF_PI) > Proj4js.common.EPSLN) {
  4036. ts1 = Proj4js.common.tsfnz(this.e,lat,sin_phi);
  4037. q = this.el / (Math.pow(ts1,this.bl));
  4038. s = .5 * (q - 1.0 / q);
  4039. t = .5 * (q + 1.0/ q);
  4040. ul = (s * this.singam - vl * this.cosgam) / t;
  4041. con = Math.cos(this.bl * dlon);
  4042. if (Math.abs(con) < .0000001) {
  4043. us = this.al * this.bl * dlon;
  4044. } else {
  4045. us = this.al * Math.atan((s * this.cosgam + vl * this.singam) / con)/this.bl;
  4046. if (con < 0) us = us + Proj4js.common.PI * this.al / this.bl;
  4047. }
  4048. } else {
  4049. if (lat >= 0) {
  4050. ul = this.singam;
  4051. } else {
  4052. ul = -this.singam;
  4053. }
  4054. us = this.al * lat / this.bl;
  4055. }
  4056. if (Math.abs(Math.abs(ul) - 1.0) <= Proj4js.common.EPSLN) {
  4057. //alert("Point projects into infinity","omer-for");
  4058. Proj4js.reportError("omercFwdInfinity");
  4059. //return(205);
  4060. }
  4061. vs = .5 * this.al * Math.log((1.0 - ul)/(1.0 + ul)) / this.bl;
  4062. us = us - this.u;
  4063. var x = this.x0 + vs * this.cosaz + us * this.sinaz;
  4064. var y = this.y0 + us * this.cosaz - vs * this.sinaz;
  4065. p.x=x;
  4066. p.y=y;
  4067. return p;
  4068. },
  4069. inverse: function(p) {
  4070. var delta_lon; /* Delta longitude (Given longitude - center */
  4071. var theta; /* angle */
  4072. var delta_theta; /* adjusted longitude */
  4073. var sin_phi, cos_phi;/* sin and cos value */
  4074. var b; /* temporary values */
  4075. var c, t, tq; /* temporary values */
  4076. var con, n, ml; /* cone constant, small m */
  4077. var vs,us,q,s,ts1;
  4078. var vl,ul,bs;
  4079. var lon, lat;
  4080. var flag;
  4081. /* Inverse equations
  4082. -----------------*/
  4083. p.x -= this.x0;
  4084. p.y -= this.y0;
  4085. flag = 0;
  4086. vs = p.x * this.cosaz - p.y * this.sinaz;
  4087. us = p.y * this.cosaz + p.x * this.sinaz;
  4088. us = us + this.u;
  4089. q = Math.exp(-this.bl * vs / this.al);
  4090. s = .5 * (q - 1.0/q);
  4091. t = .5 * (q + 1.0/q);
  4092. vl = Math.sin(this.bl * us / this.al);
  4093. ul = (vl * this.cosgam + s * this.singam)/t;
  4094. if (Math.abs(Math.abs(ul) - 1.0) <= Proj4js.common.EPSLN)
  4095. {
  4096. lon = this.longc;
  4097. if (ul >= 0.0) {
  4098. lat = Proj4js.common.HALF_PI;
  4099. } else {
  4100. lat = -Proj4js.common.HALF_PI;
  4101. }
  4102. } else {
  4103. con = 1.0 / this.bl;
  4104. ts1 =Math.pow((this.el / Math.sqrt((1.0 + ul) / (1.0 - ul))),con);
  4105. lat = Proj4js.common.phi2z(this.e,ts1);
  4106. //if (flag != 0)
  4107. //return(flag);
  4108. //~ con = Math.cos(this.bl * us /al);
  4109. theta = this.longc - Math.atan2((s * this.cosgam - vl * this.singam) , con)/this.bl;
  4110. lon = Proj4js.common.adjust_lon(theta);
  4111. }
  4112. p.x=lon;
  4113. p.y=lat;
  4114. return p;
  4115. }
  4116. };
  4117. /* ======================================================================
  4118. projCode/lcc.js
  4119. ====================================================================== */
  4120. /*******************************************************************************
  4121. NAME LAMBERT CONFORMAL CONIC
  4122. PURPOSE: Transforms input longitude and latitude to Easting and
  4123. Northing for the Lambert Conformal Conic projection. The
  4124. longitude and latitude must be in radians. The Easting
  4125. and Northing values will be returned in meters.
  4126. ALGORITHM REFERENCES
  4127. 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  4128. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  4129. State Government Printing Office, Washington D.C., 1987.
  4130. 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
  4131. U.S. Geological Survey Professional Paper 1453 , United State Government
  4132. *******************************************************************************/
  4133. //<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
  4134. // Initialize the Lambert Conformal conic projection
  4135. // -----------------------------------------------------------------
  4136. //Proj4js.Proj.lcc = Class.create();
  4137. Proj4js.Proj.lcc = {
  4138. init : function() {
  4139. // array of: r_maj,r_min,lat1,lat2,c_lon,c_lat,false_east,false_north
  4140. //double c_lat; /* center latitude */
  4141. //double c_lon; /* center longitude */
  4142. //double lat1; /* first standard parallel */
  4143. //double lat2; /* second standard parallel */
  4144. //double r_maj; /* major axis */
  4145. //double r_min; /* minor axis */
  4146. //double false_east; /* x offset in meters */
  4147. //double false_north; /* y offset in meters */
  4148. if (!this.lat2){this.lat2=this.lat0;}//if lat2 is not defined
  4149. if (!this.k0) this.k0 = 1.0;
  4150. // Standard Parallels cannot be equal and on opposite sides of the equator
  4151. if (Math.abs(this.lat1+this.lat2) < Proj4js.common.EPSLN) {
  4152. Proj4js.reportError("lcc:init: Equal Latitudes");
  4153. return;
  4154. }
  4155. var temp = this.b / this.a;
  4156. this.e = Math.sqrt(1.0 - temp*temp);
  4157. var sin1 = Math.sin(this.lat1);
  4158. var cos1 = Math.cos(this.lat1);
  4159. var ms1 = Proj4js.common.msfnz(this.e, sin1, cos1);
  4160. var ts1 = Proj4js.common.tsfnz(this.e, this.lat1, sin1);
  4161. var sin2 = Math.sin(this.lat2);
  4162. var cos2 = Math.cos(this.lat2);
  4163. var ms2 = Proj4js.common.msfnz(this.e, sin2, cos2);
  4164. var ts2 = Proj4js.common.tsfnz(this.e, this.lat2, sin2);
  4165. var ts0 = Proj4js.common.tsfnz(this.e, this.lat0, Math.sin(this.lat0));
  4166. if (Math.abs(this.lat1 - this.lat2) > Proj4js.common.EPSLN) {
  4167. this.ns = Math.log(ms1/ms2)/Math.log(ts1/ts2);
  4168. } else {
  4169. this.ns = sin1;
  4170. }
  4171. this.f0 = ms1 / (this.ns * Math.pow(ts1, this.ns));
  4172. this.rh = this.a * this.f0 * Math.pow(ts0, this.ns);
  4173. if (!this.title) this.title = "Lambert Conformal Conic";
  4174. },
  4175. // Lambert Conformal conic forward equations--mapping lat,long to x,y
  4176. // -----------------------------------------------------------------
  4177. forward : function(p) {
  4178. var lon = p.x;
  4179. var lat = p.y;
  4180. // convert to radians
  4181. if ( lat <= 90.0 && lat >= -90.0 && lon <= 180.0 && lon >= -180.0) {
  4182. //lon = lon * Proj4js.common.D2R;
  4183. //lat = lat * Proj4js.common.D2R;
  4184. } else {
  4185. Proj4js.reportError("lcc:forward: llInputOutOfRange: "+ lon +" : " + lat);
  4186. return null;
  4187. }
  4188. var con = Math.abs( Math.abs(lat) - Proj4js.common.HALF_PI);
  4189. var ts, rh1;
  4190. if (con > Proj4js.common.EPSLN) {
  4191. ts = Proj4js.common.tsfnz(this.e, lat, Math.sin(lat) );
  4192. rh1 = this.a * this.f0 * Math.pow(ts, this.ns);
  4193. } else {
  4194. con = lat * this.ns;
  4195. if (con <= 0) {
  4196. Proj4js.reportError("lcc:forward: No Projection");
  4197. return null;
  4198. }
  4199. rh1 = 0;
  4200. }
  4201. var theta = this.ns * Proj4js.common.adjust_lon(lon - this.long0);
  4202. p.x = this.k0 * (rh1 * Math.sin(theta)) + this.x0;
  4203. p.y = this.k0 * (this.rh - rh1 * Math.cos(theta)) + this.y0;
  4204. return p;
  4205. },
  4206. // Lambert Conformal Conic inverse equations--mapping x,y to lat/long
  4207. // -----------------------------------------------------------------
  4208. inverse : function(p) {
  4209. var rh1, con, ts;
  4210. var lat, lon;
  4211. var x = (p.x - this.x0)/this.k0;
  4212. var y = (this.rh - (p.y - this.y0)/this.k0);
  4213. if (this.ns > 0) {
  4214. rh1 = Math.sqrt (x * x + y * y);
  4215. con = 1.0;
  4216. } else {
  4217. rh1 = -Math.sqrt (x * x + y * y);
  4218. con = -1.0;
  4219. }
  4220. var theta = 0.0;
  4221. if (rh1 != 0) {
  4222. theta = Math.atan2((con * x),(con * y));
  4223. }
  4224. if ((rh1 != 0) || (this.ns > 0.0)) {
  4225. con = 1.0/this.ns;
  4226. ts = Math.pow((rh1/(this.a * this.f0)), con);
  4227. lat = Proj4js.common.phi2z(this.e, ts);
  4228. if (lat == -9999) return null;
  4229. } else {
  4230. lat = -Proj4js.common.HALF_PI;
  4231. }
  4232. lon = Proj4js.common.adjust_lon(theta/this.ns + this.long0);
  4233. p.x = lon;
  4234. p.y = lat;
  4235. return p;
  4236. }
  4237. };
  4238. /* ======================================================================
  4239. projCode/laea.js
  4240. ====================================================================== */
  4241. /*******************************************************************************
  4242. NAME LAMBERT AZIMUTHAL EQUAL-AREA
  4243. PURPOSE: Transforms input longitude and latitude to Easting and
  4244. Northing for the Lambert Azimuthal Equal-Area projection. The
  4245. longitude and latitude must be in radians. The Easting
  4246. and Northing values will be returned in meters.
  4247. PROGRAMMER DATE
  4248. ---------- ----
  4249. D. Steinwand, EROS March, 1991
  4250. This function was adapted from the Lambert Azimuthal Equal Area projection
  4251. code (FORTRAN) in the General Cartographic Transformation Package software
  4252. which is available from the U.S. Geological Survey National Mapping Division.
  4253. ALGORITHM REFERENCES
  4254. 1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder,
  4255. The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355.
  4256. 2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  4257. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  4258. State Government Printing Office, Washington D.C., 1987.
  4259. 3. "Software Documentation for GCTP General Cartographic Transformation
  4260. Package", U.S. Geological Survey National Mapping Division, May 1982.
  4261. *******************************************************************************/
  4262. Proj4js.Proj.laea = {
  4263. S_POLE: 1,
  4264. N_POLE: 2,
  4265. EQUIT: 3,
  4266. OBLIQ: 4,
  4267. /* Initialize the Lambert Azimuthal Equal Area projection
  4268. ------------------------------------------------------*/
  4269. init: function() {
  4270. var t = Math.abs(this.lat0);
  4271. if (Math.abs(t - Proj4js.common.HALF_PI) < Proj4js.common.EPSLN) {
  4272. this.mode = this.lat0 < 0. ? this.S_POLE : this.N_POLE;
  4273. } else if (Math.abs(t) < Proj4js.common.EPSLN) {
  4274. this.mode = this.EQUIT;
  4275. } else {
  4276. this.mode = this.OBLIQ;
  4277. }
  4278. if (this.es > 0) {
  4279. var sinphi;
  4280. this.qp = Proj4js.common.qsfnz(this.e, 1.0);
  4281. this.mmf = .5 / (1. - this.es);
  4282. this.apa = this.authset(this.es);
  4283. switch (this.mode) {
  4284. case this.N_POLE:
  4285. case this.S_POLE:
  4286. this.dd = 1.;
  4287. break;
  4288. case this.EQUIT:
  4289. this.rq = Math.sqrt(.5 * this.qp);
  4290. this.dd = 1. / this.rq;
  4291. this.xmf = 1.;
  4292. this.ymf = .5 * this.qp;
  4293. break;
  4294. case this.OBLIQ:
  4295. this.rq = Math.sqrt(.5 * this.qp);
  4296. sinphi = Math.sin(this.lat0);
  4297. this.sinb1 = Proj4js.common.qsfnz(this.e, sinphi) / this.qp;
  4298. this.cosb1 = Math.sqrt(1. - this.sinb1 * this.sinb1);
  4299. this.dd = Math.cos(this.lat0) / (Math.sqrt(1. - this.es * sinphi * sinphi) * this.rq * this.cosb1);
  4300. this.ymf = (this.xmf = this.rq) / this.dd;
  4301. this.xmf *= this.dd;
  4302. break;
  4303. }
  4304. } else {
  4305. if (this.mode == this.OBLIQ) {
  4306. this.sinph0 = Math.sin(this.lat0);
  4307. this.cosph0 = Math.cos(this.lat0);
  4308. }
  4309. }
  4310. },
  4311. /* Lambert Azimuthal Equal Area forward equations--mapping lat,long to x,y
  4312. -----------------------------------------------------------------------*/
  4313. forward: function(p) {
  4314. /* Forward equations
  4315. -----------------*/
  4316. var x,y;
  4317. var lam=p.x;
  4318. var phi=p.y;
  4319. lam = Proj4js.common.adjust_lon(lam - this.long0);
  4320. if (this.sphere) {
  4321. var coslam, cosphi, sinphi;
  4322. sinphi = Math.sin(phi);
  4323. cosphi = Math.cos(phi);
  4324. coslam = Math.cos(lam);
  4325. switch (this.mode) {
  4326. case this.OBLIQ:
  4327. case this.EQUIT:
  4328. y = (this.mode == this.EQUIT) ? 1. + cosphi * coslam : 1. + this.sinph0 * sinphi + this.cosph0 * cosphi * coslam;
  4329. if (y <= Proj4js.common.EPSLN) {
  4330. Proj4js.reportError("laea:fwd:y less than eps");
  4331. return null;
  4332. }
  4333. y = Math.sqrt(2. / y);
  4334. x = y * cosphi * Math.sin(lam);
  4335. y *= (this.mode == this.EQUIT) ? sinphi : this.cosph0 * sinphi - this.sinph0 * cosphi * coslam;
  4336. break;
  4337. case this.N_POLE:
  4338. coslam = -coslam;
  4339. case this.S_POLE:
  4340. if (Math.abs(phi + this.phi0) < Proj4js.common.EPSLN) {
  4341. Proj4js.reportError("laea:fwd:phi < eps");
  4342. return null;
  4343. }
  4344. y = Proj4js.common.FORTPI - phi * .5;
  4345. y = 2. * ((this.mode == this.S_POLE) ? Math.cos(y) : Math.sin(y));
  4346. x = y * Math.sin(lam);
  4347. y *= coslam;
  4348. break;
  4349. }
  4350. } else {
  4351. var coslam, sinlam, sinphi, q, sinb=0.0, cosb=0.0, b=0.0;
  4352. coslam = Math.cos(lam);
  4353. sinlam = Math.sin(lam);
  4354. sinphi = Math.sin(phi);
  4355. q = Proj4js.common.qsfnz(this.e, sinphi);
  4356. if (this.mode == this.OBLIQ || this.mode == this.EQUIT) {
  4357. sinb = q / this.qp;
  4358. cosb = Math.sqrt(1. - sinb * sinb);
  4359. }
  4360. switch (this.mode) {
  4361. case this.OBLIQ:
  4362. b = 1. + this.sinb1 * sinb + this.cosb1 * cosb * coslam;
  4363. break;
  4364. case this.EQUIT:
  4365. b = 1. + cosb * coslam;
  4366. break;
  4367. case this.N_POLE:
  4368. b = Proj4js.common.HALF_PI + phi;
  4369. q = this.qp - q;
  4370. break;
  4371. case this.S_POLE:
  4372. b = phi - Proj4js.common.HALF_PI;
  4373. q = this.qp + q;
  4374. break;
  4375. }
  4376. if (Math.abs(b) < Proj4js.common.EPSLN) {
  4377. Proj4js.reportError("laea:fwd:b < eps");
  4378. return null;
  4379. }
  4380. switch (this.mode) {
  4381. case this.OBLIQ:
  4382. case this.EQUIT:
  4383. b = Math.sqrt(2. / b);
  4384. if (this.mode == this.OBLIQ) {
  4385. y = this.ymf * b * (this.cosb1 * sinb - this.sinb1 * cosb * coslam);
  4386. } else {
  4387. y = (b = Math.sqrt(2. / (1. + cosb * coslam))) * sinb * this.ymf;
  4388. }
  4389. x = this.xmf * b * cosb * sinlam;
  4390. break;
  4391. case this.N_POLE:
  4392. case this.S_POLE:
  4393. if (q >= 0.) {
  4394. x = (b = Math.sqrt(q)) * sinlam;
  4395. y = coslam * ((this.mode == this.S_POLE) ? b : -b);
  4396. } else {
  4397. x = y = 0.;
  4398. }
  4399. break;
  4400. }
  4401. }
  4402. //v 1.0
  4403. /*
  4404. var sin_lat=Math.sin(lat);
  4405. var cos_lat=Math.cos(lat);
  4406. var sin_delta_lon=Math.sin(delta_lon);
  4407. var cos_delta_lon=Math.cos(delta_lon);
  4408. var g =this.sin_lat_o * sin_lat +this.cos_lat_o * cos_lat * cos_delta_lon;
  4409. if (g == -1.0) {
  4410. Proj4js.reportError("laea:fwd:Point projects to a circle of radius "+ 2.0 * R);
  4411. return null;
  4412. }
  4413. var ksp = this.a * Math.sqrt(2.0 / (1.0 + g));
  4414. var x = ksp * cos_lat * sin_delta_lon + this.x0;
  4415. var y = ksp * (this.cos_lat_o * sin_lat - this.sin_lat_o * cos_lat * cos_delta_lon) + this.y0;
  4416. */
  4417. p.x = this.a*x + this.x0;
  4418. p.y = this.a*y + this.y0;
  4419. return p;
  4420. },//lamazFwd()
  4421. /* Inverse equations
  4422. -----------------*/
  4423. inverse: function(p) {
  4424. p.x -= this.x0;
  4425. p.y -= this.y0;
  4426. var x = p.x/this.a;
  4427. var y = p.y/this.a;
  4428. var lam, phi;
  4429. if (this.sphere) {
  4430. var cosz=0.0, rh, sinz=0.0;
  4431. rh = Math.sqrt(x*x + y*y);
  4432. phi = rh * .5;
  4433. if (phi > 1.) {
  4434. Proj4js.reportError("laea:Inv:DataError");
  4435. return null;
  4436. }
  4437. phi = 2. * Math.asin(phi);
  4438. if (this.mode == this.OBLIQ || this.mode == this.EQUIT) {
  4439. sinz = Math.sin(phi);
  4440. cosz = Math.cos(phi);
  4441. }
  4442. switch (this.mode) {
  4443. case this.EQUIT:
  4444. phi = (Math.abs(rh) <= Proj4js.common.EPSLN) ? 0. : Math.asin(y * sinz / rh);
  4445. x *= sinz;
  4446. y = cosz * rh;
  4447. break;
  4448. case this.OBLIQ:
  4449. phi = (Math.abs(rh) <= Proj4js.common.EPSLN) ? this.phi0 : Math.asin(cosz * this.sinph0 + y * sinz * this.cosph0 / rh);
  4450. x *= sinz * this.cosph0;
  4451. y = (cosz - Math.sin(phi) * this.sinph0) * rh;
  4452. break;
  4453. case this.N_POLE:
  4454. y = -y;
  4455. phi = Proj4js.common.HALF_PI - phi;
  4456. break;
  4457. case this.S_POLE:
  4458. phi -= Proj4js.common.HALF_PI;
  4459. break;
  4460. }
  4461. lam = (y == 0. && (this.mode == this.EQUIT || this.mode == this.OBLIQ)) ? 0. : Math.atan2(x, y);
  4462. } else {
  4463. var cCe, sCe, q, rho, ab=0.0;
  4464. switch (this.mode) {
  4465. case this.EQUIT:
  4466. case this.OBLIQ:
  4467. x /= this.dd;
  4468. y *= this.dd;
  4469. rho = Math.sqrt(x*x + y*y);
  4470. if (rho < Proj4js.common.EPSLN) {
  4471. p.x = 0.;
  4472. p.y = this.phi0;
  4473. return p;
  4474. }
  4475. sCe = 2. * Math.asin(.5 * rho / this.rq);
  4476. cCe = Math.cos(sCe);
  4477. x *= (sCe = Math.sin(sCe));
  4478. if (this.mode == this.OBLIQ) {
  4479. ab = cCe * this.sinb1 + y * sCe * this.cosb1 / rho
  4480. q = this.qp * ab;
  4481. y = rho * this.cosb1 * cCe - y * this.sinb1 * sCe;
  4482. } else {
  4483. ab = y * sCe / rho;
  4484. q = this.qp * ab;
  4485. y = rho * cCe;
  4486. }
  4487. break;
  4488. case this.N_POLE:
  4489. y = -y;
  4490. case this.S_POLE:
  4491. q = (x * x + y * y);
  4492. if (!q ) {
  4493. p.x = 0.;
  4494. p.y = this.phi0;
  4495. return p;
  4496. }
  4497. /*
  4498. q = this.qp - q;
  4499. */
  4500. ab = 1. - q / this.qp;
  4501. if (this.mode == this.S_POLE) {
  4502. ab = - ab;
  4503. }
  4504. break;
  4505. }
  4506. lam = Math.atan2(x, y);
  4507. phi = this.authlat(Math.asin(ab), this.apa);
  4508. }
  4509. /*
  4510. var Rh = Math.Math.sqrt(p.x *p.x +p.y * p.y);
  4511. var temp = Rh / (2.0 * this.a);
  4512. if (temp > 1) {
  4513. Proj4js.reportError("laea:Inv:DataError");
  4514. return null;
  4515. }
  4516. var z = 2.0 * Proj4js.common.asinz(temp);
  4517. var sin_z=Math.sin(z);
  4518. var cos_z=Math.cos(z);
  4519. var lon =this.long0;
  4520. if (Math.abs(Rh) > Proj4js.common.EPSLN) {
  4521. var lat = Proj4js.common.asinz(this.sin_lat_o * cos_z +this. cos_lat_o * sin_z *p.y / Rh);
  4522. var temp =Math.abs(this.lat0) - Proj4js.common.HALF_PI;
  4523. if (Math.abs(temp) > Proj4js.common.EPSLN) {
  4524. temp = cos_z -this.sin_lat_o * Math.sin(lat);
  4525. if(temp!=0.0) lon=Proj4js.common.adjust_lon(this.long0+Math.atan2(p.x*sin_z*this.cos_lat_o,temp*Rh));
  4526. } else if (this.lat0 < 0.0) {
  4527. lon = Proj4js.common.adjust_lon(this.long0 - Math.atan2(-p.x,p.y));
  4528. } else {
  4529. lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x, -p.y));
  4530. }
  4531. } else {
  4532. lat = this.lat0;
  4533. }
  4534. */
  4535. //return(OK);
  4536. p.x = Proj4js.common.adjust_lon(this.long0+lam);
  4537. p.y = phi;
  4538. return p;
  4539. },//lamazInv()
  4540. /* determine latitude from authalic latitude */
  4541. P00: .33333333333333333333,
  4542. P01: .17222222222222222222,
  4543. P02: .10257936507936507936,
  4544. P10: .06388888888888888888,
  4545. P11: .06640211640211640211,
  4546. P20: .01641501294219154443,
  4547. authset: function(es) {
  4548. var t;
  4549. var APA = new Array();
  4550. APA[0] = es * this.P00;
  4551. t = es * es;
  4552. APA[0] += t * this.P01;
  4553. APA[1] = t * this.P10;
  4554. t *= es;
  4555. APA[0] += t * this.P02;
  4556. APA[1] += t * this.P11;
  4557. APA[2] = t * this.P20;
  4558. return APA;
  4559. },
  4560. authlat: function(beta, APA) {
  4561. var t = beta+beta;
  4562. return(beta + APA[0] * Math.sin(t) + APA[1] * Math.sin(t+t) + APA[2] * Math.sin(t+t+t));
  4563. }
  4564. };
  4565. /* ======================================================================
  4566. projCode/aeqd.js
  4567. ====================================================================== */
  4568. Proj4js.Proj.aeqd = {
  4569. init : function() {
  4570. this.sin_p12=Math.sin(this.lat0);
  4571. this.cos_p12=Math.cos(this.lat0);
  4572. },
  4573. forward: function(p) {
  4574. var lon=p.x;
  4575. var lat=p.y;
  4576. var ksp;
  4577. var sinphi=Math.sin(p.y);
  4578. var cosphi=Math.cos(p.y);
  4579. var dlon = Proj4js.common.adjust_lon(lon - this.long0);
  4580. var coslon = Math.cos(dlon);
  4581. var g = this.sin_p12 * sinphi + this.cos_p12 * cosphi * coslon;
  4582. if (Math.abs(Math.abs(g) - 1.0) < Proj4js.common.EPSLN) {
  4583. ksp = 1.0;
  4584. if (g < 0.0) {
  4585. Proj4js.reportError("aeqd:Fwd:PointError");
  4586. return;
  4587. }
  4588. } else {
  4589. var z = Math.acos(g);
  4590. ksp = z/Math.sin(z);
  4591. }
  4592. p.x = this.x0 + this.a * ksp * cosphi * Math.sin(dlon);
  4593. p.y = this.y0 + this.a * ksp * (this.cos_p12 * sinphi - this.sin_p12 * cosphi * coslon);
  4594. return p;
  4595. },
  4596. inverse: function(p){
  4597. p.x -= this.x0;
  4598. p.y -= this.y0;
  4599. var rh = Math.sqrt(p.x * p.x + p.y *p.y);
  4600. if (rh > (2.0 * Proj4js.common.HALF_PI * this.a)) {
  4601. Proj4js.reportError("aeqdInvDataError");
  4602. return;
  4603. }
  4604. var z = rh / this.a;
  4605. var sinz=Math.sin(z);
  4606. var cosz=Math.cos(z);
  4607. var lon = this.long0;
  4608. var lat;
  4609. if (Math.abs(rh) <= Proj4js.common.EPSLN) {
  4610. lat = this.lat0;
  4611. } else {
  4612. lat = Proj4js.common.asinz(cosz * this.sin_p12 + (p.y * sinz * this.cos_p12) / rh);
  4613. var con = Math.abs(this.lat0) - Proj4js.common.HALF_PI;
  4614. if (Math.abs(con) <= Proj4js.common.EPSLN) {
  4615. if (this.lat0 >= 0.0) {
  4616. lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2(p.x , -p.y));
  4617. } else {
  4618. lon = Proj4js.common.adjust_lon(this.long0 - Math.atan2(-p.x , p.y));
  4619. }
  4620. } else {
  4621. con = cosz - this.sin_p12 * Math.sin(lat);
  4622. if ((Math.abs(con) < Proj4js.common.EPSLN) && (Math.abs(p.x) < Proj4js.common.EPSLN)) {
  4623. //no-op, just keep the lon value as is
  4624. } else {
  4625. var temp = Math.atan2((p.x * sinz * this.cos_p12), (con * rh));
  4626. lon = Proj4js.common.adjust_lon(this.long0 + Math.atan2((p.x * sinz * this.cos_p12), (con * rh)));
  4627. }
  4628. }
  4629. }
  4630. p.x = lon;
  4631. p.y = lat;
  4632. return p;
  4633. }
  4634. };
  4635. /* ======================================================================
  4636. projCode/moll.js
  4637. ====================================================================== */
  4638. /*******************************************************************************
  4639. NAME MOLLWEIDE
  4640. PURPOSE: Transforms input longitude and latitude to Easting and
  4641. Northing for the MOllweide projection. The
  4642. longitude and latitude must be in radians. The Easting
  4643. and Northing values will be returned in meters.
  4644. PROGRAMMER DATE
  4645. ---------- ----
  4646. D. Steinwand, EROS May, 1991; Updated Sept, 1992; Updated Feb, 1993
  4647. S. Nelson, EDC Jun, 2993; Made corrections in precision and
  4648. number of iterations.
  4649. ALGORITHM REFERENCES
  4650. 1. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
  4651. U.S. Geological Survey Professional Paper 1453 , United State Government
  4652. Printing Office, Washington D.C., 1989.
  4653. 2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
  4654. Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
  4655. State Government Printing Office, Washington D.C., 1987.
  4656. *******************************************************************************/
  4657. Proj4js.Proj.moll = {
  4658. /* Initialize the Mollweide projection
  4659. ------------------------------------*/
  4660. init: function(){
  4661. //no-op
  4662. },
  4663. /* Mollweide forward equations--mapping lat,long to x,y
  4664. ----------------------------------------------------*/
  4665. forward: function(p) {
  4666. /* Forward equations
  4667. -----------------*/
  4668. var lon=p.x;
  4669. var lat=p.y;
  4670. var delta_lon = Proj4js.common.adjust_lon(lon - this.long0);
  4671. var theta = lat;
  4672. var con = Proj4js.common.PI * Math.sin(lat);
  4673. /* Iterate using the Newton-Raphson method to find theta
  4674. -----------------------------------------------------*/
  4675. for (var i=0;true;i++) {
  4676. var delta_theta = -(theta + Math.sin(theta) - con)/ (1.0 + Math.cos(theta));
  4677. theta += delta_theta;
  4678. if (Math.abs(delta_theta) < Proj4js.common.EPSLN) break;
  4679. if (i >= 50) {
  4680. Proj4js.reportError("moll:Fwd:IterationError");
  4681. //return(241);
  4682. }
  4683. }
  4684. theta /= 2.0;
  4685. /* If the latitude is 90 deg, force the x coordinate to be "0 + false easting"
  4686. this is done here because of precision problems with "cos(theta)"
  4687. --------------------------------------------------------------------------*/
  4688. if (Proj4js.common.PI/2 - Math.abs(lat) < Proj4js.common.EPSLN) delta_lon =0;
  4689. var x = 0.900316316158 * this.a * delta_lon * Math.cos(theta) + this.x0;
  4690. var y = 1.4142135623731 * this.a * Math.sin(theta) + this.y0;
  4691. p.x=x;
  4692. p.y=y;
  4693. return p;
  4694. },
  4695. inverse: function(p){
  4696. var theta;
  4697. var arg;
  4698. /* Inverse equations
  4699. -----------------*/
  4700. p.x-= this.x0;
  4701. //~ p.y -= this.y0;
  4702. var arg = p.y / (1.4142135623731 * this.a);
  4703. /* Because of division by zero problems, 'arg' can not be 1.0. Therefore
  4704. a number very close to one is used instead.
  4705. -------------------------------------------------------------------*/
  4706. if(Math.abs(arg) > 0.999999999999) arg=0.999999999999;
  4707. var theta =Math.asin(arg);
  4708. var lon = Proj4js.common.adjust_lon(this.long0 + (p.x / (0.900316316158 * this.a * Math.cos(theta))));
  4709. if(lon < (-Proj4js.common.PI)) lon= -Proj4js.common.PI;
  4710. if(lon > Proj4js.common.PI) lon= Proj4js.common.PI;
  4711. arg = (2.0 * theta + Math.sin(2.0 * theta)) / Proj4js.common.PI;
  4712. if(Math.abs(arg) > 1.0)arg=1.0;
  4713. var lat = Math.asin(arg);
  4714. //return(OK);
  4715. p.x=lon;
  4716. p.y=lat;
  4717. return p;
  4718. }
  4719. };