mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-31 05:32:29 +02:00
TAChart: Usa HTML tags in fit equation of TFitSeries. Use FitSeries in html demo.
git-svn-id: trunk@55449 -
This commit is contained in:
parent
d4b7ead41d
commit
e4049c3629
@ -1,17 +1,17 @@
|
||||
object MainForm: TMainForm
|
||||
Left = 280
|
||||
Height = 432
|
||||
Height = 452
|
||||
Top = 130
|
||||
Width = 655
|
||||
Caption = 'HTML demo'
|
||||
ClientHeight = 432
|
||||
ClientHeight = 452
|
||||
ClientWidth = 655
|
||||
OnCreate = FormCreate
|
||||
LCLVersion = '1.9.0.0'
|
||||
object BottomPanel: TPanel
|
||||
Left = 8
|
||||
Height = 91
|
||||
Top = 333
|
||||
Top = 353
|
||||
Width = 647
|
||||
Align = alBottom
|
||||
AutoSize = True
|
||||
@ -26,11 +26,11 @@ object MainForm: TMainForm
|
||||
Left = 0
|
||||
Height = 78
|
||||
Top = 8
|
||||
Width = 221
|
||||
Width = 327
|
||||
AutoFill = True
|
||||
AutoSize = True
|
||||
BorderSpacing.InnerBorder = 4
|
||||
Caption = 'HTML'
|
||||
Caption = 'Show HTML codes'
|
||||
ChildSizing.LeftRightSpacing = 6
|
||||
ChildSizing.TopBottomSpacing = 6
|
||||
ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
|
||||
@ -38,21 +38,23 @@ object MainForm: TMainForm
|
||||
ChildSizing.ShrinkHorizontal = crsScaleChilds
|
||||
ChildSizing.ShrinkVertical = crsScaleChilds
|
||||
ChildSizing.Layout = cclLeftToRightThenTopToBottom
|
||||
ChildSizing.ControlsPerLine = 3
|
||||
ChildSizing.ControlsPerLine = 4
|
||||
ClientHeight = 58
|
||||
ClientWidth = 217
|
||||
Columns = 3
|
||||
ClientWidth = 323
|
||||
Columns = 4
|
||||
Items.Strings = (
|
||||
'title'
|
||||
'footer'
|
||||
'legend'
|
||||
'series labels'
|
||||
'x axis labels'
|
||||
'x axis title'
|
||||
'y axis title'
|
||||
)
|
||||
OnItemClick = CgHTMLItemClick
|
||||
TabOrder = 0
|
||||
Data = {
|
||||
050000000202020202
|
||||
0700000002020202020202
|
||||
}
|
||||
end
|
||||
object BtnCopyToClipboard: TButton
|
||||
@ -108,7 +110,7 @@ object MainForm: TMainForm
|
||||
end
|
||||
object Chart: TChart
|
||||
Left = 8
|
||||
Height = 317
|
||||
Height = 337
|
||||
Top = 8
|
||||
Width = 639
|
||||
AxisList = <
|
||||
@ -119,7 +121,7 @@ object MainForm: TMainForm
|
||||
Title.LabelFont.Height = -16
|
||||
Title.LabelFont.Orientation = 900
|
||||
Title.Visible = True
|
||||
Title.Caption = 'Area, cm<sup>2</cm>'
|
||||
Title.Caption = 'Area A, cm<sup>2</cm>'
|
||||
Title.TextFormat = tfHTML
|
||||
end
|
||||
item
|
||||
@ -127,20 +129,22 @@ object MainForm: TMainForm
|
||||
Grid.Style = psSolid
|
||||
Grid.Visible = False
|
||||
Alignment = calBottom
|
||||
Marks.TextFormat = tfHTML
|
||||
Minors = <>
|
||||
Title.LabelFont.Height = -16
|
||||
Title.Visible = True
|
||||
Title.Caption = 'Angle α'
|
||||
Title.Caption = 'Angle α, °'
|
||||
Title.TextFormat = tfHTML
|
||||
OnMarkToText = ChartAxisList1MarkToText
|
||||
end>
|
||||
BackColor = clWhite
|
||||
Foot.Alignment = taLeftJustify
|
||||
Foot.Brush.Color = clBtnFace
|
||||
Foot.Brush.Style = bsClear
|
||||
Foot.Font.Color = clBlue
|
||||
Foot.Font.Color = clGray
|
||||
Foot.Text.Strings = (
|
||||
'<u>Reference</u>:'
|
||||
'W. Shakespeare, <i>"J. Irreproducible Results"</i>, <b>38</b>, 512 (2017)'
|
||||
'W. Shakespeare, <i>"J. Irreprod. Res."</i>, <b>38</b>, 512 (2017)'
|
||||
)
|
||||
Foot.TextFormat = tfHTML
|
||||
Foot.Visible = True
|
||||
@ -148,7 +152,7 @@ object MainForm: TMainForm
|
||||
Legend.Visible = True
|
||||
Title.Brush.Color = clBtnFace
|
||||
Title.Brush.Style = bsClear
|
||||
Title.Font.Color = clBlue
|
||||
Title.Font.Color = clNavy
|
||||
Title.Font.Height = -19
|
||||
Title.Font.Style = [fsBold]
|
||||
Title.Text.Strings = (
|
||||
@ -159,35 +163,35 @@ object MainForm: TMainForm
|
||||
Align = alClient
|
||||
BorderSpacing.Around = 8
|
||||
Color = clWhite
|
||||
object RedSeries: TLineSeries
|
||||
Title = '<font color="red">Red</font> series'
|
||||
object DataSeries: TLineSeries
|
||||
Marks.Format = '%2:s'
|
||||
Marks.Frame.Color = clGray
|
||||
Marks.LinkPen.Color = clGray
|
||||
Marks.Style = smsLabel
|
||||
Marks.TextFormat = tfHTML
|
||||
Title = '<font color="red">Measured</font>'
|
||||
LinePen.Color = clRed
|
||||
Source = RedSource
|
||||
LineType = ltNone
|
||||
Pointer.Brush.Color = clRed
|
||||
Pointer.Style = psCircle
|
||||
ShowPoints = True
|
||||
end
|
||||
object BlueSeries: TLineSeries
|
||||
Title = '<font color="blue">Blue</font> series'
|
||||
LinePen.Color = clBlue
|
||||
Source = BlueSource
|
||||
object FitSeries: TFitSeries
|
||||
Marks.Alignment = taCenter
|
||||
Marks.TextFormat = tfHTML
|
||||
Title = 'Fit curve (<font color="blue">blue</font>)'
|
||||
Pen.Color = clBlue
|
||||
Pointer.Visible = False
|
||||
Source = ListChartSource
|
||||
OnFitComplete = FitSeriesFitComplete
|
||||
end
|
||||
end
|
||||
object RedSource: TRandomChartSource
|
||||
PointsNumber = 20
|
||||
RandSeed = 1926906778
|
||||
XMax = 90
|
||||
XMin = 0
|
||||
YMax = 10
|
||||
YMin = 4
|
||||
left = 121
|
||||
top = 52
|
||||
object ListChartSource: TListChartSource
|
||||
left = 224
|
||||
top = 88
|
||||
end
|
||||
object BlueSource: TRandomChartSource
|
||||
PointsNumber = 30
|
||||
RandSeed = 1926958054
|
||||
XMax = 90
|
||||
XMin = 0
|
||||
YMax = 8
|
||||
YMin = 0
|
||||
left = 120
|
||||
top = 111
|
||||
object ListChartSource_Fit: TListChartSource
|
||||
left = 224
|
||||
top = 153
|
||||
end
|
||||
end
|
||||
|
@ -6,7 +6,7 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, FileUtil, TAGraph, TASeries, TASources, Forms, Controls,
|
||||
Graphics, Dialogs, ExtCtrls, StdCtrls;
|
||||
Graphics, Dialogs, ExtCtrls, StdCtrls, TAChartAxisUtils, TAFuncSeries;
|
||||
|
||||
type
|
||||
|
||||
@ -18,17 +18,21 @@ type
|
||||
BtnSaveSVG: TButton;
|
||||
Chart: TChart;
|
||||
CgHTML: TCheckGroup;
|
||||
RedSource: TRandomChartSource;
|
||||
BlueSource: TRandomChartSource;
|
||||
RedSeries: TLineSeries;
|
||||
BlueSeries: TLineSeries;
|
||||
FitSeries: TFitSeries;
|
||||
ListChartSource: TListChartSource;
|
||||
DataSeries: TLineSeries;
|
||||
BottomPanel: TPanel;
|
||||
ListChartSource_Fit: TListChartSource;
|
||||
procedure BtnCopyToClipboardClick(Sender: TObject);
|
||||
procedure BtnSaveWMFClick(Sender: TObject);
|
||||
procedure BtnSaveSVGClick(Sender: TObject);
|
||||
procedure CgHTMLItemClick(Sender: TObject; Index: integer);
|
||||
procedure ChartAxisList1MarkToText(var AText: String; AMark: Double);
|
||||
procedure FitSeriesFitComplete(Sender: TObject);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
|
||||
private
|
||||
procedure CreateData;
|
||||
|
||||
public
|
||||
|
||||
@ -42,7 +46,7 @@ implementation
|
||||
{$R *.lfm}
|
||||
|
||||
uses
|
||||
TAChartUtils, {$IFDEF WINDOWS}TADrawerWMF,{$ENDIF} TADrawerSVG;
|
||||
Math, TAChartUtils, {$IFDEF WINDOWS}TADrawerWMF,{$ENDIF} TADrawerSVG;
|
||||
|
||||
{ TMainForm }
|
||||
|
||||
@ -70,26 +74,86 @@ procedure TMainForm.CgHTMLItemClick(Sender: TObject; Index: integer);
|
||||
var
|
||||
tf: TChartTextFormat;
|
||||
begin
|
||||
if CgHTML.Checked[Index] then tf := tfHTML else tf := tfNormal;
|
||||
if CgHTML.Checked[Index] then tf := tfNormal else tf := tfHTML;
|
||||
case Index of
|
||||
0: Chart.Title.TextFormat := tf;
|
||||
1: Chart.Foot.TextFormat := tf;
|
||||
2: Chart.Legend.TextFormat := tf;
|
||||
3: Chart.BottomAxis.Title.TextFormat := tf;
|
||||
4: Chart.LeftAxis.Title.TextFormat := tf;
|
||||
3: DataSeries.Marks.TextFormat := tf;
|
||||
4: Chart.BottomAxis.Marks.TextFormat := tf;
|
||||
5: Chart.BottomAxis.Title.TextFormat := tf;
|
||||
6: Chart.LeftAxis.Title.TextFormat := tf;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.ChartAxisList1MarkToText(var AText: String; AMark: Double);
|
||||
begin
|
||||
AText := AText + '°';
|
||||
end;
|
||||
|
||||
procedure TMainForm.CreateData;
|
||||
const
|
||||
N = 20;
|
||||
MIN = 0;
|
||||
MAX = 90;
|
||||
OUTLIER_INDEX = 12;
|
||||
var
|
||||
i: Integer;
|
||||
x, y: Double;
|
||||
s: String;
|
||||
begin
|
||||
for i:=0 to N-1 do begin
|
||||
x := MIN + (MAX - MIN) * i / (N-1) + 5*(random - 0.5);
|
||||
if i = OUTLIER_INDEX then begin
|
||||
y := 631;
|
||||
s := 'Defective device!' + LineEnding + '(α = ' + FormatFloat('0.00', x) + '°)';
|
||||
end else
|
||||
begin
|
||||
y := x*x / 10 + (random - 0.5) * 100;
|
||||
s := '';
|
||||
end;
|
||||
ListChartSource.Add(x, y, s);
|
||||
if i <> OUTLIER_INDEX then
|
||||
ListChartSource_Fit.Add(x, y);
|
||||
end;
|
||||
DataSeries.Source := ListChartSource;
|
||||
FitSeries.Source := ListChartSource_Fit;
|
||||
end;
|
||||
|
||||
procedure TMainForm.FitSeriesFitComplete(Sender: TObject);
|
||||
var
|
||||
p: Array of Double;
|
||||
i: Integer;
|
||||
s: String;
|
||||
begin
|
||||
SetLength(p, FitSeries.ParamCount);
|
||||
for i:=0 to FitSeries.ParamCount-1 do
|
||||
p[i] := FitSeries.Param[i];
|
||||
|
||||
s := FitSeries.EquationText.
|
||||
x('α').
|
||||
y('A').
|
||||
NumFormat('%.2f').
|
||||
DecimalSeparator('.').
|
||||
Params(p).
|
||||
Get;
|
||||
FitSeries.Title := '<font color="blue">Fitted:</font> ' + s;
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormCreate(Sender: TObject);
|
||||
begin
|
||||
CgHTML.Checked[0] := Chart.Title.TextFormat = tfHTML;
|
||||
CgHTML.Checked[1] := Chart.Foot.TextFormat = tfHTML;
|
||||
CgHTML.Checked[2] := Chart.Legend.TextFormat = tfHTML;
|
||||
CgHTML.Checked[3] := Chart.BottomAxis.Title.TextFormat = tfHTML;
|
||||
CgHTML.Checked[4] := Chart.LeftAxis.Title.TextFormat = tfHTML;
|
||||
CreateData;
|
||||
|
||||
CgHTML.Checked[0] := Chart.Title.TextFormat = tfNormal;
|
||||
CgHTML.Checked[1] := Chart.Foot.TextFormat = tfNormal;
|
||||
CgHTML.Checked[2] := Chart.Legend.TextFormat = tfNormal;
|
||||
CgHTML.Checked[3] := DataSeries.Marks.TextFormat = tfNormal;
|
||||
CgHTML.Checked[4] := Chart.BottomAxis.Marks.TextFormat = tfNormal;
|
||||
CgHTML.Checked[5] := Chart.BottomAxis.Title.TextFormat = tfNormal;
|
||||
CgHTML.Checked[6] := Chart.LeftAxis.Title.TextFormat = tfNormal;
|
||||
|
||||
{$IFDEF WINDOWS}
|
||||
Chart.Foot.Text[1] := '<font name="Times New Roman" color="blue">' + Chart.Foot.Text[1] + '</font>';
|
||||
Chart.Foot.Text[1] := '<font name="Times New Roman" color="gray">' + Chart.Foot.Text[1] + '</font>';
|
||||
{$ELSE}
|
||||
BtnSaveWMF.Hide;
|
||||
{$ENDIF}
|
||||
|
@ -14,6 +14,9 @@ unit TAFitUtils;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
TAChartUtils;
|
||||
|
||||
type
|
||||
TFitEquation = (
|
||||
fePolynomial, // y = b0 + b1*x + b2*x^2 + ... bn*x^n
|
||||
@ -23,43 +26,51 @@ type
|
||||
);
|
||||
|
||||
IFitEquationText = interface
|
||||
function DecimalSeparator(AValue: Char): IFitEquationText;
|
||||
function Equation(AEquation: TFitEquation): IFitEquationText;
|
||||
function X(AText: String): IFitEquationText;
|
||||
function Y(AText: String): IFitEquationText;
|
||||
function NumFormat(AFormat: String): IFitEquationText;
|
||||
function NumFormats(const AFormats: array of String): IFitEquationText;
|
||||
function Params(const AParams: array of Double): IFitEquationText;
|
||||
function TextFormat(AFormat: TChartTextFormat): IFitEquationText;
|
||||
function Get: String;
|
||||
end;
|
||||
|
||||
TFitEmptyEquationText = class(TInterfacedObject, IFitEquationText)
|
||||
public
|
||||
function DecimalSeparator(AValue: Char): IFitEquationText;
|
||||
function Equation(AEquation: TFitEquation): IFitEquationText;
|
||||
function X(AText: String): IFitEquationText;
|
||||
function Y(AText: String): IFitEquationText;
|
||||
function NumFormat(AFormat: String): IFitEquationText;
|
||||
function NumFormats(const AFormats: array of String): IFitEquationText;
|
||||
function Params(const AParams: array of Double): IFitEquationText;
|
||||
function TextFormat(AFormat: TChartTextFormat): IFitEquationText;
|
||||
function Get: String;
|
||||
end;
|
||||
|
||||
TFitEquationText = class(TInterfacedObject, IFitEquationText)
|
||||
strict private
|
||||
FDecSep: Char;
|
||||
FEquation: TFitEquation;
|
||||
FX: String;
|
||||
FY: String;
|
||||
FNumFormat: String;
|
||||
FNumFormats: array of String;
|
||||
FParams: array of Double;
|
||||
FTextFormat: TChartTextFormat;
|
||||
function GetNumFormat(AIndex: Integer): String;
|
||||
public
|
||||
constructor Create;
|
||||
function DecimalSeparator(AValue: Char): IFitEquationText;
|
||||
function Equation(AEquation: TFitEquation): IFitEquationText;
|
||||
function X(AText: String): IFitEquationText;
|
||||
function Y(AText: String): IFitEquationText;
|
||||
function NumFormat(AFormat: String): IFitEquationText;
|
||||
function NumFormats(const AFormats: array of String): IFitEquationText;
|
||||
function Params(const AParams: array of Double): IFitEquationText;
|
||||
function TextFormat(AFormat: TChartTextFormat): IFitEquationText;
|
||||
function Get: String;
|
||||
end;
|
||||
|
||||
@ -68,15 +79,22 @@ type
|
||||
implementation
|
||||
|
||||
uses
|
||||
TAChartUtils, StrUtils, SysUtils;
|
||||
StrUtils, SysUtils;
|
||||
|
||||
operator := (AEq: IFitEquationText): String;
|
||||
begin
|
||||
Result := AEq.Get;
|
||||
end;
|
||||
|
||||
|
||||
{ TFitEmptyEquationText }
|
||||
|
||||
function TFitEmptyEquationText.DecimalSeparator(AValue: Char): IFitEquationText;
|
||||
begin
|
||||
Unused(AValue);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function TFitEmptyEquationText.Equation(
|
||||
AEquation: TFitEquation): IFitEquationText;
|
||||
begin
|
||||
@ -109,6 +127,12 @@ begin
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function TFitEmptyEquationText.TextFormat(AFormat: TChartTextFormat): IFitEquationText;
|
||||
begin
|
||||
Unused(AFormat);
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function TFitEmptyEquationText.X(AText: String): IFitEquationText;
|
||||
begin
|
||||
Unused(AText);
|
||||
@ -128,6 +152,13 @@ begin
|
||||
FX := 'x';
|
||||
FY := 'y';
|
||||
FNumFormat := '%.9g';
|
||||
FDecSep := DefaultFormatSettings.DecimalSeparator;
|
||||
end;
|
||||
|
||||
function TFitEquationText.DecimalSeparator(AValue: Char): IFitEquationText;
|
||||
begin
|
||||
FDecSep := AValue;
|
||||
Result := self;
|
||||
end;
|
||||
|
||||
function TFitEquationText.Equation(AEquation: TFitEquation): IFitEquationText;
|
||||
@ -139,24 +170,54 @@ end;
|
||||
function TFitEquationText.Get: String;
|
||||
var
|
||||
ps: String = '';
|
||||
s: String;
|
||||
i: Integer;
|
||||
fs: TFormatSettings;
|
||||
begin
|
||||
if Length(FParams) = 0 then exit('');
|
||||
Result := Format('%s = ' + GetNumFormat(0), [FY, FParams[0]]);
|
||||
if Length(FParams) = 0 then
|
||||
exit('');
|
||||
|
||||
fs := DefaultFormatSettings;
|
||||
fs.DecimalSeparator := FDecSep;
|
||||
|
||||
Result := Format('%s = ' + GetNumFormat(0), [FY, FParams[0]], fs);
|
||||
if FEquation in [fePolynomial, feLinear] then
|
||||
for i := 1 to High(FParams) do begin
|
||||
if FParams[i] = 0 then continue;
|
||||
if i > 1 then ps := Format('^%d', [i]);
|
||||
Result += Format(
|
||||
' %s ' + GetNumFormat(i) + '*%s%s',
|
||||
[IfThen(FParams[i] > 0, '+', '-'), Abs(FParams[i]), FX, ps]);
|
||||
if FParams[i] = 0 then
|
||||
continue;
|
||||
if FTextFormat = tfNormal then
|
||||
begin
|
||||
if i > 1 then ps := Format('^%d', [i]);
|
||||
s := '*%s%s';
|
||||
end else
|
||||
begin
|
||||
if i > 1 then ps := Format('<sup>%d</sup>', [i]);
|
||||
s := '·%s%s';
|
||||
end;
|
||||
Result += Format(' %s ' + GetNumFormat(i) + s,
|
||||
[IfThen(FParams[i] > 0, '+', '-'), Abs(FParams[i]), FX, ps], fs
|
||||
);
|
||||
end
|
||||
else if (Length(FParams) >= 2) and (FParams[0] <> 0) and (FParams[1] <> 0) then
|
||||
case FEquation of
|
||||
feExp:
|
||||
Result += Format(' * exp(' + GetNumFormat(1) +' * %s)', [FParams[1], FX]);
|
||||
if FTextFormat = tfNormal then
|
||||
Result += Format(' * exp(' + GetNumFormat(1) +' * %s)',
|
||||
[FParams[1], FX], fs
|
||||
)
|
||||
else
|
||||
Result += Format(' · e<sup>' + GetNumFormat(1) + '· %s</sup>',
|
||||
[FParams[1], FX], fs
|
||||
);
|
||||
fePower:
|
||||
Result += Format(' * %s^' + GetNumFormat(1), [FX, FParams[1]]);
|
||||
if FTextFormat = tfNormal then
|
||||
Result += Format(' * %s^' + GetNumFormat(1),
|
||||
[FX, FParams[1]], fs
|
||||
)
|
||||
else
|
||||
Result += Format(' · %s<sup>' + GetNumFormat(1) + '</sup>',
|
||||
[FX, FParams[1]], fs
|
||||
);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -196,6 +257,12 @@ begin
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function TFitEquationText.TextFormat(AFormat: TChartTextFormat): IFitEquationText;
|
||||
begin
|
||||
FTextFormat := AFormat;
|
||||
Result := Self;
|
||||
end;
|
||||
|
||||
function TFitEquationText.X(AText: String): IFitEquationText;
|
||||
begin
|
||||
FX := AText;
|
||||
|
@ -1489,7 +1489,7 @@ begin
|
||||
Result := TFitEquationText.Create
|
||||
else
|
||||
Result := TFitEmptyEquationText.Create;
|
||||
Result.Equation(FitEquation).Params(FFitParams);
|
||||
Result.TextFormat(Marks.TextFormat).Equation(FitEquation).Params(FFitParams);
|
||||
end;
|
||||
|
||||
procedure TFitSeries.ExecFit;
|
||||
|
Loading…
Reference in New Issue
Block a user