Exemplo n.º 1
0
        public void GeographicCoordinate_CanUpdateValidLongitude(double longitude)
        {
            ISphericalCoordinate expected = new Longitude(longitude);

            IGeographicCoordinate sut = InstantiateNewGeographicCoordinate();

            sut.Longitude = new Longitude(longitude);
            var result = sut.Longitude;

            Assert.Equal(expected, result);
        }
Exemplo n.º 2
0
        public void Vincenty_CorrectlyCalculatesDestinationCoordinates(double latA, double lonA, double bearingInRadians, double distanceInMeters,
                                                                       double expectedLat, double expectedLon, int maxIterations, double tolerance)
        {
            IGeographicCoordinate pointA = new GeographicCoordinate(latA, lonA);

            IGeographicCoordinate expected = new GeographicCoordinate(expectedLat, expectedLon);

            IGeographicCoordinate result = pointA.DestinationCoordinates(new Angle(bearingInRadians, AngleMeasurement.Radians), new Distance(distanceInMeters, DistanceMeasurement.Meters),
                                                                         maxIterations, tolerance);

            Assert.Equal(expected, result);
        }
Exemplo n.º 3
0
        private static VincentyFormulaVariables VincentysDirectFormula(IGeographicCoordinate pointA, IAngle initialBearing, IDistance distance,
                                                                       int maxInterations = 200, double tolerance = 1.0E-12)
        {
            // Source: https://www.movable-type.co.uk/scripts/latlong-vincenty.html

            VincentyFormulaVariables v = PrepareσConvergenceLoop(pointA, initialBearing, distance);

            v = RecalculateσUntilConvergence(distance, maxInterations, tolerance, v);

            v.DestinationCoordinates = CalculateDestinationCoordinates(pointA, v);
            v.FinalBearing           = Math.Atan2(v.sinα, -1.0 * (v.SinU1 * v.Sinσ - v.CosU1 * v.Cosσ * v.Cosα1));

            return(v);
        }
Exemplo n.º 4
0
        private static IGeographicCoordinate CalculateDestinationCoordinates(IGeographicCoordinate pointA, VincentyFormulaVariables v)
        {
            var tmp = v.SinU1 * v.Sinσ - v.CosU1 * v.Cosσ * v.Cosα1;

            v.φ2 = Math.Atan2(v.SinU1 * v.Cosσ + v.CosU1 * v.Sinσ * v.Cosα1, (1 - f) * Math.Sqrt(Math.Pow(v.sinα, 2.0) + Math.Pow(tmp, 2.0)));
            v.λ  = Math.Atan2(v.Sinσ * v.Sinα1, v.CosU1 * v.Cosσ - v.SinU1 * v.Sinσ * v.Cosα1);
            v.C  = f / 16.0 * v.CosSqα * (4.0 + f * (4.0 - 3.0 * v.CosSqα));
            v.L  = v.λ - (1.0 - v.C) * f * v.sinα *
                   (v.σ + v.C * v.Sinσ * (v.Cos2σM + v.C * v.Cosσ * (-1.0 + 2.0 * Math.Pow(v.Cos2σM, 2.0))));
            v.λ2 = (pointA.Longitude.Angle.ToRadians() + v.L + 3.0 * Math.PI) % (2.0 * Math.PI) - Math.PI;  // normalise to -180...+180

            var latitude  = Angle.ToDegrees(v.φ2);
            var longitude = Angle.ToDegrees(v.λ2);

            return(new GeographicCoordinate(latitude, longitude));
        }
Exemplo n.º 5
0
        private static VincentyFormulaVariables PrepareλConvergenceLoop(IGeographicCoordinate pointA, IGeographicCoordinate pointB)
        {
            var v = new VincentyFormulaVariables
            {
                U1 = Math.Atan((1.0 - f) * Math.Tan(pointA.Latitude.Angle.ToRadians())),
                U2 = Math.Atan((1.0 - f) * Math.Tan(pointB.Latitude.Angle.ToRadians())),

                L = Angle.ToRadians(pointB.Longitude.Angle.ToDegrees() - pointA.Longitude.Angle.ToDegrees())
            };

            v.λ = v.L;

            v.SinU1 = Math.Sin(v.U1);
            v.CosU1 = Math.Cos(v.U1);
            v.SinU2 = Math.Sin(v.U2);
            v.CosU2 = Math.Cos(v.U2);

            return(v);
        }
