unit uGMPLib;

{$mode delphi}

interface

uses
  zglHeader;

type

{ TPos }

TPos = record
  x, y : integer;
  class operator Add(const Left, Right: TPos): TPos; // -/-
  //class operator Divide(const Left: TPos; const Right: Integer): TPos; overload;
  //class operator Divide(const Left: TPos; const Right: Single): TPos; overload;
end;

{ ZPos }
    {
ZPos = record//(zglTPoint2D)
  x, y : Single;
  class operator Add(a, b: ZPos): ZPos;
  class operator Add(a : Single; b: ZPos): ZPos;
  class operator Subtract(a, b: ZPos): ZPos;
  class operator Subtract(a : Single; b: ZPos): ZPos;
  class operator Multiply(a, b: ZPos): ZPos;
  class operator Multiply(a : Single; b: ZPos): ZPos;
  class operator Divide(a, b: ZPos): ZPos;
  class operator Divide(a : Single; b: ZPos): ZPos;
  class operator Implicit(a: ZPos): TPos;
end;  }

ZPos = record
  x, y: Single;

  function GetRotate(A : Single) : ZPos; // -/-
  function Length: Single; // -/-
  function LengthTo(pX, pY: Single): Single; // -/-
  function SqrLength: Single; // -/-
  function Normalize: Single; // -/-
  procedure SetZero; // -/-
  procedure SetNegative; // -/-
  procedure SetValue(pX, pY: Single); // -/-
  procedure SetLength(value: Single); // -/-

  // Operators
  class operator Negative(const AValue: ZPos): ZPos; // -/-
  class operator Add(const Left, Right: ZPos): ZPos; // -/-
  class operator Subtract(const Left, Right: ZPos): ZPos; // -/-

//  class operator Multiply(const Left, Right: ZPos): ZPos;
  class operator Multiply(const Left, Right: ZPos): Single;

  class operator Multiply(const Left: ZPos; const Right: Single): ZPos; overload; // -/-
  class operator Multiply(const Left: ZPos; const Right: Double): ZPos; overload; // -/-
  class operator Multiply(const Left: ZPos; const Right: Extended): ZPos; overload; // -/-
  class operator Multiply(const Left: Single; const Right: ZPos): ZPos; overload; // -/-
  class operator Multiply(const Left: Double; const Right: ZPos): ZPos; overload; // -/-
  class operator Multiply(const Left: Extended; const Right: ZPos): ZPos; overload; // -/-

  class operator Divide(const Left: ZPos; const Right: Single): ZPos; overload; // -/-
  class operator Divide(const Left: ZPos; const Right: Double): ZPos; overload; // -/-
  class operator Divide(const Left: ZPos; const Right: Extended): ZPos; overload; // -/-

  procedure AddBy(const Operand: ZPos); // -/-
  procedure SubtractBy(const Operand: ZPos); // -/-
  procedure MultiplyBy(const Operand: Single); overload; // -/-
  procedure MultiplyBy(const Operand: Double); overload; // -/-
  procedure MultiplyBy(const Operand: Extended); overload; // -/-
  procedure DivideBy(const Operand: Single); overload; // -/-
  procedure DivideBy(const Operand: Double); overload; // -/-
  procedure DivideBy(const Operand: Extended); overload; // -/-

  class operator Implicit(a: ZPos): TPos; overload;
end;



implementation
const
  FLT_EPSILON = 1.084202172485504E-19;

{ TPos }

class operator TPos.Add(const Left, Right: TPos): TPos;
begin
  Result.x := Left.x + Right.x;
  Result.y := Left.y + Right.y;
end;

{ TPos }
  {
class operator TPos.Divide(const Left: TPos; const Right: Integer): TPos;
begin
  Result.x := Left.x div Right;
  Result.y := Left.y div Right;
end;

class operator TPos.Divide(const Left: TPos; const Right: Single): TPos;
begin
  Result.x := trunc(Left.x / Right);
  Result.y := trunc(Left.y / Right);
end;
      }
function ZPos.GetRotate(A: Single): ZPos;
var
   v_cos, v_sin, v_a : Single;
begin
  v_sin := sin(A);
  v_cos := cos(A);

  result.x := x * v_cos - y * v_sin;
  result.y := x * v_sin + y * v_cos;
end;

function ZPos.Length: Single;
begin
   Result := Sqrt(x * x + y * y);
end;

function ZPos.LengthTo(pX, pY: Single): Single;
begin
   Result := Sqrt(sqr(x - pX) + sqr(y - pY));
