| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 | using System;using System.Collections.Generic;namespace InABox.Core{    public class GeoPoint    {        public GeoPoint(double latitude = 0.0, double longitude = 0.0)        {            Latitude = latitude;            Longitude = longitude;        }        public double Longitude { get; set; }        public double Latitude { get; set; }        public GeoPoint Copy() => new GeoPoint(Latitude, Longitude);        public static double DistanceBetween(GeoPoint from, GeoPoint to, UnitOfLength? unitOfLength = null)        {            var baseRad = Math.PI * from.Latitude / 180;            var targetRad = Math.PI * to.Latitude / 180;            var theta = from.Longitude - to.Longitude;            var thetaRad = Math.PI * theta / 180;            var dist =                Math.Sin(baseRad) * Math.Sin(targetRad) + Math.Cos(baseRad) *                Math.Cos(targetRad) * Math.Cos(thetaRad);            dist = Math.Acos(dist);            dist = dist * 180 / Math.PI;            dist = dist * 60 * 1.1515;            var unit = unitOfLength ?? UnitOfLength.Kilometers;            return unit.ConvertFromMiles(dist);        }                public double DistanceTo(GeoPoint to, UnitOfLength? unitOfLength = null)             => DistanceBetween(this, to, unitOfLength);                private static double WGS84_RADIUS = 6370997.0;        private static double EarthCircumFence = 2* WGS84_RADIUS * Math.PI;        public GeoPoint Move(double mEastWest, double mNorthSouth){            double degreesPerMeterForLat = EarthCircumFence/360.0;            double shrinkFactor = Math.Cos((Latitude*Math.PI/180.0));            double degreesPerMeterForLon = degreesPerMeterForLat * shrinkFactor;            double newLat = Latitude + mNorthSouth * (1.0/degreesPerMeterForLat);            double newLng = Longitude + mEastWest * (1.0/degreesPerMeterForLon);            return new GeoPoint(newLat, newLng);        }            }        public class GeoFenceDefinition    {                public List<GeoPoint> Coordinates { get;} = new List<GeoPoint>();                public bool Contains(GeoPoint p)        {            if (Coordinates.Count < 2)                return false;                        double minX = Coordinates[0].Longitude;              double maxX = Coordinates[0].Longitude;              double minY = Coordinates[0].Latitude;              double maxY = Coordinates[0].Latitude;              for (int i = 1; i < Coordinates.Count; i++)              {                  GeoPoint q = Coordinates[i];                  minX = Math.Min(q.Longitude, minX);                  maxX = Math.Max(q.Longitude, maxX);                  minY = Math.Min(q.Latitude, minY);                  maxY = Math.Max(q.Latitude, maxY);              }                   if (p.Longitude < minX || p.Longitude > maxX || p.Latitude < minY || p.Latitude > maxY)              {                  return false;              }              bool inside = false;              for (int i = 0, j = Coordinates.Count - 1; i < Coordinates.Count; j = i++)              {                  if ((Coordinates[i].Latitude > p.Latitude) != (Coordinates[j].Latitude > p.Latitude) &&                      p.Longitude < (Coordinates[j].Longitude - Coordinates[i].Longitude) * (p.Latitude - Coordinates[i].Latitude) / (Coordinates[j].Latitude - Coordinates[i].Latitude) + Coordinates[i].Longitude)                  {                      inside = !inside;                  }              }              return inside;          }    }}
 |