コード例 #1
0
        /// <summary>
        /// Calculates distance between two geographic locations on equirectangular map projection
        /// <para>Using Pythagoras’ theorem </para>
        /// </summary>
        public static GeoDistance GetDistanceAppx(IGeoLocatable origin, IGeoLocatable destination, double radius = GeoGlobal.Earths.Radius)
        {
            origin      = origin.ToRadians();
            destination = destination.ToRadians();
            var dLat = (destination.Latitude - origin.Latitude);
            var dLon = (destination.Longitude - origin.Longitude);

            var x        = (dLon) * Math.Cos((origin.Latitude + destination.Latitude) / 2);
            var y        = (dLat);
            var distance = Math.Sqrt(x * x + y * y) * radius;

            return(new GeoDistance {
                Kilometers = distance
            });
            //return distance;

            //var yMin = Math.Min(origin.Latitude, destination.Latitude);
            //var yMax = Math.Max(origin.Latitude, destination.Latitude);
            //var xMin = Math.Min(origin.Longitude, destination.Longitude);
            //var xMax = Math.Max(origin.Longitude, destination.Longitude);
            //var yDelta = (yMax - yMin) * (yMax - yMin);
            //var xDelta = (xMax - xMin) * (xMax - xMin);

            //var distance = Math.Sqrt(xDelta + yDelta);
            //return new GeoDistance { Degrees = distance };
        }
コード例 #2
0
        /// <summary>
        /// Calculates the final bearing at destination location from origin geographic, in degrees from true North
        /// <para> North = 0, East = 90, South = 180, West = 270 </para>
        /// </summary>
        /// <param name="origin">origin location in geographic degrees</param>
        /// <param name="destination">destination location in geographic degrees</param>
        public static double GetBearingFinal(IGeoLocatable origin, IGeoLocatable destination)
        {
            var angleInital = GetBearing(destination, origin); // reversed intentionally
            var angleFinal  = angleInital.ToDegreesReversed();

            return(angleFinal);
        }
コード例 #3
0
        /// <summary>
        /// Calculates the final bearing at destination location from origin geographic, in degrees from true North
        /// <para> North = 0, East = 90, South = 180, West = 270 </para>
        /// </summary>
        /// <param name="origin">location in geographic degrees </param>
        /// <param name="bearing">bearing in geographic degrees from origin</param>
        /// <param name="distance">distance in km from origin</param>
        /// <param name="radius">radius in km</param>
        /// <remarks>radius defaults to Earth's mean radius</remarks>
        public static double GetBearingFinal(IGeoLocatable origin, double bearing, double distance, double radius = GeoGlobal.Earths.Radius)
        {
            var destination = GetDestination(origin, bearing, distance, radius);
            var angleFinal  = GetBearingFinal(origin, destination);

            return(angleFinal);
        }
コード例 #4
0
        //public static double GetRadius(double latitude, double radius = GeoGlobal.Earths.RadiusEquatorial)
        //{
        //    latitude = latitude.ToRadians();
        //    var a = GeoGlobal.Earths.RadiusEquatorial;
        //    var b = GeoGlobal.Earths.RadiusPolar;
        //    var e = Math.Pow(b*b/a*a, 1/2);
        //    return a * (1.0 - e * e) / (1.0 - e * 2 * Math.Sin ^ 2(latitude)) ^ (3 / 2);
        //}
        #endregion
        #region Geographic Path

        /// <summary>
        /// Calculates geographic path between two geographic locations on the Great Circle
        /// <para>Using the Spherical law of cosines </para>
        /// </summary>
        /// <param name="origin">origin location in geographic degrees</param>
        /// <param name="destination">destination location in geographic degrees</param>
        /// <param name="interval">interval between consecutive points of the geographic path, in kilometers</param>
        /// <param name="radius">radius of a geographic sphere, in kilometers</param>
        public static GeoPointList GetPathPoints(IGeoLocatable origin, IGeoLocatable destination, double interval = GeoGlobal.Earths.CircumferenceOneDegree, double radius = GeoGlobal.Earths.Radius)
        {
            var path     = new GeoPointList();
            var distance = GeoCalculator.GetDistance(origin, destination);

            if (double.IsNaN(distance.Kilometers))
            {
                return(path);
            }

            if (distance.Kilometers <= interval)
            {
                path.Add(origin.ToGeoPoint());
                path.Add(destination.ToGeoPoint());
            }
            else
            {
                var currentPoint = origin.ToGeoPoint();
                for (double dist = interval; dist <= distance.Kilometers; dist += interval)
                {
                    path.Add(currentPoint);
                    var bearing = GeoCalculator.GetBearing(currentPoint, destination);
                    currentPoint = GeoCalculator.GetDestination(currentPoint, bearing, interval);
                }
                path.Add(destination.ToGeoPoint());
            }
            return(path);
        }
