latlon.java
来自「world wind java sdk 源码」· Java 代码 · 共 943 行 · 第 1/3 页
JAVA
943 行
String msg = Logging.getMessage("nullValue.AngleIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } Angle lat = Angle.normalizedLatitude(this.latitude.subtract(that.latitude)); Angle lon = Angle.normalizedLongitude(this.longitude.subtract(that.longitude)); return new LatLon(lat, lon); } public LatLon add(Position that) { if (that == null) { String msg = Logging.getMessage("nullValue.AngleIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } Angle lat = Angle.normalizedLatitude(this.latitude.add(that.getLatitude())); Angle lon = Angle.normalizedLongitude(this.longitude.add(that.getLongitude())); return new LatLon(lat, lon); } public LatLon subtract(Position that) { if (that == null) { String msg = Logging.getMessage("nullValue.AngleIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } Angle lat = Angle.normalizedLatitude(this.latitude.subtract(that.getLatitude())); Angle lon = Angle.normalizedLongitude(this.longitude.subtract(that.getLongitude())); return new LatLon(lat, lon); } public static boolean positionsCrossDateLine(Iterable<? extends LatLon> positions) { if (positions == null) { String msg = Logging.getMessage("nullValue.PositionsListIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } LatLon pos = null; for (LatLon posNext : positions) { if (pos != null) { // A segment cross the line if end pos have different longitude signs // and are more than 180 degress longitude apart if (Math.signum(pos.getLongitude().degrees) != Math.signum(posNext.getLongitude().degrees)) { double delta = Math.abs(pos.getLongitude().degrees - posNext.getLongitude().degrees); if (delta > 180 && delta < 360) return true; } } pos = posNext; } return false; } public static boolean positionsCrossLongitudeBoundary(LatLon p1, LatLon p2) { if (p1 == null || p2 == null) { String msg = Logging.getMessage("nullValue.PositionIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } // A segment cross the line if end pos have different longitude signs // and are more than 180 degress longitude apart if (Math.signum(p1.getLongitude().degrees) != Math.signum(p2.getLongitude().degrees)) { double delta = Math.abs(p1.getLongitude().degrees - p2.getLongitude().degrees); if (delta > 180 && delta < 360) return true; } return false; } /** * Parses a string containing latitude and longitude coordinates in either Degrees-minutes-seconds or decimal * degrees. The latitude must precede the longitude and the angles must be separated by a comma. * * @param latLonString a string containing the comma separated latitude and longitude in either DMS or decimal * degrees. * @return a <code>LatLon</code> instance with the parsed angles. * @throws IllegalArgumentException if <code>latLonString</code> is null. * @throws NumberFormatException if the string does not form a latitude, longitude pair. */ public LatLon parseLatLon(String latLonString) // TODO { if (latLonString == null) { String msg = Logging.getMessage("nullValue.StringIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } throw new UnsupportedOperationException(); // TODO: remove when implemented } @Override public String toString() { String las = String.format("Lat %7.4f\u00B0", this.getLatitude().getDegrees()); String los = String.format("Lon %7.4f\u00B0", this.getLongitude().getDegrees()); return "(" + las + ", " + los + ")"; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final gov.nasa.worldwind.geom.LatLon latLon = (gov.nasa.worldwind.geom.LatLon) o; if (!latitude.equals(latLon.latitude)) return false; //noinspection RedundantIfStatement if (!longitude.equals(latLon.longitude)) return false; return true; } public static boolean equals(LatLon a, LatLon b) { return a.getLatitude().equals(b.getLatitude()) && a.getLongitude().equals(b.getLongitude()); } @Override public int hashCode() { int result; result = latitude.hashCode(); result = 29 * result + longitude.hashCode(); return result; } /** * Compute the forward azimuth between two positions * * @param p1 first position * @param p2 second position * @param equatorialRadius the equatorial radius of the globe in meters * @param polarRadius the polar radius of the globe in meters * @return the azimuth */ public Angle ellipsoidalForwardAzimuth(LatLon p1, LatLon p2, double equatorialRadius, double polarRadius) { // TODO: What if polar radius is larger than equatorial radius? final double F = (equatorialRadius - polarRadius) / equatorialRadius; // flattening = 1.0 / 298.257223563; final double R = 1.0 - F; if (p1 == null || p2 == null) { String message = Logging.getMessage("nullValue.PositionIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } // See ellipsoidalDistance() below for algorithm info. double GLAT1 = p1.getLatitude().radians; double GLAT2 = p2.getLatitude().radians; double TU1 = R * Math.sin(GLAT1) / Math.cos(GLAT1); double TU2 = R * Math.sin(GLAT2) / Math.cos(GLAT2); double CU1 = 1. / Math.sqrt(TU1 * TU1 + 1.); double CU2 = 1. / Math.sqrt(TU2 * TU2 + 1.); double S = CU1 * CU2; double BAZ = S * TU2; double FAZ = BAZ * TU1; return Angle.fromRadians(FAZ); } // TODO: Need method to compute end position from initial position, azimuth and distance. The companion to the // spherical version, endPosition(), above. /** * Computes the distance between two points on an ellipsoid iteratively. * <p/> * NOTE: This method was copied from the UniData NetCDF Java library. http://www.unidata.ucar.edu/software/netcdf-java/ * <p/> * Algorithm from U.S. National Geodetic Survey, FORTRAN program "inverse," subroutine "INVER1," by L. PFEIFER and * JOHN G. GERGEN. See http://www.ngs.noaa.gov/TOOLS/Inv_Fwd/Inv_Fwd.html * <p/> * Original documentation: SOLUTION OF THE GEODETIC INVERSE PROBLEM AFTER T.VINCENTY MODIFIED RAINSFORD'S METHOD * WITH HELMERT'S ELLIPTICAL TERMS EFFECTIVE IN ANY AZIMUTH AND AT ANY DISTANCE SHORT OF ANTIPODAL * STANDPOINT/FOREPOINT MUST NOT BE THE GEOGRAPHIC POLE * <p/> * Requires close to 1.4 E-5 seconds wall clock time per call on a 550 MHz Pentium with Linux 7.2. * * @param p1 first position * @param p2 second position * @param equatorialRadius the equatorial radius of the globe in meters * @param polarRadius the polar radius of the globe in meters * @return distance in meters between the two points */ public static double ellipsoidalDistance(LatLon p1, LatLon p2, double equatorialRadius, double polarRadius) { // TODO: I think there is a non-iterative way to calculate the distance. Find it and compare with this one. // TODO: What if polar radius is larger than equatorial radius? final double F = (equatorialRadius - polarRadius) / equatorialRadius; // flattening = 1.0 / 298.257223563; final double R = 1.0 - F; final double EPS = 0.5E-13; if (p1 == null || p2 == null) { String message = Logging.getMessage("nullValue.PositionIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } // Algorithm from National Geodetic Survey, FORTRAN program "inverse," // subroutine "INVER1," by L. PFEIFER and JOHN G. GERGEN. // http://www.ngs.noaa.gov/TOOLS/Inv_Fwd/Inv_Fwd.html // Conversion to JAVA from FORTRAN was made with as few changes as possible // to avoid errors made while recasting form, and to facilitate any future // comparisons between the original code and the altered version in Java. // Original documentation: // SOLUTION OF THE GEODETIC INVERSE PROBLEM AFTER T.VINCENTY // MODIFIED RAINSFORD'S METHOD WITH HELMERT'S ELLIPTICAL TERMS // EFFECTIVE IN ANY AZIMUTH AND AT ANY DISTANCE SHORT OF ANTIPODAL // STANDPOINT/FOREPOINT MUST NOT BE THE GEOGRAPHIC POLE // A IS THE SEMI-MAJOR AXIS OF THE REFERENCE ELLIPSOID // F IS THE FLATTENING (NOT RECIPROCAL) OF THE REFERNECE ELLIPSOID // LATITUDES GLAT1 AND GLAT2 // AND LONGITUDES GLON1 AND GLON2 ARE IN RADIANS POSITIVE NORTH AND EAST // FORWARD AZIMUTHS AT BOTH POINTS RETURNED IN RADIANS FROM NORTH // // Reference ellipsoid is the WGS-84 ellipsoid. // See http://www.colorado.edu/geography/gcraft/notes/datum/elist.html // FAZ is forward azimuth in radians from pt1 to pt2; // BAZ is backward azimuth from point 2 to 1; // S is distance in meters. // // Conversion to JAVA from FORTRAN was made with as few changes as possible // to avoid errors made while recasting form, and to facilitate any future // comparisons between the original code and the altered version in Java. // //IMPLICIT REAL*8 (A-H,O-Z) // COMMON/CONST/PI,RAD double GLAT1 = p1.getLatitude().radians; double GLAT2 = p2.getLatitude().radians; double TU1 = R * Math.sin(GLAT1) / Math.cos(GLAT1); double TU2 = R * Math.sin(GLAT2) / Math.cos(GLAT2); double CU1 = 1. / Math.sqrt(TU1 * TU1 + 1.); double SU1 = CU1 * TU1; double CU2 = 1. / Math.sqrt(TU2 * TU2 + 1.); double S = CU1 * CU2; double BAZ = S * TU2; double FAZ = BAZ * TU1; double GLON1 = p1.getLongitude().radians; double GLON2 = p2.getLongitude().radians; double X = GLON2 - GLON1; double D, SX, CX, SY, CY, Y, SA, C2A, CZ, E, C; do { SX = Math.sin(X); CX = Math.cos(X); TU1 = CU2 * SX; TU2 = BAZ - SU1 * CU2 * CX; SY = Math.sqrt(TU1 * TU1 + TU2 * TU2); CY = S * CX + FAZ; Y = Math.atan2(SY, CY); SA = S * SX / SY; C2A = -SA * SA + 1.; CZ = FAZ + FAZ; if (C2A > 0.) { CZ = -CZ / C2A + CY; } E = CZ * CZ * 2. - 1.; C = ((-3. * C2A + 4.) * F + 4.) * C2A * F / 16.; D = X; X = ((E * CY * C + CZ) * SY * C + Y) * SA; X = (1. - C) * X * F + GLON2 - GLON1; //IF(DABS(D-X).GT.EPS) GO TO 100 } while (Math.abs(D - X) > EPS); //FAZ = Math.atan2(TU1, TU2); //BAZ = Math.atan2(CU1 * SX, BAZ * CX - SU1 * CU2) + Math.PI; X = Math.sqrt((1. / R / R - 1.) * C2A + 1.) + 1.; X = (X - 2.) / X; C = 1. - X; C = (X * X / 4. + 1.) / C; D = (0.375 * X * X - 1.) * X; X = E * CY; S = 1. - E - E; S = ((((SY * SY * 4. - 3.) * S * CZ * D / 6. - X) * D / 4. + CZ) * SY * D + Y) * C * equatorialRadius * R; return S; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?