{ Apophysis AV "Phoenix Edition" Copyright (C) 2021 Alice V. Koryagina } unit varButterfly; interface uses BaseVariation, XFormMan; type TVariationButterfly = class(TBaseVariation) const str_sx: string = 'butterfly_scale_negX'; str_sy: string = 'butterfly_scale_negY'; str_sz: string = 'butterfly_3D_shift'; private sx, sy, sz, vpi: 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; { TVariationButterfly } /////////////////////////////////////////////////////////////////////////////// procedure TVariationButterfly.Prepare; begin vpi := vvar * 4.0 / sqrt(3.0 * pi); end; procedure TVariationButterfly.CalcFunction; var r, y2: double; begin y2 := FTy^ * 2.0; r := vpi * sqrt(abs(FTy^ * FTx^)/(sqr(FTx^) + sqr(y2) + 1E-20)); if (FTy^ < 0) then begin FPx^ := FPx^ + FTx^ * r; FPy^ := FPy^ + r * y2; end else begin FPx^ := FPx^ + sx * FTx^ * r; FPy^ := FPy^ + sy * r * y2; end; if (sz <> 0) then FPz^ := FPz^ + sz * r * abs(FTx^); //* Hypot(FTx^, FTy^); end; /////////////////////////////////////////////////////////////////////////////// constructor TVariationButterfly.Create; begin sx := 1; sy := 1; sz := 0; end; /////////////////////////////////////////////////////////////////////////////// class function TVariationButterfly.GetInstance: TBaseVariation; begin Result := TVariationButterfly.Create; end; /////////////////////////////////////////////////////////////////////////////// class function TVariationButterfly.GetName: string; begin Result := 'butterfly'; end; /////////////////////////////////////////////////////////////////////////////// function TVariationButterfly.GetVariableNameAt(const Index: integer): string; begin case Index Of 0: Result := str_sx; 1: Result := str_sy; 2: Result := str_sz; else Result := ''; end end; /////////////////////////////////////////////////////////////////////////////// function TVariationButterfly.SetVariable(const Name: string; var value: double): boolean; begin Result := False; if Name = str_sx then begin if (value < 0) then value := abs(value); sx := Value; Result := True; end else if Name = str_sy then begin if (value < 0) then value := abs(value); sy := Value; Result := True; end else if Name = str_sz then begin if (value < -0.1) then value := -0.1; sz := Value; Result := True; end; end; function TVariationButterfly.ResetVariable(const Name: string): boolean; begin Result := False; if Name = str_sx then begin sx := 1; Result := True; end else if Name = str_sy then begin sy := 1; Result := True; end else if Name = str_sz then begin sz := 0; Result := True; end; end; /////////////////////////////////////////////////////////////////////////////// function TVariationButterfly.GetNrVariables: integer; begin Result := 3; end; /////////////////////////////////////////////////////////////////////////////// function TVariationButterfly.GetVariable(const Name: string; var value: double): boolean; begin Result := False; if Name = str_sx then begin Value := sx; Result := True; end else if Name = str_sy then begin Value := sy; Result := True; end else if Name = str_sz then begin Value := sz; Result := True; end end; /////////////////////////////////////////////////////////////////////////////// initialization RegisterVariation(TVariationClassLoader.Create(TVariationButterfly), true, false); end.