{ 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.