完全实例代码。如需进一步了解,及了解更新情况请登陆独傲村里的GIS版块,支持下载。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace RadialPointInPolygon
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnIsPointInPolygon_Click(object sender, EventArgs e)
{
Point p = new Point(0, 1);
Point[] V={new Point(1, 2),new Point(1, 0),new Point(3, 3)};//程序中仅以这几个点为例
//V[0] = new Point(1, 2);
//V[1] = new Point(1, 0);
//V[2] = new Point(3, 3);
if (IsPointInPolygon(p, V, 3) == true)
{
MessageBox.Show("点在多边形内");
}
else MessageBox.Show("点在多边形外");
}
/// <summary>
/// 判断点是否在多边形内
/// </summary>
/// <param name="P"></param>
/// <param name="V"></param>
/// <param name="n"></param>
/// <returns></returns>
private Boolean IsPointInPolygon(Point P, Point[] V, int n)
//统计穿越次数,为奇数时返回true,在多边形内。n为边数。
{
int cn = 0; //the crossing number counter.
Rectangle outRec = OutRectangle(V);
if (n < 3) return false;//最多两个点时
else if ((P.X <= outRec.X + outRec.Width) && P.X >= outRec.X && P.Y >= outRec.Y && P.Y <= outRec.Y + outRec.Height)
//在外包矩形中时.
{
//set a horizontal beam from P to W.
Point W = new Point(P.X + outRec.Width + 1, P.Y);
int j = 0, k1 = 0, k2 = 0;
for (int i = 0; i < n; i++)//for里面的这段代码参考网上的代码写出的
{
j = (i + 1) % n; //i下一个数为j
if (IsLineIntersect(V[i], V[j], P, W) == true) //如果线与线相交
{
cn++;
}
else if (V[i].Y == W.Y) //点在水平射线上
{
k1 = (n + i - 1) % n;//k1为当前点的前一个点的index
while (k1 != i && V[k1].Y == W.Y) //如果前一个点也在射线上
k1 = (n + k1 - 1) % n; //k1返回到起点
k2 = (i + 1) % n; //k2为当前点的下一个点
while (k2 != i && V[k2].Y == W.Y) //如果下一个点也在射线上
k2 = (k2 + 1) % n;//k2到k2的下一个点
if (k1 != k2 && IsPointSameSide(P, W, V[k1], V[k2]) == false)//k1和k2处点不在同一侧
cn++;
if (k2 <= i)
break;
i = k2; //i从k2处开始继续走
}
}
if (cn % 2 == 1) return true;
else return false;
}
else return false;//如果不在外包矩形中,直接返回false。
}
/// <summary>
/// 求多边形的外包矩形
/// </summary>
/// <param name="v"></param>
/// <returns></returns>
private Rectangle OutRectangle(Point[] v)
{
double min_x=v[0].X , min_y=v[0].Y , max_x=v[0].X , max_y=v[0].Y ;
int x, y, w, h;
for (int i = 0; i < v.Length; i++)
{
if (v[i].X > max_x) max_x = v[i].X;
if (v[i].X < min_x) min_x = v[i].X;
if (v[i].Y > max_y) max_y = v[i].Y;
if (v[i].Y < min_y) min_y = v[i].Y;
}
x=Convert.ToInt32 (min_x);
y=Convert.ToInt32 (min_y);
w=Convert .ToInt32 (max_x -min_x)+1;
h=Convert.ToInt32 (max_y -min_y )+1;
Rectangle rec=new Rectangle(x,y,w,h);
return rec;
}
/// <summary>
/// 判断两点是否在线的同侧
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <param name="l_start"></param>
/// <param name="l_end"></param>
/// <returns></returns>
private Boolean IsPointSameSide(Point p1, Point p2, Point l_start, Point l_end)
{
double result1,result2,result;
Point s1=new Point(0,0);
Point s2 = new Point(0, 0);
Point e = new Point(0, 0);
s1.X = p1.X - l_start.X;
s1.Y = p1.Y - l_start.Y;
s2.X = p2.X - l_start.X;
s2.Y = p2.Y - l_start.Y;
e.X = l_end.X- l_start.X;
e.Y = l_end.Y - l_start.Y;
result1 =VectorCrossProduct(s1,e);//矢量叉乘
result2 = VectorCrossProduct(s2,e);
result = (result1 * result2);
if (result > 0) return true;//大于0在同侧
else return false;
}
/// <summary>
/// 判断两线相交
/// </summary>
/// <param name="s1_start"></param>
/// <param name="s1_end"></param>
/// <param name="s2_start"></param>
/// <param name="s2_end"></param>
/// <returns></returns>
private Boolean IsLineIntersect(Point s1_start, Point s1_end, Point s2_start, Point s2_end)
{
if ((!IsPointSameSide(s1_start, s1_end, s2_start, s2_end)) == true &&
(!IsPointSameSide(s2_start, s2_end, s1_start, s1_end)) == true)
return true;
else return false;
}
/// <summary>
/// 两矢量叉乘
/// </summary>
/// <param name="p"></param>
/// <param name="q"></param>
/// <returns></returns>
private double VectorCrossProduct(Point p, Point q)
{
double result = 0;
result = p.X * q.Y - q.X * p.Y;
return result;
}
}
}