using GpsCardGatewayPosition.Model.GatewayEntity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GpsCardGatewayPosition.Common
{
public class GeoUtils
{
private const decimal A = 6370996.81m;
private const double EARTH_RADIUS = 6378137;//赤道半径(单位m)
///
/// 点是否在矩形区域中
///
///
///
///
public static bool IsPointInRect(Point pt, Bounds rect)
{
var e = rect.SW;
var h = rect.NE;
return (pt.Lng >= e.Lng && pt.Lng <= h.Lng && pt.Lat >= e.Lat && pt.Lat <= h.Lat);
}
///
/// 点是否在圆形区域中
///
///
///
///
public static bool IsPointInCircle(Point pt, Circle circle)
{
var i = circle.Center;
var g = circle.Radius;
var f = GetDistance(pt, i);
return f <= g;
}
///
/// 获取形状的矩形范围
///
///
///
public static Bounds GetBound(IList pts)
{
if (pts.Count == 0)
return new Bounds(new Point(0, 0), new Point(0, 0)); ;
decimal minLat = pts[0].Lat, minLng = pts[0].Lng, maxLat = pts[0].Lat, maxLng = pts[0].Lng;
foreach (var pt in pts)
{
minLat = Math.Min(minLat, pt.Lat);
minLng = Math.Min(minLng, pt.Lng);
maxLat = Math.Max(maxLat, pt.Lat);
maxLng = Math.Max(maxLng, pt.Lng);
}
return new Bounds(new Point(minLng, minLat), new Point(maxLng, maxLat));
}
///
/// 经纬度测距算法
///
///
///
///
///
/// 单位 米
public static double GetDistance2(double lon1, double lat1, double lon2, double lat2)
{
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
double a = radLat1 - radLat2;
double b = rad(lon1) - rad(lon2);
double s = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2)));
s = s * EARTH_RADIUS;
return s;
}
///
/// 转化为弧度(rad)
///
/// 经度或纬度
/// 弧度
private static double rad(double d)
{
return d * Math.PI / 180.0;
}
///
/// 计算两点的距离 单位:米
///
///
///
///
public static decimal GetDistance(Point j, Point h)
{
j.Lng = ValidLng(j.Lng, -180, 180);
j.Lat = ValidLat(j.Lat, -74, 74);
h.Lng = ValidLng(h.Lng, -180, 180);
h.Lat = ValidLat(h.Lat, -74, 74);
decimal f, e, i, g;
f = DegreeToRad(j.Lng);
i = DegreeToRad(j.Lat);
e = DegreeToRad(h.Lng);
g = DegreeToRad(h.Lat);
return Convert.ToDecimal((double)A * Math.Acos((Math.Sin((double)i) * Math.Sin((double)g) + Math.Cos((double)i) * Math.Cos((double)g) * Math.Cos((double)e - (double)f))));
}
private static decimal DegreeToRad(decimal d)
{
return Convert.ToDecimal(Math.PI * (double)d / 180);
}
private static decimal RadToDegree(decimal d)
{
return Convert.ToDecimal((180 * (double)d) / Math.PI);
}
private static decimal ValidLng(decimal lng, decimal min, decimal max)
{
while (lng > max)
{
lng -= max - min;
}
while (lng < min)
{
lng += max - min;
}
return lng;
}
private static decimal ValidLat(decimal lat, decimal min, decimal max)
{
lat = Math.Max(lat, min);
lat = Math.Min(lat, max);
return lat;
}
}
}