{
*****************************************************************************
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
Authors: Alexander Klenin
}
unit TAFitUtils;
{$H+}
interface
uses
TAChartUtils;
type
TFitEquation = (
fePolynomial, // y = b0 + b1*x + b2*x^2 + ... bn*x^n
feLinear, // y = a + b*x
feExp, // y = a * exp(b * x)
fePower // y = a * x^b
);
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;
operator :=(AEq: IFitEquationText): String; inline;
implementation
uses
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
Unused(AEquation);
Result := Self;
end;
function TFitEmptyEquationText.Get: String;
begin
Result := '';
end;
function TFitEmptyEquationText.NumFormat(AFormat: String): IFitEquationText;
begin
Unused(AFormat);
Result := Self;
end;
function TFitEmptyEquationText.NumFormats(
const AFormats: array of String): IFitEquationText;
begin
Unused(AFormats);
Result := Self;
end;
function TFitEmptyEquationText.Params(
const AParams: array of Double): IFitEquationText;
begin
Unused(AParams);
Result := Self;
end;
function TFitEmptyEquationText.TextFormat(AFormat: TChartTextFormat): IFitEquationText;
begin
Unused(AFormat);
Result := Self;
end;
function TFitEmptyEquationText.X(AText: String): IFitEquationText;
begin
Unused(AText);
Result := Self;
end;
function TFitEmptyEquationText.Y(AText: String): IFitEquationText;
begin
Unused(AText);
Result := Self;
end;
{ TFitEquationText }
constructor TFitEquationText.Create;
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;
begin
FEquation := AEquation;
Result := Self;
end;
function TFitEquationText.Get: String;
var
ps: String = '';
s: String;
i: Integer;
fs: TFormatSettings;
begin
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 FTextFormat = tfNormal then
begin
if i > 1 then ps := Format('^%d', [i]);
s := '*%s%s';
end else
begin
if i > 1 then ps := Format('%d', [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:
if FTextFormat = tfNormal then
Result += Format(' * exp(' + GetNumFormat(1) +' * %s)',
[FParams[1], FX], fs
)
else
Result += Format(' · e' + GetNumFormat(1) + '· %s',
[FParams[1], FX], fs
);
fePower:
if FTextFormat = tfNormal then
Result += Format(' * %s^' + GetNumFormat(1),
[FX, FParams[1]], fs
)
else
Result += Format(' · %s' + GetNumFormat(1) + '',
[FX, FParams[1]], fs
);
end;
end;
function TFitEquationText.GetNumFormat(AIndex: Integer): String;
begin
if AIndex < Length(FNumFormats) then
Result := FNumFormats[AIndex]
else
Result := FNumFormat;
end;
function TFitEquationText.NumFormat(AFormat: String): IFitEquationText;
begin
FNumFormat := AFormat;
Result := Self;
end;
function TFitEquationText.NumFormats(
const AFormats: array of String): IFitEquationText;
var
i: Integer;
begin
SetLength(FNumFormats, Length(AFormats));
for i := 0 to High(AFormats) do
FNumFormats[i] := AFormats[i];
Result := Self;
end;
function TFitEquationText.Params(
const AParams: array of Double): IFitEquationText;
var
i: Integer;
begin
SetLength(FParams, Length(AParams));
for i := 0 to High(AParams) do
FParams[i] := AParams[i];
Result := Self;
end;
function TFitEquationText.TextFormat(AFormat: TChartTextFormat): IFitEquationText;
begin
FTextFormat := AFormat;
Result := Self;
end;
function TFitEquationText.X(AText: String): IFitEquationText;
begin
FX := AText;
Result := Self;
end;
function TFitEquationText.Y(AText: String): IFitEquationText;
begin
FY := AText;
Result := Self;
end;
end.