コード例 #5
0
        /// <summary>
        /// Calculates the maximum latitude of a great circle path from origin location in direction of bearing angle
        /// <para>using Clairaut’s formula</para>
        /// </summary>
        /// <param name="origin">origin location in geographic degrees</param>
        /// <param name="bearing">bearing from origin in geographic degrees</param>
        public static double GetLatitudeMax(IGeoLocatable origin, double bearing)
        {
            origin  = origin.ToRadians();
            bearing = bearing.ToRadians();
            var latMax = Math.Acos(Math.Abs(Math.Sin(bearing) * Math.Cos(origin.Latitude)));

            return(latMax);
        }
コード例 #6
0
ファイル: GeoPath.cs プロジェクト: ashx2611/wpf-samples
        public GeoPath(IGeoLocatable origin, IGeoLocatable destination, double resolution = 2.0)
        {
            Resolution   = resolution;
            _origin      = origin.ToGeoPoint();
            _destination = destination.ToGeoPoint();

            this.ComputePath();
        }
コード例 #7
0
        /// <summary>
        /// Calculates angle bearing from origin location towards destination location, in degrees
        /// <para> North = 0, East = 90, South = 180, West = 270 </para>
        /// </summary>
        /// <param name="origin">origin location in geographic degrees</param>
        /// <param name="destination">destination location in geographic degrees</param>
        public static double GetBearingAppx(IGeoLocatable origin, IGeoLocatable destination)
        {
            // from flight watcher app (not accurate)
            var dLat = destination.Latitude - origin.Latitude;
            var dLon = destination.Longitude - origin.Longitude;

            var angle = Math.Atan2((dLat), (dLon)) * 180.0 / Math.PI;

            return(-1 * angle);
            //return angle;
        }
コード例 #8
0
        public static GeoPoint GetPathDestination(IGeoLocatable origin, double bearing, double distance, double interval = GeoGlobal.Earths.CircumferenceOneDegree, double radius = GeoGlobal.Earths.Radius)
        {
            var currentPoint = origin.ToGeoPoint();

            //var previousPoint = origin.ToGeoPoint();
            for (double dist = 0; dist <= distance; dist += interval)
            {
                var previousPoint = currentPoint;
                currentPoint = GeoCalculator.GetDestination(currentPoint, bearing, interval);
                bearing      = GeoCalculator.GetBearingFinal(previousPoint, currentPoint);
            }
            return(currentPoint);
        }
コード例 #9
0
        /// <summary>
        /// Calculates the initial bearing from origin location in direction of destination location, in degrees from true North
        /// <para> North = 0, East = 90, South = 180, West = 270 </para>
        /// </summary>
        /// <param name="origin">origin location in geographic degrees</param>
        /// <param name="destination">destination location in geographic degrees</param>
        public static double GetBearing(IGeoLocatable origin, IGeoLocatable destination)
        {
            origin      = origin.ToRadians();
            destination = destination.ToRadians();

            var dLat = (destination.Latitude - origin.Latitude);
            var dLon = (destination.Longitude - origin.Longitude);
            var y    = Math.Sin(dLon) * Math.Cos(destination.Latitude);
            var x    = Math.Cos(origin.Latitude) * Math.Sin(destination.Latitude) -
                       Math.Sin(origin.Latitude) * Math.Cos(destination.Latitude) * Math.Cos(dLon);
            var angle = Math.Atan2(y, x);

            return(angle.ToDegreesNormalized());
        }
コード例 #10
0
        /// <summary>
        /// Calculates distance between two geographic locations on the Great Circle
        /// <para>Using the Spherical law of cosines </para>
        /// </summary>
        /// <param name="origin">origin location in geographic degrees</param>
        /// <param name="destination">destination location in geographic degrees</param>
        /// <param name="radius">radius of a geographic sphere, in kilometers</param>
        /// <remarks>radius defaults to Earth's mean radius</remarks>
        public static GeoDistance GetDistance(IGeoLocatable origin, IGeoLocatable destination, double radius = GeoGlobal.Earths.Radius)
        {
            origin      = origin.ToRadians();
            destination = destination.ToRadians();
            var sinProd = Math.Sin(origin.Latitude) * Math.Sin(destination.Latitude);
            var cosProd = Math.Cos(origin.Latitude) * Math.Cos(destination.Latitude);
            var dLon    = (destination.Longitude - origin.Longitude);

            var angle    = Math.Acos(sinProd + cosProd * Math.Cos(dLon));
            var distance = angle * radius;

            return(new GeoDistance {
                Kilometers = distance
            });
        }
