【问题标题】:Find out if point is inside one of N (possibly overlapping) rectangles in less than O(N)找出点是否在小于 O(N) 的 N 个(可能重叠)矩形之一内
【发布时间】:2013-05-16 09:37:43
【问题描述】:

我有一张图片,我想在鼠标移过某些矩形区域时显示工具提示。矩形区域最大可达 1000 个。但是,仅检查每个矩形是否有点在其中,即 O(N),会导致界面在移动鼠标时无响应。

有没有办法在少于 O(N) 的时间内做到这一点?我可以事先对矩形进行排序(我假设它是需要的)。矩形可能(很少)重叠,但不超过 4-5 个矩形可以重叠同一区域。在这种情况下,我可能需要获取所有矩形的列表,但即使只是其中任何一个也足够了。

但我假设这个问题已经被窗口管理器等解决了。

【问题讨论】:

  • 虽然这是一个算法问题,但所涉及的界面/上下文可以帮助提供更好的建议 - 例如。与 C++ 绘图应用程序相比,网页/Javascript 环境解决方案会有所不同
  • @ring0 很公平,我正在使用 C++ 和 Qt,我正在可视化 OCR 的输出,即边界框 + 识别符号 + 其他数据。
  • 感谢您的信息。我不太了解Qt,但是正如您所建议的,它可能会根据它们的“深度”和位置来处理窗口(小部件)-因此至少应该可以立即获得“顶部”矩形“下方”鼠标(就像通过核心算法的浏览器一样)and this 似乎是一个提示。至于获取 all rects 的列表(即从所有深度),这需要更多的研究。

标签: c++ algorithm


【解决方案1】:

听起来您想将矩形存储在R-Tree 中,然后对其进行查询。有几个可用的实现:

查看他们的 STRtree 类。

【讨论】:

    【解决方案2】:

    一种比图像树(以及可以渲染到相当小的图像上的网页)更快、更简单(尽管内存效率更低)的方法是使用模板。即,如果您有一个 x x y 像素的图像,请创建一个 x x y 大小的二维数组,并使用您的工具提示 ID 填充它。从像素位置到 ID 的搜索速度为 O(1)(我最喜欢的 O)

    【讨论】:

    • 这是一个很好的解决方案 :) 实际上这是我在遇到问题后立即做的,但感觉更像是一种解决方法而不是解决方案,这就是为什么我想知道是否有更优雅的解决方案。
    【解决方案3】:

    如果矩形是轴对齐的,则可以避免专门的数据结构。

    首先将空间细分一维,例如将屏幕水平细分为垂直条。每个矩形可以是多个条带。然后根据与该条重叠的矩形细分每个条。然后搜索涉及两个 O(log n) 二进制搜索或二叉树 - 一个用于识别条带,一个用于识别哪个矩形。

    一种公认的空间数据结构,但对我来说它并不算数 - 它只是使用普通的二叉树。您甚至可以使用 std::map<int, std::map<int, int>> 来完成。

    但实际上有一个选项支持 O(1) 搜索,称为“像素拾取”。基本上,在屏幕外的位图中绘制矩形,每个矩形使用不同的颜色,最前面的矩形最后是正常绘图(画家算法)。您可以通过简单地读取该像素来识别哪个矩形在任何点最前面。

    额外的好处 - 你的显卡甚至可以加速绘制矩形,所以当矩形集发生变化时你不需要太担心重绘(这显然不包括在那个 O(1) 中)。它的内存有点贵,但在现代机器上,你可能不在乎。

    【讨论】:

      【解决方案4】:

      使用空间搜索数据结构,例如the quad-tree

      您需要事先将矩形添加到树中,但平均搜索速度会很快。在最坏的情况下,你可能仍然有 O(N)。

      【讨论】:

      • 任何链接都可以提供有关四叉树的有趣和直观的信息以及它如何在这个问题/上下文中提供帮助?
      • @ring0:通常的嫌疑人,维基百科。
      • 谢谢。有些人在他们的解决方案中包含链接,让懒惰的其他人(比如我)只需点击而不是搜索。
      • @ring0:我通常会包含链接,除非我在手机上打字(我也很懒)。
      猜你喜欢
      • 2016-08-04
      • 2020-07-03
      • 1970-01-01
      • 1970-01-01
      • 2013-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多