Страница 1 из 2

Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 05.03.2012 (Пн) 18:01
jangle
Есть круговая диаграмма, в которой возможно 10-20 элементов, как раскрасить ее так, чтобы не было совпадение цветов у ближайших элементов? И они были максимально контрастными по отношению к соседям.
Сейчас распределяю цвета рандомно, что совсем неправильно, иногда цвет легенды у разных элементов совпадает. Нужен какой-то алгоритм, чтобы создаваемые цвета были максимально контрастными по отношению к соседям.

Re: Распределение окраски на круговой диаграмме

СообщениеДобавлено: 05.03.2012 (Пн) 19:28
Alec
А если задавать тон в цветовой модели HSV? Например, для 10 элементов задаем тоны 0, 0.1, 0.2 и т.д., а выводим в последовательности 0, 0.5, 0.2, 0.7 и т.д.

Re: Распределение окраски на круговой диаграмме

СообщениеДобавлено: 05.03.2012 (Пн) 20:04
alibek
20 цветов можно просто таблицей задать.

СообщениеДобавлено: 05.03.2012 (Пн) 20:07
Qwertiy
Вариант 1: Заранее подобрать цвета.
Вариант 2: Рассматривая цвет как Long брать I * (&H01000000 \ ColrorCount), где ColorCount - некоторая заранее подобранная константа. Насколько я помню, можно выбрать что-то типа типа 1023, 31, 17 (может поподбирать придётся).

Re: Распределение окраски на круговой диаграмме

СообщениеДобавлено: 05.03.2012 (Пн) 22:14
Sam777e
alibek писал(а):20 цветов можно просто таблицей задать.


+1

Re: Распределение окраски на круговой диаграмме

СообщениеДобавлено: 05.03.2012 (Пн) 22:17
jangle
alibek писал(а):20 цветов можно просто таблицей задать.


Пока 20 разделов, в последствии их может быть больше. В принципе это количество не ограниченно.

Re: Распределение окраски на круговой диаграмме

СообщениеДобавлено: 06.03.2012 (Вт) 5:53
Хакер
Берёшь любую радугу, которая достаточно плавная, и у которой один конец предельно близок к другому, например как здесь:
rainbow_wnd.png
rainbow_wnd.png (6.47 Кб) Просмотров: 15932


Берём полоску с радугой:
rainbow_bar.png
rainbow_bar.png (485 байт) Просмотров: 15932


Склеиваем края этой полоски, так, чтобы получилось кольцо:
ring_from_bar.png


Если вывернуть изначальный пример, получается что-то такое:
warped_ring_sample.png
warped_ring_sample.png (20.22 Кб) Просмотров: 15932


У такой окружности есть важное свойство: любой проведённый диаметр соединят пару точек с противоположенными цветами, а любые две равные хорды, проведённые две точки — пару точек «равноудалённых» по оттенку от заданной.

Теперь к делу: нам нужно выбрать цвета для N-секторной диаграммы. Для примера: нам нужно выбрать цвета для 5-секторной диаграммы.

Мы просто строим пятиконечную звезду внутри нашего кольца:
penta_ring.png
penta_ring.png (32.07 Кб) Просмотров: 15932


Всё, 5 цветов есть. Цвета нужно брать в направлении обхода звезды, то есть: красный→зелёный→фиолетовый→лайм→лазурный.

Способов построени N-угольников (включая самопересекающиеся) существуют целые семейства:
Изображение

Нужно брать зелёные звёзды — это т.н. связные звёзды.

Разумеется, что в реальности ничего не нужно строить: кольцо расчитывается математический, координаты точек расчитываются математически.

В итоге получение цвета — чисто по формуле.

Пример:

Re: Распределение окраски на круговой диаграмме

СообщениеДобавлено: 06.03.2012 (Вт) 8:48
alibek
jangle писал(а):Пока 20 разделов, в последствии их может быть больше. В принципе это количество не ограниченно.

Тогда по HSV-модели, как советовали в первом ответе. Только в этом уже мало смысла, цвета будут сливаться и глаз будет их путать.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 8:57
Хакер
Если идти по звезде, то сливаться не будут, наоборот, будут пестрить.
Другое дело, что легенду, основанную на сопоставлении цветов легенды с цветами секторов — уже не сделать.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 9:23
alibek
Хакер писал(а):Если идти по звезде, то сливаться не будут, наоборот, будут пестрить.
Другое дело, что легенду, основанную на сопоставлении цветов легенды с цветами секторов — уже не сделать.

