将一系列值隔开,使它们不重叠

时间:2011-04-27 11:59:24

标签: php algorithm graph logic pie-chart

有很多问题与这个话题非常接近,但没有一个真正帮助过我。

我一直在编写图形库,我需要一种算法来垂直放置标签而不重叠。我已经坚持了几天,并设法将其提炼到最基本的功能:

如果沿着Y轴给出一系列标签位置,比如1 1 2 3 5 6 9,分别是上限和下限100,我需要一种方法来分隔要输出的值1 2 3 4 5 6 9

333467234567加权,以接近原始坐标。

这也应该倒退,如果价值在规模的上端聚集,它们应该尽可能地分散(在溢出之前)

我不是在寻找明确的答案,但我想在如何解决这个问题上提供一些帮助。我完全卡住了。

最后的思路是扫描所有标签以查找可能的碰撞,并将它们定位为一个大块,与所有Y坐标的中心对齐。但如果存在多组碰撞,这将无效。

编辑:要将此算法放在更大的上下文中,请查看这两个谷歌图表API饼图:

1)Top stacked labels

2)Bottom Stacked Labels

标签几乎是弹性的,它们通过连接在一起并将整个质量移动到质量中心来避免碰撞。

2 个答案:

答案 0 :(得分:0)

通过插入有序集使标签集唯一。将y轴上限和下限之间的差除以集合中的元素数。这是你的间距增量。按顺序迭代集合并在每个间距增量处定位一个标签。

您没有说需要保留比例......

答案 1 :(得分:0)

嗯,经过其他来源的一些思考和建议后,我想出了一个解决方案:

伪代码:

foreach labels as label
    if label->collidesWith(labels->lowerLimit)
        label->moveAwayFrom(labels->lowerLimit)

    if label->collidesWith(labels->upperLimit)
        label->moveAwayFrom(labels->upperLimit)

    if label->collidesWith(label->previous)
        label->moveAwayFrom(label->previous)
        label->previous->moveAwayFrom(label)

    if label->collidesWith(label->next)
        label->moveAwayFrom(label->next)
        label->next->moveAwayFrom(label)
endforeach

MoveAwayFrom一次移动1个像素。当多次运行此函数时,它会重新标记标签,直到它们都没有碰撞。 (实际上我称这个循环100次,还没有找到一种方法来更加智能地进行)