{ Apophysis AV "Phoenix Edition" Copyright (C) 2021 Alice V. Koryagina }

unit varArch;

interface
uses
  BaseVariation, XFormMan;

const
  sweight = 'Z_arch_weight';

type
  TVariationArch = class(TBaseVariation)
  private
   vpi, weight: 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;
  
////////////////////////
procedure TVariationArch.Prepare;
begin
  vpi := pi * weight;   // arch behavior
end;

procedure TVariationArch.CalcFunction;
var
  sinr, cosr: double;
begin
  SinCos(random * vpi, sinr, cosr);
  if cosr = 0 then exit;
  
  FPx^ := FPx^ + vvar * sinr;
  FPy^ := FPy^ + sqr(sinr) / cosr * vvar;
end;

constructor TVariationArch.Create;
begin
  inherited Create;
  weight := 1;
end;

class function TVariationArch.GetInstance: TBaseVariation;
begin
   Result := TVariationArch.Create;
end;

class function TVariationArch.GetName: string;
begin
   Result := 'Z_arch';
end;

{ ////////////////////////////////////////////////////////////////////// }

function TVariationArch.GetVariableNameAt(const Index: integer): string;
begin
  case Index Of
  0: Result := sweight;
  else
    Result := '';
  end;
end;

function TVariationArch.GetNrVariables: integer;
begin
  Result := 1;
end;

function TVariationArch.GetVariable(const Name: string; var value: double): boolean;
begin
  Result := False;
  if Name = sweight then begin
    Value := weight;
    Result := True;
  end;
end;

function TVariationArch.SetVariable(const Name: string; var value: double): boolean;
begin
  Result := False;
  if Name = sweight then begin
    weight := Value;
    Result := True;
  end; 
end;

function TVariationArch.ResetVariable(const Name: string): boolean;
begin
  Result := False;
  if Name = sweight then begin
    weight := 1;
    Result := True;
  end;
end;

{ ///////////////////////////////////////////////////////////////////////////// }
initialization
  RegisterVariation(TVariationClassLoader.Create(TVariationArch), false, false);

end.
