无重叠的高效随机矩形放置

Posted

技术标签:

【中文标题】无重叠的高效随机矩形放置【英文标题】:Efficient random rectangle placement with no overlaps 【发布时间】:2022-01-03 16:50:41 【问题描述】:

我编写了一个算法来随机放置 X=1,000 个没有任何重叠的矩形。矩形具有大约 5 到 50 之间的随机宽度和高度,以及大约 0 到 1000 之间的随机 x 和 y。这是我现有的算法:

    获取随机候选矩形

    遍历所有已放置的现有矩形并检查以确保候选不与其中任何一个重叠(第一次重叠时循环中断)

    如果 2 中有重叠,则丢弃候选并且不增加计数,如果没有重叠,则绘制候选矩形并增加计数(使其达到 X)

我对两个矩形的重叠检查是这个 javascript

const noOverlap = testRect.rbp.y < candidateRect.ltp.y ||
    candidateRect.rbp.y < testRect.ltp.y ||
    testRect.ltp.x > candidateRect.rbp.x ||
    candidateRect.ltp.x > testRect.rbp.x

rbp 是矩形的右下点,ltp 是左上点。

当计数接近 X 时,可以连续丢弃 30,000 个。因此,我进行了优化,以在连续有一堆丢弃物时减小矩形大小。

我可以做得更好吗?

【问题讨论】:

【参考方案1】:

我会尝试一种分层方法来生成一个大小为 1000x1000 的矩形的数组,其中第一个元素必须适合。

// +----------+   ->  +----+-----+
// |          |       |   A|     |
// | +--+     |       +-+--+     |  
// | |N |     |       |B|  |D    |
// | +--+     |       | +--+-----+
// |          |       | |C       |
// +----------+       +-+--+-----+

在找到候选N适合画布后,矩形被分割成四个较小的矩形A,B,C,D。

要插入的下一个矩形必须适合 A、B、C、D 或 AB、BC、CD 或 DA 的并集。这是通过递归到单个节点或递归到两个节点并且发现没有冲突来确保的。

在没有发现碰撞后,不幸的是需要再次递归并标记所使用的区域——这不能在第一次通过时完成,因为在最坏的情况下,候选可能适合 128 个矩形中的 120 个,但是并非全部 - 使用 fifo 将递归转换为迭代将允许提前退出。

如果不需要完美的随机性,可以通过简单地随机选择区域 A、B、C、D 之一并跟随树到叶子并在其中不加选择地插入新矩形来应用相同的技术。在这种情况下,还应该如何将每个矩形拆分为更小的矩形,因为可能会出现意想不到的结构(矩形集中或缺失的线条)。

【讨论】:

这是一个新颖的想法,但我认为您不会满足矩形具有随机大小或位置的要求,因为更多矩形的放置会减小可接受邻居的大小/位置其他区域。考虑在 20、20 处放置一个很小的矩形左下角(0,0 在网格的左下角)。您现在已经为大矩形沿着底部和左侧轴创建了一个人工“边界”,并且还放置了一个禁止放置区域,以防止矩形跨越线。它看起来非常“区域化” 最后一段就是这种情况;我没有证据,但应该能够放置一个新的矩形,它跨越 AB、BC、CD 或 DA 的边界。发生这种情况时,矩形会进一步分为 3 或 2 个区域(或其他区域的面积为零),并且它们永远不会通过放置测试。这有不保证插入的问题。如果不调整参数,每次迭代的失败率接近 25%。

以上是关于无重叠的高效随机矩形放置的主要内容,如果未能解决你的问题,请参考以下文章

在 Flutter 中使用设置的 FPS 绘制大量简单、填充颜色的矩形的最高效方法是啥?

Leetcode练习(Python):数组类:第57题:给出一个无重叠的 ,按照区间起始端点排序的区间列表。 在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合

动态规划之----我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

查找包含点的矩形 - 高效算法

从线上找到矩形的高效算法?

脏矩形(高效绘图 13.3)