All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opensextant.geodesy.Ellipsoid Maven / Gradle / Ivy

Go to download

Geodesy is a small package to manipulate points on the surface of an ellipsoid model of a planetary sphere

The newest version!
/****************************************************************************************
 *  Ellipsoid.java
 *
 *  Created: Dec 29, 2006
 *
 *  @author Paul Silvey (derived from API found at
 *    "http://www.inf.ufsc.br/grafos/represen/java-or/drasys/or/geom/geo/Ellipsoid.html")
 *
 *  (C) Copyright MITRE Corporation 2007
 *
 *  The program is provided "as is" without any warranty express or implied, including 
 *  the warranty of non-infringement and the implied warranties of merchantability and 
 *  fitness for a particular purpose.  The Copyright owner will not be liable for any 
 *  damages suffered by you as a result of using the Program.  In no event will the 
 *  Copyright owner be liable for any special, indirect or consequential damages or 
 *  lost profits even if the Copyright owner has been advised of the possibility of 
 *  their occurrence.
 *
 ***************************************************************************************/
package org.opensextant.geodesy;

import edu.umd.cs.findbugs.annotations.NonNull;

import java.io.Serializable;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;

/**
 * The Ellipsoid class maintains an object pool of Singleton Ellipsoid objects (used as
 * models of a slightly flattened spherical earth), indexed by String names.  The user
 * can create additional named Ellipsoids if needed, or retrieve one of the statically
 * defined ones that are common or in historic use by geographic information and mapping
 * systems. There is an accessor method to get the list of available cached Ellipsoid
 * names, and there are accessor methods for the commonly used mathematical parameters
 * of an Ellipsoid model. 

* * TODO: implement equals() and hashCode() methods. */ public class Ellipsoid implements Serializable { private static final long serialVersionUID = 1L; private final String name; private final double a; // Radius in m of circle on equitorial plane (parameter "a") private final double b; // Distance from ellipsoid center to a pole (parameter "b") private final double f; // Flattening ratio f = (a - b) / a private final double es; // Eccentricity of ellipsoid, squared private final double ebs; // Second Eccentricity of ellipsoid, squared // Cache of frequently used singleton Ellipsoids (comment out if not needed by app) private static final Map namedEllipsoids; static { namedEllipsoids = new HashMap(); new Ellipsoid("WGS 84", 6378137.000, 1.0 / 298.25722356299722); new Ellipsoid("WGS 72", 6378135.000, 1.0 / 298.26); new Ellipsoid("WGS 66", 6378145.000, 1.0 / 298.25); new Ellipsoid("WGS 60", 6378165.000, 1.0 / 298.30); new Ellipsoid("South American 1969", 6378160.000, 1.0 / 298.25); new Ellipsoid("Krassovsky 1940", 6378245.000, 1.0 / 298.30); new Ellipsoid("Hough 1956", 6378270.000, 1.0 / 297.00); new Ellipsoid("GRS 1980", 6378137.000, 1.0 / 298.257222101); new Ellipsoid("GRS 1975", 6378140.000, 1.0 / 298.257); new Ellipsoid("GRS 1967", 6378160.000, 1.0 / 298.247167427); new Ellipsoid("Fischer 1968", 6378150.000, 1.0 / 298.30); new Ellipsoid("Fischer 1960", 6378166.000, 1.0 / 298.30); new Ellipsoid("Everest 1830", 6377276.345, 1.0 / 300.8017); new Ellipsoid("Clarke 1880", 6378249.145, 1.0 / 293.465); new Ellipsoid("Clarke 1866", 6378206.400, 1.0 / 294.9786982); new Ellipsoid("Bessel 1841", 6377397.155, 1.0 / 299.1528128); new Ellipsoid("Bessel 1841 Namibia", 6377483.865, 1.0 / 299.1528128); new Ellipsoid("Airy 1830", 6377563.396, 1.0 / 299.3249646); } /** * This is the constructor for a custom ellipsoid to be created and cached in the * object pool. If the name has not been used, the new Ellipsoid will be cached as * a singleton for future access. If already defined, an IllegalArgumentException * is thrown. Commonly used Ellipsoids are defined in a static block of this class * at class load time, so the constructor is typically not needed by client programs. * Use the getInstance method to retrieve by name instead. * * @param name String name used to get this singleton Ellipsoid instance * @param equatorialRadius radius in meters of circle on equitorial plane, a * @param flattening ratio of axes difference to equatorial radius, f = (a - b) / a * @throws IllegalArgumentException error if named ellipoid has been previously defined */ public Ellipsoid(String name, double equatorialRadius, double flattening) throws IllegalArgumentException { // User can't redefine initial named ellipsoids using standard names if (namedEllipsoids.get(name) != null) throw new IllegalArgumentException("Ellipsoid " + name + " is already defined"); // Do error checking on arguments if (equatorialRadius <= 0.0) throw new IllegalArgumentException("Ellipsoid semi-major axis (equatorialRadius)" + " must be greater than zero"); double inv_f = 1.0 / flattening; if ((inv_f < 250.0) || (350.0 < inv_f)) throw new IllegalArgumentException("Ellipsoid's inverse flattening (1/f)" + " must be between 250 and 350"); this.name = name; a = equatorialRadius; f = flattening; b = equatorialRadius * (1.0 - flattening); es = (2.0 * f) - (f * f); ebs = (1.0 / (1.0 - es)) - 1.0; namedEllipsoids.put(name, this); } /** * This method returns a Set of String names of defined Ellipsoids available in the * object pool. * * @return the Set of String names for currently defined Ellipsoid singletons */ @NonNull public static Set getEllipsoidNames() { return namedEllipsoids.keySet(); } /** * This method will retrieve the named singleton Ellipsoid, if defined. * * @param name String used to identify the Ellipsoid (e.g. "WGS 84") * @return Ellipsoid singleton with given name, retrieved from cache */ public static Ellipsoid getInstance(String name) { return namedEllipsoids.get(name); } /** * This accessor method returns the name of this Ellipsoid. * * @return name String used to identify this ellipsoid */ public String getName() { return name; } /** * This accessor method returns the equatorialRadius, ellipsoid parameter 'a' * (semi-major axis). * * @return radius in meters of circle on equitorial plane */ public double getEquatorialRadius() { return a; } /** * This accessor method returns the polarRadius, ellipsoid parameter 'b' * (semi-minor axis). * * @return distance in meters from center to pole */ public double getPolarRadius() { return b; } /** * This method returns the radius of curvature of this Ellipsoid, in meters, * at the given Latitude. It is also called the radius of curvature in the prime * vertical. * * @param lat the Latitude for which the ellipsoid's radius is desired * @return the radius of the ellipsoid at the given Latitude, in meters. */ public double getRadius(Latitude lat) { double sinLat = Math.sin(lat.inRadians()); return a / Math.sqrt(1.0 - es * sinLat * sinLat); } /** * This accessor method returns the ellipsoid flattening parameter, * 'f' = (a - b) / a. * * @return flattening ratio of axes difference to equatorial radius */ public double getFlattening() { return f; } /** * This accessor method returns the ellipsoid eccentricity parameter, * 'e' = sqrt(1 - (b^2 / a^2)). * * @return eccentricity of the ellipsoid */ public double getEccentricity() { return Math.sqrt(es); } /** * This accessor method returns the ellipsoid eccentricity value squared. * * @return eccentricity of the ellipsoid, squared */ public double getEccentricitySquared() { return es; } /** * This accessor method returns the ellipsoid second eccentricity value squared. * * @return second eccentricity of the ellipsoid, squared */ public double get2ndEccentricitySquared() { return ebs; } /** * This method calculates the orthodromic distance in meters between two points, which * is the shortest distance between two geodetic points on the surface of this ellipsoid. * * @param p1 geodetic point 1 * @param p2 geodetic point 2 * @return distance in meters */ public double orthodromicDistance(Geodetic2DPoint p1, Geodetic2DPoint p2) { Geodetic2DArc arc = new Geodetic2DArc(this, p1, p2); return arc.getDistanceInMeters(); /* // Alternate method (appears slightly faster) - don't know which method is most accurate // Adapted from H. Andoyer: from Atronomical Algorithms, Jean Meeus, 2nd edition. double lon1 = p1.getLongitude().inRadians(); double lat1 = p1.getLatitude().inRadians(); double lon2 = p2.getLongitude().inRadians(); double lat2 = p2.getLatitude().inRadians(); double f = (lat1 + lat2) / 2.0; double g = (lat1 - lat2) / 2.0; double l = (lon1 - lon2) / 2.0; double sf = Math.sin(f); double sg = Math.sin(g); double sl = Math.sin(l); double s, c, w, r, d, h1, h2; sg = sg * sg; sl = sl * sl; sf = sf * sf; s = sg * (1.0 - sl) + (1.0 - sf) * sl; c = (1.0 - sg) * (1.0 - sl) + sf * sl; if ((c == 0) || (s == 0)) { return 0.0; } else { w = Math.atan(Math.sqrt(s / c)); r = Math.sqrt(s * c) / w; d = 2.0 * w * a; h1 = (3.0 * r - 1.0) / 2.0 / c; h2 = (3.0 * r + 1.0) / 2.0 / s; return d * (1.0 + this.f * (h1 * sf * (1.0 - sg) - h2 * (1.0 - sf) * sg)); } */ } /** * This method returns the name of this Ellipsoid. * * @return name String used to identify this Ellipsoid in the object pool. */ public String toString() { return getName(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy