放射線算法,就是把一個點向任意方向發射(本程序是向下),如果跟這個面有奇數個交點,證明點在面裏面,若是偶數個,則是在外面(包括0),
struct TabPoint
{
private double x;
public double X
{
get { return x; }
set { x = value; }
}
private double y;
public double Y
{
get { return y; }
set { y = value; }
}
}
struct Polygon
{
public ArrayList pointsArray;
private double minx;
public double MinX
{
get { return minx; }
set { minx = value; }
}
private double miny;
public double MinY
{
get { return miny; }
set { miny = value; }
}
private double maxx;
public double MaxX
{
get { return maxx; }
set { maxx = value; }
}
private double maxy;
public double MaxY
{
get { return maxy; }
set { maxy = value; }
}
}
class Analyse
{
private readonly double dis = 0.0000000001;
//返回值:true點在面內 false點在面外
public bool JudgeMeetPoint(TabPoint tpt, ArrayList polygonPtArray)
{
int MeetPointNum = 0;
int PolygonPtSize = polygonPtArray.Count;
for (int k = 1; k < PolygonPtSize; k++)
{
TabPoint pt1 = (TabPoint)polygonPtArray[k - 1];
TabPoint pt2 = (TabPoint)polygonPtArray[k];
if (((tpt.X <= pt1.X && tpt.X >= pt2.X) ||
(tpt.X >= pt1.X && tpt.X <= pt2.X)) &
(tpt.Y >= pt1.Y || tpt.Y >= pt2.Y) &
(pt1.X != pt2.X && pt1.Y != pt2.Y))
{
//判斷點是否在線上
if (JudgePtInLine(pt1, pt2, tpt))
{
return true;
}
//處理特殊情況,交點是端點的情況
double temp;
//temp相當於被除數(斜率的分母)
temp = pt1.X - pt2.X;
if (temp >= -dis && temp <= dis)
{
//處理交點情況
double dx = tpt.X - pt1.X;
if (dx >= -dis && dx <= dis)
{
int[] indexs = new int[2];
indexs[0] = 0;
indexs[1] = 0;
GetNotSame(polygonPtArray, k, ref indexs);
TabPoint linePt1, linePt2;
linePt1 = (TabPoint)polygonPtArray[indexs[0]];
linePt2 = (TabPoint)polygonPtArray[indexs[1]];
if (k > indexs[0])
{
break;
}
else
{
k = indexs[0] + 1;
}
if (tpt.Y > pt1.Y && ((tpt.X >= linePt1.X && tpt.X <= linePt2.X) ||
(tpt.X >= linePt2.X && tpt.X <= linePt1.X)))
MeetPointNum++;
}
}
else
{
double kk, bb;
double MeetPtY, MeetPtX;
kk = (pt1.Y - pt2.Y) / (pt1.X - pt2.X);
bb = pt1.Y - kk * pt1.X;
MeetPtY = kk * tpt.X + bb;
MeetPtX = tpt.X;
//處理特殊情況,交點是端點的情況
double dx, dy, dx2, dy2;
dx = MeetPtX - pt1.X;
dy = MeetPtY - pt1.Y;
dx2 = MeetPtX - pt2.X;
dy2 = MeetPtY - pt2.Y;
if ((dx >= -dis && dx <= dis && dy >= -dis
&& dy <= dis))
{
TabPoint pt3;
if (k == 1)
{
pt3 = (TabPoint)polygonPtArray[PolygonPtSize - 2];
}
else
{
pt3 = (TabPoint)polygonPtArray[k - 2];
}
//提取交點的上下兩點分別在垂線的兩側
if (tpt.Y > MeetPtY && ((MeetPtX >= pt3.Y && MeetPtX <= pt2.X) ||
(MeetPtX >= pt2.X && MeetPtX <= pt3.X)))
MeetPointNum++;
}
else if (!(dx2 >= -dis && dx2 <= dis && dy2 >= -dis
&& dy2 <= dis))
{
if (tpt.Y > MeetPtY)
MeetPointNum++;
}
}
}
}
if (MeetPointNum % 2 == 1)
return true;
else
return false;
}
//判斷點是否在線上
private bool JudgePtInLine(TabPoint tpt1, TabPoint tpt2, TabPoint tpt)
{
double dx1 = GetDistance(tpt1, tpt2);
double dx2 = GetDistance(tpt, tpt1);
double dx3 = GetDistance(tpt, tpt2);
double dx = dx3 + dx2 - dx1;
if (dx >= -0.0000000001 && dx <= 0.0000000001)
{
return true;
}
return false;
}
//求取兩點之間的距離
private double GetDistance(TabPoint tpt1, TabPoint tpt2)
{
double x = tpt1.X - tpt2.X;
if (x <= 0)
{
x = -x;
}
double y = tpt1.Y - tpt2.Y;
if (y <= 0)
{
y = -y;
}
return System.Math.Sqrt(x * x + y * y);
}
//在鏈表中獲取x軸不相同的點
private void GetNotSame(ArrayList pointArray, int index, ref int[] indexs)
{
indexs[0] = indexs[1] = -1;
int size = pointArray.Count;
TabPoint buftpt, tpt;
tpt = (TabPoint)pointArray[index];
for (int i = index; i < size; i++)
{
buftpt = (TabPoint)pointArray;
if (buftpt.X != tpt.X)
{
indexs[0] = i;
break;
}
}
if (indexs[0] == -1)
{
for (int i = 0; i < size; i++)
{
buftpt = (TabPoint)pointArray;
if (buftpt.X != tpt.X)
{
indexs[0] = i;
break;
}
}
}
for (int j = index; j >= 0; j--)
{
buftpt = (TabPoint)pointArray[j];
if (buftpt.X != tpt.X)
{
indexs[1] = j;
break;
}
}
if (indexs[1] == -1)
{
for (int j = size - 1; j >= 0; j--)
{
buftpt = (TabPoint)pointArray[j];
if (buftpt.X != tpt.X)
{
indexs[1] = j;
break;
}
}
}
}
public bool JudgeInRect(TabPoint minPt,TabPoint maxPt,TabPoint pt)
{
if (pt.X >= minPt.X && pt.X <= maxPt.X && pt.Y >= minPt.Y && pt.Y <= maxPt.Y)
{
return true;
}
else
{
return false;
}
}
}