【问题标题】:Bubble chart label placement algorithm? (preferably in JavaScript)气泡图标签放置算法? (最好在 JavaScript 中)
【发布时间】:2011-08-15 13:50:52
【问题描述】:

我想自动放置 100-200 个气泡标签,以便满足以下要求:

  • 标签不应重叠
  • 标签最好不要与气泡重叠
  • 标签应靠近气泡
  • 应在一定程度上尊重首选标签位置(左上、上、下、右等)
  • 字体大小可能不同

是否有任何有用的库/算法对此? (最好是 JavaScript 或 PHP)

(图片中的标签放置不符合这些要求)

【问题讨论】:

标签: javascript algorithm visualization labels placement


【解决方案1】:

【讨论】:

  • 感谢优秀论文的链接。我进行了通读,但可能很难使算法适应 JavaScript 和上面列出的标准。如果您有更多“适用”资源要分享,我们将不胜感激。
  • @dani 我同意这个算法在 JavaScript 中不容易实现。但这表明问题有多难。该算法允许将标签放置在距气泡一定距离的位置,只要可以绘制连接线而不会相交。如果您不允许这样做,问题就会再次变得容易。
  • 仅供参考:该算法目前在 C++ 中实现,并在所有可用内核的后台运行。我们的客户发现,结果非常好,比手动标记的图表要好。
【解决方案2】:

This thread 很好地涵盖了一些方法。我正在使用具有多个焦点的力布局,因为它似乎是最好的整体方法。

【讨论】:

    【解决方案3】:

    我在 Java 中找到了一种实际上可以解决这个问题的方法,它被称为 Force Directed Map Labeling,是一种开源学院体验。

    这里是文档+项目源码:Force Directed Map Labeling

    【讨论】:

      【解决方案4】:

      我认为,如果您在工具中使用 D3,则可以使用“基于力”的标签放置算法。解决方案原本属于Max Planck Research Networks但是已经有现成的Javascript例子,这里:Force-based label placement in D3

      【讨论】:

        【解决方案5】:

        怎么样

        label.substring(0, Math.sqrt(bubbleValueOrRadius))

        我在一个 protovis.js 示例中发现了这一点。

        【讨论】:

          【解决方案6】:

          也许可以使用一些帮助工具包,如下所示:

          【讨论】:

            【解决方案7】:

            我想您正在使用 javascript、html 和 css?无论如何,我想到了两种方法。

            首先是将其表述为一个优化问题。您需要计算每个标签的理想位置。这将基于气泡的大小、所需的位置(即上、下、左、右)和标签的大小(字体和长度)。然后你需要参数化你的坐标,例如到一个包含 2N 个元素的列表中,其中 N 是标签的数量。然后,您需要在某个位置初始化标签(或者如果使用遗传算法,则初始化种群)并应用需要成本函数的优化算法。这将基于一组标签位置与理想位置的距离,以及任何违反规则的情况,例如重叠。

            或者,让它成为一个物理问题。通过一些刚性链接将每个标签“附加”到其气泡上。给每个标签和每个气泡一个排斥力,并添加一个全局和更强的重力(在首选的上/左/右/下方向)。进行简短的物理模拟,直到达到平衡。数学应该不会太难。

            【讨论】:

              【解决方案8】:

              这可以表述为线性规划问题。您希望在某些约束(您的要求)下最大化或最小化函数(代表解决方案的“权重”或“优度”)。您需要将您的要求形式化为值。像这样的:

              Variables:
              x1 = 1 if Labels overlap, 0 otherwise
              x2 = some measure of "how much" a label overlaps a bubble
              x3 = distance from label to bubble //Label should be close to bubble
              x4 = distance between ideal and actual label position
              x5 = difference between actual and ideal font size
              
              
              minimize x1 + 10*x2 + x3 + 20*x4 + 5*x5
              
              subject to constraints:
                  x1   = 0  // labels can never overlap
                  x2   < /* maximum amount a label is allowed to overlap a bubble */
                  ...
                  x5   < 6 // font size does not vary by more than +/- 6 pts.
              

              我制定了系数和约束条件,您可以使用它们根据对您最重要的特征来调整结果。系数增加了需求的价值(在这种情况下,f4 的权重最大,因此它“最重要”。约束是不能违反的硬限制。

              由于这是一个众所周知的问题,您现在可以使用多种方法来解决它。 Simplex 算法很流行。关于这些问题,Cormen et. al 有一整章。

              【讨论】:

              • 分配权重似乎很合理。然而,我想知道如何在 JavaScript 中实现所描述的单纯形算法。谢谢。
              • 投反对票,因为该问题不能被表述为线性规划问题。您的约束 x1 不是线性的,它是二元的,使这成为一个决策问题。这些很难。如果你写下交集/非交集的方程,你会注意到,约束不是线性的。
              【解决方案9】:

              不幸的是,我认为很难在 Javascript 或 PHP 中找到这个现成的解决方案。但是,我确实认为您的问题可以分解为小的子问题(根据您的规则),以帮助您设计解决方案。

              我会确定您的哪些规则最重要。从您提供的图表的外观来看,我会说规则 #1 和 #2 将最大程度地提高可读性。

              为了根据这些规则确定位置,我将计算文本和气泡的边界容器并测试相交。交叉路口后,移动到没有交叉路口的位置。如果找不到,请使用重叠最少的空间。

              这还允许您为左上角、右下角等创建加权放置启发式方法,以帮助将标签放置在“首选”位置。

              我会尝试使用两个带有两个标签的气泡写出一小部分放置算法,这两个标签通常很接近并且可能会重叠。如果您可以概括您的放置算法以适用于这个小子集,那么您应该可以继续使用更多的气泡。

              另外,也许您可​​以使用类似于 kd-tree 或其他空间分区数据结构的东西来定位最近的邻居以避免。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-04-23
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多