TAChart: Add a TChartLiveView demo for paned chart (multi-axis)

(cherry picked from commit 79a2acf298)
This commit is contained in:
wp_xyz 2021-08-09 13:44:15 +02:00
parent e61ebf84c2
commit 638e9ad8ae
4 changed files with 563 additions and 0 deletions

View File

@ -0,0 +1,257 @@
object Form1: TForm1
Left = 609
Height = 693
Top = 149
Width = 496
Caption = 'MainForm'
ClientHeight = 693
ClientWidth = 496
OnCreate = FormCreate
LCLVersion = '2.3.0.0'
object Chart1: TChart
Left = 0
Height = 624
Top = 0
Width = 496
AxisList = <
item
Grid.Color = clMenu
Grid.Style = psSolid
Alignment = calBottom
AxisPen.Visible = True
Marks.LabelBrush.Style = bsClear
Minors = <>
Range.UseMin = True
Title.LabelFont.Style = [fsBold]
Title.Visible = True
Title.Caption = 'Time, s'
Title.LabelBrush.Style = bsClear
end
item
Grid.Color = clMenu
Grid.Style = psSolid
AtDataOnly = True
AxisPen.Visible = True
Group = 1
Marks.AtDataOnly = True
Marks.LabelBrush.Style = bsClear
Minors = <>
Range.Max = 1
Range.Min = -1
Range.UseMax = True
Range.UseMin = True
Title.LabelFont.Orientation = 900
Title.LabelFont.Style = [fsBold]
Title.Visible = True
Title.Caption = 'Position, cm'
Title.LabelBrush.Style = bsClear
Title.PositionOnMarks = True
Transformations = PositionTransformations
end
item
Grid.Color = clMenu
Grid.Style = psSolid
AtDataOnly = True
AxisPen.Visible = True
Group = 1
Marks.AtDataOnly = True
Marks.LabelBrush.Style = bsClear
Minors = <>
Range.Max = 1
Range.Min = -1
Range.UseMax = True
Range.UseMin = True
Title.LabelFont.Orientation = 900
Title.LabelFont.Style = [fsBold]
Title.Visible = True
Title.Caption = 'Velocity, cm/s'
Title.LabelBrush.Style = bsClear
Title.PositionOnMarks = True
Transformations = VelocityTransformations
end
item
Grid.Color = clMenu
Grid.Style = psSolid
AtDataOnly = True
AxisPen.Visible = True
Group = 1
Marks.AtDataOnly = True
Marks.LabelBrush.Style = bsClear
Minors = <>
Range.Max = 1
Range.Min = -1
Range.UseMax = True
Range.UseMin = True
Title.LabelFont.Orientation = 900
Title.LabelFont.Style = [fsBold]
Title.Visible = True
Title.Caption = 'Acceleration, cm/s<sup>2</sup> '
Title.LabelBrush.Style = bsClear
Title.PositionOnMarks = True
Title.TextFormat = tfHTML
Transformations = AccelerationTransformations
end>
Frame.Visible = False
Title.Font.Height = -16
Title.Font.Style = [fsBold]
Title.Text.Strings = (
'Damped pendulum'
)
Title.Visible = True
Align = alClient
object PositionSeries: TLineSeries
AxisIndexX = 0
AxisIndexY = 1
end
object VelocitySeries: TLineSeries
AxisIndexX = 0
AxisIndexY = 2
end
object AccelerationSeries: TLineSeries
AxisIndexX = 0
AxisIndexY = 3
end
end
object Panel1: TPanel
Left = 8
Height = 49
Top = 636
Width = 480
Align = alBottom
AutoSize = True
BorderSpacing.Around = 8
BevelOuter = bvNone
ClientHeight = 49
ClientWidth = 480
TabOrder = 1
object cbLiveView: TCheckBox
AnchorSideLeft.Control = Panel1
AnchorSideTop.Control = btnReset
AnchorSideTop.Side = asrCenter
Left = 0
Height = 19
Top = 3
Width = 114
Caption = 'Scrolling live view'
Checked = True
OnChange = cbLiveViewChange
State = cbChecked
TabOrder = 0
end
object cbFrozenAxes: TCheckBox
AnchorSideLeft.Control = cbLiveView
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = btnReset
AnchorSideTop.Side = asrCenter
Left = 146
Height = 19
Top = 3
Width = 122
BorderSpacing.Left = 32
Caption = 'Frozen vertical axes'
Checked = True
OnChange = cbFrozenAxesChange
State = cbChecked
TabOrder = 1
end
object btnReset: TButton
AnchorSideLeft.Control = btnStopResume
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = Panel1
Left = 387
Height = 25
Top = 0
Width = 75
BorderSpacing.Left = 4
BorderSpacing.Right = 8
Caption = 'Reset'
OnClick = btnResetClick
TabOrder = 2
end
object btnStopResume: TButton
AnchorSideLeft.Control = cbFrozenAxes
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = Panel1
Left = 308
Height = 25
Top = 0
Width = 75
BorderSpacing.Left = 40
Caption = 'Stop'
OnClick = btnStopResumeClick
TabOrder = 3
end
object Label1: TLabel
AnchorSideLeft.Control = cbLiveView
AnchorSideTop.Control = seViewportSize
AnchorSideTop.Side = asrCenter
Left = 0
Height = 15
Top = 30
Width = 88
Caption = 'Viewport size (s):'
end
object seViewportSize: TFloatSpinEdit
AnchorSideLeft.Control = Label1
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = cbLiveView
AnchorSideTop.Side = asrBottom
Left = 96
Height = 23
Top = 26
Width = 58
Alignment = taRightJustify
BorderSpacing.Left = 8
BorderSpacing.Top = 4
DecimalPlaces = 0
MaxValue = 60
MinValue = 1
OnChange = seViewportSizeChange
TabOrder = 4
Value = 10
end
end
object Bevel1: TBevel
Left = 0
Height = 4
Top = 624
Width = 496
Align = alBottom
Shape = bsBottomLine
end
object PositionTransformations: TChartAxisTransformations
Left = 213
Top = 34
object PositionAutoScaleTransform: TAutoScaleAxisTransform
MaxValue = 3.4
MinValue = 2.4
end
end
object VelocityTransformations: TChartAxisTransformations
Left = 213
Top = 102
object VelocityScaleTransform: TAutoScaleAxisTransform
MaxValue = 2.2
MinValue = 1.2
end
end
object AccelerationTransformations: TChartAxisTransformations
Left = 213
Top = 176
object AccelerationAutoScaleTransform: TAutoScaleAxisTransform
end
end
object Timer: TTimer
Enabled = False
Interval = 100
OnTimer = TimerTimer
Left = 216
Top = 287
end
object ChartLiveView1: TChartLiveView
Chart = Chart1
ViewportSize = 10
Left = 216
Top = 367
end
end

