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;
- }
- }
- }
|