KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jscience > geography > coordinates > crs > ReferenceEllipsoid


1 /*
2  * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
3  * Copyright (C) 2006 - JScience (http://jscience.org/)
4  * All rights reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software is
7  * freely granted, provided that this notice is preserved.
8  */

9 package org.jscience.geography.coordinates.crs;
10
11 import javax.measure.quantities.*;
12 import javax.measure.units.SI;
13
14 /**
15  * <p> The ReferenceEllipsoid class defines a geodetic reference ellipsoid
16  * used as a standard for geodetic measurements. The World Geodetic System
17  * 1984 (WGS84) ellipsoid is the current standard for most geographic and
18  * geodetic coordinate systems, including GPS. The WGS84 ellipsoid is
19  * provided as a static instance of this class.</p>
20  *
21  * <p> The ellipsoid (actually an oblate spheroid) is uniquely specified by
22  * two parameters, the semimajor (or equatorial) radius and the ellipticity
23  * or flattening. In practice, the reciprocal of the flattening is
24  * specified.</p>
25  *
26  * <p> The ellipsoid is an approximation of the shape of the earth. Although
27  * not exact, the ellipsoid is much more accurate than a spherical
28  * approximation and is still mathematically simple. The <i>geoid</i> is
29  * a still closer approximation of the shape of the earth (intended to
30  * represent the mean sea level), and is generally specified by it's
31  * deviation from the ellipsoid.</p>
32  *
33  * <p> Different reference ellipsoids give more or less accurate results at
34  * different locations, so it was previously common for different nations
35  * to use ellipsoids that were more accurate for their areas. More recent
36  * efforts have provided ellipsoids with better overall global accuracy,
37  * such as the WGS84 ellipsiod, and these have now largely supplanted
38  * the others.</p>
39  *
40  * @author Paul D. Anderson
41  * @version 3.0, February 18, 2006
42  */

