Exemple #1
0
        public LatLon(LatLon latLon)
        {
            if (latLon == null)
            {
                throw new ArgumentException("Lat Lon Is Null");
            }

            this.latitude = latLon.latitude;
            this.longitude = latLon.longitude;
        }
Exemple #2
0
        /*
        public static Angle getAverageDistance(Iterable<? extends LatLon> locations)
        {
            // Compute the average rhumb distance between locations.

            if ((locations == null))
            {
                throw new ArgumentException("Locations List Is Null");
            }

            double totalDistance = 0.0;
            int count = 0;

            for (LatLon p1 : locations)
            {
                for (LatLon p2 : locations)
                {
                    if (p1 != p2)
                    {
                        double d = rhumbDistance(p1, p2).radians;
                        totalDistance += d;
                        count++;
                    }
                }
            }

            return (count == 0) ? Angle.ZERO : Angle.fromRadians(totalDistance / (double) count);
        }
        */
        public LatLon Add(LatLon that)
        {
            if (that == null)
            {
                throw new ArgumentException("Angle Is Null");
            }

            Angle lat = Angle.NormalizeLatitude(this.latitude.Add(that.latitude));
            Angle lon = Angle.NormalizeLongitude(this.longitude.Add(that.longitude));

            return new LatLon(lat, lon);
        }
Exemple #3
0
        /**
         * Computes the location on a rhumb line with the given starting location, rhumb azimuth, and arc distance along the
         * line.
         *
         * @param p                   LatLon of the starting location
         * @param rhumbAzimuthRadians rhumb azimuth angle (clockwise from North), in radians
         * @param pathLengthRadians   arc distance to travel, in radians
         *
         * @return LatLon location on the rhumb line.
         */
        public static LatLon rhumbEndPosition(LatLon p, double rhumbAzimuthRadians, double pathLengthRadians)
        {
            throw new NotImplementedException();
            /*
            if (p == null)
            {
                throw new ArgumentException("LatLon Is Null");
            }

            return rhumbEndPosition(p, Angle.fromRadians(rhumbAzimuthRadians), Angle.fromRadians(pathLengthRadians));
            */
        }
Exemple #4
0
        /**
         * Computes the location on a rhumb line with the given starting location, rhumb azimuth, and arc distance along the
         * line.
         *
         * @param p            LatLon of the starting location
         * @param rhumbAzimuth rhumb azimuth angle (clockwise from North)
         * @param pathLength   arc distance to travel
         *
         * @return LatLon location on the rhumb line.
         */
        public static LatLon rhumbEndPosition(LatLon p, Angle rhumbAzimuth, Angle pathLength)
        {
            throw new NotImplementedException();
            /*
            if (p == null)
            {
                throw new ArgumentException("LatLon Is Null");
            }
            if (rhumbAzimuth == null || pathLength == null)
            {
                throw new ArgumentException("Angle Is Null");
            }

            double lat1 = p.getLatitude().radians;
            double lon1 = p.getLongitude().radians;
            double azimuth = rhumbAzimuth.radians;
            double distance = pathLength.radians;

            if (distance == 0)
                return p;

            // Taken from http://www.movable-type.co.uk/scripts/latlong.html
            double lat2 = lat1 + distance * Math.cos(azimuth);
            double dPhi = Math.log(Math.tan(lat2 / 2.0 + Math.PI / 4.0) / Math.tan(lat1 / 2.0 + Math.PI / 4.0));
            double q = (lat2 - lat1) / dPhi;
            if (Double.isNaN(dPhi) || Double.isNaN(q) || Double.isInfinite(q))
            {
                q = Math.cos(lat1);
            }
            double dLon = distance * Math.sin(azimuth) / q;
            // Handle latitude passing over either pole.
            if (Math.abs(lat2) > Math.PI / 2.0)
            {
                lat2 = lat2 > 0 ? Math.PI - lat2 : -Math.PI - lat2;
            }
            double lon2 = (lon1 + dLon + Math.PI) % (2 * Math.PI) - Math.PI;

            if (Double.isNaN(lat2) || Double.isNaN(lon2))
                return p;

            return new LatLon(
                Angle.fromRadians(lat2).normalizedLatitude(),
                Angle.fromRadians(lon2).normalizedLongitude());
            */
        }
