2012-04-13 3 views
4

Можете ли вы помочь мне создать диаграмму области, где часть (сверху) диаграммы имеет другой цвет? Я хотел бы указать, что значения по любому значению числа являются критическими.Создание диаграммы области, окрашивающей часть переполненных значений другим цветом

Это скриншот: enter image description here

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

+0

Done, что пару раз, добавив пользовательские диаграммы фоновый рисунок с цветными полосками. Работает, если y-масштаб фиксирован. –

+0

Это скриншот: http://imageshack.us/photo/my-images/84/58337625.png/ Я создал две диаграммы областей, но, как вы можете видеть, каждая диаграмма имеет собственную левую ось. Лучшим решением будет раскрашивание диаграммы выше определенных значений. – user1332578

ответ

7

Существует инструмент под названием TSeriesBandTool, который может сделать это с небольшой работой.

Добавить дополнительную серию и сделать ее идентичной вашей серии, но с максимальным лимитом.

Вот как это выглядит в редакторе инструментов:

enter image description here

Она наполнит разницу между двумя рядами с цветом вашего выбора.

Update

Сделано доказательство концепции см изображение.

Добавлена ​​третья серия и второй TSeriesBandTool, чтобы заполнить нижнюю часть вторым цветом. Я уверен, что это возможно сделать с меньшим количеством кода, но это достаточно хорошо для демонстрации.

Update 2

Сделаны некоторые коды прохладительных напитков.

Update 2,5

теперь обрабатывает произвольные X-значения, а не только целые числа.

enter image description here

Вот код:

uses Series, TeeTools, TeeSeriesBandTool; 

Procedure DrawLimitAreaChart(S1, S2, S3: TLineSeries; YLimit: Double; 
    BT1, BT2: TSeriesBandTool; OutlineWidth: Integer; 
    OutlineCL, TopCl, BottomCL: TColor); 
Var 
    i: Integer; 
    iX: Double; 
Begin 
    S1.LinePen.Width := OutlineWidth; 
    S1.Color := OutlineCL; 
    S2.Color := OutlineCL; 
    S3.Color := OutlineCL; 
    for i := 0 to S1.Count - 1 do 
    if (S1.YValue[i] > YLimit) then 
    begin 
     if (i > 0) and (S1.YValue[i - 1] < YLimit) then 
     begin // Last point below limit 
     iX := (S1.XValue[i] - S1.XValue[i - 1]) * (YLimit - S1.YValue[i - 1])/
      (S1.YValue[i] - S1.YValue[i - 1]) + S1.XValue[i - 1]; 
     S2.AddXY(iX, YLimit); 
     if (i < S1.Count - 1) then 
      Continue; 
     end; 
     S2.AddXY(S1.XValue[i], YLimit); // Set to Ylimit 
    end 
    else // Below Ylimit 
    begin 
     if (i > 0) and (S1.YValue[i - 1] > YLimit) then 
     begin // Last point above limit 
     iX := (S1.XValue[i] - S1.XValue[i - 1]) * (YLimit - S1.YValue[i - 1])/
      (S1.YValue[i] - S1.YValue[i - 1]) + S1.XValue[i - 1]; 
     S2.AddXY(iX, YLimit); 
     end; 
     S2.AddXY(S1.XValue[i], S1.YValue[i]); // Same value 
    end; 

    for i := 0 to S2.Count - 1 do 
    begin 
    S3.AddXY(S2.XValue[i], 0.0); 
    end; 

    { - First TSeriesBandTool } 
    BT1.Series := S1; 
    BT1.Series2 := S2; 
    BT1.Brush.BackColor := TopCl; 
    BT1.DrawBehindSeries := True; 
    BT1.Transparency := 50; 

    { - Second TSeriesBandTool } 
    BT2.Series := S2; 
    BT2.Series2 := S3; 
    BT2.Brush.BackColor := BottomCL; 
    BT2.DrawBehindSeries := True; 
    BT2.Transparency := 50; 

End; 

procedure TForm1.Button1Click(Sender: TObject); 
const 
    // Example data 
    YVAL: array [0 .. 10] of Double = (10,40,45,20,48,5,47,47,47,47,30); 
var 
    i: Integer; 
    YLimit: Double; 
    S1, S2, S3: TLineSeries; 
begin 
    Chart1.SeriesList.Clear; 
    S1 := TLineSeries.Create(Self); // Contains real data 
    Chart1.AddSeries(S1); 
    S2 := TLineSeries.Create(Self); // Data below Ylimit 
    Chart1.AddSeries(S2); 
    S3 := TLineSeries.Create(Self); // baseline data 
    Chart1.AddSeries(S3); 
    for i := 0 to 10 do 
    S1.AddXY(i, YVAL[i]); 
    YLimit := S1.MaxYValue * 0.75; 
    DrawLimitAreaChart(S1, S2, S3, YLimit, ChartTool1, ChartTool2, 2, clBlack, 
    TColor($0024FF){clOrangeRed}, TColor($FF4D4D){clNeonBlue}); 

end; 

Так что код делает:

Заполняет в X, Y данных в серии [0]. Звонки DrawLimitAreaChart процедура, когда новая серия рассчитывается из серии [0], так что никакая часть не находится над Ylimit. Наконец, третья серия применяется в качестве базовой линии для второй серии. Три кривые вместе с двумя TSeriesBandTools теперь образуют диаграмму области с двумя цветами.

Обновление 3

По запросу здесь приведен пример диаграммы с осью X, как время. Код для этого приведен в моем комментарии ниже.

enter image description here

+0

Спасибо мастер :) Как я могу подавать данные по данным в интервале времени? Процедура будет приятной: процедура AddChartValue (ATime: TDateTime; AValue: integer); AddChartValue ('12: 00: 00 ', 30); AddChartValue ('12: 00: 10 ', 40); AddChartValue ('12: 00: 20 ', 20); ... ... AddChartValue ('12: 01: 50 ', 20); .... .... Конечно, мне нужно установить максимальное значение «x», чтобы показать max, например, 60 секунд, больше данных уменьшит четкость диаграммы. – user1332578

+0

У меня есть ответ для вас (пожалуйста, удалите свой другой ответ на вопрос, как указал Кен). Установите 'S1.XValues.DateTime: = True;' и 'Chart1.BottomAxis.DateTimeFormat: = 'nn: ss';' или любой другой формат по вашему вкусу. Добавьте значения X в формате TDateTime, то есть 'S1.AddXY (теперь + XVAL [i]/(24 * 60 * 60), YVAL [i]);'. –

+0

Надеюсь, он работает на вас. Не забудьте принять ответ, см. [Faq # howtoask] (http://stackoverflow.com/faq#howtoask). –