コード例 #11
0
        /// <summary>
        /// Calculates mid point between two geographic locations on the Great Circle
        /// <para>Using the Spherical law of cosines </para>
        /// </summary>
        /// <param name="origin">origin location in geographic degrees</param>
        /// <param name="destination">destination location in geographic degrees</param>
        public static GeoPoint GetMidpoint(IGeoLocatable origin, IGeoLocatable destination)
        {
            origin      = origin.ToRadians();
            destination = destination.ToRadians();
            var dLat = (destination.Latitude - origin.Latitude);
            var dLon = (destination.Longitude - origin.Longitude);

            var bx  = Math.Cos(destination.Latitude) * Math.Cos(dLon);
            var by  = Math.Cos(destination.Latitude) * Math.Sin(dLon);
            var lat = Math.Atan2(Math.Sin(origin.Latitude) + Math.Sin(destination.Latitude),
                                 Math.Sqrt((Math.Cos(origin.Latitude) + bx) * (Math.Cos(origin.Latitude) + bx) + by * by));
            var lon = origin.Longitude + Math.Atan2(by, Math.Cos(origin.Latitude) + bx);

            lon = (lon + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // normalize to -180..+180º

            return(new GeoPoint(lon.ToDegrees(), lat.ToDegrees()));
        }
コード例 #12
0
        /// <summary>
        /// Calculates the destination location at distance and in direction of bearing from origin location
        /// <para>Using the Spherical law of cosines </para>
        /// </summary>
        /// <param name="origin">location in geographic degrees </param>
        /// <param name="bearing">bearing in geographic degrees from origin</param>
        /// <param name="distance">distance in km</param>
        /// <param name="radius">radius in km</param>
        /// <remarks>radius defaults to Earth's mean radius</remarks>
        public static GeoPoint GetDestination(IGeoLocatable origin, double bearing, double distance, double radius = GeoGlobal.Earths.Radius)
        {
            origin   = origin.ToRadians();
            bearing  = bearing.ToRadians();
            distance = distance / radius; // angular distance in radians

            var latitude = Math.Asin(Math.Sin(origin.Latitude) * Math.Cos(distance) +
                                     Math.Cos(origin.Latitude) * Math.Sin(distance) * Math.Cos(bearing));
            var x         = Math.Sin(bearing) * Math.Sin(distance) * Math.Cos(origin.Latitude);
            var y         = Math.Cos(distance) - Math.Sin(origin.Latitude) * Math.Sin(origin.Latitude);
            var longitude = origin.Longitude + Math.Atan2(x, y);

            longitude = (longitude + 3 * Math.PI) % (2 * Math.PI) - Math.PI;  // normalize to -180..+180º

            var destination = new GeoPoint(longitude.ToDegrees(), latitude.ToDegrees());

            return(destination);
        }
コード例 #13
0
        /// <summary>
        /// Calculates distance between two geographic locations on the Great Circle
        /// <para>Using the Haversine formula</para>
        /// <remarks>"Virtues of the Haversine" by R. W. Sinnott, Sky and Telescope, vol 68, no 2, 1984</remarks>
        /// </summary>
        /// <param name="origin">origin location in geographic degrees</param>
        /// <param name="destination">destination location in geographic degrees</param>
        /// <param name="radius">radius of a geographic sphere, in kilometers</param>
        /// <remarks>radius defaults to Earth's mean radius</remarks>
        public static GeoDistance GetDistanceH(IGeoLocatable origin, IGeoLocatable destination, double radius = GeoGlobal.Earths.Radius)
        {
            origin      = origin.ToRadians();
            destination = destination.ToRadians();

            var dLat = (destination.Latitude - origin.Latitude);
            var dLon = (destination.Longitude - origin.Longitude);

            var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
                    Math.Sin(dLon / 2) * Math.Sin(dLon / 2) *
                    Math.Cos(origin.Latitude) * Math.Cos(destination.Latitude);
            var c        = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
            var distance = radius * c;

            return(new GeoDistance {
                Kilometers = distance
            });
        }
コード例 #14
0
        /// <summary>
        /// Projects a Cartesian point to geodetic point
        /// </summary>
        public static GeoPoint ProjectToGeographic(IGeoLocatable geodetic, GeoProjectionType projectionType = GeoProjectionType.SphericalMercator)
        {
            var point = ProjectToGeographic(geodetic.ToPoint(), projectionType);

            return(new GeoPoint(point));
        }
コード例 #15
0
 public GeoDistance(IGeoLocatable origin, IGeoLocatable destination)
 {
     this.Kilometers = GeoCalculator.GetDistance(origin, destination).Kilometers;
 }
コード例 #16
0
        public double ComputeProgress(IGeoLocatable currentLocation)
        {
            var distanceTraveled = GeoCalculator.GetDistance(this.Origin, currentLocation);

            return(ComputeProgress(distanceTraveled.Kilometers));
        }
コード例 #17
0
        /// <summary>
        /// Calculates intersection point of paths from two geographic locations
        /// </summary>
        /// <param name="origin1">origin of first location in geographic degrees</param>
        /// <param name="origin2">origin of second location in geographic degrees</param>
        /// <param name="bearing1">bearing from first location in geographic degrees</param>
        /// <param name="bearing2">bearing from second location in geographic degrees</param>
        /// <param name="radius">radius of a geographic sphere, in kilometers</param>
        /// <remarks>radius defaults to Earth's mean radius</remarks>
        public static GeoPoint GetIntersection(
            IGeoLocatable origin1, double bearing1,
            IGeoLocatable origin2, double bearing2, double radius = GeoGlobal.Earths.Radius)
        {
            origin1 = origin1.ToRadians();
            origin2 = origin2.ToRadians();
            var brng13 = bearing1.ToRadians();
            var brng23 = bearing2.ToRadians();
            var dLat   = (origin2.Latitude - origin1.Latitude);
            var dLon   = (origin2.Longitude - origin1.Longitude);

            var dist12 = 2 * Math.Asin(Math.Sqrt(Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
                                                 Math.Cos(origin1.Latitude) * Math.Cos(origin2.Latitude) *
                                                 Math.Sin(dLon / 2) * Math.Sin(dLon / 2)));

            if (dist12 == 0)
            {
                return(GeoPoint.Invalid);
            }

            // initial/final bearings between points
            var brngA = Math.Acos((Math.Sin(origin2.Latitude) - Math.Sin(origin1.Latitude) * Math.Cos(dist12)) /
                                  (Math.Sin(dist12) * Math.Cos(origin1.Latitude)));

            if (double.IsNaN(brngA))
            {
                brngA = 0;                       // protect against rounding
            }
            var brngB = Math.Acos((Math.Sin(origin1.Latitude) - Math.Sin(origin2.Latitude) * Math.Cos(dist12)) /
                                  (Math.Sin(dist12) * Math.Cos(origin2.Latitude)));

            double brng12, brng21;

            if (Math.Sin(dLon) > 0)
            {
                brng12 = brngA;
                brng21 = 2 * Math.PI - brngB;
            }
            else
            {
                brng12 = 2 * Math.PI - brngA;
                brng21 = brngB;
            }
            var alpha1 = (brng13 - brng12 + Math.PI) % (2 * Math.PI) - Math.PI;  // angle 2-1-3
            var alpha2 = (brng21 - brng23 + Math.PI) % (2 * Math.PI) - Math.PI;  // angle 1-2-3

            if (Math.Sin(alpha1) == 0 && Math.Sin(alpha2) == 0)
            {
                return(GeoPoint.Invalid);                                                 // infinite intersections
            }
            if (Math.Sin(alpha1) * Math.Sin(alpha2) < 0)
            {
                return(GeoPoint.Invalid);                                                 // ambiguous intersection
            }
            var alpha3 = Math.Acos(-Math.Cos(alpha1) * Math.Cos(alpha2) +
                                   Math.Sin(alpha1) * Math.Sin(alpha2) * Math.Cos(dist12));
            var dist13 = Math.Atan2(Math.Sin(dist12) * Math.Sin(alpha1) * Math.Sin(alpha2),
                                    Math.Cos(alpha2) + Math.Cos(alpha1) * Math.Cos(alpha3));
            var lat3 = Math.Asin(Math.Sin(origin1.Latitude) * Math.Cos(dist13) +
                                 Math.Cos(origin1.Latitude) * Math.Sin(dist13) * Math.Cos(brng13));
            var dLon13 = Math.Atan2(Math.Sin(brng13) * Math.Sin(dist13) * Math.Cos(origin1.Latitude),
                                    Math.Cos(dist13) - Math.Sin(origin1.Latitude) * Math.Sin(lat3));

            var lon3 = origin1.Longitude + dLon13;

            lon3 = (lon3 + 3 * Math.PI) % (2 * Math.PI) - Math.PI;  // normalize to -180..+180º

            return(new GeoPoint(lat3.ToDegrees(), lon3.ToDegrees()));
        }
コード例 #18
0
 public static GeoPoint ToGeoPoint(this IGeoLocatable geoLocation)
 {
     return(new GeoPoint(geoLocation.ToPoint()));
 }
コード例 #19
0
 //public static GeoPoint ToRadians(this GeoPoint geoPoint)
 //{
 //    return new GeoPoint(geoPoint.Longitude.ToRadians(), geoPoint.Latitude.ToRadians());
 //}
 public static GeoPoint ToRadians(this IGeoLocatable geoLocation)
 {
     return(new GeoPoint(geoLocation.Longitude.ToRadians(), geoLocation.Latitude.ToRadians()));
 }
コード例 #20
0
 public static Point GetWindowCoordinate(IGeoLocatable location)
 {
     return(GetWindowCoordinate(location.Longitude, location.Latitude));
 }