/*
 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
 * Copyright (C) 2006 - JScience (http://jscience.org/)
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software is
 * freely granted, provided that this notice is preserved.
 */
package org.jscience.geography.coordinates.crs;

import javax.measure.Measure;
import javax.measure.Measurable;
import javax.measure.quantity.*;
import javax.measure.unit.SI;

/**
 * 

The ReferenceEllipsoid class defines a geodetic reference ellipsoid * used as a standard for geodetic measurements. The World Geodetic System * 1984 (WGS84) ellipsoid is the current standard for most geographic and * geodetic coordinate systems, including GPS. The WGS84 ellipsoid is * provided as a static instance of this class.

* *

The ellipsoid (actually an oblate spheroid) is uniquely specified by * two parameters, the semimajor (or equatorial) radius and the ellipticity * or flattening. In practice, the reciprocal of the flattening is * specified.

* *

The ellipsoid is an approximation of the shape of the earth. Although * not exact, the ellipsoid is much more accurate than a spherical * approximation and is still mathematically simple. The geoid is * a still closer approximation of the shape of the earth (intended to * represent the mean sea level), and is generally specified by it's * deviation from the ellipsoid.

* *

Different reference ellipsoids give more or less accurate results at * different locations, so it was previously common for different nations * to use ellipsoids that were more accurate for their areas. More recent * efforts have provided ellipsoids with better overall global accuracy, * such as the WGS84 ellipsiod, and these have now largely supplanted * the others.

* * @author Paul D. Anderson * @version 3.0, February 18, 2006 */ public class ReferenceEllipsoid { /** * The World Geodetic System 1984 reference ellipsoid. */ public static final ReferenceEllipsoid WGS84 = new ReferenceEllipsoid(6378137.0, 298.257223563); /** * Geodetic Reference System 1980 ellipsoid. */ public static final ReferenceEllipsoid GRS80 = new ReferenceEllipsoid(6378137.0, 298.257222101); /** * The World Geodetic System 1972 reference ellipsoid. */ public static final ReferenceEllipsoid WGS72 = new ReferenceEllipsoid(6378135.0, 298.26); /** * The International 1924 reference ellipsoid, one of the earliest * "global" ellipsoids. */ public static final ReferenceEllipsoid INTERNATIONAL1924 = new ReferenceEllipsoid(6378388.0, 297.0); private final double a; private final double b; private final double f; private final double ea2; private final double e; private final double eb2; private Measurable _semimajorAxis; private Measurable _semiminorAxis; /** * Constructs an instance of a reference ellipsoid. * * @param semimajorAxis The semimajor or equatorial radius of this * reference ellipsoid, in meters. * @param inverseFlattening The reciprocal of the ellipticity or flattening * of this reference ellipsoid (dimensionless). */ public ReferenceEllipsoid(double semimajorAxis, double inverseFlattening) { this.a = semimajorAxis; f = 1.0 / inverseFlattening; b = semimajorAxis * (1.0 - f); ea2 = f * (2.0 - f); e = Math.sqrt(ea2); eb2 = ea2 / (1.0 - ea2); } private static double sqr(final double x) { return x * x; } /** * Returns the semimajor or equatorial radius of this reference ellipsoid. * * @return The semimajor radius. */ public Measurable getSemimajorAxis() { if (_semimajorAxis == null) { _semimajorAxis = Measure.valueOf(a, SI.METRE); } return _semimajorAxis; } /** * Returns the semiminor or polar radius of this reference ellipsoid. * * @return The semiminor radius. */ public Measurable getsSemiminorAxis() { if (_semiminorAxis == null) { _semiminorAxis = Measure.valueOf(b, SI.METRE); } return _semiminorAxis; } /** * Returns the flattening or ellipticity of this reference ellipsoid. * * @return The flattening. */ public double getFlattening() { return f; } /** * Returns the (first) eccentricity of this reference ellipsoid. * * @return The eccentricity. */ public double getEccentricity() { return e; } /** * Returns the square of the (first) eccentricity. This number is frequently * used in ellipsoidal calculations. * * @return The square of the eccentricity. */ public double getEccentricitySquared() { return ea2; } /** * Returns the square of the second eccentricity of this reference ellipsoid. * This number is frequently used in ellipsoidal calculations. * * @return The square of the second eccentricity. */ public double getSecondEccentricitySquared() { return eb2; } /** * Returns the radius of curvature in the prime vertical * for this reference ellipsoid at the specified latitude. * * @param phi The local latitude (radians). * @return The radius of curvature in the prime vertical (meters). */ public double verticalRadiusOfCurvature(final double phi) { return a / Math.sqrt(1.0 - (ea2 * sqr(Math.sin(phi)))); } /** * Returns the radius of curvature in the prime vertical * for this reference ellipsoid at the specified latitude. * * @param latitude The local latitude. * @return The radius of curvature in the prime vertical. */ public Measurable verticalRadiusOfCurvature(final Measurable latitude) { return Measure.valueOf(verticalRadiusOfCurvature(latitude.doubleValue(SI.RADIAN)), SI.METRE); } /** * Returns the radius of curvature in the meridian * for this reference ellipsoid at the specified latitude. * * @param phi The local latitude (in radians). * @return The radius of curvature in the meridian (in meters). */ public double meridionalRadiusOfCurvature(final double phi) { return verticalRadiusOfCurvature(phi) / (1.0 + eb2 * sqr(Math.cos(phi))); } /** * Returns the radius of curvature in the meridian * for this reference ellipsoid at the specified latitude. * * @param latitude The local latitude (in radians). * @return The radius of curvature in the meridian (in meters). */ public Measurable meridionalRadiusOfCurvature(final Measurable latitude) { return Measure.valueOf(meridionalRadiusOfCurvature(latitude.doubleValue(SI.RADIAN)), SI.METRE); } /** * Returns the meridional arc, the true meridional distance on the * ellipsoid from the equator to the specified latitude, in meters. * * @param phi The local latitude (in radians). * @return The meridional arc (in meters). */ public double meridionalArc(final double phi) { final double sin2Phi = Math.sin(2.0 * phi); final double sin4Phi = Math.sin(4.0 * phi); final double sin6Phi = Math.sin(6.0 * phi); final double sin8Phi = Math.sin(8.0 * phi); final double n = f / (2.0 - f); final double n2 = n * n; final double n3 = n2 * n; final double n4 = n3 * n; final double n5 = n4 * n; final double n1n2 = n - n2; final double n2n3 = n2 - n3; final double n3n4 = n3 - n4; final double n4n5 = n4 - n5; final double ap = a * (1.0 - n + (5.0 / 4.0) * (n2n3) + (81.0 / 64.0) * (n4n5)); final double bp = (3.0 / 2.0) * a * (n1n2 + (7.0 / 8.0) * (n3n4) + (55.0 / 64.0) * n5); final double cp = (15.0 / 16.0) * a * (n2n3 + (3.0 / 4.0) * (n4n5)); final double dp = (35.0 / 48.0) * a * (n3n4 + (11.0 / 16.0) * n5); final double ep = (315.0 / 512.0) * a * (n4n5); return ap * phi - bp * sin2Phi + cp * sin4Phi - dp * sin6Phi + ep * sin8Phi; } /** * Returns the meridional arc, the true meridional distance on the * ellipsoid from the equator to the specified latitude. * * @param latitude The local latitude. * @return The meridional arc. */ public Measurable meridionalArc(final Measurable latitude) { return Measure.valueOf(meridionalArc(latitude.doubleValue(SI.RADIAN)), SI.METRE); } }

Ads help maintain this website.