latlon.java

来自「world wind java sdk 源码」· Java 代码 · 共 943 行 · 第 1/3 页

JAVA
943
字号
/*Copyright (C) 2001, 2006 United States Governmentas represented by the Administrator of theNational Aeronautics and Space Administration.All Rights Reserved.*/package gov.nasa.worldwind.geom;import gov.nasa.worldwind.util.Logging;/** * Represents a point on the two-dimensional surface of a globe. Latitude is the degrees North and ranges between [-90, * 90], while longitude refers to degrees East, and ranges between (-180, 180]. * <p/> * Instances of <code>LatLon</code> are immutable. * * @author Tom Gaskins * @version $Id: LatLon.java 10881 2009-05-05 20:58:43Z tgaskins $ */public class LatLon{    public static final LatLon ZERO = new LatLon(Angle.ZERO, Angle.ZERO);    public final Angle latitude;    public final Angle longitude;    /**     * Factor method for obtaining a new <code>LatLon</code> from two angles expressed in radians.     *     * @param latitude  in radians     * @param longitude in radians     * @return a new <code>LatLon</code> from the given angles, which are expressed as radians     */    public static LatLon fromRadians(double latitude, double longitude)    {        return new LatLon(Math.toDegrees(latitude), Math.toDegrees(longitude));    }    /**     * Factory method for obtaining a new <code>LatLon</code> from two angles expressed in degrees.     *     * @param latitude  in degrees     * @param longitude in degrees     * @return a new <code>LatLon</code> from the given angles, which are expressed as degrees     */    public static LatLon fromDegrees(double latitude, double longitude)    {        return new LatLon(latitude, longitude);    }    private LatLon(double latitude, double longitude)    {        this.latitude = Angle.fromDegrees(latitude);        this.longitude = Angle.fromDegrees(longitude);    }    /**     * Contructs a new  <code>LatLon</code> from two angles. Neither angle may be null.     *     * @param latitude  latitude     * @param longitude longitude     * @throws IllegalArgumentException if <code>latitude</code> or <code>longitude</code> is null     */    public LatLon(Angle latitude, Angle longitude)    {        if (latitude == null || longitude == null)        {            String message = Logging.getMessage("nullValue.LatitudeOrLongitudeIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        this.latitude = latitude;        this.longitude = longitude;    }    public LatLon(LatLon latLon)    {        if (latLon == null)        {            String message = Logging.getMessage("nullValue.LatLonIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        this.latitude = latLon.latitude;        this.longitude = latLon.longitude;    }    /**     * Obtains the latitude of this <code>LatLon</code>.     *     * @return this <code>LatLon</code>'s latitude     */    public final Angle getLatitude()    {        return this.latitude;    }    /**     * Obtains the longitude of this <code>LatLon</code>.     *     * @return this <code>LatLon</code>'s longitude     */    public final Angle getLongitude()    {        return this.longitude;    }    public static LatLon interpolate(double amount, LatLon value1, LatLon value2)    {        if (value1 == null || value2 == null)        {            String message = Logging.getMessage("nullValue.LatLonIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        if (LatLon.equals(value1, value2))            return value1;        Line line = Line.fromSegment(            new Vec4(value1.getLongitude().radians, value1.getLatitude().radians, 0),            new Vec4(value2.getLongitude().radians, value2.getLatitude().radians, 0));        Vec4 p = line.getPointAt(amount);        return LatLon.fromRadians(p.y(), p.x);    }    /**     * Computes the great circle angular distance between two locations. The return value gives the distance as the     * angle between the two positions on the pi radius circle. In radians, this angle is also the arc length of the     * segment between the two positions on that circle. To compute a distance in meters from this value, multiply it by     * the radius of the globe.     *     * @param p1 LatLon of the first location     * @param p2 LatLon of the second location     * @return the angular distance between the two locations. In radians, this value is the arc length on the radius pi     *         circle.     */    public static Angle greatCircleDistance(LatLon p1, LatLon p2)    {        if ((p1 == null) || (p2 == null))        {            String message = Logging.getMessage("nullValue.LatLonIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        double lat1 = p1.getLatitude().radians;        double lon1 = p1.getLongitude().radians;        double lat2 = p2.getLatitude().radians;        double lon2 = p2.getLongitude().radians;        if (lat1 == lat2 && lon1 == lon2)            return Angle.ZERO;        // Taken from "Map Projections - A Working Manual", page 30, equation 5-3a.        // The traditional d=2*asin(a) form has been replaced with d=2*atan2(sqrt(a), sqrt(1-a))        // to reduce rounding errors with large distances.        double a = Math.sin((lat2 - lat1) / 2.0) * Math.sin((lat2 - lat1) / 2.0)            + Math.cos(lat1) * Math.cos(lat2) * Math.sin((lon2 - lon1) / 2.0) * Math.sin((lon2 - lon1) / 2.0);        double distanceRadians = 2.0 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));        return Double.isNaN(distanceRadians) ? Angle.ZERO : Angle.fromRadians(distanceRadians);    }    /**     * Computes the azimuth angle (clockwise from North) that points from the first location to the second location.     * This angle can be used as the starting azimuth for a great circle arc that begins at the first location, and     * passes through the second location.     *     * @param p1 LatLon of the first location     * @param p2 LatLon of the second location     * @return Angle that points from the first location to the second location.     */    public static Angle greatCircleAzimuth(LatLon p1, LatLon p2)    {        if ((p1 == null) || (p2 == null))        {            String message = Logging.getMessage("nullValue.LatLonIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        double lat1 = p1.getLatitude().radians;        double lon1 = p1.getLongitude().radians;        double lat2 = p2.getLatitude().radians;        double lon2 = p2.getLongitude().radians;        if (lat1 == lat2 && lon1 == lon2)            return Angle.ZERO;        if (lon1 == lon2)            return lat1 > lat2 ? Angle.POS180 : Angle.ZERO;        // Taken from "Map Projections - A Working Manual", page 30, equation 5-4b.        // The atan2() function is used in place of the traditional atan(y/x) to simplify the case when x==0.        double y = Math.cos(lat2) * Math.sin(lon2 - lon1);        double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1);        double azimuthRadians = Math.atan2(y, x);        return Double.isNaN(azimuthRadians) ? Angle.ZERO : Angle.fromRadians(azimuthRadians);    }    /**     * Computes the location on a great circle arc with the given starting location, azimuth, and arc distance.     *     * @param p                  LatLon of the starting location     * @param greatCircleAzimuth great circle azimuth angle (clockwise from North)     * @param pathLength         arc distance to travel     * @return LatLon location on the great circle arc.     */    public static LatLon greatCircleEndPosition(LatLon p, Angle greatCircleAzimuth, Angle pathLength)    {        if (p == null)        {            String message = Logging.getMessage("nullValue.LatLonIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        if (greatCircleAzimuth == null || pathLength == null)        {            String message = Logging.getMessage("nullValue.AngleIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        double lat = p.getLatitude().radians;        double lon = p.getLongitude().radians;        double azimuth = greatCircleAzimuth.radians;        double distance = pathLength.radians;        if (distance == 0)            return p;        // Taken from "Map Projections - A Working Manual", page 31, equation 5-5 and 5-6.        double endLatRadians = Math.asin(Math.sin(lat) * Math.cos(distance)            + Math.cos(lat) * Math.sin(distance) * Math.cos(azimuth));        double endLonRadians = lon + Math.atan2(            Math.sin(distance) * Math.sin(azimuth),            Math.cos(lat) * Math.cos(distance) - Math.sin(lat) * Math.sin(distance) * Math.cos(azimuth));        if (Double.isNaN(endLatRadians) || Double.isNaN(endLonRadians))            return p;        return new LatLon(            Angle.fromRadians(endLatRadians).normalizedLatitude(),            Angle.fromRadians(endLonRadians).normalizedLongitude());    }    /**     * Computes the location on a great circle arc with the given starting location, azimuth, and arc distance.     *     * @param p                         LatLon of the starting location     * @param greatCircleAzimuthRadians great circle azimuth angle (clockwise from North), in radians     * @param pathLengthRadians         arc distance to travel, in radians     * @return LatLon location on the great circle arc.     */    public static LatLon greatCircleEndPosition(LatLon p, double greatCircleAzimuthRadians, double pathLengthRadians)    {        if (p == null)        {            String message = Logging.getMessage("nullValue.LatLonIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        return greatCircleEndPosition(p,            Angle.fromRadians(greatCircleAzimuthRadians), Angle.fromRadians(pathLengthRadians));    }    /**     * Returns two locations with the most extreme latitudes on the great circle with the given starting location and     * azimuth.     *     * @param location location on the great circle.     * @param azimuth great circle azimuth angle (clockwise from North).     *     * @return two locations where the great circle has its extreme latitudes.     * @throws IllegalArgumentException if either <code>location</code> or <code>azimuth</code> are null.     */    public static LatLon[] greatCircleExtremeLocations(LatLon location, Angle azimuth)    {        if (location == null)        {            String message = Logging.getMessage("nullValue.LocationIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        if (azimuth == null)        {            String message = Logging.getMessage("nullValue.AzimuthIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        double lat0 = location.getLatitude().radians;        double az = azimuth.radians;        // Derived by solving the function for longitude on a great circle against the desired longitude. We start with        // the equation in "Map Projections - A Working Manual", page 31, equation 5-5:        //        // lat = asin( sin(lat0) * cos(c) + cos(lat0) * sin(c) * cos(Az) )        //        // Where (lat0, lon) are the starting coordinates, c is the angular distance along the great circle from the        // starting coordinate, and Az is the azimuth. All values are in radians.        //        // Solving for angular distance gives distance to the equator:        //        // tan(c) = -tan(lat0) / cos(Az)        //        // The great circle is by definition centered about the Globe's origin. Therefore intersections with the

⌨️ 快捷键说明

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