View File

@ -0,0 +1,202 @@
{ This project demonstrates application of a TChartLiveView to a multiple-axis
chart ("paned chart"). }
unit main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
Spin, TAGraph, TATransformations, TASeries, TAChartLiveView;
type
{ TForm1 }
TForm1 = class(TForm)
AccelerationAutoScaleTransform: TAutoScaleAxisTransform;
Bevel1: TBevel;
btnReset: TButton;
btnStopResume: TButton;
Chart1: TChart;
ChartLiveView1: TChartLiveView;
cbLiveView: TCheckBox;
cbFrozenAxes: TCheckBox;
Label1: TLabel;
PositionSeries: TLineSeries;
seViewportSize: TFloatSpinEdit;
Timer: TTimer;
VelocitySeries: TLineSeries;
AccelerationSeries: TLineSeries;
PositionTransformations: TChartAxisTransformations;
PositionAutoScaleTransform: TAutoScaleAxisTransform;
VelocityTransformations: TChartAxisTransformations;
AccelerationTransformations: TChartAxisTransformations;
Panel1: TPanel;
VelocityScaleTransform: TAutoScaleAxisTransform;
procedure btnResetClick(Sender: TObject);
procedure btnStopResumeClick(Sender: TObject);
procedure cbFrozenAxesChange(Sender: TObject);
procedure cbLiveViewChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure seViewportSizeChange(Sender: TObject);
procedure TimerTimer(Sender: TObject);
private
FStartTime: TDateTime;
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
uses
//DateUtils,
Math;
const
A0 = 10.0; // (initial) oscillation amplitude
t0 = 5.0; // oscillation period
td = 20.0; // damping time constant
TWO_PI = 2.0*pi;
{ TForm1 }
{ Simulates position, velocity and acceleration of an oscillating body. The
oscillation is damped, i.e. the excursions are decreasing with time. Parameters
describing this damped oscillation are A0, t0 and td given above. }
procedure TForm1.TimerTimer(Sender: TObject);
var
t: Double;
x, v, a: Double;
exp_factor, sin_factor, cos_factor: Double;
begin
if PositionSeries.Count = 0 then
FStartTime := Now();
t := (Now() - FStartTime) * SecsPerDay;
exp_factor := exp(-t/td);
sin_factor := sin(TWO_PI * t / t0);
cos_factor := cos(TWO_PI * t / t0);
// Position: an exponentially damped sinusoidal motion
x := A0 * sin_factor * exp_factor;
// velocity = dx/dt
v := 1.0 / (t0*td) * (A0 * exp_factor * (2.0*pi*td * cos_factor - t0 * sin_factor));
// acceleration = dv/dt = d2x/dt2
a := x / sqr(td) - sqr(TWO_PI/t0) * x - 2.0*TWO_PI*A0/(t0*td) * exp_factor * cos_factor;
// Add values to series
PositionSeries.AddXY(t, x);
VelocitySeries.AddXY(t, v);
AccelerationSeries.AddXY(t, a);
end;
{ Toggles between normal view and scrolling live view. In case of normal view
the entire extent of the chart is shown. }
procedure TForm1.cbLiveViewChange(Sender: TObject);
begin
ChartLiveView1.Active := cbLiveView.Checked;
if not ChartLiveView1.Active then
Chart1.ZoomFull;
end;
{ Toggles between automatic scaling of the axes and predefined axis limits
(see FormCreate for the predefined values). }
procedure TForm1.cbFrozenAxesChange(Sender: TObject);
var
i: Integer;
wasActive: Boolean;
begin
wasActive := ChartLiveView1.Active;
ChartLiveView1.Active := false; // LiveView must be off when changing axes
for i := 1 to 3 do
with Chart1.AxisList[i].Range do
begin
UseMax := cbFrozenAxes.Checked;
UseMin := cbFrozenAxes.Checked;
end;
ChartLiveView1.Active := wasActive; // Restore liveview state
end;
{ Resets and starts a new data generation run. }
procedure TForm1.btnResetClick(Sender: TObject);
begin
Timer.Enabled := false;
PositionSeries.Clear;
VelocitySeries.Clear;
AccelerationSeries.Clear;
Timer.Enabled := true;
btnStopResume.Caption := 'Stop';
end;
{ Stop or resume the data generation. When stopped a line break is added to the
series. }
procedure TForm1.btnStopResumeClick(Sender: TObject);
var
t: Double;
begin
Timer.Enabled := not Timer.Enabled;
if Timer.Enabled then
btnStopResume.Caption := 'Stop'
else begin
btnStopResume.Caption := 'Resume';
// Add a break to the curves
t := (Now() - FStartTime) * SecsPerDay;
PositionSeries.AddXY(t, NaN);
VelocitySeries.AddXY(t, NaN);
AccelerationSeries.AddXY(t, NaN);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
{ The following settings could also be made in the object inspector. }
// LiveView must be off when setting up the axes.
with Chart1.AxisList[1].Range do
begin
UseMax := true;
UseMin := true;
Max := 10;
Min := -10;
end;
with Chart1.AxisList[2].Range do
begin
UseMax := true;
UseMin := true;
Max := 15;
Min := -15;
end;
with Chart1.AxisList[3].Range do
begin
UseMax := true;
UseMin := true;
Max := 15.0;
Min := -15.0;
end;
// Activate the live view
ChartLiveView1.Active := true;
// Start the "measurement"
Timer.Enabled := true;
end;
{ Set the liveview's ViewportSize according to the value in the SpinEdit }
procedure TForm1.seViewportSizeChange(Sender: TObject);
begin
ChartLiveView1.ViewportSize := seViewportSize.Value;
end;
end.

View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="12"/>
<PathDelim Value="\"/>
<General>
<SessionStorage Value="InProjectDir"/>
<Title Value="panedliveviewdemo"/>
<Scaled Value="True"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<XPManifest>
<DpiAware Value="True"/>
</XPManifest>
</General>
<BuildModes>
<Item Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<UseFileFilters Value="True"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
</RunParams>
<RequiredPackages>
<Item>
<PackageName Value="TAChartLazarusPkg"/>
</Item>
<Item>
<PackageName Value="LCL"/>
</Item>
</RequiredPackages>
<Units>
<Unit>
<Filename Value="panedliveviewdemo.lpr"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="main.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="panedliveviewdemo"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions>
<Item>
<Name Value="EAbort"/>
</Item>
<Item>
<Name Value="ECodetoolError"/>
</Item>
<Item>
<Name Value="EFOpenError"/>
</Item>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,25 @@
program panedliveviewdemo;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
{$IFDEF HASAMIGA}
athreads,
{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, main, tachartlazaruspkg
{ you can add units after this };
{$R *.res}
begin
RequireDerivedFormResource:=True;
Application.Scaled:=True;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.