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

发布于 2024-11-03 18:18:46 字数 992 浏览 0 评论 0原文

有几个问题与这个主题非常接近,但没有一个真正对我有帮助。

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

如果给定沿 Y 轴的一系列标签位置,例如 1 1 2 3 5 6 9< /code>,以及上限和下限分别为 100,我需要一种方法来分隔输出值 1 2 3 4 5 6 9

333467 应采用 234567 加权以接近原始坐标。

这也应该向后工作,如果值聚集在刻度的上端,它们应该尽可能分散(在溢出之前)

我不是在寻找明确的答案,但我想要一些关于如何进行的帮助来解决这个问题。我完全卡住了。

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

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

1) 顶部堆叠标签

2) 底部堆叠标签

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

There have been a couple of questions very close to this topic, but none really helped me.

Ive been programming a graphing library, and I need an algorithm to vertically place labels without overlapping. I've been stuck on this for a couple of days now, and managed to distil it to the most basic function:

If given a series of label positions along the Y axis, say, 1 1 2 3 5 6 9, and an upper and a lower limits 10 and 0 respectively, I need a way to space out the values to output 1 2 3 4 5 6 9

333467 should be 234567 weighted to be close to the original coordinates.

This should also work backwards, if values are bunched up at the upper end of the scale, they should be spread as much as possible (before overflowing)

I'm not looking for a definitive answer, but I'd like some help on how to approach this problem. Im completely stuck.

Last train of thought was to scan all labels for possible collisions and position them as one big block, aligning to the centre of all the Y coordinates. But this will not work if there are multiple sets of collisions.

EDIT: To put this algorithm in a bigger context, have a look at these two google chart API pie charts:

1) Top stacked labels

2) Bottom Stacked Labels

The labels are almost springy, they avoid collisions by joining together and moving their entire mass to the center of their mass.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甜中书 2024-11-10 18:18:46

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

你没有说需要保留秤......

Make the set of labels unique by inserting into an ordered set. Divide the difference between the y-axis upper and lower bound by the number of elements in the set. This is your spacing increment. Iterate over the set in order and position one label every spacing increment.

You didn't say anything about needing to preserve a scale...

德意的啸 2024-11-10 18:18:46

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

伪代码:

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次,还没有找到更智能的方法)

Well, After some thought and advice from other sources i came up with a solution:

Pseudocode:

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 moves 1 pixel at a time. When this function is run multiple times it rejiggles the labels until none of them collide. (in reality im calling this loop 100 times, havent figured out a way to do it more inteligently)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文