Пробел ряд значений, чтобы они не перекрывались - PullRequest
1 голос
/ 27 апреля 2011

Было несколько вопросов, очень близких к этой теме, но ни один из них не помог мне.

Я программировал библиотеку графиков, и мне нужен алгоритм для вертикального размещения меток без наложения.Я застрял на этом пару дней, и мне удалось преобразовать его в самую основную функцию:

Если дать серию позиций меток вдоль оси Y, скажем, 1 1 2 3 5 6 9, иверхний и нижний пределы 10 и 0 соответственно, мне нужен способ разметки значений для вывода 1 2 3 4 5 6 9

333467 должен быть 234567 взвешенным, чтобы быть близким к оригиналукоординаты.

Это также должно работать в обратном направлении, если значения сгруппированы в верхнем конце шкалы, они должны быть распределены как можно больше (перед переполнением)

Я не смотрюдля окончательного ответа, но я хотел бы получить некоторую помощь о том, как подойти к этой проблеме.Я полностью застрял.

Последним ходом мысли было сканирование всех меток на предмет возможных столкновений и позиционирование их как одного большого блока, выравнивая по центру всех координат Y.Но это не будет работать, если есть несколько наборов коллизий.

РЕДАКТИРОВАТЬ: Чтобы поместить этот алгоритм в более широкий контекст, взгляните на эти две круговые диаграммы API Google Chart:

1) Этикетки с верхним расположением

2) Этикетки с нижним расположением

Эти этикетки почти упругие, они избегают столкновений, объединяясь и перемещая всю свою массу вцентр их массы.

Ответы [ 2 ]

0 голосов
/ 02 мая 2011

Ну, после некоторых размышлений и советов из других источников я нашел решение:

псевдокод:

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 раз, не придумав способ сделать это более разумно)

0 голосов
/ 27 апреля 2011

Сделайте набор меток уникальным, вставив их в упорядоченный набор. Разделите разницу между верхней и нижней границей оси Y на количество элементов в наборе. Это ваш шаг приращения. Выполните итерацию по набору по порядку и размещайте одну метку с каждым шагом.

Вы ничего не сказали о необходимости сохранения масштаба ...

...