点在面内的算法
来源:互联网 发布:十二星相 知乎 编辑:程序博客网 时间:2024/04/30 15:24
放射线算法,就是把一个点向任意方向发射(本程序是向下),如果跟这个面有奇数个交点,证明点在面里面,若是偶数个,则是在外面(包括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; } } }