Exemple #5
0
        /**
         * Returns two locations with the most extreme latitudes on the sequence of great circle arcs defined by each pair
         * of locations in the specified iterable.
         *
         * @param locations the pairs of locations defining a sequence of great circle arcs.
         *
         * @return two locations with the most extreme latitudes on the great circle arcs.
         *
         * @throws ArgumentException if <code>locations</code> is null.
         */
        /*
        public static LatLon[] greatCircleArcExtremeLocations(Iterable<? extends LatLon> locations)
        {
            if (locations == null)
            {
                throw new ArgumentException("Locations List Is Null");
            }

            LatLon minLatLocation = null;
            LatLon maxLatLocation = null;

            LatLon lastLocation = null;

            for (LatLon ll : locations)
            {
                if (lastLocation != null)
                {
                    LatLon[] extremes = LatLon.greatCircleArcExtremeLocations(lastLocation, ll);
                    if (extremes == null)
                        continue;

                    if (minLatLocation == null || minLatLocation.getLatitude().degrees > extremes[0].getLatitude().degrees)
                        minLatLocation = extremes[0];
                    if (maxLatLocation == null || maxLatLocation.getLatitude().degrees < extremes[1].getLatitude().degrees)
                        maxLatLocation = extremes[1];
                }

                lastLocation = ll;
            }

            return new LatLon[] {minLatLocation, maxLatLocation};
        }
        */
        /**
         * Computes the length of the rhumb line between two locations. The return value gives the distance as the angular
         * distance 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 arc length of the rhumb line between the two locations. In radians, this value is the arc length on
         *         the radius pi circle.
         */
        public static Angle rhumbDistance(LatLon p1, LatLon p2)
        {
            throw new NotImplementedException();
            /*
            if (p1 == null || p2 == null)
            {
                throw new ArgumentException("LatLon Is Null");
            }

            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 http://www.movable-type.co.uk/scripts/latlong.html
            double dLat = lat2 - lat1;
            double dLon = lon2 - lon1;
            double dPhi = Math.log(Math.tan(lat2 / 2.0 + Math.PI / 4.0) / Math.tan(lat1 / 2.0 + Math.PI / 4.0));
            double q = dLat / dPhi;
            if (Double.isNaN(dPhi) || Double.isNaN(q))
            {
                q = Math.cos(lat1);
            }
            // If lonChange over 180 take shorter rhumb across 180 meridian.
            if (Math.abs(dLon) > Math.PI)
            {
                dLon = dLon > 0 ? -(2 * Math.PI - dLon) : (2 * Math.PI + dLon);
            }

            double distanceRadians = Math.sqrt(dLat * dLat + q * q * dLon * dLon);

            return Double.isNaN(distanceRadians) ? Angle.ZERO : Angle.fromRadians(distanceRadians);
            */
        }
Exemple #6
0
        /**
         * Returns the an interpolated location along the rhumb line between <code>value1</code> and <code>value2</code>.
         * The interpolation factor <code>amount</code> defines the weight given to each value, and is clamped to the range
         * [0, 1]. If <code>a</code> is 0 or less, this returns <code>value1</code>. If <code>amount</code> is 1 or more,
         * this returns <code>value2</code>. Otherwise, this returns the location on the rhumb line between
         * <code>value1</code> and <code>value2</code> corresponding to the specified interpolation factor.
         *
         * @param amount the interpolation factor
         * @param value1 the first location.
         * @param value2 the second location.
         *
         * @return an interpolated location along the rhumb line between <code>value1</code> and <code>value2</code>
         *
         * @throws ArgumentException if either location is null.
         */
        public static LatLon interpolateRhumb(double amount, LatLon value1, LatLon value2)
        {
            throw new NotImplementedException();
            /*
            if (value1 == null || value2 == null)
            {
                throw new ArgumentException("Lat Lon Is Null");
            }

            if (LatLon.equals(value1, value2))
                return value1;

            double t = WWMath.clamp(amount, 0d, 1d);
            Angle azimuth = LatLon.rhumbAzimuth(value1, value2);
            Angle distance = LatLon.rhumbDistance(value1, value2);
            Angle pathLength = Angle.fromDegrees(t * distance.degrees);

            return LatLon.rhumbEndPosition(value1, azimuth, pathLength);
            */
        }
Exemple #7
0
        /**
         * Returns the linear interpolation of <code>value1</code> and <code>value2</code>, treating the geographic
         * locations as simple 2D coordinate pairs.
         *
         * @param amount the interpolation factor
         * @param value1 the first location.
         * @param value2 the second location.
         *
         * @return the linear interpolation of <code>value1</code> and <code>value2</code>.
         *
         * @throws IllegalArgumentException if either location is null.
         */
        public static LatLon interpolate(double amount, LatLon value1, LatLon value2)
        {
            throw new NotImplementedException();
            /*
            if (value1 == null || value2 == null)
            {
                throw new ArgumentException("Lat Lon Is Null");
            }

            if (LatLon.Equals(value1, value2))
                return value1;

            Line line;
            try
            {
                line = Line.fromSegment(
                    new Vec4(value1.getLongitude().radians, value1.getLatitude().radians, 0),
                    new Vec4(value2.getLongitude().radians, value2.getLatitude().radians, 0));
            }
            catch (ArgumentException e)
            {
                // Locations became coincident after calculations.
                return value1;
            }

            Vec4 p = line.getPointAt(amount);

            return LatLon.fromRadians(p.y(), p.x);
            */
        }
