在网上看见了一些判断的算法,都是通过射线判断与多段线的交点的个数计算的,不过没有考虑到
射线正好通过多段线端点,即端点与交点重合的情况,这里对该算法进行完善
//判断交点位于多段线端点上时,与其2个相邻点分别构成的直线是否都在射线的同一侧
BOOL IsRemoveIntersectPnt(AcDbRay &pRay ,const AcDbPolyline &poly,int pntIndex,AcGePoint3dArray &IntersectPnts)
{
BOOL result=TRUE;
AcGePoint3d pnt;
poly.getPointAt(pntIndex,pnt);
AcGePoint3d adjacentPnt1,adjacentPnt2; //与端点相邻的2个端点
if (0==pntIndex) //如果是第1点
{
poly.getPointAt(1,adjacentPnt1); //相邻点是第2点和最末点
poly.getPointAt(poly.numVerts()-1,adjacentPnt2);
}
else if(poly.numVerts()-1==pntIndex) //如果是最末1点
{
poly.getPointAt(pntIndex-1,adjacentPnt1); //相邻点是最末点前1点和第1点
poly.getPointAt(0,adjacentPnt2);
}
else
{
poly.getPointAt(pntIndex-1,adjacentPnt1);
poly.getPointAt(pntIndex+1,adjacentPnt2);
}
AcGeVector3d vec;
if (!pnt.isEqualTo(pRay.basePoint())) //如果射线起点与交点不相同
vec=pnt-pRay.basePoint(); //以这2点确定镜像向量
else //如果射线起点与交点相同
{
if (1==IntersectPnts.length()) //如果此时只有一个交点
{
return TRUE;
}else{
vec=IntersectPnts[1]-IntersectPnts[0];
}
}
AcGePlane pl(pRay.basePoint(),vec.perpVector());
//取2个相邻点中的任意一点A,以射线起点和构成的线为中线进行镜像
//如果镜像后的点A'与相邻点中的另一点B的距离小于A与B的距离
//则认为:交点与其2个相邻点分别构成的直线不在射线的同一侧
//此时,该位于多段线端点上的交点有效,无需删除
AcGePoint3d adjacentPnt1Mirrored(adjacentPnt1);
adjacentPnt1Mirrored.mirror(pl);
if (adjacentPnt2.distanceTo(adjacentPnt1)>adjacentPnt2.distanceTo(adjacentPnt1Mirrored))
{
result=FALSE;
}
return result;
}
BOOL ptInPoly(AcGePoint3d & pt, AcGePoint2dArray & verts,AcGeVector3d rayDir)
{
AcDbPolyline poly(verts.length());
Acad::ErrorStatus es;
int i,j;
for (i = 0; i < verts.length(); i++)
{
es=poly.addVertexAt(i, verts.at(i));
}
poly.setClosed(Adesk::kTrue);
AcDbRay ray;
ray.setBasePoint(pt);
ray.setUnitDir(rayDir);
AcGePoint3dArray points;
es = poly.intersectWith(&ray, AcDb::kOnBothOperands, points);
for (i=points.length()-1;i>=0;i--)
{
for ( j=0;j<poly.numVerts();j++)
{
AcGePoint3d pnt;
poly.getPointAt(j,pnt);
if (points[i].isEqualTo(pnt)) //如果射线的多段线的交点与多段线的某端点重合
{
if (IsRemoveIntersectPnt(ray,poly,j,points)) //判断这个交点是否有效
points.removeAt(i);
}
}
}
if (points.length() % 2)
return TRUE;
else
return FALSE;
}