我想自动放置100-200个气泡标签,以满足以下要求:
这有什么有用的库/算法吗? (最好是JavaScript或PHP)
(图片中的标签位置不符合这些要求)
答案 0 :(得分:9)
答案 1 :(得分:5)
我想你正在使用javascript,html和css?无论如何,我想到了两种方法。
首先是将其表述为优化问题。您需要为每个标签计算理想位置。这将基于气泡的大小,所需的位置(即顶部,底部,左侧,右侧)和标签的大小(字体和长度)。然后,您需要参数化您的坐标,例如2N元素的列表,其中N是标签的数量。然后,您需要在某个位置(或使用遗传算法的群体)初始化标签,并应用需要成本函数的优化算法。这将基于一组标签位置与理想位置的距离,以及违反规则的任何内容,例如重叠。
或者,使它成为一个物理问题。使用一些刚性链接将每个标签“附加”到其气泡上。为每个标签和每个气泡赋予一个排斥力,并增加一个全局和更强的重力(在首选的上/左/右/下方向)。进行短暂的物理模拟直到达到平衡。数学不应该太难。
答案 2 :(得分:5)
我认为如果您在工具中使用D3,则可以使用“基于强制”的标签放置算法。该解决方案最初属于Max Planck Research Networks,但已经有一个现成的Javascript示例,例如:Force-based label placement in D3
答案 3 :(得分:4)
这可以表示为线性规划问题。您希望最大化或最小化函数(表示解决方案的“权重”或“优点”)受某些约束(您的要求)。您需要将您的需求正式化为值。像这样:
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中有一整章关于这些问题。
答案 4 :(得分:3)
答案 5 :(得分:1)
不幸的是,我认为在Javascript或PHP中很难找到这个解决方案。但是,我认为您的问题可以分解为小的子问题(基于您的规则),以帮助您设计解决方案。
我会确定哪些规则最重要。从您提供的图表的外观来看,我会说规则#1和#2将提供可读性方面的最大改进。
要根据这些规则确定位置,我会计算文本和气泡的边界容器并测试交集。交叉时,移动到没有交叉点的位置。如果找不到,请使用最小重叠的空间。
这样您还可以为左上角,右下角等创建加权放置启发式,以帮助将标签放置在“首选”位置。
我尝试使用两个带有两个标签的气泡写出一小块放置算法,这两个标签通常很接近并且可能会重叠。如果您可以推广您的放置算法以适用于这个小子集,那么您应该更好地向前推进更多气泡。
此外,也许您可以使用kd-tree或其他空间分区数据结构的顺序来定位要避免的最近邻居。
答案 6 :(得分:1)
我在Java中找到了一种实际上可以解决这个问题的方法,它被称为强制定向地图标记,是一种开源的学术体验。
以下是文档+项目源代码:Force Directed Map Labeling
答案 7 :(得分:0)
怎么样
label.substring(0,Math.sqrt(bubbleValueOrRadius))
我在protovis.js的一个例子中找到了这个。
答案 8 :(得分:0)
This thread非常善于介绍一些方法。我正在使用具有多个焦点的力布局,因为它似乎是最好的整体方法。