您的位置:首页 > 其它

判断点是否在多边形内——射线法

2011-12-09 09:42 316 查看
//判断射线与也线段是否相交, 相交返回1,不相交返回0,在边上返回-1
int IsIntersectant( CPoint ptStart, CPoint ptEnd, CPoint pd )
{
double tempx = 0;
double tempy = 0;
//记录多边形边的端点坐标;
double startx = ptStart.x;
double starty = ptStart.y;
double endx = ptEnd.x;
double endy = ptEnd.y;

double maxX = startx;
double minX = endx;
if (startx<endx)
{
minX = startx;
maxX = endx;
}

//保证开始点在下(y坐标大),作为下端点
if(starty<endy)
{
double temp=starty;
starty=endy;
endy=temp;
temp=startx;
startx=endx;
endx=temp;
}

//首先排除没有交点的情况
if((pd.y>starty && pd.y>endy) || (pd.y<starty && pd.y<endy))  //水平射线在该直线段的上下两端之外
{
return 0;
}
if(pd.x>startx && pd.x>endx)    //水平射线的起点在该直线段的右边
{
return 0;
}

//如果是水平线段,在线段上返回-1,否则返回0
if (starty ==endy)
{
if (pd.x<=maxX&&pd.x>=minX)
{
return -1;
}
return 0;
}

//判断点pd是否是多边形边上的点,通过距离判断
tempx = pd.x - startx;
tempy = pd.y - starty;
double dStartToX = sqrt(tempx*tempx+tempy*tempy);

tempx = pd.x - endx;
tempy = pd.y - endy;
double dXToEnd = sqrt(tempx*tempx+tempy*tempy);

tempx = startx - endx;
tempy = starty - endy;
double dStarToEnd = sqrt(tempx*tempx+tempy*tempy);

if (dStarToEnd == (dStartToX + dXToEnd))
{
return -1;
}

//h_x记录点pd(x,y)引水平线与直线段所在直线的交点x坐标(直线坐标y=kx+b)
double h_x=(pd.y-starty)*(endx-startx)/(endy-starty)+startx;

if(pd.x>h_x)//pd点在交点的右边,则射线与线段不相交
{
return 0;
}
if(pd.y==starty)         //水平射线与直线段的上端点相交,不计交点,只考虑与直线段的下端点相交
{
return 0;
}

return 1;

}
BOOL PtInPolygon( CPoint *ptList, int ptCount, CPoint pd )
{
if (ptCount<3)
{
return FALSE;
}

int cross_num = 0;
int iFlag = 0;
//从点pd,向右引水平射线

for(int i=0;i<ptCount-1;i++)
{
iFlag = IsIntersectant(ptList[i], ptList[i+1], pd);
if (iFlag < 0)
{
return TRUE;
}
else
{
cross_num += iFlag;
}
}

//末端点与首端点连接线
iFlag = IsIntersectant(ptList[ptCount-1], ptList[0], pd);
if (iFlag < 0)
{
return TRUE;
}
else
{
cross_num += iFlag;
}

if(cross_num%2==1) //交点个数为奇
{
return TRUE;
}
else if(cross_num%2==0) //交点个数为偶
{
return FALSE;
}

return FALSE;

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