43 public class ReferenceEllipsoid {
44
45     /**
46      * The World Geodetic System 1984 reference ellipsoid.
47      */

48     public static final ReferenceEllipsoid WGS84
49         = new ReferenceEllipsoid(6378137.0, 298.257223563);
50     /**
51      * Geodetic Reference System 1980 ellipsoid.
52      */

53     public static final ReferenceEllipsoid GRS80
54         = new ReferenceEllipsoid(6378137.0, 298.257222101);
55     /**
56      * The World Geodetic System 1972 reference ellipsoid.
57      */

58     public static final ReferenceEllipsoid WGS72
59         = new ReferenceEllipsoid(6378135.0, 298.26);
60     /**
61      * The International 1924 reference ellipsoid, one of the earliest
62      * "global" ellipsoids.
63      */

64     public static final ReferenceEllipsoid INTERNATIONAL1924
65         = new ReferenceEllipsoid(6378388.0, 297.0);
66
67     private final double a;
68
69     private final double b;
70
71     private final double f;
72
73     private final double ea2;
74
75     private final double e;
76
77     private final double eb2;
78
79     private Quantity<Length> _semimajorAxis;
80
81     private Quantity<Length> _semiminorAxis;
82
83     /**
84      * Constructs an instance of a reference ellipsoid.
85      *
86      * @param semimajorAxis The semimajor or equatorial radius of this
87      * reference ellipsoid, in meters.
88      * @param inverseFlattening The reciprocal of the ellipticity or flattening
89      * of this reference ellipsoid (dimensionless).
90      */

91     public ReferenceEllipsoid(double semimajorAxis, double inverseFlattening) {
92         this.a = semimajorAxis;
93         f = 1.0 / inverseFlattening;
94         b = semimajorAxis * (1.0 - f);
95         ea2 = f * (2.0 - f);
96         e = Math.sqrt(ea2);
97         eb2 = ea2 / (1.0 - ea2);
98     }
99
100     private static double sqr(final double x) {
101         return x * x;
102     }
103
104     /**
105      * Returns the semimajor or equatorial radius of this reference ellipsoid.
106      *
107      * @return The semimajor radius.
108      */

109     public Quantity<Length> getSemimajorAxis() {
110         if (_semimajorAxis == null) {
111             _semimajorAxis = new Scalar<Length>(a, SI.METER);
112         }
113         return _semimajorAxis;
114     }
115
116     /**
117      * Returns the semiminor or polar radius of this reference ellipsoid.
118      *
119      * @return The semiminor radius.
120      */

121     public Quantity<Length> getsSemiminorAxis() {
122         if (_semiminorAxis == null) {
123             _semiminorAxis = new Scalar<Length>(b, SI.METER);
124         }
125         return _semiminorAxis;
126     }
127
128     /**
129      * Returns the flattening or ellipticity of this reference ellipsoid.
130      *
131      * @return The flattening.
132      */

133     public double getFlattening() {
134         return f;
135     }
136
137     /**
138      * Returns the (first) eccentricity of this reference ellipsoid.
139      *
140      * @return The eccentricity.
141      */

142     public double getEccentricity() {
143         return e;
144     }
145
146     /**
147      * Returns the square of the (first) eccentricity. This number is frequently
148      * used in ellipsoidal calculations.
149      *
150      * @return The square of the eccentricity.
151      */

152     public double getEccentricitySquared() {
153         return ea2;
154     }
155
156     /**
157      * Returns the square of the second eccentricity of this reference ellipsoid.
158      * This number is frequently used in ellipsoidal calculations.
159      *
160      * @return The square of the second eccentricity.
161      */

162     public double getSecondEccentricitySquared() {
163         return eb2;
164     }
165
166     /**
167       * Returns the <i>radius of curvature in the prime vertical</i>
168       * for this reference ellipsoid at the specified latitude.
169       *
170       * @param phi The local latitude (radians).
171       * @return The radius of curvature in the prime vertical (meters).
172       */

173      public double verticalRadiusOfCurvature(final double phi) {
174          return a / Math.sqrt(1.0 - (ea2 * sqr(Math.sin(phi))));
175      }
176
177     /**
178       * Returns the <i>radius of curvature in the prime vertical</i>
179       * for this reference ellipsoid at the specified latitude.
180       *
181       * @param latitude The local latitude.
182       * @return The radius of curvature in the prime vertical.
183       */

184      public Quantity<Length> verticalRadiusOfCurvature(final Quantity<Angle> latitude) {
185          return new Scalar<Length>(verticalRadiusOfCurvature(latitude.doubleValue(SI.RADIAN)), SI.METER);
186      }
187
188     /**
189      * Returns the <i>radius of curvature in the meridian<i>
190      * for this reference ellipsoid at the specified latitude.
191      *
192      * @param phi The local latitude (in radians).
193      * @return The radius of curvature in the meridian (in meters).
194      */

195     public double meridionalRadiusOfCurvature(final double phi) {
196         return verticalRadiusOfCurvature(phi)
197                / (1.0 + eb2 * sqr(Math.cos(phi)));
198     }
199
200     /**
201      * Returns the <i>radius of curvature in the meridian<i>
202      * for this reference ellipsoid at the specified latitude.
203      *
204      * @param latitude The local latitude (in radians).
205      * @return The radius of curvature in the meridian (in meters).
206      */

207     public Quantity<Length> meridionalRadiusOfCurvature(final Quantity<Angle> latitude) {
208         return new Scalar<Length>(meridionalRadiusOfCurvature(latitude.doubleValue(SI.RADIAN)), SI.METER);
209     }
210
211     /**
212      * Returns the meridional arc, the true meridional distance on the
213      * ellipsoid from the equator to the specified latitude, in meters.
214      *
215      * @param phi The local latitude (in radians).
216      * @return The meridional arc (in meters).
217      */

218     public double meridionalArc(final double phi) {
219         final double sin2Phi = Math.sin(2.0 * phi);
220         final double sin4Phi = Math.sin(4.0 * phi);
221         final double sin6Phi = Math.sin(6.0 * phi);
222         final double sin8Phi = Math.sin(8.0 * phi);
223         final double n = f / (2.0 - f);
224         final double n2 = n * n;
225         final double n3 = n2 * n;
226         final double n4 = n3 * n;
227         final double n5 = n4 * n;
228         final double n1n2 = n - n2;
229         final double n2n3 = n2 - n3;
230         final double n3n4 = n3 - n4;
231         final double n4n5 = n4 - n5;
232         final double ap = a * (1.0 - n + (5.0 / 4.0) * (n2n3) + (81.0 / 64.0) * (n4n5));
233         final double bp = (3.0 / 2.0) * a * (n1n2 + (7.0 / 8.0) * (n3n4) + (55.0 / 64.0) * n5);
234         final double cp = (15.0 / 16.0) * a * (n2n3 + (3.0 / 4.0) * (n4n5));
235         final double dp = (35.0 / 48.0) * a * (n3n4 + (11.0 / 16.0) * n5);
236         final double ep = (315.0 / 512.0) * a * (n4n5);
237         return ap * phi - bp * sin2Phi + cp * sin4Phi - dp * sin6Phi + ep * sin8Phi;
238     }
239
240     /**
241      * Returns the meridional arc, the true meridional distance on the
242      * ellipsoid from the equator to the specified latitude.
243      *
244      * @param latitude The local latitude.
245      * @return The meridional arc.
246      */

247     public Quantity<Length> meridionalArc(final Quantity<Angle> latitude) {
248         return new Scalar<Length>(meridionalArc(latitude.doubleValue(SI.RADIAN)), SI.METER);
249     }
250
251 }
Popular Tags