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 + -
显示快捷键?