231 lines
8.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
/// <summary>
///
/// </summary>
/// <param name="points">坐标(lat,lon)</param>
public TurfHelper(IEnumerable<double[]> 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);
}
/// <summary>
///
/// </summary>
/// <param name="distance">km</param>
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);
}
/// <summary>
/// 获取两个点的距离m
/// </summary>
/// <param name="from"></param>
/// <param name="to"></param>
/// <returns></returns>
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);
}
/// <summary>
///
/// https://gist.github.com/neilkennedy/9227665
/// </summary>
/// <param name="neLng"></param>
/// <param name="neLat"></param>
/// <param name="swLng"></param>
/// <param name="swLat">SouthWest</param>
/// <param name="point">lon,lat</param>
/// <returns></returns>
public static bool Inside(double neLng, double neLat, double swLng, double swLat, double[] point)
{
var poly = Turf.BboxPolygon(new List<double>() { neLng, neLat, swLng, swLat });
var ptIn = Turf.Point(point);
return Turf.Inside(ptIn, poly);
}
///// <summary>
/////
///// </summary>
///// <param name="bottomLeft">lng, lat</param>
///// <param name="bottomRight"></param>
///// <param name="topRight"></param>
///// <param name="topLeft"></param>
///// <param name="point"></param>
///// <returns></returns>
//public static bool Inside(List<double[]> 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;
}
/// <summary>
/// 坐标点是否在多边形内判断
/// https://www.cnblogs.com/yushuo/p/9304471.html
/// </summary>
/// <param name="point"></param>
/// <param name="pts"></param>
/// <returns></returns>
public static bool isPointInPolygon(location point, List<location> 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;
}
}
}
}