Exemplo n.º 6
0
        private static IBearingDistance VincentysInverseFormula(IGeographicCoordinate pointA, IGeographicCoordinate pointB, int maxInterations = 200, double tolerance = 1.0E-12)
        {
            // Source: https://nathanrooy.github.io/posts/2016-12-18/vincenty-formula-with-python/

            VincentyFormulaVariables v = PrepareλConvergenceLoop(pointA, pointB);

            v = RecalculateλUntilConvergence(v, maxInterations, tolerance);

            v = CalculateGeodesicDistanceAzimuth(v);

            IBearingDistance bearingDistance = new BearingDistance()
            {
                Distance       = new Distance(v.GeodesicLength, DistanceMeasurement.Meters),
                InitialBearing = new Angle(v.ForwardAzimuth, AngleMeasurement.Radians),
                FinalBearing   = new Angle(v.BackwardAzimuth, AngleMeasurement.Radians)
            };

            return(bearingDistance);
        }
Exemplo n.º 7
0
        private static VincentyFormulaVariables PrepareσConvergenceLoop(IGeographicCoordinate pointA, IAngle initialBearing, IDistance distance)
        {
            VincentyFormulaVariables v = new VincentyFormulaVariables();

            v.Sinα1 = Math.Sin(initialBearing.ToRadians());
            v.Cosα1 = Math.Cos(initialBearing.ToRadians());

            v.TanU1 = (1.0 - f) * Math.Tan(pointA.Latitude.Angle.ToRadians());
            v.CosU1 = 1.0 / Math.Sqrt((1 + Math.Pow(v.TanU1, 2.0)));
            v.SinU1 = v.TanU1 * v.CosU1;

            v.σ1       = Math.Atan2(v.TanU1, v.Cosα1);
            v.sinα     = v.CosU1 * v.Sinα1;
            v.CosSqα   = 1.0 - Math.Pow(v.sinα, 2.0);
            v.USquared = v.CosSqα * (Math.Pow(a, 2.0) - Math.Pow(b, 2.0)) / Math.Pow(b, 2.0);
            v.A        = 1 + v.USquared / 16384.0 * (4096.0 + v.USquared * (-768.0 + v.USquared * (320.0 - 175.0 * v.USquared)));
            v.B        = v.USquared / 1024.0 * (256.0 + v.USquared * (-128.0 + v.USquared * (74.0 - 47.0 * v.USquared)));

            v.σ = distance.ToMeters() / (b * v.A);

            return(v);
        }
Exemplo n.º 8
0
 public static IAngle BearingFrom(this IGeographicCoordinate pointA, IGeographicCoordinate pointB, int maxInterations = 200, double tolerance = 1.0E-12)
 {
     return(VincentysInverseFormula(pointA, pointB, maxInterations, tolerance).FinalBearing);
 }
Exemplo n.º 9
0
        public static IAngle BearingFrom(this IGeographicCoordinate pointA, IAngle initialBearing, IDistance distance, int maxInterations = 200, double tolerance = 1.0E-12)
        {
            var backwardAzimuth = VincentysDirectFormula(pointA, initialBearing, distance, maxInterations, tolerance).BackwardAzimuth;

            return(new Angle(backwardAzimuth, AngleMeasurement.Radians));
        }
Exemplo n.º 10
0
        public static IAngle FinalBearing(this IGeographicCoordinate pointA, IAngle initialBearing, IDistance distance, int maxInterations = 200, double tolerance = 1.0E-12)
        {
            var finalBearing = VincentysDirectFormula(pointA, initialBearing, distance, maxInterations, tolerance).FinalBearing;

            return(new Angle(finalBearing, AngleMeasurement.Radians));
        }
Exemplo n.º 11
0
 public static IGeographicCoordinate DestinationCoordinates(this IGeographicCoordinate pointA, IAngle initialBearing, IDistance distance,
                                                            int maxInterations = 200, double tolerance = 1.0E-12)
 {
     return(VincentysDirectFormula(pointA, initialBearing, distance, maxInterations, tolerance).DestinationCoordinates);
 }
Exemplo n.º 12
0
 public static IDistance GreatCircleDistanceTo(this IGeographicCoordinate pointA, IGeographicCoordinate pointB, int maxInterations = 200, double tolerance = 1.0E-12)
 {
     return(VincentysInverseFormula(pointA, pointB, maxInterations, tolerance).Distance);
 }
Exemplo n.º 13
0
        public void GeographicCoordinate_CannotUpdateInvalidLatitude(double angle)
        {
            IGeographicCoordinate sut = InstantiateNewGeographicCoordinate();

            Assert.Throws <ArgumentOutOfRangeException>(() => sut.Latitude = new Latitude(angle));
        }
Exemplo n.º 14
0
        public void GeographicCoordinate_CanInstantiate()
        {
            IGeographicCoordinate result = InstantiateNewGeographicCoordinate();

            Assert.NotNull(result);
        }