1 | /******************************************************************************* |
---|
2 | NAME VAN DER GRINTEN |
---|
3 | |
---|
4 | PURPOSE: Transforms input Easting and Northing to longitude and |
---|
5 | latitude for the Van der Grinten projection. The |
---|
6 | Easting and Northing must be in meters. The longitude |
---|
7 | and latitude values will be returned in radians. |
---|
8 | |
---|
9 | PROGRAMMER DATE |
---|
10 | ---------- ---- |
---|
11 | T. Mittan March, 1993 |
---|
12 | |
---|
13 | This function was adapted from the Van Der Grinten projection code |
---|
14 | (FORTRAN) in the General Cartographic Transformation Package software |
---|
15 | which is available from the U.S. Geological Survey National Mapping Division. |
---|
16 | |
---|
17 | ALGORITHM REFERENCES |
---|
18 | |
---|
19 | 1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, |
---|
20 | The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. |
---|
21 | |
---|
22 | 2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological |
---|
23 | Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United |
---|
24 | State Government Printing Office, Washington D.C., 1987. |
---|
25 | |
---|
26 | 3. "Software Documentation for GCTP General Cartographic Transformation |
---|
27 | Package", U.S. Geological Survey National Mapping Division, May 1982. |
---|
28 | *******************************************************************************/ |
---|
29 | |
---|
30 | Proj4js.Proj.vandg = { |
---|
31 | |
---|
32 | /* Initialize the Van Der Grinten projection |
---|
33 | ----------------------------------------*/ |
---|
34 | init: function() { |
---|
35 | this.R = 6370997.0; //Radius of earth |
---|
36 | }, |
---|
37 | |
---|
38 | forward: function(p) { |
---|
39 | |
---|
40 | var lon=p.x; |
---|
41 | var lat=p.y; |
---|
42 | |
---|
43 | /* Forward equations |
---|
44 | -----------------*/ |
---|
45 | var dlon = Proj4js.common.adjust_lon(lon - this.long0); |
---|
46 | var x,y; |
---|
47 | |
---|
48 | if (Math.abs(lat) <= Proj4js.common.EPSLN) { |
---|
49 | x = this.x0 + this.R * dlon; |
---|
50 | y = this.y0; |
---|
51 | } |
---|
52 | var theta = Proj4js.common.asinz(2.0 * Math.abs(lat / Proj4js.common.PI)); |
---|
53 | if ((Math.abs(dlon) <= Proj4js.common.EPSLN) || (Math.abs(Math.abs(lat) - Proj4js.common.HALF_PI) <= Proj4js.common.EPSLN)) { |
---|
54 | x = this.x0; |
---|
55 | if (lat >= 0) { |
---|
56 | y = this.y0 + Proj4js.common.PI * this.R * Math.tan(.5 * theta); |
---|
57 | } else { |
---|
58 | y = this.y0 + Proj4js.common.PI * this.R * - Math.tan(.5 * theta); |
---|
59 | } |
---|
60 | // return(OK); |
---|
61 | } |
---|
62 | var al = .5 * Math.abs((Proj4js.common.PI / dlon) - (dlon / Proj4js.common.PI)); |
---|
63 | var asq = al * al; |
---|
64 | var sinth = Math.sin(theta); |
---|
65 | var costh = Math.cos(theta); |
---|
66 | |
---|
67 | var g = costh / (sinth + costh - 1.0); |
---|
68 | var gsq = g * g; |
---|
69 | var m = g * (2.0 / sinth - 1.0); |
---|
70 | var msq = m * m; |
---|
71 | var con = Proj4js.common.PI * this.R * (al * (g - msq) + Math.sqrt(asq * (g - msq) * (g - msq) - (msq + asq) * (gsq - msq))) / (msq + asq); |
---|
72 | if (dlon < 0) { |
---|
73 | con = -con; |
---|
74 | } |
---|
75 | x = this.x0 + con; |
---|
76 | con = Math.abs(con / (Proj4js.common.PI * this.R)); |
---|
77 | if (lat >= 0) { |
---|
78 | y = this.y0 + Proj4js.common.PI * this.R * Math.sqrt(1.0 - con * con - 2.0 * al * con); |
---|
79 | } else { |
---|
80 | y = this.y0 - Proj4js.common.PI * this.R * Math.sqrt(1.0 - con * con - 2.0 * al * con); |
---|
81 | } |
---|
82 | p.x = x; |
---|
83 | p.y = y; |
---|
84 | return p; |
---|
85 | }, |
---|
86 | |
---|
87 | /* Van Der Grinten inverse equations--mapping x,y to lat/long |
---|
88 | ---------------------------------------------------------*/ |
---|
89 | inverse: function(p) { |
---|
90 | var dlon; |
---|
91 | var xx,yy,xys,c1,c2,c3; |
---|
92 | var al,asq; |
---|
93 | var a1; |
---|
94 | var m1; |
---|
95 | var con; |
---|
96 | var th1; |
---|
97 | var d; |
---|
98 | |
---|
99 | /* inverse equations |
---|
100 | -----------------*/ |
---|
101 | p.x -= this.x0; |
---|
102 | p.y -= this.y0; |
---|
103 | con = Proj4js.common.PI * this.R; |
---|
104 | xx = p.x / con; |
---|
105 | yy =p.y / con; |
---|
106 | xys = xx * xx + yy * yy; |
---|
107 | c1 = -Math.abs(yy) * (1.0 + xys); |
---|
108 | c2 = c1 - 2.0 * yy * yy + xx * xx; |
---|
109 | c3 = -2.0 * c1 + 1.0 + 2.0 * yy * yy + xys * xys; |
---|
110 | d = yy * yy / c3 + (2.0 * c2 * c2 * c2 / c3 / c3 / c3 - 9.0 * c1 * c2 / c3 /c3) / 27.0; |
---|
111 | a1 = (c1 - c2 * c2 / 3.0 / c3) / c3; |
---|
112 | m1 = 2.0 * Math.sqrt( -a1 / 3.0); |
---|
113 | con = ((3.0 * d) / a1) / m1; |
---|
114 | if (Math.abs(con) > 1.0) { |
---|
115 | if (con >= 0.0) { |
---|
116 | con = 1.0; |
---|
117 | } else { |
---|
118 | con = -1.0; |
---|
119 | } |
---|
120 | } |
---|
121 | th1 = Math.acos(con) / 3.0; |
---|
122 | if (p.y >= 0) { |
---|
123 | lat = (-m1 *Math.cos(th1 + Proj4js.common.PI / 3.0) - c2 / 3.0 / c3) * Proj4js.common.PI; |
---|
124 | } else { |
---|
125 | lat = -(-m1 * Math.cos(th1 + Proj4js.common.PI / 3.0) - c2 / 3.0 / c3) * Proj4js.common.PI; |
---|
126 | } |
---|
127 | |
---|
128 | if (Math.abs(xx) < Proj4js.common.EPSLN) { |
---|
129 | lon = this.long0; |
---|
130 | } |
---|
131 | 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); |
---|
132 | |
---|
133 | p.x=lon; |
---|
134 | p.y=lat; |
---|
135 | return p; |
---|
136 | } |
---|
137 | }; |
---|