geo.java

来自「OpenMap是一个基于JavaBeansTM的开发工具包。利用OpenMap你」· Java 代码 · 共 1,182 行 · 第 1/3 页

JAVA
1,182
字号
/* *                     RESTRICTED RIGHTS LEGEND * *                        BBNT Solutions LLC *                        A Verizon Company *                        10 Moulton Street *                       Cambridge, MA 02138 *                         (617) 873-3000 * * Copyright BBNT Solutions LLC 2001, 2002 All Rights Reserved * */package com.bbn.openmap.geo;import java.util.ArrayList;import java.util.Enumeration;import com.bbn.openmap.proj.Length;/** * A class that represents a point on the Earth as a three dimensional unit * length vector, rather than latitude and longitude. For the theory and an * efficient implementation using partial evaluation see: * http://openmap.bbn.com/~kanderso/lisp/performing-lisp/essence.ps *  * This implementation matches the theory carefully, but does not use partial * evaluation. *  * <p> * For the area calculation see: http://math.rice.edu/~pcmi/sphere/ *  * @author Ken Anderson * @author Sachin Date * @author Ben Lubin * @author Michael Thome * @version $Revision: 1.4.2.15 $ on $Date: 2007/02/13 20:00:54 $ */public class Geo {    /***************************************************************************     * Constants for the shape of the earth. see     * http://www.gfy.ku.dk/%7Eiag/HB2000/part4/groten.htm     **************************************************************************/    // Replaced by Length constants.    // public static final double radiusKM = 6378.13662; // in KM.    // public static final double radiusNM = 3443.9182; // in NM.    // Replaced with WGS 84 constants    // public static final double flattening = 1.0/298.25642;    public static final double flattening = 1.0 / 298.257223563;    public static final double FLATTENING_C = (1.0 - flattening)            * (1.0 - flattening);    public static final double METERS_PER_NM = 1852;    private static final double NPD_LTERM1 = 111412.84 / METERS_PER_NM;    private static final double NPD_LTERM2 = -93.5 / METERS_PER_NM;    private static final double NPD_LTERM3 = 0.118 / METERS_PER_NM;    private double x;    private double y;    private double z;    /**     * Compute nautical miles per degree at a specified latitude (in degrees).     * Calculation from NIMA: http://pollux.nss.nima.mil/calc/degree.html     */    public final static double npdAtLat(double latdeg) {        double lat = (latdeg * Math.PI) / 180.0;        return (NPD_LTERM1 * Math.cos(lat) + NPD_LTERM2 * Math.cos(3 * lat) + NPD_LTERM3                * Math.cos(5 * lat));    }    /** Convert from geographic to geocentric latitude (radians) */    public static double geocentricLatitude(double geographicLatitude) {        return Math.atan((Math.tan(geographicLatitude) * FLATTENING_C));    }    /** Convert from geocentric to geographic latitude (radians) */    public static double geographicLatitude(double geocentricLatitude) {        return Math.atan(Math.tan(geocentricLatitude) / FLATTENING_C);    }    /** Convert from degrees to radians. */    public static double radians(double degrees) {        return Length.DECIMAL_DEGREE.toRadians(degrees);    }    /** Convert from radians to degrees. */    public static double degrees(double radians) {        return Length.DECIMAL_DEGREE.fromRadians(radians);    }    /** Convert radians to kilometers. * */    public static double km(double radians) {        return Length.KM.fromRadians(radians);    }    /** Convert kilometers to radians. * */    public static double kmToAngle(double km) {        return Length.KM.toRadians(km);    }    /** Convert radians to nauticalMiles. * */    public static double nm(double radians) {        return Length.NM.fromRadians(radians);    }    /** Convert nautical miles to radians. * */    public static double nmToAngle(double nm) {        return Length.NM.toRadians(nm);    }    public Geo() {}    /**     * Construct a Geo from its latitude and longitude.     *      * @param lat latitude in decimal degrees.     * @param lon longitude in decimal degrees.     */    public Geo(double lat, double lon) {        initialize(lat, lon);    }    /**     * Construct a Geo from its latitude and longitude.     *      * @param lat latitude.     * @param lon longitude.     * @param isDegrees should be true if the lat/lon are specified in decimal     *        degrees, false if they are radians.     */    public Geo(double lat, double lon, boolean isDegrees) {        if (isDegrees) {            initialize(lat, lon);        } else {            initializeRadians(lat, lon);        }    }    /** Construct a Geo from its parts. */    public Geo(double x, double y, double z) {        this.x = x;        this.y = y;        this.z = z;    }    /** Construct a Geo from another Geo. */    public Geo(Geo geo) {        this(geo.x, geo.y, geo.z);    }    public static final Geo makeGeoRadians(double latr, double lonr) {        double rlat = geocentricLatitude(latr);        double c = Math.cos(rlat);        return new Geo(c * Math.cos(lonr), c * Math.sin(lonr), Math.sin(rlat));    }    public static final Geo makeGeoDegrees(double latd, double lond) {        return makeGeoRadians(radians(latd), radians(lond));    }    public static final Geo makeGeo(double x, double y, double z) {        return new Geo(x, y, z);    }    public static final Geo makeGeo(Geo p) {        return new Geo(p.x, p.y, p.z);    }    /**     * Initialize this Geo to match another.     *      * @param g     */    public void initialize(Geo g) {        x = g.x;        y = g.y;        z = g.z;    }    /**     * Initialize this Geo with new parameters.     *      * @param x     * @param y     * @param z     */    public void initialize(double x, double y, double z) {        this.x = x;        this.y = y;        this.z = z;    }    /**     * Initialize this Geo with to represent coordinates.     *      * @param lat latitude in decimal degrees.     * @param lon longitude in decimal degrees.     */    public void initialize(double lat, double lon) {        initializeRadians(radians(lat), radians(lon));    }    /**     * Initialize this Geo with to represent coordinates.     *      * @param lat latitude in radians.     * @param lon longitude in radians.     */    public void initializeRadians(double lat, double lon) {        double rlat = geocentricLatitude(lat);        double c = Math.cos(rlat);        x = c * Math.cos(lon);        y = c * Math.sin(lon);        z = Math.sin(rlat);    }    /**     * Find the midpoint Geo between this one and another on a Great Circle line     * between the two. The result is undefined of the two points are antipodes.     *      * @param g2     * @return midpoint Geo.     */    public Geo midPoint(Geo g2) {        return add(g2).normalize();    }    /**     * Find the midpoint Geo between this one and another on a Great Circle line     * between the two. The result is undefined of the two points are antipodes.     *      * @param g2     * @param ret a Geo value to set returned values in. Do not pass in a null     *        value.     * @return midpoint Geo.     */    public Geo midPoint(Geo g2, Geo ret) {        return add(g2).normalize(ret);    }    public Geo interpolate(Geo g2, double x) {        return scale(x).add(g2.scale(1 - x)).normalize();    }    /**     *      * @param g2     * @param x     * @param ret Do not pass in a null value.     * @return     */    public Geo interpolate(Geo g2, double x, Geo ret) {        return scale(x).add(g2.scale(1 - x, ret), ret).normalize(ret);    }    public String toString() {        return "Geo[" + getLatitude() + "," + getLongitude() + "]";    }    public double getLatitude() {        return degrees(geographicLatitude(Math.atan2(z,                Math.sqrt(x * x + y * y))));    }    public double getLongitude() {        return degrees(Math.atan2(y, x));    }    public double getLatitudeRadians() {        return geographicLatitude(Math.atan2(z, Math.sqrt(x * x + y * y)));    }    public double getLongitudeRadians() {        return Math.atan2(y, x);    }    /**     * Reader for x, in internal axis representation (positive to the right side     * of screen).     *      * @return     */    public final double x() {        return this.x;    }    /**     * Reader for y in internal axis reprensentation (positive into screen).     *      * @return     */    public final double y() {        return this.y;    }    /**     * Reader for z in internal axis representation (positive going to top of     * screen).     *      * @return     */    public final double z() {        return this.z;    }    public void setLength(double r) {        // It's tempting to call getLatitudeRadians() here, but it changes the        // angle. I think we want to keep the angles the same, and just extend        // x, y, z, and then let the latitudes get refigured out for the        // ellipsoid when they are asked for.        double rlat = Math.atan2(z, Math.sqrt(x * x + y * y));        double rlon = getLongitudeRadians();        double c = r * Math.cos(rlat);        x = c * Math.cos(rlon);        y = c * Math.sin(rlon);        z = r * Math.sin(rlat);    }    /** North pole. */    public static final Geo north = new Geo(0.0, 0.0, 1.0);    /** Dot product. */    public double dot(Geo b) {        return (this.x() * b.x() + this.y() * b.y() + this.z() * b.z());    }    /** Dot product. */    public static double dot(Geo a, Geo b) {        return (a.x() * b.x() + a.y() * b.y() + a.z() * b.z());    }    /** Euclidian length. */    public double length() {        return Math.sqrt(this.dot(this));    }    /** Multiply this by s. * */    public Geo scale(double s) {        return scale(s, new Geo());    }    /**     * Multiply this by s.     *      * @return ret that was passed in, filled in with scaled values. Do not pass     *         in a null value.     */    public Geo scale(double s, Geo ret) {        ret.initialize(this.x() * s, this.y() * s, this.z() * s);        return ret;    }    /** Returns a unit length vector parallel to this. */    public Geo normalize() {        return this.scale(1.0 / this.length());    }    /**     * Returns a unit length vector parallel to this.     *      * @return ret with normalized values. Do not pass in a null value.     */    public Geo normalize(Geo ret) {        return this.scale(1.0 / this.length(), ret);    }    /** Vector cross product. */    public Geo cross(Geo b) {        return cross(b, new Geo());    }    /**     * Vector cross product.     *      * @return ret Do not pass in a null value.     */    public Geo cross(Geo b, Geo ret) {        ret.initialize(this.y() * b.z() - this.z() * b.y(), this.z() * b.x()                - this.x() * b.z(), this.x() * b.y() - this.y() * b.x());        return ret;    }    /** Eqvivalent to this.cross(b).length(). */    public double crossLength(Geo b) {        double x = this.y() * b.z() - this.z() * b.y();        double y = this.z() * b.x() - this.x() * b.z();        double z = this.x() * b.y() - this.y() * b.x();        return Math.sqrt(x * x + y * y + z * z);    }    /** Eqvivalent to <code>this.cross(b).normalize()</code>. */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?