避免线的交叉

时间:2016-02-25 09:44:01

标签: algorithm geometry

我的时间线应该出现与其原始日期相关的约会(见下文)。此问题的问题是将图标放在正确的位置,以便连接线不会交叉。

所以我到目前为止:

initial positioning

为了轻松操作我已经实现了区域,时间线被划分为区域,我将所有图标放在此区域中。这是越过的行的问题。

grid pattern

理想解决方案就是这个,随机分散线条不会交叉的图标:

ideal

我想过制作“网格图案”,定义图标可以放置的位置,而不是逻辑哪一个连接到哪个点。(例如,区域中最多12-15个点,它们都可以在同一个日期也是如此)我在项目实施之前已经在JSFiddle实现了我的但是它并不保证我想要的结果,也不是优化

//See the demo on JSFiddle

所以请你,也许你有一些想法如何达到我想要的结果(见上文)。

2 个答案:

答案 0 :(得分:4)

如果您只是需要不交叉的线条,您可以将图标放在任何位置,进行初始分配然后,只要可以交换一对图标以使这些线条的总长度减少,去做。正确性的证明非常简单。假设我们有一对交叉任务

A   B
 \ /
  X
 / \
Y   Z

其中X是交叉点。假设AXYBXZ是非简并三角形,则它来自三角形不等式

d(A, Y) + d(B, Z) < d(A, X) + d(X, Y) + d(B, X) + d(X, Z)
                  = d(A, X) + d(X, Z) + d(B, X) + d(X, Y)
                  = d(A, Z) + d(B, Y),

所以我们会这样重新分配。

A   B
|   |
|   |
|   |
Y   Z

保证收敛,因为总长度总是在减少。

您可能还希望线条不要靠近,在这种情况下,我建议您研究力导向布局算法。

答案 1 :(得分:3)

要确保线条不交叉,请将时间线上的点连接到约会图标,如下所示:

  • 将图标放在顶部的初步位置(如网格)
  • 从左到右浏览时间轴点
  • 计算从点到每个未连接图标的方向
  • 将点连接到最左侧的图标

从时间轴点到图标的方向可以使用Math.atan2(dy,dx)函数在JavaScript中计算,其中dy是y icon - y point 和dx是x icon - x point 。对于向左移动的线,结果大于π/ 2,对于垂直线,结果大于π/ 2,小于π/ 2;对于向右走的线。

app lay-out example

完成此操作后,您可以沿着连接线向下移动一些图标,以创建更加视觉上令人愉悦的分布。这可以在没有创建交叉线的风险的情况下完成。

如果要水平移动图标,请检查其相邻线条的方向,以确保不会太靠近其他线条。

更新:

我认为从左到中,然后从右到中工作可能是有益的,以获得更加对称的分布;否则最右边的点会连接到底行的图标,这是不理想的。

您需要尝试沿着连接线向下拖动图标。从底行开始向上,您可以根据时间轴点与其邻居的距离,相邻线是否收敛,连接线的垂直距离,拖动首先是中心或侧面的图标......您必须检查哪些选项可以获得最佳效果。