点与多边形的包含判定,代码
点与多边形的包含判定,代码
--------------------------------------------------------------------
有朋友问起这个问题的处理,就总是回复说,射线求交,可自己从来没真正下手写过
到自己需要了,竟然到处都找不到,网上也搜不见,真是奇怪,讨论的是挺多的。难道大家都停留在讨论阶段,还是windows api中的PtInRegion就够用了呢。我也挺懒,有的东西向来喜欢拿来主义,这次写写看吧,不过感觉例外情况很多,处理繁琐。比如这个代码没有处理相邻两边在同一条直线且跟射线也共线的情况。---好像说起来满别扭的.
发上来大家或许可以借鉴一下,并恳请各位帮忙检查一下还有哪些错误的地方。有劳,谢了!
一点说明,多边形定点值数组为pllPoint,nPoiCount是其定点数或者说边数
/*
* function: PtInRegion
* ascertain that a point in region or not.
* parameter: coordinate of point.
* return value:
* 0 --- out of the region;
* 1 --- in;
* 2 --- is climax;
* 3 --- in edge.
* code by Homer Lu, 2003-11-13
*/
int CRegion::PtInRegion(double fX, double fY)
{
int nStartP, nEndP;
double fX0, fY0 = fY;
int nCrossCount = 0;
for (int i = 0; i < nPoiCount; i++)
{
nStartP = i;
if(i + 1 == nPoiCount)
nEndP = 0;
else
nEndP = i + 1;
if(fY > pllPoint[nStartP].lat && fY > pllPoint[nEndP].lat) //on top of
continue ;
else if(fY < pllPoint[nStartP].lat && fY < pllPoint[nEndP].lat) //foot
continue ;
else if(fY == pllPoint[nStartP].lat && fX == pllPoint[nStartP].lon)
return 2;
else if(fY == pllPoint[nStartP].lat && fY == pllPoint[nEndP].lat)
{
if(fX > max(pllPoint[nStartP].lon, pllPoint[nEndP].lon))
continue ;
else if(fX < max(pllPoint[nStartP].lon, pllPoint[nEndP].lon) && fX > min(pllPoint[nStartP].lon, pllPoint[nEndP].lon))
return 3;
else //fX <= min(pllPoint[i].lon, pllPoint[i + 1].lon)
{
if(i - 1 < 0)
nStartP = nPoiCount - 1;
else
nStartP = i - 1;
if(i + 2 >= nPoiCount)
nEndP = i + 2 - nPoiCount;
else
nEndP = i + 2;
i++;
if(fY > max(pllPoint[nStartP].lat, pllPoint[nEndP].lat) ||
fY < min(pllPoint[nStartP].lat, pllPoint[nEndP].lat))
{
nCrossCount ++ ;
continue ;
}
else
continue ;
}
}
else if(fY == pllPoint[nStartP].lat)
{
if(fX < pllPoint[nStartP].lon)
nCrossCount ++ ;
else
continue ;
}
else if(fY == pllPoint[nEndP].lat)
{
nStartP = i;
if(i + 2 >= nPoiCount)
nEndP = i + 2 - nPoiCount;
else
nEndP = i + 2;
if(fY > max(pllPoint[nStartP].lat, pllPoint[nEndP].lat) ||
fY < min(pllPoint[nStartP].lat, pllPoint[nEndP].lat))
{
nCrossCount ++ ;
continue ;
}
else
continue ;
}
else //if (fY < max(pllPoint[nStartP].lat, pllPoint[nEndP].lat) &&
// (fY > min(pllPoint[nStartP].lat, pllPoint[nEndP].lat)))
{
// get cross-point. formula: x0 = x1 + (x2 - x1) * (y0 - y1) / (y2 - y1)
fX0 = pllPoint[nStartP].lon + (pllPoint[nEndP].lon - pllPoint[nStartP].lon) * (fY - pllPoint[nStartP].lat) / (pllPoint[nEndP].lat - pllPoint[nStartP].lat);
if(fX0 == fX)
return 3;
else if(fX0 > fX)
{
nCrossCount ++ ;
continue ;
}
else // fX0 < fX
continue ;
}
} // end for (int i = 0; i < nPoiCount - 1; i++)
return nCrossCount % 2;
}