using System;
using System.Collections.Generic;
using System.Text;
namespace TelpoPush.Fence.Worker.Models.Fence
{
public class Bounds
{
public GpsPoint SW { get; set; }
public GpsPoint NE { get; set; }
public Bounds(GpsPoint sw, GpsPoint ne)
{
SW = sw;
NE = ne;
}
public GpsPoint GetCenter()
{
return new GpsPoint((SW.Lng + NE.Lng) / 2, (SW.Lat + NE.Lat) / 2);
}
}
public class GeoUtils
{
private const decimal A = 6370996.81m;
private const double EARTH_RADIUS = 6378137;//赤道半径(单位m)
///
/// 点是否在矩形区域中
///
///
///
///
public static bool IsPointInRect(GpsPoint 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(GpsPoint pt, Circle circle)
{
var i = circle.Center;
var g = circle.Radius;
var f = GetDistance(pt, i);
return f <= g;
}
///
/// 圆和圆是否有交点
///
///
///
///
public static bool IsCircle2Circle(Circle _circle, Circle circle)
{
var _r = _circle.Radius;
var r = circle.Radius;
var f = GetDistance(_circle.Center, circle.Center);
//判断两圆是否相交
if (f > _r + r)
{
return false;
}
return true;
}
///
/// 获取形状的矩形范围
///
///
///
public static Bounds GetBound(IList pts)
{
if (pts.Count == 0)
return new Bounds(new GpsPoint(0, 0), new GpsPoint(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 GpsPoint(minLng, minLat), new GpsPoint(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(GpsPoint j, GpsPoint 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;
}
}
}