File: main.pas

package info (click to toggle)
lazarus 2.0.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 214,460 kB
  • sloc: pascal: 1,862,622; xml: 265,709; cpp: 56,595; sh: 3,008; java: 609; makefile: 535; perl: 297; sql: 222; ansic: 137
file content (173 lines) | stat: -rw-r--r-- 3,740 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
unit main;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
  TAGraph, TASeries, TAChartUtils, TATools, Types;

type

  { TMainForm }

  TMainForm = class(TForm)
    Chart: TChart;
    ReferenceLine: TConstantLine;
    Series: TUserDrawnSeries;
    ChartToolset: TChartToolset;
    DataPointDragTool: TDataPointDragTool;
    cbShowDataPoints: TCheckBox;
    Panel: TPanel;
    procedure SeriesDraw(ACanvas: TCanvas; const ARect: TRect);
    procedure SeriesGetBounds(var ABounds: TDoubleRect);
    procedure cbShowDataPointsChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    Pen: TPen;

  public

  end;

var
  MainForm: TMainForm;

implementation

{$R *.lfm}

uses
  Math, TAGeometry;

const
  COLOR_ABOVE = clRed;
  COLOR_BELOW = clGreen;
  RADIUS = 4;

type
  TDataRec = record
    x, y: Double;
  end;

var
  Data: array of TDataRec;
  Extent: TDoubleRect;

function Intersect(p1, p2: TPoint; y: Integer): Integer;
begin
  if p1.x = p2.x then
    Result := p1.x
  else
    Result := round((p2.x - p1.x) / (p2.y - p1.y) * (y - p1.y) + p1.x);
end;


{ TMainForm }

procedure TMainForm.SeriesDraw(ACanvas: TCanvas;
  const ARect: TRect);

  procedure DrawCircle(p: TPoint; AColor: TColor; R: Integer);
  begin
    Chart.Drawer.SetBrushParams(bsSolid, AColor);
    Chart.Drawer.Ellipse(P.x - R, P.y - R, P.x + R, P.y + R);
  end;

  function GetColor(y, yref: Integer): TColor;
  begin
    if y > yref then Result := COLOR_BELOW else Result := COLOR_ABOVE;
  end;

var
  i: Integer;
  gp: TDoublePoint;
  p1, p2, p3: TPoint;
  yref: Integer;
  x: Integer;
  showDataPoints: Boolean;
begin
  showDataPoints := cbShowDataPoints.Checked;
  Chart.Drawer.Pen := Pen;
  yref := Chart.YGraphToImage(ReferenceLine.Position);

  i := 0;
  gp := DoublePoint(Data[i].X, Data[i].Y);
  p1 := Chart.GraphToImage(gp);
  if showDataPoints then begin
    Chart.Drawer.SetPenParams(psSolid, GetColor(p1.y, yref));
    DrawCircle(p2, GetColor(p2.y, yref), RADIUS);
  end;

  for i:=0 to High(Data)-1 do begin
    gp := DoublePoint(Data[i].X, Data[i].Y);
    p2 := Chart.GraphToImage(gp);
    if (p2.y - yref) * (p1.y - yref) < 0 then begin
      p3 := Point(Intersect(p1, p2, yref), yref);
      Chart.Drawer.SetPenParams(psSolid, GetColor(p1.y, yref));
      Chart.Drawer.Line(p1, p3);
      Chart.Drawer.SetPenParams(psSolid, GetColor(p2.y, yref));
      Chart.Drawer.Line(p3, p2);
    end else begin
      Chart.Drawer.SetPenParams(psSolid, GetColor(p2.y, yref));
      Chart.Drawer.Line(p1, p2);
    end;
    if showDataPoints then
      DrawCircle(p2, GetColor(p2.y, yref), RADIUS);
    p1 := p2;
  end;
end;

procedure TMainForm.SeriesGetBounds(var ABounds: TDoubleRect);
begin
  ABounds := Extent;
end;

procedure TMainForm.cbShowDataPointsChange(Sender: TObject);
begin
  Chart.Invalidate;
end;

procedure TMainForm.FormCreate(Sender: TObject);
const
  N = 20;
  XMIN = -10;
  XMAX = +10;
var
  i: Integer;
  x, y: Double;
begin
  Chart.DoubleBuffered := true;

  Pen := TPen.Create;
  Pen.Width := 3;

  SetLength(Data, N);
  for i:=0 to N-1 do begin
    Data[i].x := XMIN + (XMAX - XMIN) / (N - 1) * i;
//    Data[i].y := sin(Data[i].x);
    Data[i].y := (Random * 2 - 1) * 100;
  end;

  Extent.a.x := Data[0].x;
  Extent.a.y := Data[0].y;
  Extent.b.x := Data[0].x;
  Extent.b.y := Data[0].y;
  for i:= 1 to High(Data) do begin
    Extent.a.x := Min(Extent.a.x, Data[i].x);
    Extent.b.x := Max(Extent.b.x, Data[i].x);
    Extent.a.y := Min(Extent.a.y, Data[i].y);
    Extent.b.y := Max(Extent.b.y, Data[i].y);
  end;
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  Pen.Free;
end;


end.