在小于0 (N)的时间内找出点是否在N个(可能重叠)矩形中的一个内

Find out if point is inside one of N (possibly overlapping) rectangles in less than O(N)

本文关键字:一个 重叠 出点 小于 时间 是否      更新时间:2023-10-16

我有一个图像,我想在鼠标移动到特定矩形区域时显示工具提示。矩形面积可达1000。但是,如果只是检查每个矩形中是否有点,即0 (N),则会导致移动鼠标时界面无响应。

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

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

听起来您想要将矩形存储在R-Tree中,然后进行查询。这里有一些可用的实现:

  • JTS Topology Suite (Java)
  • 网络拓扑套件(.Net)
  • GeoTools (net)

查看他们的STRtree类

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

如果矩形与轴对齐,则可以避免特殊的数据结构。

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

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

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

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

使用四叉树等空间搜索数据结构

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