找到一个不在任何旋转矩形内的点

时间:2017-01-26 16:53:40

标签: algorithm intersection

我正在寻找能够快速(我受性能严重限制)的算法找到圆内的一个点,这个点在所提供的集合中的所有矩形之外(这些矩形可以旋转)。 或者,找到一个圆圈A,其中心位于圆圈B内,圆圈A不与一组线段相交。

我能想出的唯一解决方案是循环遍历点的样本,然后遍历每个点的矩形。但由于我的空间是连续的,这非常痛苦。我基本上只对一个不相交的点感到满意,但是会出现没有这样的点的情况。在后一种情况下,我最好尝试找到交点最少的点,或者能够找到没有这一点的答案。

有没有人知道任何能在低于O(n ^ 2)的情况下完成此任务的算法?任何有助于识别好候选点的东西都会很棒。

这种情况的一个典型例子是: 很多大的矩形,有一个小圆圈,我希望找到一个点(这里用蓝色表示)。很常见的是,许多矩形完全落在圆圈之外,并且通常圆圈完全被覆盖。只有一小部分长度和宽度倾向于用于矩形。

enter image description here

2 个答案:

答案 0 :(得分:1)

可能来自sub-n ^ 2的想法取决于矩形的排列方式:

明确计算可能的区域。

表示它的数据结构是一个非重叠子区域的列表,每个子区域都是一个三角形(如果你接近圆圈)或一个"庞大的三角形" (其中一边可以是圆弧段)。

首先是圆圈的三等分(或表示它的一组三角形),然后连续减去矩形。您可以通过交叉可行区域的每个子区域来实现这一点,从而产生一组(可能是空的)新子区域。

这可能起作用的方式是,在任何给定时间,可行的子区域的数量可能很小。处理一对矩形和子区域具有O(1)上限,因此如果我们期望m个子区域将是手波形O(nm)。在最坏的情况下,这可能比O(n ^ 2)差得多(比如在圆圈中完全包含许多不相交的矩形),但在典型的情况下(大矩形,小圆圈),子区域的数量可能不会超过39; t增长很高,然后几乎是O(n)"。

可行区域可以是链接列表,您只需在末尾添加子区域并在开头删除它们,因此访问可以是恒定时间。

子区域(如果有的话)是凸的并且不重叠,因此一旦计算出可行区域,得到它内部的点将是微不足道的。

答案 1 :(得分:0)

可能有几种有趣的方法可以做到这一点。我能想到的最简单的算法可以提供良好的运行时,其算法如下:

  1. 将所有矩形视为一组线段。
  2. 使用高效的算法来查找所有线段的交点(例如Bentley-Ottmann algorithm。)
  3. 创建兴趣点(POI)的列表,这些兴趣点可以是a)矩形的角或b)2中计算的交点。
  4. 创建一组更精细的线段,以使每个线段都终止于3中定义的POI。
  5. 使用POI和来自4的更细的线段集,计算约束三角剖分(例如Constrained Delaunay Triangulation。)
  6. 选择任何(未标记)三角形开始。确定三角形是否位于至少一个矩形内(将其标记为COVERED三角形)或否(将其标记为FREE三角形)。为此,您可以使用任何point in polygon算法,例如光线投射。
  7. 首先从该三角形开始进行深度或广度搜索,然后扩展到邻居,请注意不要在需要穿过4中定义的线段的任何三角形对之间交叉。对于每个访问的三角形,将其标记为相同的标签作为起始三角形。
  8. 重复6-7,直到标记了所有三角形(或标记了覆盖感兴趣圆的所有三角形。)

与感兴趣的圆相交的所有FREE三角形的并集,将精确地产生未被任何矩形覆盖且在圆内的点。

请注意,此算法有点通用,可以通过仅将焦点集中在圆周围的区域进行改进(例如,只能考虑边界框区域,边界框包含与该圆相交的所有矩形。)

要分析运行时,请考虑每个关键步骤的运行时:

    1. 运行时为O((n + k)log n),其中k是交叉点数,其中n是线段数。
    1. 运行时为O(m log m),其中m为POI数,m为O(n + k)
    1. 和7.应该一起分析。在最坏的情况下,每个三角形都需要O(n)计算以检查矩形中的包含性。假设有O(m)个三角形,这将产生O(nm)界。但是,三角剖分的目的是将多边形计算中的点重新用于播种三角形,以标记尽可能多的相邻三角形。实际上,在多边形计算中需要一个点的三角形数量应该可以忽略不计。因此,此步骤的运行时间为O(tn),其中t是为其执行多边形计算中的点的链齿的数量。

因此,期望的运行时间为O((n + k)log n + t(n + k)),其中k是步骤2中的交点数,t是多边形计算中该点的三角形数执行。在最坏的情况下,这是O(n ^ 2 log n),因为您可以创建具有n ^ 2个交集的病理示例,但是如果不可能的话,这应该不太可能。同样,应将数量t保持最小,以使其尽可能有效。如果t << n和k << n ^ 2都非常有效。

一种可以提高性能的近似值:

  • 考虑通过一组r线段来近似圆,并在步骤1-5中包括这些线段。尽管这是一个近似值,但它可能会改善运行时间,因为只需要考虑圆内的三角形即可。