-- $Date: 2004/02/27 01:00:09 $
-- $Revision: 1.17 $
-- $Author: jcrocholl $

package body Vectors is

   --------------------
   -- Vector operations
   --------------------

   -- Unary plus: identity.
   function "+"
     (A : in Vector)  -- Copy this vector.
     return Vector is -- The same vector.
   begin
      return A;
   end "+";

   -- Unary minus: mirror a vector.
   function "-"
     (A : in Vector)  -- Mirror this vector.
     return Vector is -- The mirrored vector.
   begin
      return (-A.X, -A.Y);
   end "-";

   -- Vector addition.
   function "+"
     (A, B : in Vector-- Add these two vectors.
     return Vector is   -- The result vector.
   begin
      return (A.X + B.X, A.Y + B.Y);
   end "+";

   -- Vector subtraction.
   function "-"
     (A, B : in Vector-- Subtract B From A.
     return Vector is   -- The result vector.
   begin
      return (A.X - B.X, A.Y - B.Y);
   end "-";

   -- Multiplication for corresponding components.
   function "*"
     (A, B : in Vector-- Multiply components of these vectors.
     return Vector is   -- The result vector.
   begin
      return (A.X * B.X, A.Y * B.Y);
   end "*";

   -- Multiply a vector with a scalar number.
   function "*"
     (A : in Vector;  -- Scale this vector.
      B : in Number)  -- Scalar factor.
     return Vector is -- The result vector.
   begin
      return (A.X * B, A.Y * B);
   end "*";

   -- Multiply a vector with a scalar number.
   function "*"
     (A : in Number;  -- Scalar factor.
      B : in Vector)  -- Scale this vector.
     return Vector is -- The result vector.
   begin
      return (A * B.X, A * B.Y);
   end "*";

   -- Divide a vector by a scalar number.
   function "/"
     (A : in Vector;  -- Divide this vector.
      B : in Number)  -- Scalar divisor.
     return Vector is -- The result vector.
   begin
      return (A.X / B, A.Y / B);
   end "/";

   -- Calculate the length of a vector.
   function "abs"
     (A : in Vector-- Calculate length of this vector.
     return Number   -- The length of the vector.
   is
      S : Number := A.X * A.X + A.Y * A.Y;
   begin
      if S > Zero then
         return Sqrt(S);
      else
         return Zero;
      end if;
   end "abs";

   function Mirror_Y
     (A : in Vector-- Convert this vector.
     return Vector is
   begin
      return (A.X, -A.Y);
   end Mirror_Y;

   -- Convert a vector to a string.
   function To_String
     (A : in Vector)  -- Convert this vector.
     return String is -- The string representation.
   begin
      return To_String(A.X) & " " & To_String(A.Y);
   end To_String;

   -- Convert a vector to a string, with explicit tolerance.
   function To_String
     (A         : in Vector-- Convert this vector.
      Tolerance : in Number-- Tolerance level.
     return String is        -- The string representation.
   begin
      return To_String(A.X, Tolerance) & " " & To_String(A.Y, Tolerance);
   end To_String;

   -------------------------
   -- Rectangle calculations
   -------------------------

   -- Calculate a bounding box.
   function Max
     (A, B : in Rectangle)
     return Rectangle is
   begin
      return (
        Min(A.Left, B.Left), Min(A.Top, B.Top),
        Max(A.Right, B.Right), Max(A.Bottom, B.Bottom));
   end Max;

   function "+"
     (A : in Rectangle;
      B : in Vector)
     return Rectangle is
   begin
      return (
        A.Left + B.X, A.Top + B.Y,
        A.Right + B.X, A.Bottom + B.Y);
   end "+";

   ------------------
   -- Rectangle sizes
   ------------------

   -- Calculate the width of the rectangle.
   function Get_Width
     (This : in Rectangle-- Calculate width of this rectangle.
     return Number is      -- Difference between right and left.
   begin
      return This.Right - This.Left;
   end Get_Width;
   pragma Inline(Get_Width);

   -- Calculate the height of the rectangle.
   function Get_Height
     (This : in Rectangle-- Calculate height of this rectangle.
     return Number is      -- Difference between top and bottom.
   begin
      return This.Bottom - This.Top;
   end Get_Height;
   pragma Inline(Get_Height);

   ------------------------
   -- Rectangle coordinates
   ------------------------

   -- Get the bottom left corner.
   function Get_Bottom_Left
     (This : in Rectangle-- Get corner from this rectangle.
     return Vector is      -- A vector containing left and bottom.
   begin
      return Vector'(This.Left, This.Bottom);
   end Get_Bottom_Left;

   -- Get the top right corner.
   function Get_Top_Right
     (This : in Rectangle-- Get corner from this rectangle.
     return Vector is      -- A vector containing right and top.
   begin
      return Vector'(This.Right, This.Top);
   end Get_Top_Right;

   -- Get the bottom left corner.
   function Get_Bottom_Right
     (This : in Rectangle-- Get corner from this rectangle.
     return Vector is      -- A vector containing right and bottom.
   begin
      return Vector'(This.Right, This.Bottom);
   end Get_Bottom_Right;

   -- Get the top right corner.
   function Get_Top_Left
     (This : in Rectangle-- Get corner from this rectangle.
     return Vector is      -- A vector containing left and top.
   begin
      return Vector'(This.Left, This.Top);
   end Get_Top_Left;

   --------------------
   -- String conversion
   --------------------

   -- Convert a rectangle to a string, with explicit tolerance.
   function To_String
     (This : in Rectangle-- Convert this rectangle.
     return String is      -- The string representation.
   begin
      return
        To_String(This.Left) & " " &
        To_String(This.Top) & " " &
        To_String(This.Right) & " " &
        To_String(This.Bottom);
   end To_String;

   -- Convert a rectangle to a string, with explicit tolerance.
   function To_String
     (This      : in Rectangle-- Convert this rectangle.
      Tolerance : in Number)    -- Tolerance level.
     return String is           -- The string representation.
   begin
      return
        To_String(This.Left, Tolerance) & " " &
        To_String(This.Top, Tolerance) & " " &
        To_String(This.Right, Tolerance) & " " &
        To_String(This.Bottom, Tolerance);
   end To_String;

end Vectors;