Сопоставить неограниченный диапазон значений с 10 цветами?

У меня есть следующий список из 10 цветов:

public static readonly IList<Brush> lineColors = new ReadOnlyCollection<Brush>
        (new List<Brush> { 
            new SolidColorBrush(Color.FromRgb(35, 31, 32)),
            new SolidColorBrush(Color.FromRgb(64, 64, 66)),
            new SolidColorBrush(Color.FromRgb(89, 89, 91)),
            new SolidColorBrush(Color.FromRgb(110, 111, 113)),
            new SolidColorBrush(Color.FromRgb(129, 130, 132)),
            new SolidColorBrush(Color.FromRgb(148, 149, 153)),
            new SolidColorBrush(Color.FromRgb(168, 169, 173)),
            new SolidColorBrush(Color.FromRgb(189, 190, 193)),
            new SolidColorBrush(Color.FromRgb(210, 211, 213)),
            new SolidColorBrush(Color.FromRgb(231, 231, 232))
        });

Теперь у меня также есть диапазон от 1 до n. Я хотел бы сопоставить эти значения в равной степени с этими 10 цветами, чтобы наименьшее значение было первым цветом, а самое высокое значение было сопоставлено с последним цветом. Все остальные цвета должны покрывать одинаковое расстояние в диапазоне значений.

Как это сделать?

Я думаю, что это, возможно, сделает это:

int position = Math.floor( value / ((max - min) / lineColors.Count));
lineColors.ElementAt(position);

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


person Community    schedule 05.02.2011    source источник
comment
Разве вы не можете просто использовать index-1? извините, я, вероятно, не совсем понял вопрос.   -  person Felice Pollano    schedule 05.02.2011
comment
да, чтобы получить доступ к списку, но я должен рассчитать индекс.   -  person    schedule 05.02.2011
comment
Если вы имеете в виду реализацию градиента, вы можете посмотреть здесь: stackoverflow.com/questions/986352/   -  person Felice Pollano    schedule 05.02.2011
comment
так что реальный вопрос не имеет значения с цветом/Wpf/C#, это просто: учитывая действительное число от 1..N, сопоставьте его в целочисленном диапазоне 0-M правильно?   -  person Felice Pollano    schedule 05.02.2011
comment
хм да :D это можно упростить   -  person    schedule 05.02.2011
comment
хорошо, я предлагаю вам отредактировать. Кстати, решение, которое вы представили как автоматический ответ, выглядит нормально, просто нужно решить, где округлить   -  person Felice Pollano    schedule 05.02.2011


Ответы (2)


Значения отображения могут быть выражены линейной функцией: f(x) = ax + b

Оба ваших диапазона дают точки для этой функции, из которых ее можно вычислить.
f(1) = 0
f(n) = 9 | Высший индекс в списке из десяти цветов.

0 = a * 1 + b
9 = a * n + b

9 = a * (n - 1)
a = 9 / (n - 1)
=> b = -9 / (n - 1)

=> f(x) = 9 / ( n - 1) * (x - 1)

Проблема здесь в том, что если вы округлите это сразу, меньше значений будет сопоставлено с 0 и 9, потому что диапазон округления составляет всего 0,5 (от 0 до 0,5 и от 8,5 до 9), поэтому вы можете растянуть диапазон и сдвинуть его назад на 0,5, чтобы учесть это.

private int MapValue(int value, int n)
{
    int output = (int)Math.Round((10.0 / (n - 1) * (value - 1)) - 0.5, 0);
    if (output == -1) return 0;
    else return output;
}
person H.B.    schedule 05.02.2011
comment
Спасибо. Это работает для меня. Теперь я столкнулся с другой проблемой. В одном примере у меня есть диапазон от 0 до 1116. Однако большинство значений находятся в диапазоне от 0 до 50 или, может быть, от 0 до 100. Тем не менее, большинство значений отображаются в один и тот же цвет. Как я могу избежать того, что такие выбросы вмешиваются в мое отображение? - person RoflcoptrException; 06.02.2011
comment
Уравнение предназначено для входных диапазонов от 1 до n, как вы указали в своем вопросе, если ваш диапазон теперь начинается с 0, что приведет к неточностям. Кроме того, есть погрешность базы от округления. Я попытался сопоставить диапазон от 1 до 1116, и разница в длине полосы для разных индексов составляет всего одно значение, поэтому большого расхождения нет. - person H.B.; 06.02.2011

Вы не ввели value, min и max -- я предполагаю, что min и max являются соответственно минимальным и максимальным диапазоном чисел, которые вы хотите отображать (в вашем текстовом изложении проблемы это будет означать min = 1 и max = n), и это value является значением, которое вы пытаетесь отобразить.

Предлагаемое вами решение содержит пару проблем:

а) Вам также нужно вычесть min из value.
б) Если эти переменные объявлены как целые числа (как я полагаю, так и должно быть), результаты деления будут усечены.
в) Если value равно max, вам нужен lineColors.Count - 1, а не lineColors.Count.
d) Используя floor, вы вводите асимметрию - диапазон значений отображается в самый низкий цвет, но только max отображается в самый высокий цвет. Вместо этого кажется предпочтительным использовать round, чтобы обрабатывать оба конца спектра одинаково.

Таким образом, решение будет:

int position = Math.round ((значение - мин.) / ((макс. - мин.) / (lineColors.Count - 1.))); lineColors.ElementAt(позиция);

(Десятичная точка в «1» заставляет все арифметические операции выполняться с плавающей запятой.)

person joriki    schedule 05.02.2011
comment
Извините, но у меня это не работает с десятичными точками, а также ваши значения выходят за пределы допустимого диапазона. - person RoflcoptrException; 05.02.2011
comment
В каком смысле у вас не работает десятичная точка? Из ответа HB я вижу, что в конце вам может понадобиться приведение к (int). Я не понимаю, как значения могут быть вне диапазона - если вы введете min, вы получите 0; если вы укажете max, вы получите lineColors.Count - 1 -- пожалуйста, приведите пример, когда значения выходят за пределы допустимого диапазона. - person joriki; 05.02.2011