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