判断点在多边形内

来源:互联网 发布:php购物车源代码 编辑:程序博客网 时间:2024/04/29 06:16

1. 角度和判别法(适用于任意多边形)

double angle = 0;

realPointList::iterator iter1 = points.begin();

for (realPointList::iterator iter2 = (iter1 + 1); iter2 < points.end(); ++iter1, ++iter2)

 {

   double x1 = (*iter1).x - p.x;  

   double y1 = (*iter1).y - p.y;  

   double x2 = (*iter2).x - p.x;

   double y2 = (*iter2).y - p.y;  

   angle += angle2D(x1, y1, x2, y2);

 }

if (fabs(angle - span::PI2) < 0.01) return true;

else return false;

另外,可以使用bounding box来加速。

if (p.x < (*iter)->boundingBox.left ||

   p.x > (*iter)->boundingBox.right ||

   p.y < (*iter)->boundingBox.bottom ||

   p.y > (*iter)->boundingBox.top) 。。。。。。

对于多边形来说,计算bounding box非常的简单。只需要把水平和垂直方向上的最大最小值找出来就可以了。

1. 角度和判别法(适用于任意多边形)

double angle = 0;
realPointList::iterator iter1 = points.begin();
for (realPointList::iterator iter2 = (iter1 + 1); iter2 < points.end(); ++iter1, ++iter2)
 {
   double x1 = (*iter1).x - p.x;  
   double y1 = (*iter1).y - p.y;  
   double x2 = (*iter2).x - p.x;
   double y2 = (*iter2).y - p.y;  
   angle += angle2D(x1, y1, x2, y2);
 }

if (fabs(angle - span::PI2) < 0.01) return true;
else return false;

另外,可以使用bounding box来加速。
if (p.x < (*iter)->boundingBox.left ||
   p.x > (*iter)->boundingBox.right ||
   p.y < (*iter)->boundingBox.bottom ||
   p.y > (*iter)->boundingBox.top) 。。。。。。

对于多边形来说,计算bounding box非常的简单。只需要把水平和垂直方向上的最大最小值找出来就可以了。

对于三角形:第四点分别与三角形的两个点的交线组成的角度分别设为j1,j2,j3,只要j1+j2+j3>360就不在三角形范围中。

2. 水平/垂直交叉点数判别法(适用于任意多边形)

注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数,如果P在多边形外部,则交点个数必为偶数(0也在内)。所以,我们可以顺序考虑多边形的每条边,求出交点的总个数。还有一些特殊情况要考虑。假如考虑边(P1,P2),
1)如果射线正好穿过P1或者P2,那么这个交点会被算作2次,处理办法是如果P的从坐标与P1,P2中较小的纵坐标相同,则直接忽略这种情况
2)如果射线水平,则射线要么与其无交点,要么有无数个,这种情况也直接忽略。
3)如果射线竖直,而P0的横坐标小于P1,P2的横坐标,则必然相交。
4)再判断相交之前,先判断P是否在边(P1,P2)的上面,如果在,则直接得出结论:P再多边形内部。

对于三角形:第四点分别与三角形的两个点的交线组成的角度分别设为j1,j2,j3,只要j1+j2+j3>360就不在三角形范围中。

2. 水平/垂直交叉点数判别法(适用于任意多边形)

注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数,如果P在多边形外部,则交点个数必为偶数(0也在内)。所以,我们可以顺序考虑多边形的每条边,求出交点的总个数。还有一些特殊情况要考虑。假如考虑边(P1,P2),

1)如果射线正好穿过P1或者P2,那么这个交点会被算作2次,处理办法是如果P的从坐标与P1,P2中较小的纵坐标相同,则直接忽略这种情况

2)如果射线水平,则射线要么与其无交点,要么有无数个,这种情况也直接忽略。

3)如果射线竖直,而P0的横坐标小于P1,P2的横坐标,则必然相交。

4)再判断相交之前,先判断P是否在边(P1,P2)的上面,如果在,则直接得出结论:P再多边形内部。

==================================================================================

int CUtility::IsPtOnGon(const AcGePoint2dArray& ptArr,AcGePoint2d& pt)
{
 if(ptArr.length()<=2) return 0;
 //判是否在线上===================================================
 AcGeCurve2d* pCurve = (AcGeCurve2d*) new AcGePolyline2d(ptArr);
 if(pCurve->isOn(pt))
 {
  delete pCurve;
  pCurve= NULL;
  return 1;
 }
 delete pCurve;
 pCurve = NULL;
 //三角形===========================================================
 if(ptArr.length() == 3)
 {
  AcGeVector2d a,b,c;
  a = ptArr[0] - pt;
  b = ptArr[1] - pt;
  c = ptArr[2] - pt;
  double angle = a.angleTo(b);
  angle += b.angleTo(c);
  angle += c.angleTo(a);

  if(fabs(angle - PI*2.0) < 0.001) return 1;
  return 0;
 }

 //多边形===============================================================
 //判是否在Extend外
 AcGePoint2d ptMin,ptMax;
 FindExtInPtArr(ptArr,ptMin,ptMax);
 if(pt.x - ptMin.x < 0.0001 || pt.x - ptMax.x > 0.0001) return 0;
 if(pt.y - ptMin.y < 0.0001 || pt.y - ptMax.y > 0.0001) return 0;

 //点到各顶点的夹角和=2PI
 AcGeVector3dArray vArr;
 AcGeVector3d pRef;
 for(int i=0;i<ptArr.length();i++)
 {
  AcGeVector3d pVec = AcGePoint3d(ptArr[i].x,ptArr[i].y,0) - AcGePoint3d(pt.x,pt.y,0);
  vArr.append(pVec);
 }
 double angle = 0.0;
 int j=0;
 for(int i=0;i<vArr.length()-1;i++)
 {
  pRef = vArr[i].crossProduct(vArr[i+1]);
  pRef.normalize();
  angle += -pRef.z * vArr[i].angleTo(vArr[i+1]);
  j++;
 }
 pRef = vArr[j].crossProduct(vArr[0]);
 pRef.normalize();

 angle += -pRef.z * vArr[j].angleTo(vArr[0],pRef);
 double sumAngle = PI*2.0;
 if(fabs(fabs(angle) - sumAngle) < 0.001) return 1;
 else return 0;
}

原创粉丝点击