Я имел ввиду под "сливаться" именно это, глаз не сможет однозначно определить соответствие цвета легенде.
Если идти не по звезде, а просто по HSV-окружности с определенным шагом (n/1 в твоей диаграмме), тогда сопоставлять цвета легенде будет проще, но тогда наглядность пострадает.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 9:50
jangle
Берёшь любую радугу, которая достаточно плавная, и у которой один конец предельно близок к другому, например как здесь:


Хакер спасибо! Очень интересный алгоритм, буду пробовать его реализовать.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 9:51
Хакер
Я реализовал, но исходник утрачен — пропало напряжение на полсекунды.
Там строк 80 кода.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 10:22
Proxy
Alec писал(а):А если задавать тон в цветовой модели HSV? Например, для 10 элементов задаем тоны 0, 0.1, 0.2 и т.д., а выводим в последовательности 0, 0.5, 0.2, 0.7 и т.д.

Хакер писал(а):Разумеется, что в реальности ничего не нужно строить: кольцо расчитывается математический, координаты точек расчитываются математически.


2 идентичных варианта, в первом лишь шаг неудачный (помимо шага в варианте Хакера всё аналогично, тоже работа с тоном (Hue), значит помимо шага сам математически "круг" выразить очень просто из системы уравнений HSV -> RGB).
И я вижу недочёт при большом количестве секторов: если у кого-то возникнет желание сопоставить сектора с легендой, то он сядет на сопоставлении оттенков синего (физиология, оттенки синего человек различает хуже всего). ИМХО можно заведомо выбирать на несколько процентов больше цветов, а затем отбрасывать слишком близко расположенные оттенки синего. При таком шаге это не скажется на различимости двух соседних секторов. Так можно будет сохранить читаемость при большей плотности (выноски едва ли помогут, они вообще перекроются, если сектора будут маленькими и их придётся при перекрытии вообще скрывать).

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 10:26
Хакер
Мой вариант предполагает в частности выбор произвольной радуги. То есть необязательно прогон Hue от 0° до 360°, хотя лично я реализовывал именно этот вариант. Но радугу можно выбирать такой, что разные оттенки будут иметь разные SB-составляющие, плюс можно сделать немонотонный dH/dx.

Ну и плюс шаг выбирается не от-балды, а по закономерности (причём вариантов закономерности — вон сколько).

Но вообще да, идея та же, не спорю.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 10:31
Proxy
Хакер писал(а):Ну и плюс шаг выбирается не от-балды, а по закономерности (причём вариантов закономерности — вон сколько).

А где я сказал про шаг от балды? :) Шаг лучше и не придумать.
Хакер писал(а):Мой вариант предполагает в частности выбор произвольной радуги.

Не знал. В любом случае с составлением "умной" радуги + шагом по звезде будет не проще, чем с использованием готовой радуги Hue из HSV (при прочих константах), шага по звезде, а затем отбросом лишних цветов. А лучше было бы и вовсе добавить зависимость смещения от целевого угла и красиво и равномерно "разуплотнить" кольцо к Юго-Западу.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 11:41
alibek
Proxy писал(а):В любом случае с составлением "умной" радуги + шагом по звезде будет не проще, чем с использованием готовой радуги Hue из HSV (при прочих константах), шага по звезде, а затем отбросом лишних цветов.

Это по сути одно и то же. Просто Хакер визуализировал алгоритм выбора оптимального шага.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 13:58
Proxy
Извиняюсь заранее за оффтоп, но как тут найти угол между вершиной A звезды, центром описанной окружности и вершиной B, смежной с вершиной A? Ака выше "шаг".

Хакер писал(а):Там строк 80 кода.

Полагаю поиск этого угла занял порядка 40 строк?

UPD. Кажется придумал

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 14:01
Хакер
На картинке написано. {m/n}
n — кол-во вершин.
m — константа, определяющая способ построение.

Дробь {m/n} определяет, на сколько частей делить окружность. Иначе говоря: 360 / (m/n) = угол.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 14:12
Proxy
Без разуплотнения синего:

Печатает 5, а затем 8 цифр разных цветов с "шагом" "по звезде"
Код: Выделить всё
Option Explicit

Private Sub Form_Load()
AutoRedraw = True
PrintCols 5
PrintCols 8
End Sub

Private Sub PrintCols(totalCols As Long) 'печатает цифры уникальных цветов
Dim i As Long
Dim lastCornerAngle As Single
Dim AngleStep As Single
lastCornerAngle = 0
AngleStep = 180 - IIf(totalCols Mod 2 = 0, 1, 0.5) * (360 / totalCols)
For i = 1 To totalCols
  lastCornerAngle = lastCornerAngle + AngleStep
  Form1.ForeColor = HSV2RGBeasy(lastCornerAngle, 1, 1)
  Print i
Next
End Sub

