unit dresize;

interface

uses
  dvector2i,
  dvector2f;

function GetResizeCoeff(const Base, Screen: TVec2i): Single; overload;
function GetWorkSize(const Base, Screen: TVec2i): TVec2i; overload;
function Centrize(const Length, ScreenSize: LongInt): LongInt; overload; inline;
function Centrize(const WorkSize, ScreenSize: TVec2i): TVec2i; overload;
function TransformWorkToScreen(const Pos: TVec2f; const WorkPos: TVec2i; WorkCoeff: Single): TVec2f;
function TransformCursorToWork(const Cursor: TVec2f; const WorkPos: TVec2i; WorkCoeff: Single): TVec2f;

type
TWorkSpace = object
public
  Size: TVec2i;
  Pos: TVec2i;
  Coeff: Single;
  procedure Setup(const MapSize: TVec2i; const WindowSize: TVec2i);
  function CursorToWork(const Cursor: TVec2f): TVec2f; inline;
end;

implementation

function GetResizeCoeff(const Base, Screen: TVec2i): Single;
begin
  if Screen.X * Base.Y >= Screen.Y * Base.X then begin
    Result := Screen.Y / Base.Y;
  end else
    Result := Screen.X / Base.X;
end;

function GetWorkSize(const Base, Screen: TVec2i): TVec2i;
//var
//  C: Double;
begin
  if Screen.X * Base.Y >= Screen.Y * Base.X then begin
    Result := Vec2i(Screen.Y * Base.X div Base.Y, Screen.Y);
  end else
    Result := Vec2i(Screen.X, Screen.X * Base.Y div Base.X);
  // better just in one test, but slower
  //if Screen.X * Base.Y >= Screen.Y * Base.X then begin
  //  C := Screen.Y / Base.Y;
  //end else
  //  C := Screen.X / Base.X;
  //Result := Vec2i(Round(C * Base.X), Round(C * Base.Y));
end;

function Centrize(const Length, ScreenSize: LongInt): LongInt;
begin
  Result := (ScreenSize - Length) div 2;
end;

function Centrize(const WorkSize, ScreenSize: TVec2i): TVec2i;
begin
  Result := Vec2i(Centrize(WorkSize.X, ScreenSize.X),
                  Centrize(WorkSize.Y, ScreenSize.Y));
end;

function TransformWorkToScreen(const Pos: TVec2f; const WorkPos: TVec2i; WorkCoeff: Single): TVec2f;
begin
  Result := Mul2f(Pos, WorkCoeff) + Vec2f(WorkPos);
end;

function TransformCursorToWork(const Cursor: TVec2f; const WorkPos: TVec2i; WorkCoeff: Single): TVec2f;
begin
  Result := Mul2f(Cursor - Vec2f(WorkPos), 1/WorkCoeff);
end;

procedure TWorkSpace.Setup(const MapSize: TVec2i; const WindowSize: TVec2i);
begin
  Size := GetWorkSize(MapSize, WindowSize);
  Pos := Centrize(Size, WindowSize);
  Coeff := GetResizeCoeff(MapSize, WindowSize);
end;

function TWorkSpace.CursorToWork(const Cursor: TVec2f): TVec2f;
begin
  Result := TransformCursorToWork(Cursor, Pos, Coeff);
end;

end.
