[76] | 1 | /******************************************************************************* |
---|
| 2 | NAME TRANSVERSE MERCATOR |
---|
| 3 | |
---|
| 4 | PURPOSE: Transforms input longitude and latitude to Easting and |
---|
| 5 | Northing for the Transverse Mercator projection. The |
---|
| 6 | longitude and latitude must be in radians. The Easting |
---|
| 7 | and Northing values will be returned in meters. |
---|
| 8 | |
---|
| 9 | ALGORITHM REFERENCES |
---|
| 10 | |
---|
| 11 | 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological |
---|
| 12 | Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United |
---|
| 13 | State Government Printing Office, Washington D.C., 1987. |
---|
| 14 | |
---|
| 15 | 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections", |
---|
| 16 | U.S. Geological Survey Professional Paper 1453 , United State Government |
---|
| 17 | Printing Office, Washington D.C., 1989. |
---|
| 18 | *******************************************************************************/ |
---|
| 19 | |
---|
| 20 | |
---|
| 21 | /** |
---|
| 22 | Initialize Transverse Mercator projection |
---|
| 23 | */ |
---|
| 24 | |
---|
| 25 | Proj4js.Proj.tmerc = { |
---|
| 26 | init : function() { |
---|
| 27 | this.e0 = Proj4js.common.e0fn(this.es); |
---|
| 28 | this.e1 = Proj4js.common.e1fn(this.es); |
---|
| 29 | this.e2 = Proj4js.common.e2fn(this.es); |
---|
| 30 | this.e3 = Proj4js.common.e3fn(this.es); |
---|
| 31 | this.ml0 = this.a * Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0); |
---|
| 32 | }, |
---|
| 33 | |
---|
| 34 | /** |
---|
| 35 | Transverse Mercator Forward - long/lat to x/y |
---|
| 36 | long/lat in radians |
---|
| 37 | */ |
---|
| 38 | forward : function(p) { |
---|
| 39 | var lon = p.x; |
---|
| 40 | var lat = p.y; |
---|
| 41 | |
---|
| 42 | var delta_lon = Proj4js.common.adjust_lon(lon - this.long0); // Delta longitude |
---|
| 43 | var con; // cone constant |
---|
| 44 | var x, y; |
---|
| 45 | var sin_phi=Math.sin(lat); |
---|
| 46 | var cos_phi=Math.cos(lat); |
---|
| 47 | |
---|
| 48 | if (this.sphere) { /* spherical form */ |
---|
| 49 | var b = cos_phi * Math.sin(delta_lon); |
---|
| 50 | if ((Math.abs(Math.abs(b) - 1.0)) < .0000000001) { |
---|
| 51 | Proj4js.reportError("tmerc:forward: Point projects into infinity"); |
---|
| 52 | return(93); |
---|
| 53 | } else { |
---|
| 54 | x = .5 * this.a * this.k0 * Math.log((1.0 + b)/(1.0 - b)); |
---|
| 55 | con = Math.acos(cos_phi * Math.cos(delta_lon)/Math.sqrt(1.0 - b*b)); |
---|
| 56 | if (lat < 0) con = - con; |
---|
| 57 | y = this.a * this.k0 * (con - this.lat0); |
---|
| 58 | } |
---|
| 59 | } else { |
---|
| 60 | var al = cos_phi * delta_lon; |
---|
| 61 | var als = Math.pow(al,2); |
---|
| 62 | var c = this.ep2 * Math.pow(cos_phi,2); |
---|
| 63 | var tq = Math.tan(lat); |
---|
| 64 | var t = Math.pow(tq,2); |
---|
| 65 | con = 1.0 - this.es * Math.pow(sin_phi,2); |
---|
| 66 | var n = this.a / Math.sqrt(con); |
---|
| 67 | var ml = this.a * Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat); |
---|
| 68 | |
---|
| 69 | 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; |
---|
| 70 | 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; |
---|
| 71 | |
---|
| 72 | } |
---|
| 73 | p.x = x; p.y = y; |
---|
| 74 | return p; |
---|
| 75 | }, // tmercFwd() |
---|
| 76 | |
---|
| 77 | /** |
---|
| 78 | Transverse Mercator Inverse - x/y to long/lat |
---|
| 79 | */ |
---|
| 80 | inverse : function(p) { |
---|
| 81 | var con, phi; /* temporary angles */ |
---|
| 82 | var delta_phi; /* difference between longitudes */ |
---|
| 83 | var i; |
---|
| 84 | var max_iter = 6; /* maximun number of iterations */ |
---|
| 85 | var lat, lon; |
---|
| 86 | |
---|
| 87 | if (this.sphere) { /* spherical form */ |
---|
| 88 | var f = Math.exp(p.x/(this.a * this.k0)); |
---|
| 89 | var g = .5 * (f - 1/f); |
---|
| 90 | var temp = this.lat0 + p.y/(this.a * this.k0); |
---|
| 91 | var h = Math.cos(temp); |
---|
| 92 | con = Math.sqrt((1.0 - h * h)/(1.0 + g * g)); |
---|
| 93 | lat = Proj4js.common.asinz(con); |
---|
| 94 | if (temp < 0) |
---|
| 95 | lat = -lat; |
---|
| 96 | if ((g == 0) && (h == 0)) { |
---|
| 97 | lon = this.long0; |
---|
| 98 | } else { |
---|
| 99 | lon = Proj4js.common.adjust_lon(Math.atan2(g,h) + this.long0); |
---|
| 100 | } |
---|
| 101 | } else { // ellipsoidal form |
---|
| 102 | var x = p.x - this.x0; |
---|
| 103 | var y = p.y - this.y0; |
---|
| 104 | |
---|
| 105 | con = (this.ml0 + y / this.k0) / this.a; |
---|
| 106 | phi = con; |
---|
| 107 | for (i=0;true;i++) { |
---|
| 108 | 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; |
---|
| 109 | phi += delta_phi; |
---|
| 110 | if (Math.abs(delta_phi) <= Proj4js.common.EPSLN) break; |
---|
| 111 | if (i >= max_iter) { |
---|
| 112 | Proj4js.reportError("tmerc:inverse: Latitude failed to converge"); |
---|
| 113 | return(95); |
---|
| 114 | } |
---|
| 115 | } // for() |
---|
| 116 | if (Math.abs(phi) < Proj4js.common.HALF_PI) { |
---|
| 117 | // sincos(phi, &sin_phi, &cos_phi); |
---|
| 118 | var sin_phi=Math.sin(phi); |
---|
| 119 | var cos_phi=Math.cos(phi); |
---|
| 120 | var tan_phi = Math.tan(phi); |
---|
| 121 | var c = this.ep2 * Math.pow(cos_phi,2); |
---|
| 122 | var cs = Math.pow(c,2); |
---|
| 123 | var t = Math.pow(tan_phi,2); |
---|
| 124 | var ts = Math.pow(t,2); |
---|
| 125 | con = 1.0 - this.es * Math.pow(sin_phi,2); |
---|
| 126 | var n = this.a / Math.sqrt(con); |
---|
| 127 | var r = n * (1.0 - this.es) / con; |
---|
| 128 | var d = x / (n * this.k0); |
---|
| 129 | var ds = Math.pow(d,2); |
---|
| 130 | 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))); |
---|
| 131 | 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)); |
---|
| 132 | } else { |
---|
| 133 | lat = Proj4js.common.HALF_PI * Proj4js.common.sign(y); |
---|
| 134 | lon = this.long0; |
---|
| 135 | } |
---|
| 136 | } |
---|
| 137 | p.x = lon; |
---|
| 138 | p.y = lat; |
---|
| 139 | return p; |
---|
| 140 | } // tmercInv() |
---|
| 141 | }; |
---|