Private Function HSV2RGBeasy(Hue As Single, Saturation As Single, ValueBr As Single) As Long 'просто получает RGB из HSV
Dim f As Single, p As Single, q As Single, t As Single
f = (Hue / 60) - (Hue \ 60)
p = (ValueBr * (1 - Saturation)) * 255
q = (ValueBr * (1 - f * Saturation)) * 255
t = (ValueBr * (1 - (1 - f) * Saturation)) * 255
f = f * 255: ValueBr = ValueBr * 255
Select Case ((Hue \ 60) Mod 6)
  Case 0
   HSV2RGBeasy = RGB(ValueBr, t, p)
  Case 1
   HSV2RGBeasy = RGB(q, ValueBr, p)
  Case 2
   HSV2RGBeasy = RGB(p, ValueBr, t)
  Case 3
   HSV2RGBeasy = RGB(p, q, ValueBr)
  Case 4
   HSV2RGBeasy = RGB(t, p, ValueBr)
  Case 5
   HSV2RGBeasy = RGB(ValueBr, p, q)
End Select
End Function


Можно просто вместо печати циферок помещать в массив цвета, чтобы потом использовать. Число уникальных цветов назначается через параметр процедуры PrintCols

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 14:54
Хакер
Нда.
Стоило ли писать гигантскую функцию HSV2RGBeasy, принимающую 3 параметра, чтобы потом при вызове в качестве двух последних всегда указывать 1 и 1?

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 16:19
Proxy
Хакер писал(а):Нда.
Стоило ли писать гигантскую функцию HSV2RGBeasy, принимающую 3 параметра, чтобы потом при вызове в качестве двух последних всегда указывать 1 и 1?

На перспективу, может насыщенность иная потребуется или ещё что.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 18:29
Mikle
Можно представить диапазон доступных цветов, как RGB куб, точнее параллелепипед, коэффициенты "заметности" RGB компонентов давно известны: R=77, G=150, B=28. Делаем параллелепипед с такими сторонами, первый цвет берём случайный, каждый следующий - точка, максимально удалённая от уже занятых.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 19:18
Proxy
Mikle писал(а):первый цвет берём случайный, каждый следующий - точка, максимально удалённая от уже занятых.

В такой формулировке первой точкой будет произвольная, второй вершина, третей противоположная вершина, четвёртой опять первая вершина и т.д. Или же я что-то неправильно понял.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 06.03.2012 (Вт) 19:24
Mikle
Вторая-третья - точно вершины, а дальше - зависит от первой точки.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 07.03.2012 (Ср) 12:31
Antonariy
jangle писал(а):
Берёшь любую радугу, которая достаточно плавная, и у которой один конец предельно близок к другому, например как здесь:


Хакер спасибо! Очень интересный алгоритм, буду пробовать его реализовать.
Дальтоники в пролете с этим алгоритмом.
Наверно поэтому в MS цветовые схемы для винды создают вручную.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 07.03.2012 (Ср) 12:33
Хакер
Дальтоники в пролёте с любым алгоритмом, если у них расстройство восприятие такое, что цветов нет вообще.
Если же расстройство такое, что есть частичное нарушение восприятия, то это решается подбором соответствующей радуги.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 07.03.2012 (Ср) 12:44
Antonariy
Значит нужно предоставить на выбор несколько радуг. Или как-то ее параметризировать. Даже человеку с нормальным зрением может выпасть неудобная комбинация.

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 07.03.2012 (Ср) 13:10
Хакер
Пример с человеком с нормальным зрением и неудачной комбинацией, выбранной по «звёздному» методу?

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 07.03.2012 (Ср) 13:59
Proxy
Antonariy писал(а):Значит нужно предоставить на выбор несколько радуг. Или как-то ее параметризировать. Даже человеку с нормальным зрением может выпасть неудобная комбинация.
Antonariy писал(а):Дальтоники в пролете с этим алгоритмом.


48 элементов. Звезда работает как надо. Единственное чуть-чуть увеличить угол между оттенками синего (всего 1 функция потребуется, у которой параметром оригинальный угол, а выводит скорректированный), а в плане дальтонизма едва ли лучше может получиться при таком количестве элементов. Можно для них по контрасту добавить коррекцию, чтобы вся "гамма" серого использовалась (впрочем даже попробую...).

Re: Алгоритм подбора цветов секторов круговой диаграммы

СообщениеДобавлено: 07.03.2012 (Ср) 14:14
Antonariy
Хакер писал(а):Пример с человеком с нормальным зрением и неудачной комбинацией, выбранной по «звёздному» методу?
Мне не нравится 19-23 и 43-45 со скриншота Proxy. Но в целом результат достойный.