using GeoJSON.Net.Geometry;
using System;
using System.Collections.Generic;
using System.Linq;
using TurfCS;
namespace Assets.Scenes.Ride.Scripts
{
public class TurfHelper
{
//static TurfHelper()
//{
// string name = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".Resources.turf.min.js";
// System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
//}
private LineString _line;
///
///
///
/// 坐标(lat,lon)
public TurfHelper(IEnumerable points)
{
//var list = new GeoJSON.Net.Geometry.GeographicPosition();
var list = points.Select(p => new GeoJSON.Net.Geometry.GeographicPosition(p[0], p[1]));
_line = new LineString(list);
}
///
///
///
/// km
public GeographicPosition Along(double distance)
{
var pt1 = Turf.Along(_line, distance);
return ((GeographicPosition)((GeoJSON.Net.Geometry.Point)pt1.Geometry).Coordinates);
}
public double Bearing(double[] p1, double[] p2)
{
var pt1 = Turf.Point(p1);
var pt2 = Turf.Point(p2);
return Turf.Bearing(pt1, pt2);
}
///
/// 获取两个点的距离m
///
///
///
///
public static double GetDistances(double[] from, double[] to)
{
var pt1 = Turf.Point(from);
var pt2 = Turf.Point(to);
var value = Turf.Distance(pt1, pt2, "kilometers") * 1000;
return Math.Round(value, 2);
}
///
///
/// https://gist.github.com/neilkennedy/9227665
///
///
///
///
/// SouthWest
/// lon,lat
///
public static bool Inside(double neLng, double neLat, double swLng, double swLat, double[] point)
{
var poly = Turf.BboxPolygon(new List() { neLng, neLat, swLng, swLat });
var ptIn = Turf.Point(point);
return Turf.Inside(ptIn, poly);
}
/////
/////
/////
///// lng, lat
/////
/////
/////
/////
/////
//public static bool Inside(List points, double[] point)
//{
// var script = new StringBuilder("var points = [];");
// foreach (var item in points)
// {
// script.AppendLine($"points.push([{ string.Join(",", item) }]);");
// }
// script.AppendLine($"points.push([{ string.Join(",", points.First()) }]);");
// script.AppendLine("var poly = turf.polygon([points]);");
// script.AppendLine($"turf.booleanPointInPolygon([{ string.Join(",", point) }], poly);");
// var result = (bool)engine.Evaluate(script.ToString());
// return result;
//}
public class location
{
public double lat;
public double lng;
}
///
/// 坐标点是否在多边形内判断
/// https://www.cnblogs.com/yushuo/p/9304471.html
///
///
///
///
public static bool isPointInPolygon(location point, List pts)
{
//检查类型
if (point == null || pts == null)
return false;
var N = pts.Count;
var boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
var intersectCount = 0; //cross points count of x
var precision = 2e-10; //浮点类型计算时候与0比较时候的容差
location p1, p2; //neighbour bound vertices
var p = point; //测试点
p1 = pts[0]; //left vertex
for (var i = 1; i <= N; ++i)
{
//check all rays
if (p.lat.Equals(p1.lat) && p.lng.Equals(p1.lng))
{
return boundOrVertex; //p is an vertex
}
p2 = pts[i % N]; //right vertex
if (p.lat < Math.Min(p1.lat, p2.lat) || p.lat > Math.Max(p1.lat, p2.lat))
{
//ray is outside of our interests
p1 = p2;
continue; //next ray left point
}
if (p.lat > Math.Min(p1.lat, p2.lat) && p.lat < Math.Max(p1.lat, p2.lat))
{
//ray is crossing over by the algorithm (common part of)
if (p.lng <= Math.Max(p1.lng, p2.lng))
{
//x is before of ray
if (p1.lat == p2.lat && p.lng >= Math.Min(p1.lng, p2.lng))
{
//overlies on a horizontal ray
return boundOrVertex;
}
if (p1.lng == p2.lng)
{
//ray is vertical
if (p1.lng == p.lng)
{
//overlies on a vertical ray
return boundOrVertex;
}
else
{
//before ray
++intersectCount;
}
}
else
{
//cross point on the left side
var xinters =
(p.lat - p1.lat) * (p2.lng - p1.lng) / (p2.lat - p1.lat) +
p1.lng; //cross point of lng
if (Math.Abs(p.lng - xinters) < precision)
{
//overlies on a ray
return boundOrVertex;
}
if (p.lng < xinters)
{
//before ray
++intersectCount;
}
}
}
}
else
{
//special case when ray is crossing through the vertex
if (p.lat == p2.lat && p.lng <= p2.lng)
{
//p crossing over p2
var p3 = pts[(i + 1) % N]; //next vertex
if (p.lat >= Math.Min(p1.lat, p3.lat) && p.lat <= Math.Max(p1.lat, p3.lat))
{
//p.lat lies between p1.lat & p3.lat
++intersectCount;
}
else
{
intersectCount += 2;
}
}
}
p1 = p2; //next ray left point
}
if (intersectCount % 2 == 0)
{
//偶数在多边形外
return false;
}
else
{
//奇数在多边形内
return true;
}
}
}
}