├── .gitignore ├── LICENSE ├── README.md ├── example ├── custom.geo.json ├── index.html ├── lambert.html ├── lib │ ├── proj4js-compressed.js │ └── proj4leaflet.js └── mollweide.html └── leaflet.latlng-graticule.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.pyc 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) JS Foundation and other contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | leaflet.latlng-graticule 2 | =========================== 3 | 4 | Create a Canvas as ImageOverlay to draw the Lat/Lon Graticule, 5 | 6 | and show the grid tick label at the edges of the map. 7 | 8 | Check out the [demo](https://cloudybay.github.io/leaflet.latlng-graticule/example/). 9 | 10 | 11 | ### Usage example 12 | 13 | ```javascript 14 | L.latlngGraticule({ 15 | showLabel: true, 16 | dashArray: [5, 5], 17 | zoomInterval: [ 18 | {start: 2, end: 3, interval: 30}, 19 | {start: 4, end: 4, interval: 10}, 20 | {start: 5, end: 7, interval: 5}, 21 | {start: 8, end: 10, interval: 1} 22 | ] 23 | }).addTo(map); 24 | ``` 25 | 26 | 27 | ### Options 28 | - **showLabel**: Show the grid tick label at the edges of the map. Default `true` 29 | - **opacity**: Opacity of the Graticule and Label. Default `1` 30 | - **weight**: The width of the graticule lines. Default `0.8` 31 | - **color**: The color of the graticule lines. Default `#aaa` 32 | - **font**: Font Style for the tick label. Default `12px Verdana` 33 | - **fontColor**: Color of the tick label. Default `#aaa` 34 | - **dashArray**: Used to achieve dashed lines. Default `[0,0]` 35 | - **sides**: Used to name sides of the world. Default `['N', 'S', 'E', 'W']` 36 | - **zoomInterval**: Use different intervals in different zoom levels. You can set for both latitude and longitude lines as the example, or set different intervals for latitude and longitude like below: 37 | ```javascript 38 | zoomInterval: { 39 | latitude: [ 40 | {start: 4, end: 6, interval: 5}, 41 | {start: 7, end: 20, interval: 1} 42 | ], 43 | longitude: [ 44 | {start: 4, end: 6, interval: 10}, 45 | {start: 7, end: 20, interval: 2} 46 | ] 47 | } 48 | ``` 49 | - ***Default***: 50 | ```javascript 51 | zoomInterval: [ 52 | {start: 2, end: 2, interval: 40}, 53 | {start: 3, end: 3, interval: 20}, 54 | {start: 4, end: 4, interval: 10}, 55 | {start: 5, end: 7, interval: 5}, 56 | {start: 8, end: 20, interval: 1} 57 | ] 58 | ``` 59 | 60 | #### Special Options 61 | Some of the projections (like Lambert) is no straight line, set those options to draw a polyline graticule. 62 | - **lngLineCurved**: Interval of polyline. Deafult `0` 63 | - **latLineCurved**: Interval of polyline. Deafult `0` 64 | 65 | Check out the [Lambert projection example](https://cloudybay.github.io/leaflet.latlng-graticule/example/lambert.html). 66 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet Lat/Lon Graticule Demo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 18 | 19 | 20 |
21 | 22 |
23 |
24 | 25 | 26 | 27 | 28 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /example/lambert.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leaflet Graticule 6 | 7 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 73 | 74 | -------------------------------------------------------------------------------- /example/lib/proj4js-compressed.js: -------------------------------------------------------------------------------- 1 | /* 2 | proj4js.js -- Javascript reprojection library. 3 | 4 | Authors: Mike Adair madairATdmsolutions.ca 5 | Richard Greenwood richATgreenwoodmap.com 6 | Didier Richard didier.richardATign.fr 7 | Stephen Irons stephen.ironsATclear.net.nz 8 | Olivier Terral oterralATgmail.com 9 | 10 | License: 11 | Copyright (c) 2012, Mike Adair, Richard Greenwood, Didier Richard, 12 | Stephen Irons and Olivier Terral 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a 15 | copy of this software and associated documentation files (the "Software"), 16 | to deal in the Software without restriction, including without limitation 17 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 | and/or sell copies of the Software, and to permit persons to whom the 19 | Software is furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included 22 | in all copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 25 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 27 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 29 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 30 | DEALINGS IN THE SOFTWARE. 31 | 32 | Note: This program is an almost direct port of the C library PROJ.4. 33 | */ 34 | var Proj4js={defaultDatum:"WGS84",transform:function(a,c,b){if(!a.readyToUse)return this.reportError("Proj4js initialization for:"+a.srsCode+" not yet complete"),b;if(!c.readyToUse)return this.reportError("Proj4js initialization for:"+c.srsCode+" not yet complete"),b;if(a.datum&&c.datum&&((a.datum.datum_type==Proj4js.common.PJD_3PARAM||a.datum.datum_type==Proj4js.common.PJD_7PARAM)&&"WGS84"!=c.datumCode||(c.datum.datum_type==Proj4js.common.PJD_3PARAM||c.datum.datum_type==Proj4js.common.PJD_7PARAM)&& 35 | "WGS84"!=a.datumCode)){var d=Proj4js.WGS84;this.transform(a,d,b);a=d}"enu"!=a.axis&&this.adjust_axis(a,!1,b);"longlat"==a.projName?(b.x*=Proj4js.common.D2R,b.y*=Proj4js.common.D2R):(a.to_meter&&(b.x*=a.to_meter,b.y*=a.to_meter),a.inverse(b));a.from_greenwich&&(b.x+=a.from_greenwich);b=this.datum_transform(a.datum,c.datum,b);c.from_greenwich&&(b.x-=c.from_greenwich);"longlat"==c.projName?(b.x*=Proj4js.common.R2D,b.y*=Proj4js.common.R2D):(c.forward(b),c.to_meter&&(b.x/=c.to_meter,b.y/=c.to_meter)); 36 | "enu"!=c.axis&&this.adjust_axis(c,!0,b);return b},datum_transform:function(a,c,b){if(a.compare_datums(c)||a.datum_type==Proj4js.common.PJD_NODATUM||c.datum_type==Proj4js.common.PJD_NODATUM)return b;if(a.es!=c.es||a.a!=c.a||a.datum_type==Proj4js.common.PJD_3PARAM||a.datum_type==Proj4js.common.PJD_7PARAM||c.datum_type==Proj4js.common.PJD_3PARAM||c.datum_type==Proj4js.common.PJD_7PARAM)a.geodetic_to_geocentric(b),(a.datum_type==Proj4js.common.PJD_3PARAM||a.datum_type==Proj4js.common.PJD_7PARAM)&&a.geocentric_to_wgs84(b), 37 | (c.datum_type==Proj4js.common.PJD_3PARAM||c.datum_type==Proj4js.common.PJD_7PARAM)&&c.geocentric_from_wgs84(b),c.geocentric_to_geodetic(b);return b},adjust_axis:function(a,c,b){for(var d=b.x,e=b.y,f=b.z||0,g,i,h=0;3>h;h++)if(!c||!(2==h&&void 0===b.z))switch(0==h?(g=d,i="x"):1==h?(g=e,i="y"):(g=f,i="z"),a.axis[h]){case "e":b[i]=g;break;case "w":b[i]=-g;break;case "n":b[i]=g;break;case "s":b[i]=-g;break;case "u":void 0!==b[i]&&(b.z=g);break;case "d":void 0!==b[i]&&(b.z=-g);break;default:return alert("ERROR: unknow axis ("+ 38 | a.axis[h]+") - check definition of "+a.projName),null}return b},reportError:function(){},extend:function(a,c){a=a||{};if(c)for(var b in c){var d=c[b];void 0!==d&&(a[b]=d)}return a},Class:function(){for(var a=function(){this.initialize.apply(this,arguments)},c={},b,d=0;d=f;f++)if(d=a*Math.sin(e),d=this.HALF_PI-2*Math.atan(c*Math.pow((1-d)/(1+d),b))-e,e+=d,1.0E-10>=Math.abs(d))return e;alert("phi2z has NoConvergence");return-9999},qsfnz:function(a,c){var b;return 1.0E-7a?-1:1},adjust_lon:function(a){return a=Math.abs(a)this.HALF_PI)return+Number.NaN;if(c==this.HALF_PI)return Number.POSITIVE_INFINITY;if(c==-1*this.HALF_PI)return-1*Number.POSITIVE_INFINITY;b*=a;return Math.log(Math.tan((this.HALF_PI+c)/2))+a*Math.log((1-b)/(1+b))/2},fL:function(a,c){return 2*Math.atan(a*Math.exp(c))-this.HALF_PI},invlatiso:function(a,c){var b=this.fL(1,c),d=0,e=0;do d=b,e=a*Math.sin(d),b=this.fL(Math.exp(a*Math.log((1+e)/(1-e))/2),c);while(1.0E-12< 62 | Math.abs(b-d));return b},sinh:function(a){a=Math.exp(a);return(a-1/a)/2},cosh:function(a){a=Math.exp(a);return(a+1/a)/2},tanh:function(a){a=Math.exp(a);return(a-1/a)/(a+1/a)},asinh:function(a){return(0<=a?1:-1)*Math.log(Math.abs(a)+Math.sqrt(a*a+1))},acosh:function(a){return 2*Math.log(Math.sqrt((a+1)/2)+Math.sqrt((a-1)/2))},atanh:function(a){return Math.log((a-1)/(a+1))/2},gN:function(a,c,b){c*=b;return a/Math.sqrt(1-c*c)},pj_enfn:function(a){var c=[];c[0]=this.C00-a*(this.C02+a*(this.C04+a*(this.C06+ 63 | a*this.C08)));c[1]=a*(this.C22-a*(this.C04+a*(this.C06+a*this.C08)));var b=a*a;c[2]=b*(this.C44-a*(this.C46+a*this.C48));b*=a;c[3]=b*(this.C66-a*this.C68);c[4]=b*a*this.C88;return c},pj_mlfn:function(a,c,b,d){b*=c;c*=c;return d[0]*a-b*(d[1]+c*(d[2]+c*(d[3]+c*d[4])))},pj_inv_mlfn:function(a,c,b){for(var d=1/(1-c),e=a,f=Proj4js.common.MAX_ITER;f;--f){var g=Math.sin(e),i=1-c*g*g,i=(this.pj_mlfn(e,g,Math.cos(e),b)-a)*i*Math.sqrt(i)*d,e=e-i;if(Math.abs(i)-1.001*Proj4js.common.HALF_PI)b=-Proj4js.common.HALF_PI;else if(b>Proj4js.common.HALF_PI&&b<1.001*Proj4js.common.HALF_PI)b=Proj4js.common.HALF_PI;else if(b<-Proj4js.common.HALF_PI||b>Proj4js.common.HALF_PI)return Proj4js.reportError("geocent:lat out of range:"+b),null;c>Proj4js.common.PI&&(c-=2*Proj4js.common.PI);f=Math.sin(b);g=Math.cos(b);e=this.a/Math.sqrt(1-this.es*f*f);b=(e+d)*g*Math.cos(c); 69 | c=(e+d)*g*Math.sin(c);d=(e*(1-this.es)+d)*f;a.x=b;a.y=c;a.z=d;return 0},geocentric_to_geodetic:function(a){var c,b,d,e,f,g,i,h,j,k,l=a.x;d=a.y;var m=a.z?a.z:0;c=Math.sqrt(l*l+d*d);b=Math.sqrt(l*l+d*d+m*m);if(1.0E-12>c/this.a){if(l=0,1.0E-12>b/this.a)return}else l=Math.atan2(d,l);d=m/b;e=c/b;f=1/Math.sqrt(1-this.es*(2-this.es)*e*e);i=e*(1-this.es)*f;h=d*f;k=0;do k++,g=this.a/Math.sqrt(1-this.es*h*h),b=c*i+m*h-g*(1-this.es*h*h),g=this.es*g/(g+b),f=1/Math.sqrt(1-g*(2-g)*e*e),g=e*(1-g)*f,f*=d,j=f*i-g* 70 | h,i=g,h=f;while(1.0E-24k);c=Math.atan(f/Math.abs(g));a.x=l;a.y=c;a.z=b;return a},geocentric_to_geodetic_noniter:function(a){var c=a.x,b=a.y,d=a.z?a.z:0,e,f,g,i,h,c=parseFloat(c),b=parseFloat(b),d=parseFloat(d);h=!1;if(0!=c)e=Math.atan2(b,c);else if(0b)e=-Proj4js.common.HALF_PI;else if(h=!0,e=0,0d)f=-Proj4js.common.HALF_PI;else return;g=c*c+b*b;c=Math.sqrt(g);b=d*Proj4js.common.AD_C;g=Math.sqrt(b*b+g);b/=g;g=c/g;b= 71 | d+this.b*this.ep2*b*b*b;i=c-this.a*this.es*g*g*g;g=Math.sqrt(b*b+i*i);b/=g;g=i/g;i=this.a/Math.sqrt(1-this.es*b*b);d=g>=Proj4js.common.COS_67P5?c/g-i:g<=-Proj4js.common.COS_67P5?c/-g-i:d/b+i*(this.es-1);!1==h&&(f=Math.atan(b/g));a.x=e;a.y=f;a.z=d;return a},geocentric_to_wgs84:function(a){if(this.datum_type==Proj4js.common.PJD_3PARAM)a.x+=this.datum_params[0],a.y+=this.datum_params[1],a.z+=this.datum_params[2];else if(this.datum_type==Proj4js.common.PJD_7PARAM){var c=this.datum_params[3],b=this.datum_params[4], 72 | d=this.datum_params[5],e=this.datum_params[6],f=e*(d*a.x+a.y-c*a.z)+this.datum_params[1],c=e*(-b*a.x+c*a.y+a.z)+this.datum_params[2];a.x=e*(a.x-d*a.y+b*a.z)+this.datum_params[0];a.y=f;a.z=c}},geocentric_from_wgs84:function(a){if(this.datum_type==Proj4js.common.PJD_3PARAM)a.x-=this.datum_params[0],a.y-=this.datum_params[1],a.z-=this.datum_params[2];else if(this.datum_type==Proj4js.common.PJD_7PARAM){var c=this.datum_params[3],b=this.datum_params[4],d=this.datum_params[5],e=this.datum_params[6],f=(a.x- 73 | this.datum_params[0])/e,g=(a.y-this.datum_params[1])/e,e=(a.z-this.datum_params[2])/e;a.x=f+d*g-b*e;a.y=-d*f+g+c*e;a.z=b*f-c*g+e}}}); 74 | Proj4js.Point=Proj4js.Class({initialize:function(a,c,b){"object"==typeof a?(this.x=a[0],this.y=a[1],this.z=a[2]||0):"string"==typeof a&&"undefined"==typeof c?(a=a.split(","),this.x=parseFloat(a[0]),this.y=parseFloat(a[1]),this.z=parseFloat(a[2])||0):(this.x=a,this.y=c,this.z=b||0)},clone:function(){return new Proj4js.Point(this.x,this.y,this.z)},toString:function(){return"x="+this.x+",y="+this.y},toShortString:function(){return this.x+", "+this.y}}); 75 | Proj4js.PrimeMeridian={greenwich:0,lisbon:-9.131906111111,paris:2.337229166667,bogota:-74.080916666667,madrid:-3.687938888889,rome:12.452333333333,bern:7.439583333333,jakarta:106.807719444444,ferro:-17.666666666667,brussels:4.367975,stockholm:18.058277777778,athens:23.7163375,oslo:10.722916666667}; 76 | Proj4js.Ellipsoid={MERIT:{a:6378137,rf:298.257,ellipseName:"MERIT 1983"},SGS85:{a:6378136,rf:298.257,ellipseName:"Soviet Geodetic System 85"},GRS80:{a:6378137,rf:298.257222101,ellipseName:"GRS 1980(IUGG, 1980)"},IAU76:{a:6378140,rf:298.257,ellipseName:"IAU 1976"},airy:{a:6377563.396,b:6356256.91,ellipseName:"Airy 1830"},"APL4.":{a:6378137,rf:298.25,ellipseName:"Appl. Physics. 1965"},NWL9D:{a:6378145,rf:298.25,ellipseName:"Naval Weapons Lab., 1965"},mod_airy:{a:6377340.189,b:6356034.446,ellipseName:"Modified Airy"}, 77 | andrae:{a:6377104.43,rf:300,ellipseName:"Andrae 1876 (Den., Iclnd.)"},aust_SA:{a:6378160,rf:298.25,ellipseName:"Australian Natl & S. Amer. 1969"},GRS67:{a:6378160,rf:298.247167427,ellipseName:"GRS 67(IUGG 1967)"},bessel:{a:6377397.155,rf:299.1528128,ellipseName:"Bessel 1841"},bess_nam:{a:6377483.865,rf:299.1528128,ellipseName:"Bessel 1841 (Namibia)"},clrk66:{a:6378206.4,b:6356583.8,ellipseName:"Clarke 1866"},clrk80:{a:6378249.145,rf:293.4663,ellipseName:"Clarke 1880 mod."},CPM:{a:6375738.7,rf:334.29, 78 | ellipseName:"Comm. des Poids et Mesures 1799"},delmbr:{a:6376428,rf:311.5,ellipseName:"Delambre 1810 (Belgium)"},engelis:{a:6378136.05,rf:298.2566,ellipseName:"Engelis 1985"},evrst30:{a:6377276.345,rf:300.8017,ellipseName:"Everest 1830"},evrst48:{a:6377304.063,rf:300.8017,ellipseName:"Everest 1948"},evrst56:{a:6377301.243,rf:300.8017,ellipseName:"Everest 1956"},evrst69:{a:6377295.664,rf:300.8017,ellipseName:"Everest 1969"},evrstSS:{a:6377298.556,rf:300.8017,ellipseName:"Everest (Sabah & Sarawak)"}, 79 | fschr60:{a:6378166,rf:298.3,ellipseName:"Fischer (Mercury Datum) 1960"},fschr60m:{a:6378155,rf:298.3,ellipseName:"Fischer 1960"},fschr68:{a:6378150,rf:298.3,ellipseName:"Fischer 1968"},helmert:{a:6378200,rf:298.3,ellipseName:"Helmert 1906"},hough:{a:6378270,rf:297,ellipseName:"Hough"},intl:{a:6378388,rf:297,ellipseName:"International 1909 (Hayford)"},kaula:{a:6378163,rf:298.24,ellipseName:"Kaula 1961"},lerch:{a:6378139,rf:298.257,ellipseName:"Lerch 1979"},mprts:{a:6397300,rf:191,ellipseName:"Maupertius 1738"}, 80 | new_intl:{a:6378157.5,b:6356772.2,ellipseName:"New International 1967"},plessis:{a:6376523,rf:6355863,ellipseName:"Plessis 1817 (France)"},krass:{a:6378245,rf:298.3,ellipseName:"Krassovsky, 1942"},SEasia:{a:6378155,b:6356773.3205,ellipseName:"Southeast Asia"},walbeck:{a:6376896,b:6355834.8467,ellipseName:"Walbeck"},WGS60:{a:6378165,rf:298.3,ellipseName:"WGS 60"},WGS66:{a:6378145,rf:298.25,ellipseName:"WGS 66"},WGS72:{a:6378135,rf:298.26,ellipseName:"WGS 72"},WGS84:{a:6378137,rf:298.257223563,ellipseName:"WGS 84"}, 81 | sphere:{a:6370997,b:6370997,ellipseName:"Normal Sphere (r=6370997)"}}; 82 | Proj4js.Datum={WGS84:{towgs84:"0,0,0",ellipse:"WGS84",datumName:"WGS84"},GGRS87:{towgs84:"-199.87,74.79,246.62",ellipse:"GRS80",datumName:"Greek_Geodetic_Reference_System_1987"},NAD83:{towgs84:"0,0,0",ellipse:"GRS80",datumName:"North_American_Datum_1983"},NAD27:{nadgrids:"@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat",ellipse:"clrk66",datumName:"North_American_Datum_1927"},potsdam:{towgs84:"606.0,23.0,413.0",ellipse:"bessel",datumName:"Potsdam Rauenberg 1950 DHDN"},carthage:{towgs84:"-263.0,6.0,431.0", 83 | ellipse:"clark80",datumName:"Carthage 1934 Tunisia"},hermannskogel:{towgs84:"653.0,-212.0,449.0",ellipse:"bessel",datumName:"Hermannskogel"},ire65:{towgs84:"482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15",ellipse:"mod_airy",datumName:"Ireland 1965"},nzgd49:{towgs84:"59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993",ellipse:"intl",datumName:"New Zealand Geodetic Datum 1949"},OSGB36:{towgs84:"446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894",ellipse:"airy",datumName:"Airy 1830"}}; 84 | Proj4js.WGS84=new Proj4js.Proj("WGS84");Proj4js.Datum.OSB36=Proj4js.Datum.OSGB36;Proj4js.wktProjections={"Lambert Tangential Conformal Conic Projection":"lcc",Mercator:"merc","Popular Visualisation Pseudo Mercator":"merc",Mercator_1SP:"merc",Transverse_Mercator:"tmerc","Transverse Mercator":"tmerc","Lambert Azimuthal Equal Area":"laea","Universal Transverse Mercator System":"utm"}; 85 | Proj4js.Proj.aea={init:function(){Math.abs(this.lat1+this.lat2)Proj4js.common.EPSLN?(this.ms1*this.ms1-this.ms2*this.ms2)/(this.qs2-this.qs1):this.con,this.c=this.ms1*this.ms1+this.ns0*this.qs1,this.rh=this.a*Math.sqrt(this.c-this.ns0*this.qs0)/ 87 | this.ns0)},forward:function(a){var c=a.x,b=a.y;this.sin_phi=Math.sin(b);this.cos_phi=Math.cos(b);var b=Proj4js.common.qsfnz(this.e3,this.sin_phi,this.cos_phi),b=this.a*Math.sqrt(this.c-this.ns0*b)/this.ns0,d=this.ns0*Proj4js.common.adjust_lon(c-this.long0),c=b*Math.sin(d)+this.x0,b=this.rh-b*Math.cos(d)+this.y0;a.x=c;a.y=b;return a},inverse:function(a){var c,b,d;a.x-=this.x0;a.y=this.rh-a.y+this.y0;0<=this.ns0?(c=Math.sqrt(a.x*a.x+a.y*a.y),b=1):(c=-Math.sqrt(a.x*a.x+a.y*a.y),b=-1);d=0;0!=c&&(d=Math.atan2(b* 88 | a.x,b*a.y));b=c*this.ns0/this.a;c=(this.c-b*b)/this.ns0;1.0E-10<=this.e3?(b=1-0.5*(1-this.es)*Math.log((1-this.e3)/(1+this.e3))/this.e3,b=1.0E-10=h;h++)if(b=Math.sin(g),d=Math.cos(g), 89 | e=a*b,f=1-e*e,b=0.5*f*f/d*(c/(1-i)-b/f+0.5/a*Math.log((1-e)/(1+e))),g+=b,1.0E-7>=Math.abs(b))return g;Proj4js.reportError("aea:phi1z:Convergence error");return null}}; 90 | Proj4js.Proj.sterea={dependsOn:"gauss",init:function(){Proj4js.Proj.gauss.init.apply(this);this.rc?(this.sinc0=Math.sin(this.phic0),this.cosc0=Math.cos(this.phic0),this.R2=2*this.rc,this.title||(this.title="Oblique Stereographic Alternative")):Proj4js.reportError("sterea:init:E_ERROR_0")},forward:function(a){var c,b,d,e;a.x=Proj4js.common.adjust_lon(a.x-this.long0);Proj4js.Proj.gauss.forward.apply(this,[a]);c=Math.sin(a.y);b=Math.cos(a.y);d=Math.cos(a.x);e=this.k0*this.R2/(1+this.sinc0*c+this.cosc0* 91 | b*d);a.x=e*b*Math.sin(a.x);a.y=e*(this.cosc0*c-this.sinc0*b*d);a.x=this.a*a.x+this.x0;a.y=this.a*a.y+this.y0;return a},inverse:function(a){var c,b,d,e;a.x=(a.x-this.x0)/this.a;a.y=(a.y-this.y0)/this.a;a.x/=this.k0;a.y/=this.k0;(e=Math.sqrt(a.x*a.x+a.y*a.y))?(d=2*Math.atan2(e,this.R2),c=Math.sin(d),b=Math.cos(d),d=Math.asin(b*this.sinc0+a.y*c*this.cosc0/e),c=Math.atan2(a.x*c,e*this.cosc0*b-a.y*this.sinc0*c)):(d=this.phic0,c=0);a.x=c;a.y=d;Proj4js.Proj.gauss.inverse.apply(this,[a]);a.x=Proj4js.common.adjust_lon(a.x+ 92 | this.long0);return a}};function phi4z(a,c,b,d,e,f,g,i,h){var j,k,l,m,n,o,h=f;for(o=1;15>=o;o++)if(j=Math.sin(h),l=Math.tan(h),i=l*Math.sqrt(1-a*j*j),k=Math.sin(2*h),m=c*h-b*k+d*Math.sin(4*h)-e*Math.sin(6*h),n=c-2*b*Math.cos(2*h)+4*d*Math.cos(4*h)-6*e*Math.cos(6*h),j=2*m+i*(m*m+g)-2*f*(i*m+1),l=a*k*(m*m+g-2*f*m)/(2*i),i=2*(f-m)*(i*n-2/k)-2*n,j/=l+i,h+=j,1.0E-10>=Math.abs(j))return h;Proj4js.reportError("phi4z: No convergence");return null} 93 | function e4fn(a){var c;c=1+a;a=1-a;return Math.sqrt(Math.pow(c,c)*Math.pow(a,a))} 94 | Proj4js.Proj.poly={init:function(){0==this.lat0&&(this.lat0=90);this.temp=this.b/this.a;this.es=1-Math.pow(this.temp,2);this.e=Math.sqrt(this.es);this.e0=Proj4js.common.e0fn(this.es);this.e1=Proj4js.common.e1fn(this.es);this.e2=Proj4js.common.e2fn(this.es);this.e3=Proj4js.common.e3fn(this.es);this.ml0=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat0)},forward:function(a){var c,b,d,e,f;d=a.y;b=Proj4js.common.adjust_lon(a.x-this.long0);1.0E-7>=Math.abs(d)?(f=this.x0+this.a*b,c=this.y0- 95 | this.a*this.ml0):(c=Math.sin(d),b=Math.cos(d),d=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,d),e=Proj4js.common.msfnz(this.e,c,b),b=c,f=this.x0+this.a*e*Math.sin(b)/c,c=this.y0+this.a*(d-this.ml0+e*(1-Math.cos(b))/c));a.x=f;a.y=c;return a},inverse:function(a){var c,b;a.x-=this.x0;a.y-=this.y0;c=this.ml0+a.y/this.a;if(1.0E-7>=Math.abs(c))c=a.x/this.a+this.long0,b=0;else{c=c*c+a.x/this.a*(a.x/this.a);c=phi4z(this.es,this.e0,this.e1,this.e2,this.e3,this.al,c,void 0,b);if(1!=c)return c;c=Proj4js.common.adjust_lon(Proj4js.common.asinz(NaN* 96 | a.x/this.a)/Math.sin(b)+this.long0)}a.x=c;a.y=b;return a}}; 97 | Proj4js.Proj.equi={init:function(){this.x0||(this.x0=0);this.y0||(this.y0=0);this.lat0||(this.lat0=0);this.long0||(this.long0=0)},forward:function(a){var c=a.y,b=this.x0+this.a*Proj4js.common.adjust_lon(a.x-this.long0)*Math.cos(this.lat0),c=this.y0+this.a*c;this.t1=b;this.t2=Math.cos(this.lat0);a.x=b;a.y=c;return a},inverse:function(a){a.x-=this.x0;a.y-=this.y0;var c=a.y/this.a;Math.abs(c)>Proj4js.common.HALF_PI&&Proj4js.reportError("equi:Inv:DataError");var b=Proj4js.common.adjust_lon(this.long0+ 98 | a.x/(this.a*Math.cos(this.lat0)));a.x=b;a.y=c}}; 99 | Proj4js.Proj.merc={init:function(){this.lat_ts&&(this.k0=this.sphere?Math.cos(this.lat_ts):Proj4js.common.msfnz(this.es,Math.sin(this.lat_ts),Math.cos(this.lat_ts)))},forward:function(a){var c=a.x,b=a.y;if(90b*Proj4js.common.R2D&&180c*Proj4js.common.R2D)return Proj4js.reportError("merc:forward: llInputOutOfRange: "+c+" : "+b),null;if(Math.abs(Math.abs(b)-Proj4js.common.HALF_PI)<=Proj4js.common.EPSLN)return Proj4js.reportError("merc:forward: ll2mAtPoles"),null; 100 | if(this.sphere)c=this.x0+this.a*this.k0*Proj4js.common.adjust_lon(c-this.long0),b=this.y0+this.a*this.k0*Math.log(Math.tan(Proj4js.common.FORTPI+0.5*b));else var d=Math.sin(b),b=Proj4js.common.tsfnz(this.e,b,d),c=this.x0+this.a*this.k0*Proj4js.common.adjust_lon(c-this.long0),b=this.y0-this.a*this.k0*Math.log(b);a.x=c;a.y=b;return a},inverse:function(a){var c=a.x-this.x0,b=a.y-this.y0;if(this.sphere)b=Proj4js.common.HALF_PI-2*Math.atan(Math.exp(-b/this.a*this.k0));else if(b=Math.exp(-b/(this.a*this.k0)), 101 | b=Proj4js.common.phi2z(this.e,b),-9999==b)return Proj4js.reportError("merc:inverse: lat = -9999"),null;c=Proj4js.common.adjust_lon(this.long0+c/(this.a*this.k0));a.x=c;a.y=b;return a}};Proj4js.Proj.utm={dependsOn:"tmerc",init:function(){this.zone?(this.lat0=0,this.long0=(6*Math.abs(this.zone)-183)*Proj4js.common.D2R,this.x0=5E5,this.y0=this.utmSouth?1E7:0,this.k0=0.9996,Proj4js.Proj.tmerc.init.apply(this),this.forward=Proj4js.Proj.tmerc.forward,this.inverse=Proj4js.Proj.tmerc.inverse):Proj4js.reportError("utm:init: zone must be specified for UTM")}}; 102 | Proj4js.Proj.eqdc={init:function(){this.mode||(this.mode=0);this.temp=this.b/this.a;this.es=1-Math.pow(this.temp,2);this.e=Math.sqrt(this.es);this.e0=Proj4js.common.e0fn(this.es);this.e1=Proj4js.common.e1fn(this.es);this.e2=Proj4js.common.e2fn(this.es);this.e3=Proj4js.common.e3fn(this.es);this.sinphi=Math.sin(this.lat1);this.cosphi=Math.cos(this.lat1);this.ms1=Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi);this.ml1=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat1);0!=this.mode? 103 | (Math.abs(this.lat1+this.lat2)=Proj4js.common.EPSLN?(this.ms1-this.ms2)/(this.ml2-this.ml1):this.sinphi):this.ns=this.sinphi;this.g=this.ml1+this.ms1/this.ns;this.ml0=Proj4js.common.mlfn(this.e0, 104 | this.e1,this.e2,this.e3,this.lat0);this.rh=this.a*(this.g-this.ml0)},forward:function(a){var c=a.x,b=this.a*(this.g-Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,a.y)),d=this.ns*Proj4js.common.adjust_lon(c-this.long0),c=this.x0+b*Math.sin(d),b=this.y0+this.rh-b*Math.cos(d);a.x=c;a.y=b;return a},inverse:function(a){a.x-=this.x0;a.y=this.rh-a.y+this.y0;var c,b;0<=this.ns?(b=Math.sqrt(a.x*a.x+a.y*a.y),c=1):(b=-Math.sqrt(a.x*a.x+a.y*a.y),c=-1);var d=0;0!=b&&(d=Math.atan2(c*a.x,c*a.y));c=this.phi3z(this.g- 105 | b/this.a,this.e0,this.e1,this.e2,this.e3);d=Proj4js.common.adjust_lon(this.long0+d/this.ns);a.x=d;a.y=c;return a},phi3z:function(a,c,b,d,e){var f,g;f=a;for(var i=0;15>i;i++)if(g=(a+b*Math.sin(2*f)-d*Math.sin(4*f)+e*Math.sin(6*f))/c-f,f+=g,1.0E-10>=Math.abs(g))return f;Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations");return null}}; 106 | Proj4js.Proj.tmerc={init:function(){this.e0=Proj4js.common.e0fn(this.es);this.e1=Proj4js.common.e1fn(this.es);this.e2=Proj4js.common.e2fn(this.es);this.e3=Proj4js.common.e3fn(this.es);this.ml0=this.a*Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat0)},forward:function(a){var c=a.y,b=Proj4js.common.adjust_lon(a.x-this.long0),d,e;d=Math.sin(c);var f=Math.cos(c);if(this.sphere){var g=f*Math.sin(b);if(1.0E-10>Math.abs(Math.abs(g)-1))return Proj4js.reportError("tmerc:forward: Point projects into infinity"), 107 | 93;e=0.5*this.a*this.k0*Math.log((1+g)/(1-g));d=Math.acos(f*Math.cos(b)/Math.sqrt(1-g*g));0>c&&(d=-d);c=this.a*this.k0*(d-this.lat0)}else{e=f*b;var b=Math.pow(e,2),f=this.ep2*Math.pow(f,2),g=Math.tan(c),i=Math.pow(g,2);d=1-this.es*Math.pow(d,2);d=this.a/Math.sqrt(d);c=this.a*Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,c);e=this.k0*d*e*(1+b/6*(1-i+f+b/20*(5-18*i+Math.pow(i,2)+72*f-58*this.ep2)))+this.x0;c=this.k0*(c-this.ml0+d*g*b*(0.5+b/24*(5-i+9*f+4*Math.pow(f,2)+b/30*(61-58*i+Math.pow(i, 108 | 2)+600*f-330*this.ep2))))+this.y0}a.x=e;a.y=c;return a},inverse:function(a){var c,b,d,e;if(this.sphere){b=Math.exp(a.x/(this.a*this.k0));var f=0.5*(b-1/b);d=this.lat0+a.y/(this.a*this.k0);e=Math.cos(d);c=Math.sqrt((1-e*e)/(1+f*f));b=Proj4js.common.asinz(c);0>d&&(b=-b);c=0==f&&0==e?this.long0:Proj4js.common.adjust_lon(Math.atan2(f,e)+this.long0)}else{var f=a.x-this.x0,g=a.y-this.y0;b=c=(this.ml0+g/this.k0)/this.a;for(e=0;;e++){d=(c+this.e1*Math.sin(2*b)-this.e2*Math.sin(4*b)+this.e3*Math.sin(6*b))/ 109 | this.e0-b;b+=d;if(Math.abs(d)<=Proj4js.common.EPSLN)break;if(6<=e)return Proj4js.reportError("tmerc:inverse: Latitude failed to converge"),95}if(Math.abs(b)this.a+1.0E-7&&Proj4js.reportError("orthoInvDataError");b=Proj4js.common.asinz(c/this.a);d=Math.sin(b);e=Math.cos(b);b=this.long0;Math.abs(c);d=Proj4js.common.asinz(e*this.sin_p14+a.y*d*this.cos_p14/c);c=Math.abs(this.lat0)-Proj4js.common.HALF_PI;Math.abs(c)<=Proj4js.common.EPSLN&&(b=0<=this.lat0?Proj4js.common.adjust_lon(this.long0+Math.atan2(a.x,-a.y)):Proj4js.common.adjust_lon(this.long0-Math.atan2(-a.x,a.y)));Math.sin(d);a.x=b;a.y=d;return a}}; 116 | Proj4js.Proj.krovak={init:function(){this.a=6377397.155;this.es=0.006674372230614;this.e=Math.sqrt(this.es);this.lat0||(this.lat0=0.863937979737193);this.long0||(this.long0=0.4334234309119251);this.k0||(this.k0=0.9999);this.s45=0.785398163397448;this.s90=2*this.s45;this.fi0=this.lat0;this.e2=this.es;this.e=Math.sqrt(this.e2);this.alfa=Math.sqrt(1+this.e2*Math.pow(Math.cos(this.fi0),4)/(1-this.e2));this.uq=1.04216856380474;this.u0=Math.asin(Math.sin(this.fi0)/this.alfa);this.g=Math.pow((1+this.e*Math.sin(this.fi0))/ 117 | (1-this.e*Math.sin(this.fi0)),this.alfa*this.e/2);this.k=Math.tan(this.u0/2+this.s45)/Math.pow(Math.tan(this.fi0/2+this.s45),this.alfa)*this.g;this.k1=this.k0;this.n0=this.a*Math.sqrt(1-this.e2)/(1-this.e2*Math.pow(Math.sin(this.fi0),2));this.s0=1.37008346281555;this.n=Math.sin(this.s0);this.ro0=this.k1*this.n0/Math.tan(this.s0);this.ad=this.s90-this.uq},forward:function(a){var c,b,d;b=a.y;d=Proj4js.common.adjust_lon(a.x-this.long0);c=Math.pow((1+this.e*Math.sin(b))/(1-this.e*Math.sin(b)),this.alfa* 118 | this.e/2);c=2*(Math.atan(this.k*Math.pow(Math.tan(b/2+this.s45),this.alfa)/c)-this.s45);b=-d*this.alfa;d=Math.asin(Math.cos(this.ad)*Math.sin(c)+Math.sin(this.ad)*Math.cos(c)*Math.cos(b));c=this.n*Math.asin(Math.cos(c)*Math.sin(b)/Math.cos(d));d=this.ro0*Math.pow(Math.tan(this.s0/2+this.s45),this.n)/Math.pow(Math.tan(d/2+this.s45),this.n);a.y=d*Math.cos(c)/1;a.x=d*Math.sin(c)/1;this.czech&&(a.y*=-1,a.x*=-1);return a},inverse:function(a){var c,b,d;c=a.x;a.x=a.y;a.y=c;this.czech&&(a.y*=-1,a.x*=-1); 119 | c=Math.sqrt(a.x*a.x+a.y*a.y);b=Math.atan2(a.y,a.x)/Math.sin(this.s0);d=2*(Math.atan(Math.pow(this.ro0/c,1/this.n)*Math.tan(this.s0/2+this.s45))-this.s45);c=Math.asin(Math.cos(this.ad)*Math.sin(d)-Math.sin(this.ad)*Math.cos(d)*Math.cos(b));b=Math.asin(Math.cos(d)*Math.sin(b)/Math.cos(c));a.x=this.long0-b/this.alfa;b=c;var e=d=0;do a.y=2*(Math.atan(Math.pow(this.k,-1/this.alfa)*Math.pow(Math.tan(c/2+this.s45),1/this.alfa)*Math.pow((1+this.e*Math.sin(b))/(1-this.e*Math.sin(b)),this.e/2))-this.s45),1.0E-10> 120 | Math.abs(b-a.y)&&(d=1),b=a.y,e+=1;while(0==d&&15>e);return 15<=e?(Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations"),null):a}}; 121 | Proj4js.Proj.somerc={init:function(){var a=this.lat0;this.lambda0=this.long0;var c=Math.sin(a),b=this.a,d=1/this.rf,d=2*d-Math.pow(d,2),e=this.e=Math.sqrt(d);this.R=this.k0*b*Math.sqrt(1-d)/(1-d*Math.pow(c,2));this.alpha=Math.sqrt(1+d/(1-d)*Math.pow(Math.cos(a),4));this.b0=Math.asin(c/this.alpha);this.K=Math.log(Math.tan(Math.PI/4+this.b0/2))-this.alpha*Math.log(Math.tan(Math.PI/4+a/2))+this.alpha*e/2*Math.log((1+e*c)/(1-e*c))},forward:function(a){var c=Math.log(Math.tan(Math.PI/4-a.y/2)),b=this.e/ 122 | 2*Math.log((1+this.e*Math.sin(a.y))/(1-this.e*Math.sin(a.y))),b=2*(Math.atan(Math.exp(-this.alpha*(c+b)+this.K))-Math.PI/4),d=this.alpha*(a.x-this.lambda0),c=Math.atan(Math.sin(d)/(Math.sin(this.b0)*Math.tan(b)+Math.cos(this.b0)*Math.cos(d))),b=Math.asin(Math.cos(this.b0)*Math.sin(b)-Math.sin(this.b0)*Math.cos(b)*Math.cos(d));a.y=this.R/2*Math.log((1+Math.sin(b))/(1-Math.sin(b)))+this.y0;a.x=this.R*c+this.x0;return a},inverse:function(a){for(var c=(a.x-this.x0)/this.R,b=2*(Math.atan(Math.exp((a.y- 123 | this.y0)/this.R))-Math.PI/4),d=Math.asin(Math.cos(this.b0)*Math.sin(b)+Math.sin(this.b0)*Math.cos(b)*Math.cos(c)),c=this.lambda0+Math.atan(Math.sin(c)/(Math.cos(this.b0)*Math.cos(c)-Math.sin(this.b0)*Math.tan(b)))/this.alpha,b=0,e=d,f=-1E3,g=0;1.0E-7this.lat0?this.S_POLE:this.N_POLE:a>Proj4js.common.EPSLN?this.OBLIQ:this.EQUIT;this.phits=Math.abs(this.phits);if(this.es){var c;switch(this.mode){case this.N_POLE:case this.S_POLE:Math.abs(this.phits-Proj4js.common.HALF_PI)< 126 | Proj4js.common.EPSLN?this.akm1=2*this.k0/Math.sqrt(Math.pow(1+this.e,1+this.e)*Math.pow(1-this.e,1-this.e)):(a=Math.sin(this.phits),this.akm1=Math.cos(this.phits)/Proj4js.common.tsfnz(this.e,this.phits,a),a*=this.e,this.akm1/=Math.sqrt(1-a*a));break;case this.EQUIT:this.akm1=2*this.k0;break;case this.OBLIQ:a=Math.sin(this.lat0),c=2*Math.atan(this.ssfn_(this.lat0,a,this.e))-Proj4js.common.HALF_PI,a*=this.e,this.akm1=2*this.k0*Math.cos(this.lat0)/Math.sqrt(1-a*a),this.sinX1=Math.sin(c),this.cosX1=Math.cos(c)}}else switch(this.mode){case this.OBLIQ:this.sinph0= 127 | Math.sin(this.lat0),this.cosph0=Math.cos(this.lat0);case this.EQUIT:this.akm1=2*this.k0;break;case this.S_POLE:case this.N_POLE:this.akm1=Math.abs(this.phits-Proj4js.common.HALF_PI)>=Proj4js.common.EPSLN?Math.cos(this.phits)/Math.tan(Proj4js.common.FORTPI-0.5*this.phits):2*this.k0}},forward:function(a){var c=a.x,c=Proj4js.common.adjust_lon(c-this.long0),b=a.y,d,e;if(this.sphere){var f,g,i;f=Math.sin(b);g=Math.cos(b);i=Math.cos(c);c=Math.sin(c);switch(this.mode){case this.EQUIT:e=1+g*i;e<=Proj4js.common.EPSLN&& 128 | Proj4js.reportError("stere:forward:Equit");e=this.akm1/e;d=e*g*c;e*=f;break;case this.OBLIQ:e=1+this.sinph0*f+this.cosph0*g*i;e<=Proj4js.common.EPSLN&&Proj4js.reportError("stere:forward:Obliq");e=this.akm1/e;d=e*g*c;e*=this.cosph0*f-this.sinph0*g*i;break;case this.N_POLE:i=-i,b=-b;case this.S_POLE:Math.abs(b-Proj4js.common.HALF_PI)=f;f++)d*=c,e+=this.A[f]*d;for(var c=e,d=1,g=0,i=0,h=0,f=1;6>=f;f++)e=d*c-g*b,g=g*c+d*b,d=e,i=i+this.B_re[f]*d-this.B_im[f]*g,h=h+this.B_im[f]*d+this.B_re[f]*g;a.x=h*this.a+this.x0;a.y=i*this.a+this.y0;return a},inverse:function(a){for(var c=(a.y-this.y0)/this.a,b=(a.x-this.x0)/this.a,d=1,e=0,f,g=0,i=0,h=1;6>=h;h++)f= 136 | d*c-e*b,e=e*c+d*b,d=f,g=g+this.C_re[h]*d-this.C_im[h]*e,i=i+this.C_im[h]*d+this.C_re[h]*e;for(d=0;d=h;h++)l=j*g-k*i,k=k*g+j*i,j=l,f+=(h-1)*(this.B_re[h]*j-this.B_im[h]*k),e+=(h-1)*(this.B_im[h]*j+this.B_re[h]*k);for(var j=1,k=0,m=this.B_re[1],n=this.B_im[1],h=2;6>=h;h++)l=j*g-k*i,k=k*g+j*i,j=l,m+=h*(this.B_re[h]*j-this.B_im[h]*k),n+=h*(this.B_im[h]*j+this.B_re[h]*k);i=m*m+n*n;g=(f*m+e*n)/i;i=(e*m-f*n)/i}c=g;b=1;g=0;for(h=1;9>=h;h++)b*=c,g+=this.D[h]* 137 | b;h=this.lat0+1E5*g*Proj4js.common.SEC_TO_RAD;a.x=this.long0+i;a.y=h;return a}};Proj4js.Proj.mill={init:function(){},forward:function(a){var c=a.y,b=this.x0+this.a*Proj4js.common.adjust_lon(a.x-this.long0),c=this.y0+1.25*this.a*Math.log(Math.tan(Proj4js.common.PI/4+c/2.5));a.x=b;a.y=c;return a},inverse:function(a){a.x-=this.x0;a.y-=this.y0;var c=Proj4js.common.adjust_lon(this.long0+a.x/this.a),b=2.5*(Math.atan(Math.exp(0.8*a.y/this.a))-Proj4js.common.PI/4);a.x=c;a.y=b;return a}}; 138 | Proj4js.Proj.gnom={init:function(){this.sin_p14=Math.sin(this.lat0);this.cos_p14=Math.cos(this.lat0);this.infinity_dist=1E3*this.a;this.rc=1},forward:function(a){var c,b,d,e,f;b=a.y;d=Proj4js.common.adjust_lon(a.x-this.long0);c=Math.sin(b);b=Math.cos(b);e=Math.cos(d);f=this.sin_p14*c+this.cos_p14*b*e;0b&&(f=-f);b=this.x0+f;f=Math.abs(f/(Proj4js.common.PI*this.R));c=0<=c?this.y0+Proj4js.common.PI*this.R*Math.sqrt(1-f*f-2*e*f):this.y0-Proj4js.common.PI*this.R*Math.sqrt(1-f*f-2*e*f);a.x=b;a.y=c;return a},inverse:function(a){var c,b,d,e,f,g,i,h;a.x-=this.x0;a.y-=this.y0;h=Proj4js.common.PI*this.R;c=a.x/h;d=a.y/h;e=c*c+d*d;f=-Math.abs(d)*(1+e);b=f-2*d*d+c*c;g=-2*f+1+2*d*d+e*e;h=d*d/g+(2*b*b*b/g/g/g-9*f*b/g/g)/27;i=(f-b*b/3/g)/g;f=2*Math.sqrt(-i/3);h=3*h/i/f;1Math.abs(b-a.y))break;a.y=b}if(!e)return Proj4js.reportError("gauss:inverse:convergence failed"),null;a.x=c;a.y=b;return a}}; 155 | Proj4js.Proj.omerc={init:function(){this.mode||(this.mode=0);this.lon1||(this.lon1=0,this.mode=1);this.lon2||(this.lon2=0);this.lat2||(this.lat2=0);var a=1-Math.pow(this.b/this.a,2);Math.sqrt(a);this.sin_p20=Math.sin(this.lat0);this.cos_p20=Math.cos(this.lat0);this.con=1-this.es*this.sin_p20*this.sin_p20;this.com=Math.sqrt(1-a);this.bl=Math.sqrt(1+this.es*Math.pow(this.cos_p20,4)/(1-a));this.al=this.a*this.bl*this.k0*this.com/this.con;Math.abs(this.lat0) 157 | Proj4js.common.EPSLN&&Math.abs(this.con-Proj4js.common.HALF_PI)>Proj4js.common.EPSLN?(this.singam=Math.sin(this.gama),this.cosgam=Math.cos(this.gama),this.sinaz=Math.sin(this.alpha),this.cosaz=Math.cos(this.alpha),this.u=0<=this.lat0?this.al/this.bl*Math.atan(Math.sqrt(this.d*this.d-1)/this.cosaz):-(this.al/this.bl)*Math.atan(Math.sqrt(this.d*this.d-1)/this.cosaz)):Proj4js.reportError("omerc:Init:DataError")):(this.sinphi=Math.sin(this.at1),this.ts1=Proj4js.common.tsfnz(this.e,this.lat1,this.sinphi), 158 | this.sinphi=Math.sin(this.lat2),this.ts2=Proj4js.common.tsfnz(this.e,this.lat2,this.sinphi),this.h=Math.pow(this.ts1,this.bl),this.l=Math.pow(this.ts2,this.bl),this.f=this.el/this.h,this.g=0.5*(this.f-1/this.f),this.j=(this.el*this.el-this.l*this.h)/(this.el*this.el+this.l*this.h),this.p=(this.l-this.h)/(this.l+this.h),this.dlon=this.lon1-this.lon2,this.dlon<-Proj4js.common.PI&&(this.lon2-=2*Proj4js.common.PI),this.dlon>Proj4js.common.PI&&(this.lon2+=2*Proj4js.common.PI),this.dlon=this.lon1-this.lon2, 159 | this.longc=0.5*(this.lon1+this.lon2)-Math.atan(this.j*Math.tan(0.5*this.bl*this.dlon)/this.p)/this.bl,this.dlon=Proj4js.common.adjust_lon(this.lon1-this.longc),this.gama=Math.atan(Math.sin(this.bl*this.dlon)/this.g),this.alpha=Proj4js.common.asinz(this.d*Math.sin(this.gama)),Math.abs(this.lat1-this.lat2)<=Proj4js.common.EPSLN?Proj4js.reportError("omercInitDataError"):this.con=Math.abs(this.lat1),this.con<=Proj4js.common.EPSLN||Math.abs(this.con-Proj4js.common.HALF_PI)<=Proj4js.common.EPSLN?Proj4js.reportError("omercInitDataError"): 160 | Math.abs(Math.abs(this.lat0)-Proj4js.common.HALF_PI)<=Proj4js.common.EPSLN&&Proj4js.reportError("omercInitDataError"),this.singam=Math.sin(this.gam),this.cosgam=Math.cos(this.gam),this.sinaz=Math.sin(this.alpha),this.cosaz=Math.cos(this.alpha),this.u=0<=this.lat0?this.al/this.bl*Math.atan(Math.sqrt(this.d*this.d-1)/this.cosaz):-(this.al/this.bl)*Math.atan(Math.sqrt(this.d*this.d-1)/this.cosaz))},forward:function(a){var c,b,d,e,f;d=a.x;b=a.y;c=Math.sin(b);e=Proj4js.common.adjust_lon(d-this.longc); 161 | d=Math.sin(this.bl*e);Math.abs(Math.abs(b)-Proj4js.common.HALF_PI)>Proj4js.common.EPSLN?(c=Proj4js.common.tsfnz(this.e,b,c),c=this.el/Math.pow(c,this.bl),f=0.5*(c-1/c),c=(f*this.singam-d*this.cosgam)/(0.5*(c+1/c)),b=Math.cos(this.bl*e),1.0E-7>Math.abs(b)?d=this.al*this.bl*e:(d=this.al*Math.atan((f*this.cosgam+d*this.singam)/b)/this.bl,0>b&&(d+=Proj4js.common.PI*this.al/this.bl))):(c=0<=b?this.singam:-this.singam,d=this.al*b/this.bl);Math.abs(Math.abs(c)-1)<=Proj4js.common.EPSLN&&Proj4js.reportError("omercFwdInfinity"); 162 | e=0.5*this.al*Math.log((1-c)/(1+c))/this.bl;d-=this.u;c=this.y0+d*this.cosaz-e*this.sinaz;a.x=this.x0+e*this.cosaz+d*this.sinaz;a.y=c;return a},inverse:function(a){var c,b,d,e;a.x-=this.x0;a.y-=this.y0;c=a.x*this.cosaz-a.y*this.sinaz;d=a.y*this.cosaz+a.x*this.sinaz;d+=this.u;b=Math.exp(-this.bl*c/this.al);c=0.5*(b-1/b);b=0.5*(b+1/b);d=Math.sin(this.bl*d/this.al);e=(d*this.cosgam+c*this.singam)/b;Math.abs(Math.abs(e)-1)<=Proj4js.common.EPSLN?(c=this.longc,e=0<=e?Proj4js.common.HALF_PI:-Proj4js.common.HALF_PI): 163 | (b=1/this.bl,e=Math.pow(this.el/Math.sqrt((1+e)/(1-e)),b),e=Proj4js.common.phi2z(this.e,e),c=this.longc-Math.atan2(c*this.cosgam-d*this.singam,b)/this.bl,c=Proj4js.common.adjust_lon(c));a.x=c;a.y=e;return a}}; 164 | Proj4js.Proj.lcc={init:function(){this.lat2||(this.lat2=this.lat0);this.k0||(this.k0=1);if(Math.abs(this.lat1+this.lat2)Proj4js.common.EPSLN?Math.log(c/e)/Math.log(b/d):a;this.f0=c/(this.ns*Math.pow(b,this.ns));this.rh=this.a*this.f0*Math.pow(f,this.ns);this.title||(this.title="Lambert Conformal Conic")}},forward:function(a){var c=a.x,b=a.y;if(!(90>=b&&-90<=b&&180>=c&&-180<=c))return Proj4js.reportError("lcc:forward: llInputOutOfRange: "+c+" : "+b),null;var d=Math.abs(Math.abs(b)-Proj4js.common.HALF_PI);if(d>Proj4js.common.EPSLN)b=Proj4js.common.tsfnz(this.e, 166 | b,Math.sin(b)),b=this.a*this.f0*Math.pow(b,this.ns);else{d=b*this.ns;if(0>=d)return Proj4js.reportError("lcc:forward: No Projection"),null;b=0}c=this.ns*Proj4js.common.adjust_lon(c-this.long0);a.x=this.k0*b*Math.sin(c)+this.x0;a.y=this.k0*(this.rh-b*Math.cos(c))+this.y0;return a},inverse:function(a){var c,b,d,e=(a.x-this.x0)/this.k0,f=this.rh-(a.y-this.y0)/this.k0;0this.lat0?this.S_POLE:this.N_POLE:Math.abs(a)g){Proj4js.reportError("aeqd:Fwd:PointError");return}}else b=Math.acos(g),b/=Math.sin(b);a.x=this.x0+this.a*b*e*Math.sin(c);a.y=this.y0+this.a*b*(this.cos_p12*d-this.sin_p12*e*f);return a}, 177 | inverse:function(a){a.x-=this.x0;a.y-=this.y0;var c=Math.sqrt(a.x*a.x+a.y*a.y);if(c>2*Proj4js.common.HALF_PI*this.a)Proj4js.reportError("aeqdInvDataError");else{var b=c/this.a,d=Math.sin(b),b=Math.cos(b),e=this.long0,f;if(Math.abs(c)<=Proj4js.common.EPSLN)f=this.lat0;else{f=Proj4js.common.asinz(b*this.sin_p12+a.y*d*this.cos_p12/c);var g=Math.abs(this.lat0)-Proj4js.common.HALF_PI;Math.abs(g)<=Proj4js.common.EPSLN?e=0<=this.lat0?Proj4js.common.adjust_lon(this.long0+Math.atan2(a.x,-a.y)):Proj4js.common.adjust_lon(this.long0- 178 | Math.atan2(-a.x,a.y)):(g=b-this.sin_p12*Math.sin(f),Math.abs(g)Proj4js.common.PI&&(b=Proj4js.common.PI);c=(2*c+Math.sin(2*c))/Proj4js.common.PI;1 1e-3) { 116 | throw new Error("Projected bounds does not match grid at zoom " + i); 117 | } 118 | } 119 | }, 120 | 121 | getTileUrl: function(tilePoint) { 122 | var gridHeight = 123 | Math.round((this.crs.projectedBounds[3] - this.crs.projectedBounds[1]) / 124 | this._projectedTileSize(this._map.getZoom())); 125 | 126 | // TODO: relies on some of TileLayer's internals 127 | return L.Util.template(this._url, L.Util.extend({ 128 | s: this._getSubdomain(tilePoint), 129 | z: this._getZoomForUrl(), 130 | x: tilePoint.x, 131 | y: gridHeight - tilePoint.y - 1 132 | }, this.options)); 133 | }, 134 | 135 | _projectedTileSize: function(zoom) { 136 | return (this.options.tileSize / this.crs.scale(zoom)); 137 | } 138 | }); 139 | 140 | if (typeof module !== 'undefined') module.exports = L.Proj; 141 | 142 | if (typeof L !== 'undefined' && typeof L.CRS !== 'undefined') { 143 | // This is left here for backwards compatibility 144 | L.CRS.proj4js = (function () { 145 | return function (code, def, transformation, options) { 146 | options = options || {}; 147 | if (transformation) options.transformation = transformation; 148 | 149 | return new L.Proj.CRS(code, def, options); 150 | }; 151 | }()); 152 | } -------------------------------------------------------------------------------- /example/mollweide.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leaflet Graticule 6 | 7 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 56 | 57 | -------------------------------------------------------------------------------- /leaflet.latlng-graticule.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable indent,semi */ 2 | /** 3 | * Create a Canvas as ImageOverlay to draw the Lat/Lon Graticule, 4 | * and show the axis tick label on the edge of the map. 5 | * Author: lanwei@cloudybay.com.tw 6 | */ 7 | 8 | (function (window, document, undefined) { 9 | 10 | L.LatLngGraticule = L.Layer.extend({ 11 | includes: (L.Evented.prototype || L.Mixin.Events), 12 | options: { 13 | showLabel: true, 14 | opacity: 1, 15 | weight: 0.8, 16 | color: '#aaa', 17 | font: '12px Verdana', 18 | dashArray: [0,0], 19 | lngLineCurved: 0, 20 | latLineCurved: 0, 21 | zoomInterval: [ 22 | {start: 2, end: 2, interval: 40}, 23 | {start: 3, end: 3, interval: 20}, 24 | {start: 4, end: 4, interval: 10}, 25 | {start: 5, end: 7, interval: 5}, 26 | {start: 8, end: 20, interval: 1} 27 | ], 28 | sides: ['N', 'S', 'E', 'W'] 29 | }, 30 | 31 | initialize: function (options) { 32 | L.setOptions(this, options); 33 | 34 | var defaultFontName = 'Verdana'; 35 | var _ff = this.options.font.split(' '); 36 | if (_ff.length < 2) { 37 | this.options.font += ' ' + defaultFontName; 38 | } 39 | 40 | if (!this.options.fontColor) { 41 | this.options.fontColor = this.options.color; 42 | } 43 | 44 | if (this.options.zoomInterval) { 45 | if (this.options.zoomInterval.latitude) { 46 | this.options.latInterval = this.options.zoomInterval.latitude; 47 | if (!this.options.zoomInterval.longitude) { 48 | this.options.lngInterval = this.options.zoomInterval.latitude; 49 | } 50 | } 51 | if (this.options.zoomInterval.longitude) { 52 | this.options.lngInterval = this.options.zoomInterval.longitude; 53 | if (!this.options.zoomInterval.latitude) { 54 | this.options.latInterval = this.options.zoomInterval.longitude; 55 | } 56 | } 57 | if (!this.options.latInterval) { 58 | this.options.latInterval = this.options.zoomInterval; 59 | } 60 | if (!this.options.lngInterval) { 61 | this.options.lngInterval = this.options.zoomInterval; 62 | } 63 | } 64 | }, 65 | 66 | onAdd: function (map) { 67 | this._map = map; 68 | 69 | if (!this._canvas) { 70 | this._initCanvas(); 71 | } 72 | 73 | map._panes.overlayPane.appendChild(this._canvas); 74 | 75 | map.on('viewreset', this._reset, this); 76 | map.on('move', this._reset, this); 77 | map.on('moveend', this._reset, this); 78 | 79 | if (map.options.zoomAnimation && L.Browser.any3d) { 80 | map.on('zoomanim', this._animateZoom, this); 81 | } 82 | 83 | this._reset(); 84 | }, 85 | 86 | onRemove: function (map) { 87 | L.DomUtil.remove(this._canvas); 88 | 89 | map.off('viewreset', this._reset, this); 90 | map.off('move', this._reset, this); 91 | map.off('moveend', this._reset, this); 92 | 93 | if (map.options.zoomAnimation) { 94 | map.off('zoomanim', this._animateZoom, this); 95 | } 96 | }, 97 | 98 | addTo: function (map) { 99 | map.addLayer(this); 100 | return this; 101 | }, 102 | 103 | setOpacity: function (opacity) { 104 | this.options.opacity = opacity; 105 | this._updateOpacity(); 106 | return this; 107 | }, 108 | 109 | bringToFront: function () { 110 | if (this._canvas) { 111 | //this._map._panes.overlayPane.appendChild(this._canvas); 112 | } 113 | return this; 114 | }, 115 | 116 | bringToBack: function () { 117 | var pane = this._map._panes.overlayPane; 118 | if (this._canvas) { 119 | //pane.insertBefore(this._canvas, pane.firstChild); 120 | } 121 | return this; 122 | }, 123 | 124 | getAttribution: function () { 125 | return this.options.attribution; 126 | }, 127 | 128 | _initCanvas: function () { 129 | 130 | this._canvas = L.DomUtil.create('canvas', ''); 131 | 132 | if (this._map.options.zoomAnimation && L.Browser.any3d) { 133 | L.DomUtil.addClass(this._canvas, 'leaflet-zoom-animated'); 134 | } else { 135 | L.DomUtil.addClass(this._canvas, 'leaflet-zoom-hide'); 136 | } 137 | 138 | this._updateOpacity(); 139 | 140 | 141 | L.extend(this._canvas, { 142 | onselectstart: L.Util.falseFn, 143 | onmousemove: L.Util.falseFn, 144 | onload: L.bind(this._onCanvasLoad, this) 145 | }); 146 | }, 147 | 148 | _animateZoom: function (e) { 149 | var map = this._map, 150 | canvas = this._canvas, 151 | scale = map.getZoomScale(e.zoom), 152 | nw = map.containerPointToLatLng([0, 0]), 153 | se = map.containerPointToLatLng([canvas.width, canvas.height]), 154 | topLeft = map._latLngToNewLayerPoint(nw, e.zoom, e.center), 155 | size = map._latLngToNewLayerPoint(se, e.zoom, e.center)._subtract(topLeft), 156 | origin = topLeft._add(size._multiplyBy((1 / 2) * (1 - 1 / scale))); 157 | 158 | L.DomUtil.setTransform(canvas, origin, scale); 159 | }, 160 | 161 | _reset: function () { 162 | var canvas = this._canvas, 163 | size = this._map.getSize(), 164 | lt = this._map.containerPointToLayerPoint([0, 0]); 165 | 166 | L.DomUtil.setPosition(canvas, lt); 167 | 168 | canvas.width = size.x; 169 | canvas.height = size.y; 170 | canvas.style.width = size.x + 'px'; 171 | canvas.style.height = size.y + 'px'; 172 | 173 | this.__calcInterval(); 174 | 175 | this.__draw(true); 176 | }, 177 | 178 | _onCanvasLoad: function () { 179 | this.fire('load'); 180 | }, 181 | 182 | _updateOpacity: function () { 183 | L.DomUtil.setOpacity(this._canvas, this.options.opacity); 184 | }, 185 | 186 | __format_lat: function(lat) { 187 | if (this.options.latFormatTickLabel) { 188 | return this.options.latFormatTickLabel(lat); 189 | } 190 | 191 | // todo: format type of float 192 | if (lat < 0) { 193 | return '' + (lat*-1) + this.options.sides[1]; 194 | } 195 | else if (lat > 0) { 196 | return '' + lat + this.options.sides[0]; 197 | } 198 | return '' + lat; 199 | }, 200 | 201 | __format_lng: function(lng) { 202 | if (this.options.lngFormatTickLabel) { 203 | return this.options.lngFormatTickLabel(lng); 204 | } 205 | 206 | // todo: format type of float 207 | if (lng > 180) { 208 | return '' + (360 - lng) + this.options.sides[3]; 209 | } 210 | else if (lng > 0 && lng < 180) { 211 | return '' + lng + this.options.sides[2]; 212 | } 213 | else if (lng < 0 && lng > -180) { 214 | return '' + (lng*-1) + this.options.sides[3]; 215 | } 216 | else if (lng == -180) { 217 | return '' + (lng*-1); 218 | } 219 | else if (lng < -180) { 220 | return '' + (360 + lng) + this.options.sides[3]; 221 | } 222 | return '' + lng; 223 | }, 224 | 225 | __calcInterval: function() { 226 | var zoom = this._map.getZoom(); 227 | if (this._currZoom != zoom) { 228 | this._currLngInterval = 0; 229 | this._currLatInterval = 0; 230 | this._currZoom = zoom; 231 | } 232 | 233 | var interv; 234 | 235 | if (!this._currLngInterval) { 236 | try { 237 | for (var idx in this.options.lngInterval) { 238 | var dict = this.options.lngInterval[idx]; 239 | if (dict.start <= zoom) { 240 | if (dict.end && dict.end >= zoom) { 241 | this._currLngInterval = dict.interval; 242 | break; 243 | } 244 | } 245 | } 246 | } 247 | catch(e) { 248 | this._currLngInterval = 0; 249 | } 250 | } 251 | 252 | if (!this._currLatInterval) { 253 | try { 254 | for (var idx in this.options.latInterval) { 255 | var dict = this.options.latInterval[idx]; 256 | if (dict.start <= zoom) { 257 | if (dict.end && dict.end >= zoom) { 258 | this._currLatInterval = dict.interval; 259 | break; 260 | } 261 | } 262 | } 263 | } 264 | catch(e) { 265 | this._currLatInterval = 0; 266 | } 267 | } 268 | }, 269 | 270 | __draw: function(label) { 271 | function _parse_px_to_int(txt) { 272 | if (txt.length > 2) { 273 | if (txt.charAt(txt.length-2) == 'p') { 274 | txt = txt.substr(0, txt.length-2); 275 | } 276 | } 277 | try { 278 | return parseInt(txt, 10); 279 | } 280 | catch(e) {} 281 | return 0; 282 | }; 283 | 284 | var self = this, 285 | canvas = this._canvas, 286 | map = this._map, 287 | curvedLon = this.options.lngLineCurved, 288 | curvedLat = this.options.latLineCurved; 289 | 290 | if (L.Browser.canvas && map) { 291 | if (!this._currLngInterval || !this._currLatInterval) { 292 | this.__calcInterval(); 293 | } 294 | 295 | var latInterval = this._currLatInterval, 296 | lngInterval = this._currLngInterval; 297 | 298 | var ctx = canvas.getContext('2d'); 299 | ctx.clearRect(0, 0, canvas.width, canvas.height); 300 | ctx.lineWidth = this.options.weight; 301 | ctx.strokeStyle = this.options.color; 302 | ctx.fillStyle = this.options.fontColor; 303 | ctx.setLineDash(this.options.dashArray); 304 | 305 | if (this.options.font) { 306 | ctx.font = this.options.font; 307 | } 308 | var txtWidth = ctx.measureText('0').width; 309 | var txtHeight = 12; 310 | try { 311 | var _font_size = ctx.font.trim().split(' ')[0]; 312 | txtHeight = _parse_px_to_int(_font_size); 313 | } 314 | catch(e) {} 315 | 316 | var ww = canvas.width, 317 | hh = canvas.height; 318 | 319 | var lt = map.containerPointToLatLng(L.point(0, 0)); 320 | var rt = map.containerPointToLatLng(L.point(ww, 0)); 321 | var rb = map.containerPointToLatLng(L.point(ww, hh)); 322 | 323 | var _lat_b = rb.lat, 324 | _lat_t = lt.lat; 325 | var _lon_l = lt.lng, 326 | _lon_r = rt.lng; 327 | 328 | var _point_per_lat = (_lat_t - _lat_b) / (hh * 0.2); 329 | if (isNaN(_point_per_lat)) { 330 | return; 331 | } 332 | 333 | if (_point_per_lat < 1) { _point_per_lat = 1; } 334 | if (_lat_b < -90) { 335 | _lat_b = -90; 336 | } 337 | else { 338 | _lat_b = parseInt(_lat_b - _point_per_lat, 10); 339 | } 340 | 341 | if (_lat_t > 90) { 342 | _lat_t = 90; 343 | } 344 | else { 345 | _lat_t = parseInt(_lat_t + _point_per_lat, 10); 346 | } 347 | 348 | var _point_per_lon = (_lon_r - _lon_l) / (ww * 0.2); 349 | if (_point_per_lon < 1) { _point_per_lon = 1; } 350 | if (_lon_l > 0 && _lon_r < 0) { 351 | _lon_r += 360; 352 | } 353 | _lon_r = parseInt(_lon_r + _point_per_lon, 10); 354 | _lon_l = parseInt(_lon_l - _point_per_lon, 10); 355 | 356 | var ll, latstr, lngstr, _lon_delta = 0.5; 357 | function __draw_lat_line(self, lat_tick) { 358 | ll = self._latLngToCanvasPoint(L.latLng(lat_tick, _lon_l)); 359 | latstr = self.__format_lat(lat_tick); 360 | txtWidth = ctx.measureText(latstr).width; 361 | var spacer = self.options.showLabel && label ? txtWidth + 10 : 0; 362 | 363 | if (curvedLat) { 364 | if (typeof(curvedLat) == 'number') { 365 | _lon_delta = curvedLat; 366 | } 367 | 368 | var __lon_left = _lon_l, __lon_right = _lon_r; 369 | if (ll.x > 0) { 370 | var __lon_left = map.containerPointToLatLng(L.point(0, ll.y)); 371 | __lon_left = __lon_left.lng - _point_per_lon; 372 | ll.x = 0; 373 | } 374 | var rr = self._latLngToCanvasPoint(L.latLng(lat_tick, __lon_right)); 375 | if (rr.x < ww) { 376 | __lon_right = map.containerPointToLatLng(L.point(ww, rr.y)); 377 | __lon_right = __lon_right.lng + _point_per_lon; 378 | if (__lon_left > 0 && __lon_right < 0) { 379 | __lon_right += 360; 380 | } 381 | } 382 | 383 | ctx.beginPath(); 384 | ctx.moveTo(ll.x + spacer, ll.y); 385 | var _prev_p = null; 386 | for (var j=__lon_left; j<=__lon_right; j+=_lon_delta) { 387 | rr = self._latLngToCanvasPoint(L.latLng(lat_tick, j)); 388 | ctx.lineTo(rr.x - spacer, rr.y); 389 | 390 | if (self.options.showLabel && label && _prev_p != null) { 391 | if (_prev_p.x < 0 && rr.x >= 0) { 392 | var _s = (rr.x - 0) / (rr.x - _prev_p.x); 393 | var _y = rr.y - ((rr.y - _prev_p.y) * _s); 394 | ctx.fillText(latstr, 0, _y + (txtHeight/2)); 395 | } 396 | else if (_prev_p.x <= (ww-txtWidth) && rr.x > (ww-txtWidth)) { 397 | var _s = (rr.x - ww) / (rr.x - _prev_p.x); 398 | var _y = rr.y - ((rr.y - _prev_p.y) * _s); 399 | ctx.fillText(latstr, ww-txtWidth, _y + (txtHeight/2)-2); 400 | } 401 | } 402 | 403 | _prev_p = {x:rr.x, y:rr.y, lon:j, lat:i}; 404 | } 405 | ctx.stroke(); 406 | } 407 | else { 408 | var __lon_right = _lon_r; 409 | var rr = self._latLngToCanvasPoint(L.latLng(lat_tick, __lon_right)); 410 | if (curvedLon) { 411 | __lon_right = map.containerPointToLatLng(L.point(0, rr.y)); 412 | __lon_right = __lon_right.lng; 413 | rr = self._latLngToCanvasPoint(L.latLng(lat_tick, __lon_right)); 414 | 415 | var __lon_left = map.containerPointToLatLng(L.point(ww, rr.y)); 416 | __lon_left = __lon_left.lng; 417 | ll = self._latLngToCanvasPoint(L.latLng(lat_tick, __lon_left)); 418 | } 419 | 420 | ctx.beginPath(); 421 | ctx.moveTo(1 + spacer, ll.y); 422 | ctx.lineTo(rr.x-1 - spacer, rr.y); 423 | ctx.stroke(); 424 | if (self.options.showLabel && label) { 425 | var _yy = ll.y + (txtHeight/2)-2; 426 | ctx.fillText(latstr, 0, _yy); 427 | ctx.fillText(latstr, ww-txtWidth, _yy); 428 | } 429 | } 430 | }; 431 | 432 | if (latInterval > 0) { 433 | for (var i=latInterval; i<=_lat_t; i+=latInterval) { 434 | if (i >= _lat_b) { 435 | __draw_lat_line(this, i); 436 | } 437 | } 438 | for (var i=0; i>=_lat_b; i-=latInterval) { 439 | if (i <= _lat_t) { 440 | __draw_lat_line(this, i); 441 | } 442 | } 443 | } 444 | 445 | function __draw_lon_line(self, lon_tick) { 446 | lngstr = self.__format_lng(lon_tick); 447 | txtWidth = ctx.measureText(lngstr).width; 448 | var bb = self._latLngToCanvasPoint(L.latLng(_lat_b, lon_tick)); 449 | var spacer = self.options.showLabel && label ? txtHeight + 5 : 0; 450 | 451 | if (curvedLon) { 452 | if (typeof(curvedLon) == 'number') { 453 | _lat_delta = curvedLon; 454 | } 455 | 456 | ctx.beginPath(); 457 | ctx.moveTo(bb.x, 5 + spacer); 458 | var _prev_p = null; 459 | for (var j=_lat_b; j<_lat_t; j+=_lat_delta) { 460 | var tt = self._latLngToCanvasPoint(L.latLng(j, lon_tick)); 461 | ctx.lineTo(tt.x, tt.y - spacer); 462 | 463 | if (self.options.showLabel && label && _prev_p != null) { 464 | if (_prev_p.y > 8 && tt.y <= 8) { 465 | ctx.fillText(lngstr, tt.x - (txtWidth/2), txtHeight + 5); 466 | } 467 | else if (_prev_p.y >= hh && tt.y < hh) { 468 | ctx.fillText(lngstr, tt.x - (txtWidth/2), hh-2); 469 | } 470 | } 471 | 472 | _prev_p = {x:tt.x, y:tt.y, lon:lon_tick, lat:j}; 473 | } 474 | ctx.stroke(); 475 | } 476 | else { 477 | var __lat_top = _lat_t; 478 | var tt = self._latLngToCanvasPoint(L.latLng(__lat_top, lon_tick)); 479 | if (curvedLat) { 480 | __lat_top = map.containerPointToLatLng(L.point(tt.x, 0)); 481 | __lat_top = __lat_top.lat; 482 | if (__lat_top > 90) { __lat_top = 90; } 483 | tt = self._latLngToCanvasPoint(L.latLng(__lat_top, lon_tick)); 484 | 485 | var __lat_bottom = map.containerPointToLatLng(L.point(bb.x, hh)); 486 | __lat_bottom = __lat_bottom.lat; 487 | if (__lat_bottom < -90) { __lat_bottom = -90; } 488 | bb = self._latLngToCanvasPoint(L.latLng(__lat_bottom, lon_tick)); 489 | } 490 | 491 | ctx.beginPath(); 492 | ctx.moveTo(tt.x, 5 + spacer); 493 | ctx.lineTo(bb.x, hh-1 - spacer); 494 | ctx.stroke(); 495 | 496 | if (self.options.showLabel && label) { 497 | ctx.fillText(lngstr, tt.x - (txtWidth/2), txtHeight+5); 498 | ctx.fillText(lngstr, bb.x - (txtWidth/2), hh-3); 499 | } 500 | } 501 | }; 502 | 503 | if (lngInterval > 0) { 504 | for (var i=lngInterval; i<=_lon_r; i+=lngInterval) { 505 | if (i >= _lon_l) { 506 | __draw_lon_line(this, i); 507 | } 508 | } 509 | for (var i=0; i>=_lon_l; i-=lngInterval) { 510 | if (i <= _lon_r) { 511 | __draw_lon_line(this, i); 512 | } 513 | } 514 | } 515 | } 516 | }, 517 | 518 | _latLngToCanvasPoint: function(latlng) { 519 | var map = this._map; 520 | var projectedPoint = map.project(L.latLng(latlng)); 521 | projectedPoint._subtract(map.getPixelOrigin()); 522 | return L.point(projectedPoint).add(map._getMapPanePos()); 523 | } 524 | 525 | }); 526 | 527 | L.latlngGraticule = function (options) { 528 | return new L.LatLngGraticule(options); 529 | }; 530 | 531 | 532 | }(this, document)); 533 | --------------------------------------------------------------------------------