计算坐标点是否在多边形、圆内

方法类:
public class Polygon
{
public Polygon(){}
private readonly PointF[] _vertices;
/// <summary>
/// Creates a new instance of the <see cref="Polygon"/> class with the specified vertices.
/// </summary>
/// <param name="vertices">
/// An array of <see cref="PointF"/> structures representing the points between the sides of the polygon.
/// </param>
public Polygon(PointF[] vertices)
{
_vertices = vertices;
}
/// <summary>
/// Determines if the specified <see cref="PointF"/> if within this polygon.
/// </summary>
/// <remarks>
/// This algorithm is extremely fast, which makes it appropriate for use in brute force algorithms.
/// </remarks>
/// <param name="point">
/// The point containing the x,y coordinates to check.
/// </param>
/// <returns>
/// <c>true</c> if the point is within the polygon, otherwise <c>false</c>
/// </returns>
public bool PointInPolygon(PointF point)
{
var j = _vertices.Length - 1;
var oddNodes = false;
for (var i = 0; i < _vertices.Length; i++)
{
if (_vertices[i].Y < point.Y && _vertices[j].Y >= point.Y || _vertices[j].Y < point.Y && _vertices[i].Y >= point.Y)
{
if (_vertices[i].X + (point.Y - _vertices[i].Y) / (_vertices[j].Y - _vertices[i].Y) * (_vertices[j].X - _vertices[i].X) < point.X)
{
oddNodes = !oddNodes;
}
}
j = i;
}
return oddNodes;
}
static double DEF_PI = 3.14159265359; // PI
static double DEF_2PI = 6.28318530712; // 2*PI
static double DEF_PI180 = 0.01745329252; // PI/180.0
static double DEF_R = 6370693.5; // radius of earth
/// <summary>
/// 计算两点间的距离
/// </summary>
/// <param name="lon1">坐标1经度</param>
/// <param name="lat1">坐标1纬度</param>
/// <param name="lon2">坐标2经度</param>
/// <param name="lat2">坐标2纬度</param>
/// <returns></returns>
public double GetLongDistance(double lon1, double lat1, double lon2, double lat2)
{
double ew1, ns1, ew2, ns2;
double distance;
// 角度转换为弧度
ew1 = lon1 * DEF_PI180;
ns1 = lat1 * DEF_PI180;
ew2 = lon2 * DEF_PI180;
ns2 = lat2 * DEF_PI180;
// 求大圆劣弧与球心所夹的角(弧度)
distance = Math.Sin(ns1) * Math.Sin(ns2) + Math.Cos(ns1) * Math.Cos(ns2) * Math.Cos(ew1 - ew2);
// 调整到[-1..1]范围内,避免溢出
if (distance > 1.0)
distance = 1.0;
else if (distance < -1.0)
distance = -1.0;
// 求大圆劣弧长度
distance = DEF_R * Math.Acos(distance);
return distance;
}
/// <summary>
/// 计算点是否在圆内
/// </summary>
/// <param name="point">比较坐标点</param>
/// <param name="roundCenterPoint">圆中心点</param>
/// <param name="r">圆半径</param>
/// <returns>True False</returns>
public bool PointInRound(PointF point, PointF roundCenterPoint, double r)
{
//两点之间的距离
var distance = GetLongDistance(point.X, point.Y, roundCenterPoint.X, roundCenterPoint.Y);
return distance < r;
}
调用:
//测试多边形
var vertices = new PointF[4]
{
new PointF(1, 3),
new PointF(1, 1),
new PointF(4, 1),
new PointF(4, 3)
};
var p = new Polygon(vertices);
var isIn=p.PointInPolygon(new PointF(2,2));
//测试圆
var p = new Polygon();
var isOk = p.PointInRound(new PointF(float.Parse("120.784584"), float.Parse("31.287565")), new PointF(float.Parse("120.782357"), float.Parse("31.28633")), 154.8930217136462);
参考:
http://www.ytechie.com/2009/08/determine-if-a-point-is-contained-within-a-polygon.html
http://alienryderflex.com/polygon/
http://erich.realtimerendering.com/ptinpoly/
http://www.geeksforgeeks.org/how-to-check-if-a-given-point-lies-inside-a-polygon/
浙公网安备 33010602011771号