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

unit varPostBoarders2;

interface

uses
  BaseVariation, XFormMan;

const
  sb2c = 'post_boarders2_c';
  sleft = 'post_boarders2_left';
  sright = 'post_boarders2_right';
  eps: double = 1e-30;  
type
  TVariationPostBoarders2 = class(TBaseVariation)
  private
    b2c, left, right, cc, cl, cr: 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;

{ TVariationPostBoarders2 }

//////////////////////////////////////////
procedure TVariationPostBoarders2.Prepare;
begin
    cc := abs(b2c);
    cl := cc * abs(left);
    cr := cc + (cc * abs(right));
end;

//////////////////////////////////////////
procedure TVariationPostBoarders2.CalcFunction;
var	
	roundX, roundY, offsetX, offsetY: double;
begin
    roundX := round(FPx^);
    roundY := round(FPy^);
    offsetX := FPx^ - roundX;
    offsetY := FPy^ - roundY;

    if (random >= cr) then
    begin
        FPx^ := VVAR * (offsetX * cc + roundX);
        FPy^ := VVAR * (offsetY * cc + roundY);
    end
    else begin
        if (abs(offsetX) >= abs(offsetY)) then
        begin
            if(offsetX >= 0.0) then
            begin
                FPx^ := VVAR * (offsetX * cc + roundX + cl);
                FPy^ := VVAR * (offsetY * cc + roundY + cl * offsetY / offsetX);
            end
            else begin
                FPx^ := VVAR * (offsetX * cc + roundX - cl);
                FPy^ := VVAR * (offsetY * cc + roundY - cl * offsetY / offsetX);
            end;
        end
        else begin
            if(offsetY >= 0.0) then
            begin
                FPy^ := VVAR * (offsetY * cc + roundY + cl);
                FPx^ := VVAR * (offsetX * cc + roundX + offsetX / offsetY * cl);
            end
            else begin
                FPy^ := VVAR * (offsetY * cc + roundY - cl);
                FPx^ := VVAR * (offsetX * cc + roundX - offsetX / offsetY * cl);
            end;
        end;
    end;
end;

///////////////////////////////////////////////////////////////////////////////

constructor TVariationPostBoarders2.Create;
begin
  b2c := 0.5;
  left := 0.5;
  right := 0.5;
end;

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

///////////////////////////////////////////////////////////////////////////////
class function TVariationPostBoarders2.GetName: string;
begin
  Result := 'post_boarders2';
end;

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
function TVariationPostBoarders2.GetVariableNameAt(const Index: integer): string;
begin
  case Index of
    0: Result := sb2c;
    1: Result := sleft;
	  2: Result := sright;
  else
    Result := '';
  end
end;

///////////////////////////////////////////////////////////////////////////////
function TVariationPostBoarders2.SetVariable(const Name: string; var value: double): boolean;
begin
  Result := False;
  if Name = sb2c then begin
	if abs(value) = 0 then value := eps;
    b2c := value;
    Result := True;
  end else if Name = sleft then begin
	if abs(value) = 0 then value := eps;
	left := Value;
    Result := True;
  end else if Name = sright then begin
	if abs(value) = 0 then value := eps;
	right := Value;
    Result := True;
  end;
end;

function TVariationPostBoarders2.ResetVariable(const Name: string): boolean;
begin
  Result := False;
  if Name = sb2c then begin
    b2c := 0.5;
    Result := True;
  end else if Name = sleft then begin
	left := 0.5;
    Result := True;
  end else if Name = sright then begin
	right := 0.5;
    Result := True;
  end;
end;

/////////////////////////////////////////////////////////////////////

function TVariationPostBoarders2.GetNrVariables: integer;
begin
  Result := 3;
end;

///////////////////////////////////////////////////////////////////////////////
function TVariationPostBoarders2.GetVariable(const Name: string; var value: double): boolean;
begin
  Result := False;
  if Name = sb2c then begin
    Value := b2c; 
    Result := True;
  end else if Name = sleft then begin
    Value := left;
    Result := True;
  end else if Name = sright then begin
	Value := right;
    Result := True;
  end;
end;

///////////////////////////////////////////////////////////////////////////////
initialization
  RegisterVariation(TVariationClassLoader.Create(TVariationPostBoarders2), false, false);
end.