package bbox;

# 14.4.2001 IK  bugfix

# some constant values (modify in streambuf::GetPos too!)
($SB_C, $SB_R, $SB_T, $SB_TL, $SB_TR, $SB_L, $SB_B, $SB_BR, $SB_BL) =
 (0, 1, 2, 3, 4, 5, 6, 7, 8);

#
#  create new box object.
#  $box1 = box->new()            create with default (0,0,0,0)
#  $box2 = box->new(xu,yu,xo,yo) create with (xu,yu,xo,yo)
#  $box3 = box->new($loc)        create with (x,y,x,y)
#  $box4 = $box1->new()          clone $loc1
#
sub new
{
   my $r_bbox;
   my $pck = shift;    # first parameter is class name
   if (ref($pck))
   # called as instance method $locobject->new()
   {
       $r_bbox = { "xu" => $pck->{"xu"},
                   "yu" => $pck->{"yu"},
                   "xo" => $pck->{"xo"},
                   "yo" => $pck->{"yo"}
                };
   }
   else
   # called as class method loc->new()
   {
       if (@_)
       {
           if (ref($p1 = $_[0]) eq "loc")
           {
               $xu = $xo = $p1->{"x"};
               $yu = $yo = $p1->{"y"};
           }
           else
           {
               if (scalar(@_)==2)
               {
                   $xu = $xo = $_[0];
                   $yu = $yo = $_[1];
               }
               else
               {
                   $xu = $_[0];
                   $yu = $_[1];
                   $xo = $_[2];
                   $yo = $_[3];
               }
           }
       }
       else
       {
           $xu = $yu = $xo = $yo = 0;
       }
       $r_bbox = { "xu" => $xu,
                   "yu" => $yu,
                   "xo" => $xo,
                   "yo" => $yo
                };
   }
   bless $r_bbox, 'bbox';
   return $r_bbox;
}


#
# initialize existing box
# $box->init()
# $box->init(x,y)
# $box->init($loc)
#
sub init
{
   my $r_bbox = shift;
   my ($xu, $yu, $xo, $yo);
   if (@_)
   # called with arguments
   {
       if (ref($p1 = $_[0]) eq "loc")
       # called with location object
       {
           $xu = $xo = $p1->{"x"};
           $yu = $yo = $p1->{"y"};
       }
       else
       # called with numbers
       {
           $xu = $xo = $_[0];
           $yu = $yo = $_[1];
       }
   }
   else
   # no arguments
   {
       $xu = $yu = $xo = $yo = 0;
   }
   $r_bbox->{"xu"} = $xu;
   $r_bbox->{"yu"} = $yu;
   $r_bbox->{"xo"} = $xo;
   $r_bbox->{"yo"} = $yo;
}

#
# copy box dimensions
# $box->eq($box1)
#
sub eq
{
   my $r_bbox = shift;
   my ($r_box1) = @_;
   $r_bbox->{"xu"} = $r_box1->{"xu"};
   $r_bbox->{"yu"} = $r_box1->{"yu"};
   $r_bbox->{"xo"} = $r_box1->{"xo"};
   $r_bbox->{"yo"} = $r_box1->{"yo"};
}


#
#  returns width and height of box
#
sub width
{
   my $r_bbox = shift;
   return ($r_bbox->{"xo"} - $r_bbox->{"xu"});
}

sub height
{
   my $r_bbox = shift;
   return ($r_bbox->{"yo"} - $r_bbox->{"yu"});
}


#
#  $box1->minmax(x,y)
#  $box1->minmax($loc)
#  $box1->minmax($box)
#
sub MinMax
{
   my $r_bbox = shift;
   my $p1 = shift;
   if (ref($p1) eq "bbox")
   # box extends box
   {
       $r_bbox->{"xu"} = $p1->{"xu"} if $p1->{"xu"} < $r_bbox->{"xu"};
       $r_bbox->{"yu"} = $p1->{"yu"} if $p1->{"yu"} < $r_bbox->{"yu"};
       $r_bbox->{"xo"} = $p1->{"xo"} if $p1->{"xo"} > $r_bbox->{"xo"};
       $r_bbox->{"yo"} = $p1->{"yo"} if $p1->{"yo"} > $r_bbox->{"yo"};
   }
   else
   {
       if (ref($p1) eq "loc")
       # location object extends box
       {
           $r_bbox->{"xu"} = $p1->{"x"} if $p1->{"x"} < $r_bbox->{"xu"};
           $r_bbox->{"yu"} = $p1->{"y"} if $p1->{"y"} < $r_bbox->{"yu"};
           $r_bbox->{"xo"} = $p1->{"x"} if $p1->{"x"} > $r_bbox->{"xo"};
           $r_bbox->{"yo"} = $p1->{"y"} if $p1->{"y"} > $r_bbox->{"yo"};
       }
       else
       # point given
       {
           my $p2 = shift;
           $r_bbox->{"xu"} = $p1 if $p1 < $r_bbox->{"xu"};
           $r_bbox->{"yu"} = $p2 if $p2 < $r_bbox->{"yu"};
           $r_bbox->{"xo"} = $p1 if $p1 > $r_bbox->{"xo"};
           $r_bbox->{"yo"} = $p2 if $p2 > $r_bbox->{"yo"};
       }
   }
}


