基于C#窗体应用程序,通过用户自定义的多边形与点,判断点与多边形的关系。
一、射线法
1 射线法原理
用交点个数的奇偶性来判定目标点是否在目标多边形内部,由目标点出发,向任意方向作射线,统计与目标多边形的交点个数。一般情况下,交点个数若为偶数则在多边形外部;若为奇数则在多边形内部。当出现点在边上,所作射线与多边形的边重合时应另作处理。
2 射线法的优缺点
优点:算法简单,容易实现;易于改进结合。
缺点:要对每一条边都需要做两次以上的乘法运算,涉及大量的求教运算;很难处理一些临界性的问题,对于特殊情况(射线法过定点的情况,点在边上的情况,射线所水平边的情况)的处理能力不足,易出错,稳定性较差,灵活性低。
3 射线法代码
int num = newploy.Count;
水平射线法
正常情况与多边形的交点为偶数的话在多边形外(一进一出),奇数的话在多边形内
特殊情况1:点为多边形顶点,点在多边形上
特殊情况2:射线经过多边形顶点
bool flag = true;
for (int i = 0; i < num; i++)
{
//点为多边形顶点
if ((p == newploy[i]) || (p == newploy[(i + 1) % num]))
return 0;
else if ((p.Y >= newploy[i].Y && p.Y < newploy[(i + 1) % num].Y) ||
(p.Y >= newploy[(i + 1) % num].Y && p.Y < newploy[i].Y))
{
double x = (double)(newploy[i].X - newploy[(i + 1) % num].X) * (p.Y - newploy[i].Y)
/ (newploy[i].Y - newploy[(i + 1) % num].Y) + newploy[i].X;
if (Math.Abs(x - p.X) < 1e-4)
return 0;
if (x > p.X)
flag = !flag;
}
}
return flag ? 1 : -1;
二、旋转法
1 旋转法原理
用角度值来判定目标点是否在目标多边形内部,由目标点出发,引线延伸到多边形的每一个顶点,按逆时针方向进行,完成多边形的封闭(由起始点开始回到起始点)。如果点到顶点的角度之和为o,则点位于多边形之外,超过T的以其补角的负值进行叠加。若所有角度之和非零则目标点位于多边形内或多边形上。
2 旋转法的优缺点
优点:旋转法算法周全,对于特殊情况的处理灵活判断准确不易出错。旋转法是判断点在多边形内外的最流行的算法之一,用程序语言表示较射线法更简洁,更容易理解和掌握,且精度较高
缺点:旋转法算法判断条件较复杂,相比射线法实现较为困难;需要计算大量的反三角函数,时间复杂度较大,且当点落于多边形的边上时,算法会恒认为其在多边形的内部;处理凹多边形时存在歧义。
3 旋转法代码
for (int i = 0; i < newploy.Count; i++)
{
//计算点到多边形顶点的距离
double res1 = TwoPDistance(p.X, newploy[i].X, p.Y, newploy[i].Y);
Arraylist.Add(res1);
}
for (int j = 0; j < newploy.Count; j++)
{
double a = j + 1 < newploy.Count ? TwoPDistance(newploy[j].X, newploy[j + 1].X, newploy[j].Y, newploy[j + 1].Y)
: TwoPDistance(newploy[0].X, newploy[j].X, newploy[0].Y, newploy[j].Y);
if(j+1 < newploy.Count)
{
temp = Angle(a, Convert.ToDouble(Arraylist[j]), Convert.ToDouble(Arraylist[j + 1]));
if (temp >= 180)
{
temp = -(180 - temp);
}
sumAngle += temp;
}
else
{
temp1 = Angle(a, Convert.ToDouble(Arraylist[j]), Convert.ToDouble(Arraylist[0]));
if (temp1 >= 180)
{
temp1 = -(180 - temp1);
}
sumAngle += temp1;
}
}
double res = Math.Abs(sumAngle);
public ArrayList Arraylist = new ArrayList();
其中Angle()是用来计算角度的函数、TwoPDistance()是用来计算两点间距离的函数。
三、实现效果
原创内容
请勿抄袭
欢迎留言