TAChart: Usa HTML tags in fit equation of TFitSeries. Use FitSeries in html demo.

git-svn-id: trunk@55449 -
This commit is contained in:
wp 2017-07-05 11:03:02 +00:00
parent d4b7ead41d
commit e4049c3629
4 changed files with 201 additions and 66 deletions

View File

@ -1,17 +1,17 @@
object MainForm: TMainForm object MainForm: TMainForm
Left = 280 Left = 280
Height = 432 Height = 452
Top = 130 Top = 130
Width = 655 Width = 655
Caption = 'HTML demo' Caption = 'HTML demo'
ClientHeight = 432 ClientHeight = 452
ClientWidth = 655 ClientWidth = 655
OnCreate = FormCreate OnCreate = FormCreate
LCLVersion = '1.9.0.0' LCLVersion = '1.9.0.0'
object BottomPanel: TPanel object BottomPanel: TPanel
Left = 8 Left = 8
Height = 91 Height = 91
Top = 333 Top = 353
Width = 647 Width = 647
Align = alBottom Align = alBottom
AutoSize = True AutoSize = True
@ -26,11 +26,11 @@ object MainForm: TMainForm
Left = 0 Left = 0
Height = 78 Height = 78
Top = 8 Top = 8
Width = 221 Width = 327
AutoFill = True AutoFill = True
AutoSize = True AutoSize = True
BorderSpacing.InnerBorder = 4 BorderSpacing.InnerBorder = 4
Caption = 'HTML' Caption = 'Show HTML codes'
ChildSizing.LeftRightSpacing = 6 ChildSizing.LeftRightSpacing = 6
ChildSizing.TopBottomSpacing = 6 ChildSizing.TopBottomSpacing = 6
ChildSizing.EnlargeHorizontal = crsHomogenousChildResize ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
@ -38,21 +38,23 @@ object MainForm: TMainForm
ChildSizing.ShrinkHorizontal = crsScaleChilds ChildSizing.ShrinkHorizontal = crsScaleChilds
ChildSizing.ShrinkVertical = crsScaleChilds ChildSizing.ShrinkVertical = crsScaleChilds
ChildSizing.Layout = cclLeftToRightThenTopToBottom ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 3 ChildSizing.ControlsPerLine = 4
ClientHeight = 58 ClientHeight = 58
ClientWidth = 217 ClientWidth = 323
Columns = 3 Columns = 4
Items.Strings = ( Items.Strings = (
'title' 'title'
'footer' 'footer'
'legend' 'legend'
'series labels'
'x axis labels'
'x axis title' 'x axis title'
'y axis title' 'y axis title'
) )
OnItemClick = CgHTMLItemClick OnItemClick = CgHTMLItemClick
TabOrder = 0 TabOrder = 0
Data = { Data = {
050000000202020202 0700000002020202020202
} }
end end
object BtnCopyToClipboard: TButton object BtnCopyToClipboard: TButton
@ -108,7 +110,7 @@ object MainForm: TMainForm
end end
object Chart: TChart object Chart: TChart
Left = 8 Left = 8
Height = 317 Height = 337
Top = 8 Top = 8
Width = 639 Width = 639
AxisList = < AxisList = <
@ -119,7 +121,7 @@ object MainForm: TMainForm
Title.LabelFont.Height = -16 Title.LabelFont.Height = -16
Title.LabelFont.Orientation = 900 Title.LabelFont.Orientation = 900
Title.Visible = True Title.Visible = True
Title.Caption = 'Area, cm<sup>2</cm>' Title.Caption = 'Area A, cm<sup>2</cm>'
Title.TextFormat = tfHTML Title.TextFormat = tfHTML
end end
item item
@ -127,20 +129,22 @@ object MainForm: TMainForm
Grid.Style = psSolid Grid.Style = psSolid
Grid.Visible = False Grid.Visible = False
Alignment = calBottom Alignment = calBottom
Marks.TextFormat = tfHTML
Minors = <> Minors = <>
Title.LabelFont.Height = -16 Title.LabelFont.Height = -16
Title.Visible = True Title.Visible = True
Title.Caption = 'Angle &alpha;' Title.Caption = 'Angle &alpha;, &deg;'
Title.TextFormat = tfHTML Title.TextFormat = tfHTML
OnMarkToText = ChartAxisList1MarkToText
end> end>
BackColor = clWhite BackColor = clWhite
Foot.Alignment = taLeftJustify Foot.Alignment = taLeftJustify
Foot.Brush.Color = clBtnFace Foot.Brush.Color = clBtnFace
Foot.Brush.Style = bsClear Foot.Brush.Style = bsClear
Foot.Font.Color = clBlue Foot.Font.Color = clGray
Foot.Text.Strings = ( Foot.Text.Strings = (
'<u>Reference</u>:' '<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.TextFormat = tfHTML
Foot.Visible = True Foot.Visible = True
@ -148,7 +152,7 @@ object MainForm: TMainForm
Legend.Visible = True Legend.Visible = True
Title.Brush.Color = clBtnFace Title.Brush.Color = clBtnFace
Title.Brush.Style = bsClear Title.Brush.Style = bsClear
Title.Font.Color = clBlue Title.Font.Color = clNavy
Title.Font.Height = -19 Title.Font.Height = -19
Title.Font.Style = [fsBold] Title.Font.Style = [fsBold]
Title.Text.Strings = ( Title.Text.Strings = (
@ -159,35 +163,35 @@ object MainForm: TMainForm
Align = alClient Align = alClient
BorderSpacing.Around = 8 BorderSpacing.Around = 8
Color = clWhite Color = clWhite
object RedSeries: TLineSeries object DataSeries: TLineSeries
Title = '<font color="red">Red</font> series' 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 LinePen.Color = clRed
Source = RedSource LineType = ltNone
Pointer.Brush.Color = clRed
Pointer.Style = psCircle
ShowPoints = True
end end
object BlueSeries: TLineSeries object FitSeries: TFitSeries
Title = '<font color="blue">Blue</font> series' Marks.Alignment = taCenter
LinePen.Color = clBlue Marks.TextFormat = tfHTML
Source = BlueSource Title = 'Fit curve (<font color="blue">blue</font>)'
Pen.Color = clBlue
Pointer.Visible = False
Source = ListChartSource
OnFitComplete = FitSeriesFitComplete
end end
end end
object RedSource: TRandomChartSource object ListChartSource: TListChartSource
PointsNumber = 20 left = 224
RandSeed = 1926906778 top = 88
XMax = 90
XMin = 0
YMax = 10
YMin = 4
left = 121
top = 52
end end
object BlueSource: TRandomChartSource object ListChartSource_Fit: TListChartSource
PointsNumber = 30 left = 224
RandSeed = 1926958054 top = 153
XMax = 90
XMin = 0
YMax = 8
YMin = 0
left = 120
top = 111
end end
end end

View File

@ -6,7 +6,7 @@ interface
uses uses
Classes, SysUtils, FileUtil, TAGraph, TASeries, TASources, Forms, Controls, Classes, SysUtils, FileUtil, TAGraph, TASeries, TASources, Forms, Controls,
Graphics, Dialogs, ExtCtrls, StdCtrls; Graphics, Dialogs, ExtCtrls, StdCtrls, TAChartAxisUtils, TAFuncSeries;
type type
@ -18,17 +18,21 @@ type
BtnSaveSVG: TButton; BtnSaveSVG: TButton;
Chart: TChart; Chart: TChart;
CgHTML: TCheckGroup; CgHTML: TCheckGroup;
RedSource: TRandomChartSource; FitSeries: TFitSeries;
BlueSource: TRandomChartSource; ListChartSource: TListChartSource;
RedSeries: TLineSeries; DataSeries: TLineSeries;
BlueSeries: TLineSeries;
BottomPanel: TPanel; BottomPanel: TPanel;
ListChartSource_Fit: TListChartSource;
procedure BtnCopyToClipboardClick(Sender: TObject); procedure BtnCopyToClipboardClick(Sender: TObject);
procedure BtnSaveWMFClick(Sender: TObject); procedure BtnSaveWMFClick(Sender: TObject);
procedure BtnSaveSVGClick(Sender: TObject); procedure BtnSaveSVGClick(Sender: TObject);
procedure CgHTMLItemClick(Sender: TObject; Index: integer); procedure CgHTMLItemClick(Sender: TObject; Index: integer);
procedure ChartAxisList1MarkToText(var AText: String; AMark: Double);
procedure FitSeriesFitComplete(Sender: TObject);
procedure FormCreate(Sender: TObject); procedure FormCreate(Sender: TObject);
private private
procedure CreateData;
public public
@ -42,7 +46,7 @@ implementation
{$R *.lfm} {$R *.lfm}
uses uses
TAChartUtils, {$IFDEF WINDOWS}TADrawerWMF,{$ENDIF} TADrawerSVG; Math, TAChartUtils, {$IFDEF WINDOWS}TADrawerWMF,{$ENDIF} TADrawerSVG;
{ TMainForm } { TMainForm }
@ -70,26 +74,86 @@ procedure TMainForm.CgHTMLItemClick(Sender: TObject; Index: integer);
var var
tf: TChartTextFormat; tf: TChartTextFormat;
begin begin
if CgHTML.Checked[Index] then tf := tfHTML else tf := tfNormal; if CgHTML.Checked[Index] then tf := tfNormal else tf := tfHTML;
case Index of case Index of
0: Chart.Title.TextFormat := tf; 0: Chart.Title.TextFormat := tf;
1: Chart.Foot.TextFormat := tf; 1: Chart.Foot.TextFormat := tf;
2: Chart.Legend.TextFormat := tf; 2: Chart.Legend.TextFormat := tf;
3: Chart.BottomAxis.Title.TextFormat := tf; 3: DataSeries.Marks.TextFormat := tf;
4: Chart.LeftAxis.Title.TextFormat := tf; 4: Chart.BottomAxis.Marks.TextFormat := tf;
5: Chart.BottomAxis.Title.TextFormat := tf;
6: Chart.LeftAxis.Title.TextFormat := tf;
end; end;
end; end;
procedure TMainForm.ChartAxisList1MarkToText(var AText: String; AMark: Double);
begin
AText := AText + '&deg;';
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 + '(&alpha; = ' + FormatFloat('0.00', x) + '&deg;)';
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('&alpha;').
y('A').
NumFormat('%.2f').
DecimalSeparator('.').
Params(p).
Get;
FitSeries.Title := '<font color="blue">Fitted:</font> ' + s;
end;
procedure TMainForm.FormCreate(Sender: TObject); procedure TMainForm.FormCreate(Sender: TObject);
begin begin
CgHTML.Checked[0] := Chart.Title.TextFormat = tfHTML; CreateData;
CgHTML.Checked[1] := Chart.Foot.TextFormat = tfHTML;
CgHTML.Checked[2] := Chart.Legend.TextFormat = tfHTML; CgHTML.Checked[0] := Chart.Title.TextFormat = tfNormal;
CgHTML.Checked[3] := Chart.BottomAxis.Title.TextFormat = tfHTML; CgHTML.Checked[1] := Chart.Foot.TextFormat = tfNormal;
CgHTML.Checked[4] := Chart.LeftAxis.Title.TextFormat = tfHTML; 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} {$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} {$ELSE}
BtnSaveWMF.Hide; BtnSaveWMF.Hide;
{$ENDIF} {$ENDIF}

View File

@ -14,6 +14,9 @@ unit TAFitUtils;
interface interface
uses
TAChartUtils;
type type
TFitEquation = ( TFitEquation = (
fePolynomial, // y = b0 + b1*x + b2*x^2 + ... bn*x^n fePolynomial, // y = b0 + b1*x + b2*x^2 + ... bn*x^n
@ -23,43 +26,51 @@ type
); );
IFitEquationText = interface IFitEquationText = interface
function DecimalSeparator(AValue: Char): IFitEquationText;
function Equation(AEquation: TFitEquation): IFitEquationText; function Equation(AEquation: TFitEquation): IFitEquationText;
function X(AText: String): IFitEquationText; function X(AText: String): IFitEquationText;
function Y(AText: String): IFitEquationText; function Y(AText: String): IFitEquationText;
function NumFormat(AFormat: String): IFitEquationText; function NumFormat(AFormat: String): IFitEquationText;
function NumFormats(const AFormats: array of String): IFitEquationText; function NumFormats(const AFormats: array of String): IFitEquationText;
function Params(const AParams: array of Double): IFitEquationText; function Params(const AParams: array of Double): IFitEquationText;
function TextFormat(AFormat: TChartTextFormat): IFitEquationText;
function Get: String; function Get: String;
end; end;
TFitEmptyEquationText = class(TInterfacedObject, IFitEquationText) TFitEmptyEquationText = class(TInterfacedObject, IFitEquationText)
public public
function DecimalSeparator(AValue: Char): IFitEquationText;
function Equation(AEquation: TFitEquation): IFitEquationText; function Equation(AEquation: TFitEquation): IFitEquationText;
function X(AText: String): IFitEquationText; function X(AText: String): IFitEquationText;
function Y(AText: String): IFitEquationText; function Y(AText: String): IFitEquationText;
function NumFormat(AFormat: String): IFitEquationText; function NumFormat(AFormat: String): IFitEquationText;
function NumFormats(const AFormats: array of String): IFitEquationText; function NumFormats(const AFormats: array of String): IFitEquationText;
function Params(const AParams: array of Double): IFitEquationText; function Params(const AParams: array of Double): IFitEquationText;
function TextFormat(AFormat: TChartTextFormat): IFitEquationText;
function Get: String; function Get: String;
end; end;
TFitEquationText = class(TInterfacedObject, IFitEquationText) TFitEquationText = class(TInterfacedObject, IFitEquationText)
strict private strict private
FDecSep: Char;
FEquation: TFitEquation; FEquation: TFitEquation;
FX: String; FX: String;
FY: String; FY: String;
FNumFormat: String; FNumFormat: String;
FNumFormats: array of String; FNumFormats: array of String;
FParams: array of Double; FParams: array of Double;
FTextFormat: TChartTextFormat;
function GetNumFormat(AIndex: Integer): String; function GetNumFormat(AIndex: Integer): String;
public public
constructor Create; constructor Create;
function DecimalSeparator(AValue: Char): IFitEquationText;
function Equation(AEquation: TFitEquation): IFitEquationText; function Equation(AEquation: TFitEquation): IFitEquationText;
function X(AText: String): IFitEquationText; function X(AText: String): IFitEquationText;
function Y(AText: String): IFitEquationText; function Y(AText: String): IFitEquationText;
function NumFormat(AFormat: String): IFitEquationText; function NumFormat(AFormat: String): IFitEquationText;
function NumFormats(const AFormats: array of String): IFitEquationText; function NumFormats(const AFormats: array of String): IFitEquationText;
function Params(const AParams: array of Double): IFitEquationText; function Params(const AParams: array of Double): IFitEquationText;
function TextFormat(AFormat: TChartTextFormat): IFitEquationText;
function Get: String; function Get: String;
end; end;
@ -68,15 +79,22 @@ type
implementation implementation
uses uses
TAChartUtils, StrUtils, SysUtils; StrUtils, SysUtils;
operator := (AEq: IFitEquationText): String; operator := (AEq: IFitEquationText): String;
begin begin
Result := AEq.Get; Result := AEq.Get;
end; end;
{ TFitEmptyEquationText } { TFitEmptyEquationText }
function TFitEmptyEquationText.DecimalSeparator(AValue: Char): IFitEquationText;
begin
Unused(AValue);
Result := Self;
end;
function TFitEmptyEquationText.Equation( function TFitEmptyEquationText.Equation(
AEquation: TFitEquation): IFitEquationText; AEquation: TFitEquation): IFitEquationText;
begin begin
@ -109,6 +127,12 @@ begin
Result := Self; Result := Self;
end; end;
function TFitEmptyEquationText.TextFormat(AFormat: TChartTextFormat): IFitEquationText;
begin
Unused(AFormat);
Result := Self;
end;
function TFitEmptyEquationText.X(AText: String): IFitEquationText; function TFitEmptyEquationText.X(AText: String): IFitEquationText;
begin begin
Unused(AText); Unused(AText);
@ -128,6 +152,13 @@ begin
FX := 'x'; FX := 'x';
FY := 'y'; FY := 'y';
FNumFormat := '%.9g'; FNumFormat := '%.9g';
FDecSep := DefaultFormatSettings.DecimalSeparator;
end;
function TFitEquationText.DecimalSeparator(AValue: Char): IFitEquationText;
begin
FDecSep := AValue;
Result := self;
end; end;
function TFitEquationText.Equation(AEquation: TFitEquation): IFitEquationText; function TFitEquationText.Equation(AEquation: TFitEquation): IFitEquationText;
@ -139,24 +170,54 @@ end;
function TFitEquationText.Get: String; function TFitEquationText.Get: String;
var var
ps: String = ''; ps: String = '';
s: String;
i: Integer; i: Integer;
fs: TFormatSettings;
begin begin
if Length(FParams) = 0 then exit(''); if Length(FParams) = 0 then
Result := Format('%s = ' + GetNumFormat(0), [FY, FParams[0]]); exit('');
fs := DefaultFormatSettings;
fs.DecimalSeparator := FDecSep;
Result := Format('%s = ' + GetNumFormat(0), [FY, FParams[0]], fs);
if FEquation in [fePolynomial, feLinear] then if FEquation in [fePolynomial, feLinear] then
for i := 1 to High(FParams) do begin for i := 1 to High(FParams) do begin
if FParams[i] = 0 then continue; if FParams[i] = 0 then
continue;
if FTextFormat = tfNormal then
begin
if i > 1 then ps := Format('^%d', [i]); if i > 1 then ps := Format('^%d', [i]);
Result += Format( s := '*%s%s';
' %s ' + GetNumFormat(i) + '*%s%s', end else
[IfThen(FParams[i] > 0, '+', '-'), Abs(FParams[i]), FX, ps]); begin
if i > 1 then ps := Format('<sup>%d</sup>', [i]);
s := '&middot;%s%s';
end;
Result += Format(' %s ' + GetNumFormat(i) + s,
[IfThen(FParams[i] > 0, '+', '-'), Abs(FParams[i]), FX, ps], fs
);
end end
else if (Length(FParams) >= 2) and (FParams[0] <> 0) and (FParams[1] <> 0) then else if (Length(FParams) >= 2) and (FParams[0] <> 0) and (FParams[1] <> 0) then
case FEquation of case FEquation of
feExp: 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(' &middot; e<sup>' + GetNumFormat(1) + '&middot; %s</sup>',
[FParams[1], FX], fs
);
fePower: 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(' &middot; %s<sup>' + GetNumFormat(1) + '</sup>',
[FX, FParams[1]], fs
);
end; end;
end; end;
@ -196,6 +257,12 @@ begin
Result := Self; Result := Self;
end; end;
function TFitEquationText.TextFormat(AFormat: TChartTextFormat): IFitEquationText;
begin
FTextFormat := AFormat;
Result := Self;
end;
function TFitEquationText.X(AText: String): IFitEquationText; function TFitEquationText.X(AText: String): IFitEquationText;
begin begin
FX := AText; FX := AText;

View File

@ -1489,7 +1489,7 @@ begin
Result := TFitEquationText.Create Result := TFitEquationText.Create
else else
Result := TFitEmptyEquationText.Create; Result := TFitEmptyEquationText.Create;
Result.Equation(FitEquation).Params(FFitParams); Result.TextFormat(Marks.TextFormat).Equation(FitEquation).Params(FFitParams);
end; end;
procedure TFitSeries.ExecFit; procedure TFitSeries.ExecFit;