Как нарисовать тепловую карту (heatmap)?

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Как нарисовать тепловую карту (heatmap)?

Сообщение CRobin » 02.12.2016 00:47:26

Здравствуйте, хочу нарисовать тепловую карту процесса. Соответствующего чарта не нашел, стало быть рисовать надо самому на канве. В связи с этим вопрос - как написать, или где взять готовую функцию, которая будет принимать в качестве аргументов диапазон значений и значение, а возвращать соотвествующий цвет за заранее заданному градиенту
Код: Выделить всё
getColor(min, max, current: integer): TColor;
Пример градусника
Изображение
CRobin
постоялец
 
Сообщения: 145
Зарегистрирован: 26.01.2016 12:15:39

Re: Как нарисовать тепловую карту (heatmap)?

Сообщение runewalsh » 02.12.2016 01:29:56

Код: Выделить всё
function ColorFromTemperature(Temp, Min, Max: Integer): TColor;
const
   ReferenceDivisions = 4500;
   ControlPoints: array[0 .. 6] of record
      Position: 0 .. ReferenceDivisions;
      R, G, B: byte;
   end =
   (
      (Position:    0; R:   0; G:   0; B: 128), // тёмно-синий
      (Position:  500; R:   0; G:   0; B: 255), // синий
      (Position: 1500; R:   0; G: 255; B: 255), // голубой
      (Position: 2000; R:   0; G: 255; B: 128), // зелёно-голубой
      (Position: 2750; R: 255; G: 255; B:   0), // жёлтый
      (Position: 3750; R: 255; G:   0; B:   0), // красный
      (Position: ReferenceDivisions; R: 128; G: 0; B: 0) // тёмно-красный
   );

   // линейная интерполяция между A и B с параметром N/D: Result = B*(N/D) + A*(1 - N/D)
   function Mix(A, B: Integer; N, D: Integer): Integer;
   begin
      result := A + (B - A) * N div D;
   end;

var
   I, N, D: Integer;
begin
   Temp := Temp - Min;
   Max  := Max - Min;
   if Temp <= 0 then Exit(RGBToColor(ControlPoints[0].R, ControlPoints[0].G, ControlPoints[0].B));

   for I := 1 to High(ControlPoints) do
      if {Temp/Max <= ControlPoints[I].Position/ReferenceDivisions}
         Temp * ReferenceDivisions <= ControlPoints[I].Position * Max then
      begin
         // N/D = параметр интерполяции между цветами
         // N/D = (Temp/Max - ControlPoints[I - 1].Position/ReferenceDivisions) / ((ControlPoints[I].Position - ControlPoints[I - 1].Position)/ReferenceDivisions)
         N := Temp * ReferenceDivisions - ControlPoints[I-1].Position * Max;
         D := (ControlPoints[I].Position - ControlPoints[I - 1].Position) * Max;
         Exit(RGBToColor(
            Mix(ControlPoints[I-1].R, ControlPoints[I].R, N, D),
            Mix(ControlPoints[I-1].G, ControlPoints[I].G, N, D),
            Mix(ControlPoints[I-1].B, ControlPoints[I].B, N, D)));
      end;

   result := RGBToColor(ControlPoints[High(ControlPoints)].R, ControlPoints[High(ControlPoints)].G, ControlPoints[High(ControlPoints)].B);
end;
Последний раз редактировалось runewalsh 02.12.2016 01:53:27, всего редактировалось 3 раз(а).
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: Как нарисовать тепловую карту (heatmap)?

Сообщение olegy123 » 02.12.2016 01:40:59

вопрос рассматривался для питона:
http://stackoverflow.com/questions/2079 ... e-heat-map
приведены несколько функций..
olegy123
долгожитель
 
Сообщения: 1643
Зарегистрирован: 25.02.2016 12:10:20

Re: Как нарисовать тепловую карту (heatmap)?

Сообщение Alex2013 » 02.12.2016 19:36:50

Я бы нарисовал грубые квадратики (по точкам измерения), а после сгладил бы например по Гауссу(красивей) или "семплами" (быстрей) )
Красивый спектр сделать тоже не проблема ....
https://ru.wikipedia.org/wiki/HSL
https://ru.wikipedia.org/wiki/HSV_(%D1% ... 0%BB%D1%8C)
Alex2013
долгожитель
 
Сообщения: 2925
Зарегистрирован: 03.04.2013 11:59:44

Re: Как нарисовать тепловую карту (heatmap)?

Сообщение mig-31 » 05.12.2016 18:59:07

TAChart color map можно подогнать под задачую
mig-31
постоялец
 
Сообщения: 224
Зарегистрирован: 14.07.2011 13:46:48


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 34

Рейтинг@Mail.ru