Exemple #8
0
        /**
         * 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)
        {
            throw new NotImplementedException();
            /*
            if (p == null)
            {
                throw new ArgumentException("Lat Lon Is Null");
            }
            if (greatCircleAzimuth == null || pathLength == null)
            {
                throw new ArgumentException("Angle Is Null");
            }

            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());
            */
        }
Exemple #9
0
        /**
         * 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 ArgumentException if either <code>location</code> or <code>azimuth</code> are null.
         */
        public static LatLon[] greatCircleExtremeLocations(LatLon location, Angle azimuth)
        {
            throw new NotImplementedException();
            /*
            if (location == null)
            {
                throw new ArgumentException("Location Is Null");
            }

            if (azimuth == null)
            {
                throw new ArgumentException("Azimuth Is Null");
            }

            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
            // equator will be antipodal (exactly 180 degrees opposite each other), as will be the extreme latitudes.
            // My observing the symmetry of a great circle, it is also apparent that the extreme latitudes will be 90
            // degrees from either interseciton with the equator.
            //
            // d1 = c + 90
            // d2 = c - 90

            double tanDistance = -Math.tan(lat0) / Math.cos(az);
            double distance = Math.atan(tanDistance);

            Angle extremeDistance1 = Angle.fromRadians(distance + (Math.PI / 2.0));
            Angle extremeDistance2 = Angle.fromRadians(distance - (Math.PI / 2.0));

            return new LatLon[]
            {
                greatCircleEndPosition(location, azimuth, extremeDistance1),
                greatCircleEndPosition(location, azimuth, extremeDistance2)
            };
            */
        }
Exemple #10
0
        /**
         * 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)
        {
            throw new NotImplementedException();
            /*
            if ((p1 == null) || (p2 == null))
            {
                throw new ArgumentException("Lat Lon Is Null");
            }

            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);
            */
        }
Exemple #11
0
        /**
         * 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)
        {
            throw new NotImplementedException();
            /*
            if ((p1 == null) || (p2 == null))
            {
                throw new ArgumentException("Lat Lon Is Null");
            }

            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;

            // "Haversine formula," taken from http://en.wikipedia.org/wiki/Great-circle_distance#Formul.C3.A6
            double a = Math.sin((lat2 - lat1) / 2.0);
            double b = Math.sin((lon2 - lon1) / 2.0);
            double c = a * a + +Math.cos(lat1) * Math.cos(lat2) * b * b;
            double distanceRadians = 2.0 * Math.asin(Math.sqrt(c));

            return Double.isNaN(distanceRadians) ? Angle.ZERO : Angle.fromRadians(distanceRadians);
            */
        }
Exemple #12
0
        /**
         * Returns two locations with the most extreme latitudes on the great circle arc defined by, and limited to, the two
         * locations.
         *
         * @param begin beginning location on the great circle arc.
         * @param end   ending location on the great circle arc.
         *
         * @return two locations with the most extreme latitudes on the great circle arc.
         *
         * @throws ArgumentException if either <code>begin</code> or <code>end</code> are null.
         */
        public static LatLon[] greatCircleArcExtremeLocations(LatLon begin, LatLon end)
        {
            throw new NotImplementedException();
            /*
            if (begin == null)
            {
                throw new ArgumentException("Begin Is Null");
            }

            if (end == null)
            {
                throw new ArgumentException("End Is Null");
            }

            LatLon minLatLocation = null;
            LatLon maxLatLocation = null;
            double minLat = Angle.POS90.degrees;
            double maxLat = Angle.NEG90.degrees;

            // Compute the min and max latitude and assocated locations from the arc endpoints.
            for (LatLon ll : java.util.Arrays.asList(begin, end))
            {
                if (minLat >= ll.getLatitude().degrees)
                {
                    minLat = ll.getLatitude().degrees;
                    minLatLocation = ll;
                }
                if (maxLat <= ll.getLatitude().degrees)
                {
                    maxLat = ll.getLatitude().degrees;
                    maxLatLocation = ll;
                }
            }

            // Compute parameters for the great circle arc defined by begin and end. Then compute the locations of extreme
            // latitude on entire the great circle which that arc is part of.
            Angle greatArcAzimuth = greatCircleAzimuth(begin, end);
            Angle greatArcDistance = greatCircleDistance(begin, end);
            LatLon[] greatCircleExtremes = greatCircleExtremeLocations(begin, greatArcAzimuth);

            // Determine whether either of the extreme locations are inside the arc defined by begin and end. If so,
            // adjust the min and max latitude accordingly.
            for (LatLon ll : greatCircleExtremes)
            {
                Angle az = LatLon.greatCircleAzimuth(begin, ll);
                Angle d = LatLon.greatCircleDistance(begin, ll);

                // The extreme location must be between the begin and end locations. Therefore its azimuth relative to
                // the begin location should have the same signum, and its distance relative to the begin location should
                // be between 0 and greatArcDistance, inclusive.
                if (Math.signum(az.degrees) == Math.signum(greatArcAzimuth.degrees))
                {
                    if (d.degrees >= 0 && d.degrees <= greatArcDistance.degrees)
                    {
                        if (minLat >= ll.getLatitude().degrees)
                        {
                            minLat = ll.getLatitude().degrees;
                            minLatLocation = ll;
                        }
                        if (maxLat <= ll.getLatitude().degrees)
                        {
                            maxLat = ll.getLatitude().degrees;
                            maxLatLocation = ll;
                        }
                    }
                }
            }

            return new LatLon[] {minLatLocation, maxLatLocation};
            */
        }
