您的位置:首页 > 编程语言

射线法判断点是否在多边形内的关键代码

2009-10-21 22:16 561 查看
完全实例代码。如需进一步了解,及了解更新情况请登陆独傲村里的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;

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: