Apophysis-AV/Variations/varCpow3.pas
2022-03-08 20:25:51 +03:00

193 lines
4.6 KiB
ObjectPascal

{ Apophysis AV "Phoenix Edition" Copyright (C) 2021 Alice V. Koryagina }
unit varCpow3;
interface
uses
BaseVariation, XFormMan;
const
sr = 'cpow3_r';
sd = 'cpow3_d';
sdivisor = 'cpow3_divisor';
sspread = 'cpow3_spread';
type
TVariationCpow3 = class(TBaseVariation)
private
r, d1, spread: double;
divisor: integer;
ang, a2, d2, half_d, c2, half_c, coeff: double;
public
constructor Create;
class function GetName: string; override;
class function GetInstance: TBaseVariation; override;
function GetNrVariables: integer; override;
function GetVariableNameAt(const Index: integer): string; override;
function SetVariable(const Name: string; var value: double): boolean; override;
function GetVariable(const Name: string; var value: double): boolean; override;
function ResetVariable(const Name: string): boolean; override;
procedure Prepare; override;
procedure CalcFunction; override;
end;
implementation
uses
Math;
{ TVariationCpow3 }
//////////////////////////////////////////
procedure TVariationCpow3.Prepare;
var ca, sa: double;
begin
ang := PI2 / divisor;
if (d1 < 0) then
a2 := arctan2(-ln(-d1) * r, PI2)
else
a2 := arctan2(ln(d1) * r, PI2);
SinCos(a2, sa, ca);
c2 := ca * r * ca / divisor;
d2 := ca * r * sa / divisor;
half_c := c2 * 0.5;
half_d := d2 * 0.5;
if (d2 = 0) then
coeff := 0
else
coeff := -0.095 * spread / d2;
end;
//////////////////////////////////////////
procedure TVariationCpow3.CalcFunction;
var t, sn, cn, r2, lnr2: double;
begin
t := arctan2(FTy^, FTx^);
if (t < 0) then t := t + PI2;
if (cos(t * 0.5) < (2 * random - 1)) then
t := t - PI2;
if (random < 0.5) then
t := t + PI2 * round(ln(random) * coeff)
else
t := t - PI2 * round(ln(random) * coeff);
lnr2 := ln(FTx^ * FTx^ + FTy^ * FTy^);
r2 := vvar * exp(half_c * lnr2 - d2 * t);
SinCos(c2 * t + half_d * lnr2 + ang * random(32767), sn, cn);
FPx^ := FPx^ + r2 * cn;
FPy^ := FPy^ + r2 * sn;
end;
///////////////////////////////////////////////////////////////////////////////
constructor TVariationCpow3.Create;
begin
r := 1;
d1 := 1;
divisor := 1;
spread := 1;
end;
///////////////////////////////////////////////////////////////////////////////
class function TVariationCpow3.GetInstance: TBaseVariation;
begin
Result := TVariationCpow3.Create;
end;
///////////////////////////////////////////////////////////////////////////////
class function TVariationCpow3.GetName: string;
begin
Result := 'cpow3';
end;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
function TVariationCpow3.GetVariableNameAt(const Index: integer): string;
begin
case Index of
0: Result := sr;
1: Result := sd;
2: Result := sdivisor;
3: Result := sspread;
else
Result := '';
end
end;
///////////////////////////////////////////////////////////////////////////////
function TVariationCpow3.SetVariable(const Name: string; var value: double): boolean;
begin
Result := False;
if Name = sr then begin
r := Value;
Result := True;
end else if Name = sd then begin
if (Value = 0) then Value := 1;
d1 := value;
Result := True;
end else if Name = sdivisor then begin
if (Value = 0) then Value := 1;
divisor := Round(Value);
Result := True;
end else if Name = sspread then begin
spread := Value;
Result := True;
end;
end;
function TVariationCpow3.ResetVariable(const Name: string): boolean;
begin
Result := False;
if Name = sr then begin
r := 1;
Result := True;
end else if Name = sd then begin
d1 := 1;
Result := True;
end else if Name = sspread then begin
spread := 1;
Result := True;
end else if Name = sdivisor then begin
divisor := 1;
Result := True;
end;
end;
/////////////////////////////////////////////////////////////////////
function TVariationCpow3.GetNrVariables: integer;
begin
Result := 4;
end;
///////////////////////////////////////////////////////////////////////////////
function TVariationCpow3.GetVariable(const Name: string; var value: double): boolean;
begin
Result := False;
if Name = sr then begin
Value := r;
Result := true;
end
else if Name = sd then begin
Value := d1;
Result := true;
end else if Name = sspread then begin
Value := spread;
Result := true;
end else if Name = sdivisor then begin
Value := divisor;
Result := true;
end;
end;
///////////////////////////////////////////////////////////////////////////////
initialization
RegisterVariation(TVariationClassLoader.Create(TVariationCpow3), false, false);
end.