给定一组圆圈,我如何才能有效地找到仅由其中一个包围的点?

时间:2015-06-08 07:18:55

标签: math grid 2d geometry points

给定2D网格中的一组中心点和公共半径,我现在想要标记由中心点和半径形成的任何圆内的所有其他点(或者更确切地说是单元格)。

通过在一个四分之一中找到这些点并应用对称性,可以找到其中一个圆内的所有点。

然而,一旦标记了一些点,我现在想省略为了效率而再次标记它们。因此,在要绘制的下一个中心点的相关距离内的所有已经“膨胀”的中心点已经标记了我们也被下一个圆圈包围的点。 (也就是说,从我们的点到它们每个的矢量的大小小于直径)。

如何在下一个圆圈中找到之前未标记的点集?

下图显示了我想省略的示例。给定三点,我在每个点周围绘制一个圆圈,并用圆圈中的每个单元格标记蓝色,红色,黄色。如您所见,圆圈的大部分是重叠的,因此一些单元格已用每种颜色标记。

An example: Once coloured,

1 个答案:

答案 0 :(得分:1)

对于网格中的给定行,使用给定的Y值,您可以编写一个函数来计算该行中圆圈内是否有任何点,如果是,则该间隔的起始和结束X坐标行穿过圆圈。在C ++中 - 就像伪代码:

bool getRowCircleInterval(float fRowY, float fCenterX, float fCenterY, float fRadius, float &fStartX, float &fStartY)
{
     if((fRowY < fCenterY - fRadius) || (fRowY > fCenterY + fRadius))
         return false; // circle does not intersect this row

     float fYDiff = fCenterY - fRadius;
     float fIntervalWidth = sqrt((fRadius * fRadius) - (fYDiff * fYDiff));

     fStartX = fCenterX - fIntervalWidth;
     fEndX = fCenterX + fIntervalWidth;

     return true;
}

对于fCenterY范围内的每一行 - 要绘制圆圈的fRadius到fCenterY + fRadius:

  • 调用此函数传递最新的圆圈以获得间隔。
  • 对于已经绘制的每个圆圈,在同一行Y坐标中重复再次调用该函数。如果它返回true,则将返回的间隔与现有间隔相交,并切掉相交的现有间隔的那一部分。重复操作,直到没有剩余间隔或您已处理完所有前面的圆圈。
  • 如果处理完所有前一个圆圈后剩余的最后间隔非空,请填写该行间隔范围内的所有网格单元格。

将浮点X值转换为整数网格单元索引时,需要使用一致的填充约定。例如,您可以除以网格单元格,然后转换为整数,然后填充开始X到结束X范围内的所有点。在这种情况下,当您检查重叠的两个间隔时,如果新间隔被前一个间隔剪切,则新间隔将不包括前一个间隔的端点。