#
#  determines $loc so that $loc is in relation $iPos to $box
#  $box->ToConPoint($iPos, $loc)
#
sub ToConPoint
{
   my ($r_bbox, $iPos, $r_loc) = @_;
   $r_loc->{"x"} = $r_bbox->{"xo"} if grep($iPos==$_, ($SB_R, $SB_TR, $SB_BR));
   $r_loc->{"x"} = $r_bbox->{"xu"} if grep($iPos==$_, ($SB_L, $SB_TL, $SB_BL));
   $r_loc->{"x"} = ($r_bbox->{"xu"} + $r_bbox->{"xo"})/2
                                if grep($iPos==$_, ($SB_T, $SB_C, $SB_B));
   $r_loc->{"y"} = $r_bbox->{"yo"} if grep($iPos==$_, ($SB_TR, $SB_T, $SB_TL));
   $r_loc->{"y"} = $r_bbox->{"yu"} if grep($iPos==$_, ($SB_BR, $SB_B, $SB_BL));
   $r_loc->{"y"} = ($r_bbox->{"yu"} + $r_bbox->{"yo"})/2
                                if grep($iPos==$_, ($SB_L, $SB_C, $SB_R));
}


#
#  determines $loc so that $box is in relation $iPos to $locg
#  $box->OrigConPoint($iPos, $loc, $locg)
#
sub OrigConPoint
{
   my ($r_bbox, $iPos, $r_loc, $r_locg) = @_;
   $r_loc->{"x"} = $r_locg->{"x"} - $r_bbox->{"xo"}
                               if grep($iPos==$_, ($SB_R, $SB_TR, $SB_BR));
   $r_loc->{"x"} = $r_locg->{"x"} - $r_bbox->{"xu"}
                               if grep($iPos==$_, ($SB_L, $SB_TL, $SB_BL));
   $r_loc->{"x"} = $r_locg->{"x"} - ($r_bbox->{"xu"} + $r_bbox->{"xo"})/2
                               if grep($iPos==$_, ($SB_T, $SB_C, $SB_B));

   $r_loc->{"y"} = $r_locg->{"y"} - $r_bbox->{"yo"}
                               if grep($iPos==$_, ($SB_TR, $SB_T, $SB_TL));
   $r_loc->{"y"} = $r_locg->{"y"} - $r_bbox->{"yu"}
                               if grep($iPos==$_, ($SB_BR, $SB_B, $SB_BL));
   $r_loc->{"y"} = $r_locg->{"y"} - ($r_bbox->{"yu"} + $r_bbox->{"yo"})/2
                               if grep($iPos==$_, ($SB_L, $SB_C, $SB_R));
}


#
#  adds offset $loc2 or vec(x,y) to $bbox
#  $box->translate(x,y)
#  $box->translate($loc2)
#
sub translate
{
   my $r_box = shift;
   my $p1 = shift;
   if (ref($p1) eq "loc")
   {
       $r_box->{"xu"} += $p1->{"x"};
       $r_box->{"yu"} += $p1->{"y"};
       $r_box->{"xo"} += $p1->{"x"};
       $r_box->{"yo"} += $p1->{"y"};
   }
   else
   {
       my $p2 = shift;
       $r_box->{"xu"} += $p1;
       $r_box->{"yu"} += $p2;
       $r_box->{"xo"} += $p1;
       $r_box->{"yo"} += $p2;
   }
}


#
# show values
# $loc->dump( [name])
#
sub dump
{
   my $r_bbox = shift;
   my $name = shift;
   printf "%s (BBOX): xu = %f, yu = %f xo = %f yo = %f\n", $name,
       $r_bbox->{"xu"}, $r_bbox->{"yu"}, $r_bbox->{"xo"}, $r_bbox->{"yo"};
}

1;