有一架飞机,上面有许多不同的物体。如果这很重要,那就让有不同半径的圆或正方形——这并不重要。就说圆圈吧。
对于任意点的任务是快速确定哪个邻域未被占用。也就是说,对于圆,我们只需查看从中心到该点的距离减去圆的半径,然后寻找最小值。
但圈子多,时间少。解决这个问题最简单的方法是什么?我研究了四叉树、R 树。但要么我不太理解他们的想法,要么他们适合找点,但不适合找圆。对于点 - 如果四叉树中最近的点位于相邻象限 - 这对我们有什么帮助?不管怎样,事实证明几乎整棵树都需要重新考虑?
告诉我在这种情况下应该使用什么算法?检查尽可能少的不同圆圈?
首先,我们可以假设这些圆不相交(如果有帮助的话)。但一般来说,这不是事实。
理论
构建搜索树
对于沿轴定向的圆和正方形,我们将学习确定从正方形中的点到圆的最短距离:d min。如果它们相交,我们就将该距离视为零。我们还将确定从正方形点到圆的最大距离:d max。如果正方形完全在圆内,我们将其设置为零。
让我们有一个正方形和一组圆形。对于所有圆,我们选择最大距离中的最小值:h = min{d max }。我们将条件d min ≤ h的圆的索引写为正方形。如果该点落在一个正方形中,您将只需要计算到这组圆的距离,其余的距离正好更远。
让我们用一个正方形覆盖我们想要寻找最近的圆的区域。让我们计算一下合适的圆圈列表。如果列表太长,请将正方形分成四个较小的正方形,然后递归地重复构建列表。如果圆列表不长于某个阈值,则递归停止。递归的深度也必须受到限制。
本土化
点的定位是这样完成的:该点相对于正方形进行定位,然后选择它的四分之一,依此类推,直到我们到达纸张。让我们计算工作表中圆列表中的点到圆的最小距离。
定位时间包括通过正方形下降(不超过最大递归深度)并计算列表到圆的距离(通常不超过列表长度的阈值)。
该方法不限于圆圈。如果您知道如何构造从正方形到图形的最小和最大距离,则该图形可以参与定位。
缺陷
如果平面上存在最大空圆同时接触k 个障碍物的点,则正方形中的列表将至少为k长。换句话说,如果 Voronoi 图包含高度顶点,定位会浪费大量内存并且速度很慢。如果我们准确地解决这个问题,那么这个弊端是无法避免的。如果可以以一定的精度返回答案,则可以将列表缩小到所需的大小。
实际上,除非您以特殊方式设计场景,否则十个圆圈聚集在一个公共点周围的可能性微乎其微。此外,你有一切手段在构建搜索树的阶段检测问题,并以另一种方式解决在一个不好的、非常小的方格中的定位问题,当然,如果你想出这样的方法的话。
例子
红色圆圈是障碍物。黑色圆圈跟随鼠标光标并显示给定点的最大半径。黑圈里面有两个数字:树中某个节点的深度和该节点中障碍盘的数量。运行代码并将鼠标光标移到图片上。在一百个随机障碍物的示例中,对于任何光标位置,计算到最多五个障碍物的距离。
图片
为了绘制加权 Voronoi 图,列表长度的阈值设置为 1。然后,仅当正方形位于一个圆的 Voronoi 单元内部时,递归才会停止。在图的边缘附近,除法继续直至递归深度的极限。小灰色方块沿着图的边缘和顶点聚集,并且变得可见。
不同半径的圆之间的细胞边界是弯曲的——这些是双曲线的片段。