end;

function ZPos.Normalize: Single;
begin
   Result := Length();
	 if Result < FLT_EPSILON then
   begin
      Result := 0.0;
      Exit;
   end;
   x := x / Result;
   y := y / Result;
end;

procedure ZPos.SetZero;
begin
   x := 0.0;
   y := 0.0;
end;

procedure ZPos.SetNegative;
begin
   x := -x;
   y := -y;
end;

procedure ZPos.SetValue(pX, pY: Single);
begin
   x := pX;
   y := pY;
end;

procedure ZPos.SetLength(value: Single);
var
   l: Single;
begin
   l := value / Length;
   x := x * l;
   y := y * l;
end;

function ZPos.SqrLength: Single;
begin
   Result := x * x + y * y;
end;

class operator ZPos.Negative(const AValue: ZPos): ZPos;
begin
   Result.x := -AValue.x;
   Result.y := -AValue.y;
end;

class operator ZPos.Add(const Left, Right: ZPos): ZPos;
begin
   Result.x := Left.x + Right.x;
   Result.y := Left.y + Right.y;
end;

class operator ZPos.Subtract(const Left, Right: ZPos): ZPos;
begin
   Result.x := Left.x - Right.x;
   Result.y := Left.y - Right.y;
end;
  {
class operator ZPos.Multiply(const Left, Right: ZPos): ZPos;
begin
  Result.x := Left.x * Right.x;
  Result.y := Left.y * Right.y;
end;
   }

class operator ZPos.Multiply(const Left, Right: ZPos): Single;
begin
  Result := Left.x * Right.x + Left.y * Right.y;
end;

class operator ZPos.Multiply(const Left: ZPos; const Right: Single): ZPos;
begin
   Result.x := Left.x * Right;
   Result.y := Left.y * Right;
end;

class operator ZPos.Multiply(const Left: ZPos; const Right: Double): ZPos;
begin
   Result.x := Left.x * Right;
   Result.y := Left.y * Right;
end;

class operator ZPos.Multiply(const Left: ZPos; const Right: Extended): ZPos;
begin
   Result.x := Left.x * Right;
   Result.y := Left.y * Right;
end;

class operator ZPos.Multiply(const Left: Single; const Right: ZPos): ZPos;
begin
   Result.x := Left * Right.x;
   Result.y := Left * Right.y;
end;

class operator ZPos.Multiply(const Left: Double; const Right: ZPos): ZPos;
begin
   Result.x := Left * Right.x;
   Result.y := Left * Right.y;
end;

class operator ZPos.Multiply(const Left: Extended; const Right: ZPos): ZPos;
begin
   Result.x := Left * Right.x;
   Result.y := Left * Right.y;
end;

class operator ZPos.Divide(const Left: ZPos; const Right: Single): ZPos;
begin
   Result.x := Left.x / Right;
   Result.y := Left.y / Right;
end;

class operator ZPos.Divide(const Left: ZPos; const Right: Double): ZPos;
begin
   Result.x := Left.x / Right;
   Result.y := Left.y / Right;
end;

class operator ZPos.Divide(const Left: ZPos; const Right: Extended): ZPos;
begin
   Result.x := Left.x / Right;
   Result.y := Left.y / Right;
end;

procedure ZPos.AddBy(const Operand: ZPos);
begin
   x := x + Operand.x;
   y := y + Operand.y;
end;

procedure ZPos.SubtractBy(const Operand: ZPos);
begin
   x := x - Operand.x;
   y := y - Operand.y;
end;

procedure ZPos.MultiplyBy(const Operand: Single);
begin
   x := x * Operand;
   y := y * Operand;
end;

procedure ZPos.MultiplyBy(const Operand: Double);
begin
   x := x * Operand;
   y := y * Operand;
end;

procedure ZPos.MultiplyBy(const Operand: Extended);
begin
   x := x * Operand;
   y := y * Operand;
end;

procedure ZPos.DivideBy(const Operand: Single);
begin
   x := x / Operand;
   y := y / Operand;
end;

procedure ZPos.DivideBy(const Operand: Double);
begin
   x := x / Operand;
   y := y / Operand;
end;

procedure ZPos.DivideBy(const Operand: Extended);
begin
   x := x / Operand;
   y := y / Operand;
end;

class operator ZPos.Implicit(a: ZPos): TPos;
begin
  result.x := trunc(a.x);
  result.y := trunc(a.y);
end;

end.

