我试图检测任意多边形是否在另一个内部。 它在几乎所有形状上都能完美地运作,但发现了一个我不知道如何解决的案例。
我有顶点定义的多边形。 为了检查一个多边形是否在另一个内,我循环顶点并检查它们是否在“轮廓”形状之外。为了检查一个点是否位于轮廓的船体内部,我从它向正X施放一条“射线”并检查我碰撞的“轮廓”的多少段。
http://en.wikipedia.org/wiki/Even%E2%80%93odd_rule
我考虑过水平段的问题。
光线投射算法的大多数实现依次连续检查光线与多边形所有边的交点。在这种情况下,必须解决以下问题。 如果光线准确地穿过多边形的顶点,那么它将在它们的端点处与两个段相交。虽然对于示例中最顶部顶点或交叉4和5之间的顶点的情况是可以的,但是最右边顶点(在示例中)的情况要求我们计算一个交叉点以使算法正常工作。类似的问题出现在碰巧落在光线上的水平段上。该问题解决如下:如果交叉点是测试多边形边的顶点,则只有当边的第二个顶点位于光线下方时,交点才会计数。这实际上相当于将光线上的顶点视为略微位于光线上方。
当我试图检查2个完全对齐的盒子,宽度相同的高度(为了精确度,Arial字体上的'''字形时,问题就变成了。
任何一个方框的所有顶点都会与另一个方框的水平方向碰撞,让我无法检查它是在内部还是外部。如果我检查它是否是水平的,并且测试点是否留在测试点,它可以工作,但是“#”字形将在其内部轮廓上给出误报。
有我的算法:
bool GRPOBJECTBUILDER::CheckPointInsideContour(GRPPOINT testedpoint, GRPSPLINE* processedspline)
{
bool isinside = false;
XDWORD i;
XDWORD j;
for(i=0, j = processedspline->points.GetSize()-2; i < processedspline->points.GetSize()-1; j = i++)
{
GRPANCHORPOINT* splinepointi = processedspline->points.Get(i);
GRPANCHORPOINT* splinepointj = processedspline->points.Get(j);
if (testedpoint.y == splinepointi->value.y == splinepointj->value.y) //es un segmento horizontal y estamos en el espacio
{
if ((splinepointi->value.x>splinepointj->value.x && testedpoint.x>splinepointi->value.x) ||
(splinepointi->value.x<splinepointj->value.x && testedpoint.x<splinepointi->value.x))
return true;
}
bool isbetweeny = (splinepointi->value.y > testedpoint.y && splinepointj->value.y < testedpoint.y) ||
(splinepointi->value.y < testedpoint.y && splinepointj->value.y > testedpoint.y);
if ((testedpoint.y == splinepointi->value.y) && (splinepointi->value.y!=splinepointj->value.y)) //check con vertice
isbetweeny=true;
GLFLOAT m = 0.0f;
if((splinepointi->value.y - splinepointj->value.y) != 0.0f)
m = (splinepointi->value.x - splinepointj->value.x) / (splinepointi->value.y - splinepointj->value.y);
else
m = 0;
bool islefttox = (testedpoint.x <= ((m*(testedpoint.y - splinepointj->value.y)) + splinepointj->value.x));
if(isbetweeny && islefttox)
isinside = !isinside;
}
if (isinside)
return true;
return false;
}
我应该检查一下我忘了吗?
感谢。