{ Apophysis AV "Phoenix Edition" Copyright (C) 2021 Alice V. Koryagina } unit varInversion3D; interface uses BaseVariation, XFormMan; const sr = 'inversion3D_radius'; sx0 = 'inversion3D_x0'; sy0 = 'inversion3D_y0'; sz0 = 'inversion3D_z0'; type TVariationInversion3D = class(TBaseVariation) private r, r2, x0, y0, z0: 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; { TVariationInversion3D } ////////////////////////////////////////// procedure TVariationInversion3D.Prepare; begin r2 := sqr(r); end; ////////////////////////////////////////// procedure TVariationInversion3D.CalcFunction; var x, y, z, dist: double; begin x := FTx^ - x0; y := FTy^ - y0; z := FTz^ - z0; dist := sqr(x) + sqr(y) + sqr(z) + 1E-30; FPx^ := FPx^ + vvar * (r2 * x / dist + x0); FPy^ := FPy^ + vvar * (r2 * y / dist + y0); FPz^ := FPz^ + vvar * (r2 * z / dist + z0); end; /////////////////////////////////////////////////////////////////////////////// constructor TVariationInversion3D.Create; begin r := 1; x0 := 0; y0 := 0; z0 := 0; end; /////////////////////////////////////////////////////////////////////////////// class function TVariationInversion3D.GetInstance: TBaseVariation; begin Result := TVariationInversion3D.Create; end; /////////////////////////////////////////////////////////////////////////////// class function TVariationInversion3D.GetName: string; begin Result := 'inversion3D'; end; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// function TVariationInversion3D.GetVariableNameAt(const Index: integer): string; begin case Index of 0: Result := sr; 1: Result := sx0; 2: Result := sy0; 3: Result := sz0; else Result := ''; end end; /////////////////////////////////////////////////////////////////////////////// function TVariationInversion3D.SetVariable(const Name: string; var value: double): boolean; begin Result := False; if Name = sr then begin if (Value < 1E-6) then Value := 1E-6; r := value; Result := True; end else if Name = sx0 then begin x0 := Value; Result := True; end else if Name = sy0 then begin y0 := Value; Result := True; end else if Name = sz0 then begin z0 := Value; Result := True; end; end; function TVariationInversion3D.ResetVariable(const Name: string): boolean; begin Result := False; if Name = sr then begin r := 1; Result := True; end else if Name = sx0 then begin x0 := 0; Result := True; end else if Name = sy0 then begin y0 := 0; Result := True; end else if Name = sz0 then begin z0 := 0; Result := True; end; end; ///////////////////////////////////////////////////////////////////// function TVariationInversion3D.GetNrVariables: integer; begin Result := 4; end; /////////////////////////////////////////////////////////////////////////////// function TVariationInversion3D.GetVariable(const Name: string; var value: double): boolean; begin Result := False; if Name = sr then begin Value := r; Result := True; end else if Name = sx0 then begin Value := x0; Result := True; end else if Name = sy0 then begin Value := y0; Result := True; end else if Name = sz0 then begin Value := z0; Result := True; end; end; /////////////////////////////////////////////////////////////////////////////// initialization RegisterVariation(TVariationClassLoader.Create(TVariationInversion3D), true, false); end.