/[projects]/android/DatumConversion/src/dk/thoerup/datumconversion/DatumConverter.java
ViewVC logotype

Annotation of /android/DatumConversion/src/dk/thoerup/datumconversion/DatumConverter.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 262 - (hide annotations) (download)
Tue Aug 11 19:13:16 2009 UTC (14 years, 9 months ago) by torben
File size: 12573 byte(s)


1 torben 262 package dk.thoerup.datumconversion;
2    
3     public class DatumConverter {
4    
5     static Utm LLtoUTM(int ReferenceEllipsoid, Ll ll)
6     {
7     //converts lat/long to UTM coords. Equations from USGS Bulletin 1532
8     //East Longitudes are positive, West longitudes are negative.
9     //North latitudes are positive, South latitudes are negative
10     //Lat and Long are in decimal degrees
11     //Written by Chuck Gantz- chuck.gantz@globalstar.com
12    
13    
14     double UTMNorthing;
15     double UTMEasting;
16     String UTMZone;
17    
18     double Lat = ll.lattitude;
19     double Long = ll.longitude;
20    
21    
22    
23     double a = Constants.ellipsoid[ReferenceEllipsoid].EquatorialRadius;
24     double eccSquared = Constants.ellipsoid[ReferenceEllipsoid].eccentricitySquared;
25     double k0 = 0.9996;
26    
27     double LongOrigin;
28     double eccPrimeSquared;
29     double N, T, C, A, M;
30    
31     //Make sure the longitude is between -180.00 .. 179.9
32     double LongTemp = (Long+180) - ((int)(Long+180)/360)*360-180; // -180.00 .. 179.9;
33    
34     double LatRad = Lat * Constants.deg2rad;
35     double LongRad = LongTemp * Constants.deg2rad;
36     double LongOriginRad;
37     int ZoneNumber;
38    
39     ZoneNumber = ( (int)((LongTemp + 180)/6) ) + 1;
40    
41     if( Lat >= 56.0 && Lat < 64.0 && LongTemp >= 3.0 && LongTemp < 12.0 )
42     ZoneNumber = 32;
43    
44     // Special zones for Svalbard
45     if( Lat >= 72.0 && Lat < 84.0 )
46     {
47     if( LongTemp >= 0.0 && LongTemp < 9.0 ) ZoneNumber = 31;
48     else if( LongTemp >= 9.0 && LongTemp < 21.0 ) ZoneNumber = 33;
49     else if( LongTemp >= 21.0 && LongTemp < 33.0 ) ZoneNumber = 35;
50     else if( LongTemp >= 33.0 && LongTemp < 42.0 ) ZoneNumber = 37;
51     }
52     LongOrigin = (ZoneNumber - 1)*6 - 180 + 3; //+3 puts origin in middle of zone
53     LongOriginRad = LongOrigin * Constants.deg2rad;
54    
55     //compute the UTM Zone from the latitude and longitude
56     UTMZone = ""+ ZoneNumber + UTMLetterDesignator(Lat);
57    
58     eccPrimeSquared = (eccSquared)/(1-eccSquared);
59    
60     N = a/Math.sqrt(1-eccSquared * Math.sin(LatRad) * Math.sin(LatRad));
61     T = Math.tan(LatRad) * Math.tan(LatRad);
62     C = eccPrimeSquared * Math.cos(LatRad) * Math.cos(LatRad);
63     A = Math.cos(LatRad)*(LongRad-LongOriginRad);
64    
65     M = a*((1 - eccSquared/4 - 3*eccSquared*eccSquared/64 - 5*eccSquared*eccSquared*eccSquared/256)*LatRad
66     - (3*eccSquared/8 + 3*eccSquared*eccSquared/32 + 45*eccSquared*eccSquared*eccSquared/1024)*Math.sin(2*LatRad)
67     + (15*eccSquared*eccSquared/256 + 45*eccSquared*eccSquared*eccSquared/1024)*Math.sin(4*LatRad)
68     - (35*eccSquared*eccSquared*eccSquared/3072)*Math.sin(6*LatRad));
69    
70     UTMEasting = (double)(k0*N*(A+(1-T+C)*A*A*A/6
71     + (5-18*T+T*T+72*C-58*eccPrimeSquared)*A*A*A*A*A/120)
72     + 500000.0);
73    
74     UTMNorthing = (double)(k0*(M+N*Math.tan(LatRad)*(A*A/2+(5-T+9*C+4*C*C)*A*A*A*A/24
75     + (61-58*T+T*T+600*C-330*eccPrimeSquared)*A*A*A*A*A*A/720)));
76     if(Lat < 0)
77     UTMNorthing += 10000000.0; //10000000 meter offset for southern hemisphere
78    
79     return new Utm(UTMNorthing, UTMEasting,UTMZone);
80     }
81    
82     static char UTMLetterDesignator(double Lat)
83     {
84     //This routine determines the correct UTM letter designator for the given latitude
85     //returns 'Z' if latitude is outside the UTM limits of 84N to 80S
86     //Written by Chuck Gantz- chuck.gantz@globalstar.com
87     char LetterDesignator;
88    
89     if((84 >= Lat) && (Lat >= 72)) LetterDesignator = 'X';
90     else if((72 > Lat) && (Lat >= 64)) LetterDesignator = 'W';
91     else if((64 > Lat) && (Lat >= 56)) LetterDesignator = 'V';
92     else if((56 > Lat) && (Lat >= 48)) LetterDesignator = 'U';
93     else if((48 > Lat) && (Lat >= 40)) LetterDesignator = 'T';
94     else if((40 > Lat) && (Lat >= 32)) LetterDesignator = 'S';
95     else if((32 > Lat) && (Lat >= 24)) LetterDesignator = 'R';
96     else if((24 > Lat) && (Lat >= 16)) LetterDesignator = 'Q';
97     else if((16 > Lat) && (Lat >= 8)) LetterDesignator = 'P';
98     else if(( 8 > Lat) && (Lat >= 0)) LetterDesignator = 'N';
99     else if(( 0 > Lat) && (Lat >= -8)) LetterDesignator = 'M';
100     else if((-8> Lat) && (Lat >= -16)) LetterDesignator = 'L';
101     else if((-16 > Lat) && (Lat >= -24)) LetterDesignator = 'K';
102     else if((-24 > Lat) && (Lat >= -32)) LetterDesignator = 'J';
103     else if((-32 > Lat) && (Lat >= -40)) LetterDesignator = 'H';
104     else if((-40 > Lat) && (Lat >= -48)) LetterDesignator = 'G';
105     else if((-48 > Lat) && (Lat >= -56)) LetterDesignator = 'F';
106     else if((-56 > Lat) && (Lat >= -64)) LetterDesignator = 'E';
107     else if((-64 > Lat) && (Lat >= -72)) LetterDesignator = 'D';
108     else if((-72 > Lat) && (Lat >= -80)) LetterDesignator = 'C';
109     else LetterDesignator = 'Z'; //This is here as an error flag to show that the Latitude is outside the UTM limits
110    
111     return LetterDesignator;
112     }
113    
114    
115     static Ll UTMtoLL(int ReferenceEllipsoid, Utm utm )
116     {
117     //converts UTM coords to lat/long. Equations from USGS Bulletin 1532
118     //East Longitudes are positive, West longitudes are negative.
119     //North latitudes are positive, South latitudes are negative
120     //Lat and Long are in decimal degrees.
121     //Written by Chuck Gantz- chuck.gantz@globalstar.com
122    
123     double k0 = 0.9996;
124     double a = Constants.ellipsoid[ReferenceEllipsoid].EquatorialRadius;
125     double eccSquared = Constants.ellipsoid[ReferenceEllipsoid].eccentricitySquared;
126     double eccPrimeSquared;
127     double e1 = (1-Math.sqrt(1-eccSquared))/(1+Math.sqrt(1-eccSquared));
128     double N1, T1, C1, R1, D, M;
129     double LongOrigin;
130     double mu, phi1, phi1Rad;
131     double x, y;
132     int ZoneNumber;
133     char ZoneLetter;
134     int NorthernHemisphere; //1 for northern hemispher, 0 for southern
135    
136     double Lat;
137     double Long;
138    
139     double UTMNorthing = utm.northing;
140     double UTMEasting = utm.easting;
141     String UTMZone = utm.utmZone;
142    
143     x = UTMEasting - 500000.0; //remove 500,000 meter offset for longitude
144     y = UTMNorthing;
145    
146     ZoneNumber = Integer.parseInt(UTMZone.substring(0,UTMZone.length()-1));
147     ZoneLetter = UTMZone.charAt(UTMZone.length()-1);
148     //ZoneNumber = strtoul(UTMZone, &ZoneLetter, 10);
149     if((ZoneLetter - 'N') >= 0)
150     NorthernHemisphere = 1;//point is in northern hemisphere
151     else
152     {
153     NorthernHemisphere = 0;//point is in southern hemisphere
154     y -= 10000000.0;//remove 10,000,000 meter offset used for southern hemisphere
155     }
156    
157     LongOrigin = (ZoneNumber - 1)*6 - 180 + 3; //+3 puts origin in middle of zone
158    
159     eccPrimeSquared = (eccSquared)/(1-eccSquared);
160    
161     M = y / k0;
162     mu = M/(a*(1-eccSquared/4-3*eccSquared*eccSquared/64-5*eccSquared*eccSquared*eccSquared/256));
163    
164     phi1Rad = mu + (3*e1/2-27*e1*e1*e1/32)*Math.sin(2*mu)
165     + (21*e1*e1/16-55*e1*e1*e1*e1/32)*Math.sin(4*mu)
166     +(151*e1*e1*e1/96)*Math.sin(6*mu);
167     phi1 = phi1Rad*Constants.rad2deg;
168    
169     N1 = a/Math.sqrt(1-eccSquared*Math.sin(phi1Rad)*Math.sin(phi1Rad));
170     T1 = Math.tan(phi1Rad)*Math.tan(phi1Rad);
171     C1 = eccPrimeSquared*Math.cos(phi1Rad)*Math.cos(phi1Rad);
172     R1 = a*(1-eccSquared)/Math.pow(1-eccSquared*Math.sin(phi1Rad)*Math.sin(phi1Rad), 1.5);
173     D = x/(N1*k0);
174    
175     Lat = phi1Rad - (N1*Math.tan(phi1Rad)/R1)*(D*D/2-(5+3*T1+10*C1-4*C1*C1-9*eccPrimeSquared)*D*D*D*D/24
176     +(61+90*T1+298*C1+45*T1*T1-252*eccPrimeSquared-3*C1*C1)*D*D*D*D*D*D/720);
177     Lat = Lat * Constants.rad2deg;
178    
179     Long = (D-(1+2*T1+C1)*D*D*D/6+(5-2*C1+28*T1-3*C1*C1+8*eccPrimeSquared+24*T1*T1)
180     *D*D*D*D*D/120)/Math.cos(phi1Rad);
181     Long = LongOrigin + Long * Constants.rad2deg;
182    
183     return new Ll(Lat,Long);
184     }
185    
186     ///////////////////////////////////////////////////////////////////////////////////////////////////////
187    
188     static Swiss LLtoSwissGrid(double Lat, double Long)
189     {
190     //converts lat/long to Swiss Grid coords. Equations from "Supplementary PROJ.4 Notes-
191     //Swiss Oblique Mercator Projection", August 5, 1995, Release 4.3.3, by Gerald I. Evenden
192     //Lat and Long are in decimal degrees
193     //This transformation is, of course, only valid in Switzerland
194     //Written by Chuck Gantz- chuck.gantz@globalstar.com
195     double a = Constants.ellipsoid[3].EquatorialRadius; //Bessel ellipsoid
196     double eccSquared = Constants.ellipsoid[3].eccentricitySquared;
197     double ecc = Math.sqrt(eccSquared);
198    
199     double LongOrigin = 7.43958333; //E7d26'22.500"
200     double LatOrigin = 46.95240556; //N46d57'8.660"
201    
202     double SwissNorthing;
203     double SwissEasting;
204    
205     double LatRad = Lat*Constants.deg2rad;
206     double LongRad = Long*Constants.deg2rad;
207     double LatOriginRad = LatOrigin*Constants.deg2rad;
208     double LongOriginRad = LongOrigin*Constants.deg2rad;
209    
210     double c = Math.sqrt(1+((eccSquared * Math.pow(Math.cos(LatOriginRad), 4)) / (1-eccSquared)));
211    
212     double equivLatOrgRadPrime = Math.asin(Math.sin(LatOriginRad) / c);
213    
214     //eqn. 1
215     double K = Math.log(Math.tan(Constants.FOURTHPI + equivLatOrgRadPrime/2))
216     -c*(Math.log(Math.tan(Constants.FOURTHPI + LatOriginRad/2))
217     - ecc/2 * Math.log((1+ecc*Math.sin(LatOriginRad)) / (1-ecc*Math.sin(LatOriginRad))));
218    
219    
220     double LongRadPrime = c*(LongRad - LongOriginRad); //eqn 2
221     double w = c*(Math.log(Math.tan(Constants.FOURTHPI + LatRad/2))
222     - ecc/2 * Math.log((1+ecc*Math.sin(LatRad)) / (1-ecc*Math.sin(LatRad)))) + K; //eqn 1
223     double LatRadPrime = 2 * (Math.atan(Math.exp(w)) - Constants.FOURTHPI); //eqn 1
224    
225     //eqn 3
226     double sinLatDoublePrime = Math.cos(equivLatOrgRadPrime) * Math.sin(LatRadPrime)
227     - Math.sin(equivLatOrgRadPrime) * Math.cos(LatRadPrime) * Math.cos(LongRadPrime);
228     double LatRadDoublePrime = Math.asin(sinLatDoublePrime);
229    
230     //eqn 4
231     double sinLongDoublePrime = Math.cos(LatRadPrime)*Math.sin(LongRadPrime) / Math.cos(LatRadDoublePrime);
232     double LongRadDoublePrime = Math.asin(sinLongDoublePrime);
233    
234     double R = a*Math.sqrt(1-eccSquared) / (1-eccSquared*Math.sin(LatOriginRad) * Math.sin(LatOriginRad));
235    
236     SwissNorthing = R*Math.log(Math.tan(Constants.FOURTHPI + LatRadDoublePrime/2)) + 200000.0; //eqn 5
237     SwissEasting = R*LongRadDoublePrime + 600000.0; //eqn 6
238    
239     return new Swiss(SwissNorthing, SwissEasting);
240     }
241    
242    
243     static Ll SwissGridtoLL(double SwissNorthing, double SwissEasting)
244     {
245     double Lat;
246     double Long;
247    
248     double a = Constants.ellipsoid[3].EquatorialRadius; //Bessel ellipsoid
249     double eccSquared = Constants.ellipsoid[3].eccentricitySquared;
250     double ecc = Math.sqrt(eccSquared);
251    
252     double LongOrigin = 7.43958333; //E7d26'22.500"
253     double LatOrigin = 46.95240556; //N46d57'8.660"
254    
255     double LatOriginRad = LatOrigin*Constants.deg2rad;
256     double LongOriginRad = LongOrigin*Constants.deg2rad;
257    
258     double R = a*Math.sqrt(1-eccSquared) / (1-eccSquared*Math.sin(LatOriginRad) * Math.sin(LatOriginRad));
259    
260     double LatRadDoublePrime = 2*(Math.atan(Math.exp((SwissNorthing - 200000.0)/R)) - Constants.FOURTHPI); //eqn. 7
261     double LongRadDoublePrime = (SwissEasting - 600000.0)/R; //eqn. 8 with equation corrected
262    
263    
264     double c = Math.sqrt(1+((eccSquared * Math.pow(Math.cos(LatOriginRad), 4)) / (1-eccSquared)));
265     double equivLatOrgRadPrime = Math.asin(Math.sin(LatOriginRad) / c);
266    
267     double sinLatRadPrime = Math.cos(equivLatOrgRadPrime)*Math.sin(LatRadDoublePrime)
268     + Math.sin(equivLatOrgRadPrime)*Math.cos(LatRadDoublePrime)*Math.cos(LongRadDoublePrime);
269     double LatRadPrime = Math.asin(sinLatRadPrime);
270    
271     double sinLongRadPrime = Math.cos(LatRadDoublePrime)*Math.sin(LongRadDoublePrime)/Math.cos(LatRadPrime);
272     double LongRadPrime = Math.asin(sinLongRadPrime);
273    
274     Long = (LongRadPrime/c + LongOriginRad) * Constants.rad2deg;
275    
276     Lat = NewtonRaphson(LatRadPrime) * Constants.rad2deg;
277    
278     return new Ll(Lat, Long);
279     }
280    
281     static double NewtonRaphson( double initEstimate)
282     {
283     double Estimate = initEstimate;
284     double tol = 0.00001;
285     double corr;
286    
287     double eccSquared = Constants.ellipsoid[3].eccentricitySquared;
288     double ecc = Math.sqrt(eccSquared);
289    
290     double LatOrigin = 46.95240556; //N46d57'8.660"
291     double LatOriginRad = LatOrigin*Constants.deg2rad;
292    
293     double c = Math.sqrt(1+((eccSquared * Math.pow(Math.cos(LatOriginRad), 4)) / (1-eccSquared)));
294    
295     double equivLatOrgRadPrime = Math.asin(Math.sin(LatOriginRad) / c);
296    
297     //eqn. 1
298     double K = Math.log(Math.tan(Constants.FOURTHPI + equivLatOrgRadPrime/2))
299     -c*(Math.log(Math.tan(Constants.FOURTHPI + LatOriginRad/2))
300     - ecc/2 * Math.log((1+ecc*Math.sin(LatOriginRad)) / (1-ecc*Math.sin(LatOriginRad))));
301     double C = (K - Math.log(Math.tan(Constants.FOURTHPI + initEstimate/2)))/c;
302    
303     do
304     {
305     corr = CorrRatio(Estimate, C);
306     Estimate = Estimate - corr;
307     }
308     while (Math.abs(corr) > tol);
309    
310     return Estimate;
311     }
312    
313    
314    
315     static double CorrRatio(double LatRad, double C)
316     {
317     double eccSquared = Constants.ellipsoid[3].eccentricitySquared;
318     double ecc = Math.sqrt(eccSquared);
319     double corr = (C + Math.log(Math.tan(Constants.FOURTHPI + LatRad/2))
320     - ecc/2 * Math.log((1+ecc*Math.sin(LatRad)) / (1-ecc*Math.sin(LatRad)))) * (((1-eccSquared*Math.sin(LatRad)*Math.sin(LatRad)) * Math.cos(LatRad)) / (1-eccSquared));
321    
322     return corr;
323     }
324    
325    
326     }

  ViewVC Help
Powered by ViewVC 1.1.20