diff --git a/components/tachart/tafuncseries.pas b/components/tachart/tafuncseries.pas index 6f3e766ac4..963ddaeb95 100644 --- a/components/tachart/tafuncseries.pas +++ b/components/tachart/tafuncseries.pas @@ -209,6 +209,38 @@ type ); TFitSeries = class(TBasicPointSeries) + public + type + IEquationText = interface + function Equation(AEquation: TFitEquation): IEquationText; + function X(AText: String): IEquationText; + function Y(AText: String): IEquationText; + function NumFormat(AFormat: String): IEquationText; + function NumFormats(const AFormats: array of String): IEquationText; + function Params(const AParams: array of Double): IEquationText; + function Get: String; + end; + + TEquationText = class(TInterfacedObject, IEquationText) + strict private + FEquation: TFitEquation; + FX: String; + FY: String; + FNumFormat: String; + FNumFormats: array of String; + FParams: array of Double; + function GetNumFormat(AIndex: Integer): String; + public + constructor Create; + function Equation(AEquation: TFitEquation): IEquationText; + function X(AText: String): IEquationText; + function Y(AText: String): IEquationText; + function NumFormat(AFormat: String): IEquationText; + function NumFormats(const AFormats: array of String): IEquationText; + function Params(const AParams: array of Double): IEquationText; + function Get: String; + end; + strict private FDrawFitRangeOnly: Boolean; FFitEquation: TFitEquation; @@ -242,8 +274,10 @@ type function Calculate(AX: Double): Double; virtual; procedure Draw(ADrawer: IChartDrawer); override; procedure ExecFit; virtual; + function EquationText: IEquationText; function GetFitEquationString( - ANumFormat: String; AXText: String = 'x'; AYText: String = 'y'): String; virtual; + ANumFormat: String; AXText: String = 'x'; AYText: String = 'y'): String; + deprecated 'Use EquationText'; function GetNearestPoint( const AParams: TNearestPointParams; out AResults: TNearestPointResults): Boolean; override; @@ -311,9 +345,14 @@ type read FStepY write SetStepY default DEF_COLORMAP_STEP; end; + // Builds an equation string based on the parameters and the type of equation. + // AXText and AYText are placeholders for the x and y variables, respectively. + // Parameters are formatted by passing ANumFormat to the "Format" function. function ParamsToEquation( AEquation: TFitEquation; const AParams: array of Double; ANumFormat: String; AXText: String = 'x'; AYText: String = 'y'): String; + deprecated 'Use TFitSeries.IEquationText'; + operator :=(AEq: TFitSeries.IEquationText): String; inline; implementation @@ -365,35 +404,108 @@ begin Result.Y := AX; end; -// Builds an equation string based on the parameters and the type of equation. -// AXText and AYText are placeholders for the x and y variables, respectively. -// Parameters are formatted by passing ANumFormat to the "Format" function. function ParamsToEquation( AEquation: TFitEquation; const AParams: array of Double; ANumFormat, AXText, AYText: String): String; +begin + Result := + TFitSeries.TEquationText.Create.Equation(AEquation). + X(AXText).Y(AYText).NumFormat(ANumFormat).Params(AParams); +end; + +operator := (AEq: TFitSeries.IEquationText): String; +begin + Result := AEq.Get; +end; + +{ TFitSeries.TEquationText } + +constructor TFitSeries.TEquationText.Create; +begin + FX := 'x'; + FY := 'y'; + FNumFormat := '%.9g'; +end; + +function TFitSeries.TEquationText.Equation( + AEquation: TFitEquation): IEquationText; +begin + FEquation := AEquation; + Result := Self; +end; + +function TFitSeries.TEquationText.Get: String; var ps: String = ''; i: Integer; begin - if Length(AParams) = 0 then exit(''); - Result := Format('%s = ' + ANumFormat, [AYText, AParams[0]]); - if AEquation in [fePolynomial, feLinear] then - for i := 1 to High(AParams) do begin - if AParams[i] = 0 then continue; + if Length(FParams) = 0 then exit(''); + Result := Format('%s = ' + GetNumFormat(0), [FY, FParams[0]]); + 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 ' + ANumFormat + '*%s%s', - [IfThen(AParams[i] > 0, '+', '-'), Abs(AParams[i]), AXText, ps]); + ' %s ' + GetNumFormat(i) + '*%s%s', + [IfThen(FParams[i] > 0, '+', '-'), Abs(FParams[i]), FX, ps]); end - else if (Length(AParams) >= 2) and (AParams[0] <> 0) and (AParams[1] <> 0) then - case AEquation of + else if (Length(FParams) >= 2) and (FParams[0] <> 0) and (FParams[1] <> 0) then + case FEquation of feExp: - Result += Format(' * exp(' + ANumFormat +' * %s)', [AParams[1], AXText]); + Result += Format(' * exp(' + GetNumFormat(1) +' * %s)', [FParams[1], FX]); fePower: - Result += Format(' * %s^' + ANumFormat, [AXText, AParams[1]]); + Result += Format(' * %s^' + GetNumFormat(1), [FX, FParams[1]]); end; end; +function TFitSeries.TEquationText.GetNumFormat(AIndex: Integer): String; +begin + if AIndex < Length(FNumFormats) then + Result := FNumFormats[AIndex] + else + Result := FNumFormat; +end; + +function TFitSeries.TEquationText.NumFormat(AFormat: String): IEquationText; +begin + FNumFormat := AFormat; + Result := Self; +end; + +function TFitSeries.TEquationText.NumFormats( + const AFormats: array of String): IEquationText; +var + i: Integer; +begin + SetLength(FNumFormats, Length(AFormats)); + for i := 0 to High(AFormats) do + FNumFormats[i] := AFormats[i]; + Result := Self; +end; + +function TFitSeries.TEquationText.Params( + const AParams: array of Double): IEquationText; +var + i: Integer; +begin + SetLength(FParams, Length(AParams)); + for i := 0 to High(AParams) do + FParams[i] := AParams[i]; + Result := Self; +end; + +function TFitSeries.TEquationText.X(AText: String): IEquationText; +begin + FX := AText; + Result := Self; +end; + +function TFitSeries.TEquationText.Y(AText: String): IEquationText; +begin + FY := AText; + Result := Self; +end; + { TFitSeriesRange } constructor TFitSeriesRange.Create(ASeries: TFitSeries); @@ -1159,6 +1271,11 @@ begin end; end; +function TFitSeries.EquationText: IEquationText; +begin + Result := TEquationText.Create.Equation(FitEquation).Params(FFitParams); +end; + procedure TFitSeries.ExecFit; var i, j, term, ns, np, n: Integer; @@ -1214,10 +1331,10 @@ begin UpdateParentChart; end; -function TFitSeries.GetFitEquationString( - ANumFormat, AXText, AYText: String): String; +function TFitSeries.GetFitEquationString(ANumFormat: String; AXText: String; + AYText: String): String; begin - Result := ParamsToEquation(FFitEquation, FFitParams, ANumFormat, AXText, AYText); + Result := EquationText.NumFormat(ANumFormat).X(AXText).Y(AYText); end; procedure TFitSeries.GetLegendItems(AItems: TChartLegendItems); @@ -1227,7 +1344,7 @@ begin if Legend.Format = '' then t := Title else - t := Format(Legend.Format, [Title, Index, GetFitEquationString('%f')]); + t := Format(Legend.Format, [Title, Index, EquationText.NumFormat('%f').Get]); AItems.Add(TLegendItemLine.Create(Pen, t)); end;