Social Icons

четверг, 17 января 2013 г.

Штриховка в TChart

На днях коллега поинтересовался вопросом - а можно ли в стандартном TChart сделать что-то наподобии такого:

Гугл ответа не дал, поэтому пришлось думать над решением самому :). Нашлось оно довольно быстро следующим образом:
...
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VCLTee.TeEngine, VCLTee.Series,
  Vcl.ExtCtrls, VCLTee.TeeProcs, VCLTee.Chart, System.Generics.Collections;

type
  THatchDirection = (hdUp, hdDown);

  TForm1 = class(TForm)
    Chart1: TChart;
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Chart1AfterDraw(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    var
      FHatchDirectionList: TList<THatchDirection>;
    procedure DrawHatch(Series: TChartSeries; HatchDirection: THatchDirection);
    procedure AddInEquation(XStart, XEnd, XStep: Double; YFunc: TFunc<Double,
        Double>; AHatchDirection: THatchDirection; AColor: TColor);
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Содержит список направлений штриховок, индексация FHatchDirectionList[I} = Chart1.Series[I]
  FHatchDirectionList := TList<THatchDirection>.Create;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  FHatchDirectionList.Clear;
  Chart1.ClearChart;
  Chart1.View3D := False;

  // Прямая
  AddInEquation(0, 50, 1,
                function(x: Double): Double
                begin
                  Result := x;
                end,
                THatchDirection.hdDown, clRed);

  // Еще одна
  AddInEquation(0, 50, 1,
                function(x: Double): Double
                begin
                  Result := 50 - x;
                end,
                THatchDirection.hdDown, clBlue);

  // Парабола
  AddInEquation(10, 40, 1,
                function(x: Double): Double
                begin
                  Result := 0.2 * sqr(x - 25) + 8;
                end,
                THatchDirection.hdUp, clGreen);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeAndNil(FHatchDirectionList);
end;

procedure TForm1.DrawHatch(Series: TChartSeries; HatchDirection: THatchDirection);
const
  HATCH_SIZE = 10;
var
  i, k: Integer;
  XPos, YPos: Integer;
begin
  Chart1.Canvas.Pen.Color := Series.Color;
  Chart1.Canvas.Pen.Width := Series.Pen.Width - 1;
  case HatchDirection of
    hdUp:   k := -1;
    hdDown: k := 1;
  end;

  for i := 0 to Series.XValues.Count - 1 do
  begin
    XPos := Series.CalcXPosValue(Series.XValue[i]);
    YPos := Series.CalcYPosValue(Series.YValue[i]);
    Chart1.Canvas.Line(XPos, YPos, XPos, YPos + k*HATCH_SIZE);
  end;
end;

procedure TForm1.Chart1AfterDraw(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to FHatchDirectionList.Count - 1 do
    DrawHatch(Chart1.Series[i], FHatchDirectionList[i]);
end;

procedure TForm1.AddInEquation(XStart, XEnd, XStep: Double; YFunc: TFunc<Double, Double>;
  AHatchDirection: THatchDirection; AColor: TColor);
var
  i: Double;
  SR1: TLineSeries;
begin
  SR1 := TLineSeries.Create(Chart1);
  SR1.Color := AColor;
  SR1.Pen.Width := 3;
  i := XStart;
  while i <= XEnd do
  begin
    SR1.AddXY(i, YFunc(i));
    i := i + XStep;
  end;
  Chart1.AddSeries(SR1);
  FHatchDirectionList.Add(AHatchDirection);
end;

end.
Остановлюсь на нескольких моментах (этапы реализации):
  1. Первым делом заводим тип штриховки (THatchDirection = (hdUp, hdDown)) и список (FHatchDirectionList: TList), хранящий ее состояния для каждой серии чарта.
  2. Далее, при добавлении серии (неравенства) - AddInEquation (стоит обратить внимание на использование анонимных методов), добавляем тип штриховки.
  3. И, наконец, в методе Chart1.AfterDraw "дорисовываем" к графикам штриховку в нужном направлении (соль - в методе DrawHatch).

Вот результат:



Проект можно воспроизвести, лишь кинув на форму TChart и заменив код формы на приведенный.

Поделитесь с друзьями!

 

Подписчики

Статистика