Exemple #13
0
 public static bool Equals(LatLon a, LatLon b)
 {
     return a.Latitude.Equals(b.Latitude) && a.Longitude.Equals(b.Longitude);
 }
Exemple #14
0
        /**
         * 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 static Angle ellipsoidalForwardAzimuth(LatLon p1, LatLon p2, double equatorialRadius, double polarRadius)
        {
            throw new NotImplementedException();
            /*
            if (p1 == null || p2 == null)
            {
                throw new ArgumentException("Position Is Null");
            }

            // TODO: What if polar radius is larger than equatorial radius?
            // Calculate flattening
            final double f = (equatorialRadius - polarRadius) / equatorialRadius; // flattening

            // Calculate reduced latitudes and related sines/cosines
            final double U1 = Math.atan((1.0 - f) * Math.tan(p1.latitude.radians));
            final double cU1 = Math.cos(U1);
            final double sU1 = Math.sin(U1);

            final double U2 = Math.atan((1.0 - f) * Math.tan(p2.latitude.radians));
            final double cU2 = Math.cos(U2);
            final double sU2 = Math.sin(U2);

            // Calculate difference in longitude
            final double L = p2.longitude.subtract(p1.longitude).radians;

            // Vincenty's Formula for Forward Azimuth
            // iterate until change in lambda is negligible (e.g. 1e-12 ~= 0.06mm)
            // first approximation
            double lambda = L;
            double sLambda = Math.sin(lambda);
            double cLambda = Math.cos(lambda);

            // dummy value to ensure
            double lambda_prev = Double.MAX_VALUE;
            int count = 0;
            while (Math.abs(lambda - lambda_prev) > 1e-12 && count++ < 100)
            {
                // Store old lambda
                lambda_prev = lambda;
                // Calculate new lambda
                double sSigma = Math.sqrt(Math.pow(cU2 * sLambda, 2)
                                          + Math.pow(cU1 * sU2 - sU1 * cU2 * cLambda, 2));
                double cSigma = sU1 * sU2 + cU1 * cU2 * cLambda;
                double sigma = Math.atan2(sSigma, cSigma);
                double sAlpha = cU1 * cU2 * sLambda / sSigma;
                double cAlpha2 = 1 - sAlpha * sAlpha; // trig identity
                // As cAlpha2 approaches zeros, set cSigmam2 to zero to converge on a solution
                double cSigmam2;
                if (Math.abs(cAlpha2) < 1e-6)
                {
                    cSigmam2 = 0;
                }
                else
                {
                    cSigmam2 = cSigma - 2 * sU1 * sU2 / cAlpha2;
                }
                double c = f / 16 * cAlpha2 * (4 + f * (4 - 3 * cAlpha2));

                lambda = L + (1 - c) * f * sAlpha * (sigma + c * sSigma * (cSigmam2 + c * cSigma * (-1 + 2 * cSigmam2)));
                sLambda = Math.sin(lambda);
                cLambda = Math.cos(lambda);
            }

            return Angle.fromRadians(Math.atan2(cU2 * sLambda, cU1 * sU2 - sU1 * cU2 * cLambda));
            */
        }
Exemple #15
0
        // 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)
        {
            throw new NotImplementedException();
            /*
            // 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)
            {
                throw new ArgumentException("Position Is Null");
            }

            // 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;
            */
        }
Exemple #16
0
 public Position(LatLon latLon, double elevation)
     : base(latLon)
 {
     this.elevation = elevation;
 }