【发布时间】:2011-05-04 08:22:44
【问题描述】:
我正在寻找解决这个问题的算法:
给定笛卡尔坐标上的 N 个矩形,找出这些矩形的交点是否为空。每个矩形可以位于任何方向(不必使其边缘平行于 Ox 和 Oy)
您对解决这个问题有什么建议吗? :) 我可以考虑测试每个矩形对的交集。但是,它是 O(N*N) 并且非常慢:(
【问题讨论】:
标签: algorithm geometry computational-geometry
我正在寻找解决这个问题的算法:
给定笛卡尔坐标上的 N 个矩形,找出这些矩形的交点是否为空。每个矩形可以位于任何方向(不必使其边缘平行于 Ox 和 Oy)
您对解决这个问题有什么建议吗? :) 我可以考虑测试每个矩形对的交集。但是,它是 O(N*N) 并且非常慢:(
【问题讨论】:
标签: algorithm geometry computational-geometry
要么根据矩形的最小 X 值使用排序算法,要么将矩形存储在 R-tree 中并搜索它。
让我们表示low_x() - 矩形的最小(最左侧)X 值,high_x() - 矩形的最高(最右侧)X 值。
算法:
Sort the rectangles according to low_x(). # O(n log n)
For each rectangle in sorted array: # O(n)
Finds its highest X point. # O(1)
Compare it with all rectangles whose low_x() is smaller # O(log n)
than this.high(x)
这应该适用于均匀分布的矩形上的O(n log n)。
最坏的情况是O(n^2),例如当矩形不重叠但一个在另一个之上时。在这种情况下,将算法推广到也有low_y() 和high_y()。
R-trees(B-trees 的空间泛化)是存储地理空间数据的最佳方式之一,可用于解决此问题。只需将矩形存储在 R-tree 中,您就可以通过简单的O(n log n) 复杂性发现交叉点。 (n 搜索,log n 每个时间)。
【讨论】:
{ [k, 2n-k]×[0, 1] | k ∈ {0, ..., n-1} }
O(n log n)。
{ [k, 2n-k]×[k, 2n-k] | k ∈ {0, ..., n-1} } — 随心所欲地排序,使用 R-tree... 它仍然是 O(n^2)。
观察 1:给定一个多边形 A 和一个矩形 B,交点 A ∩ B 可以通过与 B 的每条边对应的半平面的 4 个交点来计算。
观察 2:从凸多边形切割半平面会得到一个凸多边形。第一个矩形是凸多边形。这个操作最多每增加1个顶点数。
观察 3:凸多边形的顶点到直线的有符号距离是单峰函数。
这是算法的草图:
在平衡二叉树中按逆时针顺序维护当前部分交集D。
当切割由直线 L 定义的半平面时,找到 D 中与 L 相交的两条边。这可以通过一些巧妙的二元或三元搜索在对数时间内完成,该搜索利用到 L 的有符号距离的单峰性。(这是我不太记得的部分。)从D中删除L一侧的所有顶点,并将交点插入D。
对所有矩形的所有边 L 重复。
【讨论】:
这似乎是克利测量的一个很好的应用。基本上,如果您阅读http://en.wikipedia.org/wiki/Klee%27s_measure_problem,则可以在 O(n log n) 处找到直线交叉点的最佳算法的运行时间下限。
【讨论】:
我认为你应该使用sweep line algorithm 之类的东西:寻找交叉点是它的应用之一。另外,看看answers to this questions
【讨论】:
由于矩形不能平行于轴,将问题转换为已经解决的问题更容易:计算矩形的边界的交点 .
扫描线在 S 中的每个 x 坐标处停止,即所有起始值和所有结束值。对于每一个新的起始坐标,将对应的线放入一个临时集合 I。对于每个新的结束坐标,从 I 中删除对应的线。
除了向 I 添加新线之外,您还可以检查每条新线是否与当前 I 中的一条线相交。如果相交,相应的矩形也会相交。
你可以找到这个算法的详细解释here。
运行时间为O(n*log(n) + c*log(n)),其中c是I中线的交点数。
【讨论】:
从集合中选择最小的矩形(或任何矩形),然后遍历其中的每个点。如果其中一个点也存在于所有其他矩形中,则交点不为空。如果所有点都没有 ALL 其他矩形,则交点为空。
【讨论】: