【问题标题】:How to horizontally distribute rectangles with different sizes?如何水平分布不同大小的矩形?
【发布时间】:2016-07-29 08:16:38
【问题描述】:

我有一组不同大小的矩形:

所有矩形都被限制在 Y 方向,即 Y 坐标是固定的,它们只能沿 X 轴移动。 现在,我想以相等的分布间距水平排列所有这些矩形,但其中一些(图中的灰色矩形)受左右邻居(红色矩形)的约束,也受下面的矩形和上面也是。

编辑: 矩形的初始位置按行顺序定义。 此外,在我的第一次实现尝试中,我还在每一行中存储了垂直矩形的存在,它与两行或多行重叠,如下所示:

Row 1: {id:1,w:15,h:10},{id:2,w:10,h:40},{id:3,w:10,h:40},{id:4,w:20,h:10}
Row 2: {id:2,w:10,h:40},{id:5,w:10,h:40},{id:3,w:10,h:40},{id:6,w:10,h:10},{id:7,w:10,h:10}
Row 3: {id:8,w:10,h:10},{id:9,w:18,h:10},{id:5,w:10,h:40},{id:10,w:10,h:10}

我正在寻找一种算法来水平分布所有这些矩形,以便每个矩形的左右间距相同,如图所示。

编辑 2: 任何提示如何处理更高的复杂性,也将不胜感激:

【问题讨论】:

  • 矩形集合的初始状态是什么?一些矩形在初始状态下可以重叠吗?
  • @sarasvati:请看我的编辑 - 没有一个矩形可以重叠。
  • 如果我正确理解您的问题,我觉得您需要实现layout constraint solverGrid Style Sheets 可能值得一看。
  • 通常会有多少个矩形?

标签: javascript algorithm geometry


【解决方案1】:

使用最左边的坐标从左到右对矩形进行排序,如下图所示:

然后,从左到右遍历每个矩形,并查看它们与左侧的哪些矩形垂直重叠(即,如果将它们向左移动,它们会碰到哪些矩形)。

A 和 B 到达左侧窗口边缘,而不会碰到任何其他矩形。
C撞到A。
D撞到B。
E 撞到 A、C 和 D。
F 撞到 B、D 和 E。
G 撞到 D、E 和 F。
H 撞到 A、C 和 E。
我撞到了 B、D 和 F。
J 撞到 D、E、F 和 G。

使用此信息构建如下图所示。当一个矩形撞到其他几个矩形时,例如E 撞到 A、C 和 D,这些矩形本身就是同一分支的一部分,例如A和C,然后只连接到最右边的矩形,即矩形C。

然后,将每个矩形的宽度(以像素为单位)存储在图形中。然后我们将尝试找到边的权重 X,它表示矩形之间的空间宽度。

要做到这一点,我们需要在图中找到许多路径。首先,我们搜索最长的路径,即矩形最多的路径,而不考虑它们的宽度;在示例中是:

左窗口边缘 → A → C → E → F → G → J
左窗口边缘 → B → D → E → F → G → J

然后我们检查哪些路径的组合宽度最大:

左窗口边缘 → A → C → E → F → G → J = 240

然后我们看看更短的路径,看看它们是否有更大的宽度:

左窗口边缘 → A → C → E → F → I = 230
左窗口边缘 → B → D → E → F → I = 220
左窗口边缘 → A → C → E → H = 168
左窗口边缘 → B → D → E → H = 158

在示例中,较短的路径都没有较大的宽度。如果他们中的一些人这样做,我们也必须考虑每个长度的最宽路径。事实上,我们只需要查看路径:

左窗口边缘 → A → C → E → F → G → J = 240

将此路径连接到右侧窗口边缘,使其具有额外的边缘;现在有 7 个宽度为 X 的边。矩形的组合宽度为 240 像素,所以如果窗口是例如450 像素宽,然后 X = (450 - 240) / 7 = 30 像素。 如果要考虑多条路径,您将采用 X 的最小结果。

路径中 X 的最小结果的矩形之间将有正好 X 个像素的空间;其他矩形有一些回旋余地。您可以输入 X 作为图中最长路径中边的权重,然后使用该图进一步计算其他矩形的等间距。或者你可以把它们放在离它们的左邻或右邻距离 X 的地方。


对于更复杂的情况,假设在示例中矩形 I 的宽度为 90 像素,矩形 H 的宽度为 120 像素。这些是路径:

6 个矩形:
左窗口边缘 → A → C → E → F → G → J = 240
左窗边 → B → D → E → F → G → J = 230

5 个矩形:
左窗口边缘 → A → C → E → F → I = 254
左窗口边缘 → B → D → E → F → I = 244

4 个矩形:
左窗口边缘 → A → C → E → H = 250
左窗口边缘 → B → D → E → H = 240

那么要考虑的路径是:

左窗口边缘 → A → C → E → F → G → J = 240

因为它是具有最多 (6) 个矩形的路径中最宽的,并且:

左窗口边缘 → A → C → E → F → I = 254

因为它是 5 个矩形的路径中最宽的,并且比 6 个矩形的路径更宽。

(最宽的4-矩形路径比6-矩形路径宽,但不比5-矩形路径宽,所以可以忽略。)

这给出了条件:

240 + 7 × X = W
254 + 6 × X = W

所以对于窗口宽度 290,这将给出:

240 + 7 × X = 290 → X = 7
254 + 6 × X = 290 → X = 6

所以路径 A → C → E → F → I 确定了空间的宽度,为 6 个像素。

但是对于宽度为 390 的窗口,这将给出:

240 + 7 × X = 390 → X = 21
254 + 6 × X = 390 → X = 22

所以现在路径 A → C → E → F → G → J 确定了空间的宽度,为 21 像素。

【讨论】:

  • 什么是侵蚀我的大脑,是如何找到图中的所有路径...
  • @deblocker 在图中寻找路径是一个被大量研究的主题;您会在 SO 上找到数以千计的问题和答案。
  • @deblocker 好吧,可以进行一些简化,例如在示例中,所有路径都经过 E,因此您可以独立处理图形的左右部分。
  • 我必须承认,你的解释是我在网上搜索能找到的最好和更详细的解释。
  • @deblocker 实际上,第二个例子并不比第一个复杂,因为它由三个独立的区域组成:上半部分(原始示例),中间的小块行,和下半部分。只要您可以从左窗口边缘到右窗口边缘绘制一条水平线,而不触及任何矩形,这会将矩形划分为可以独立解决的单独问题。
猜你喜欢
  • 2020-09-19
  • 2013-02-09
  • 1970-01-01
  • 1970-01-01
  • 2013-01-21
  • 2022-01-18
  • 1970-01-01
  • 2020-06-15
  • 1970-01-01
相关资源
最近更新 更多