- Rectangle

- Synopsis
- Description
- Constructors

- new
- rectangle

- Methods

- check
- is
- a,b,c
- clone
- accuracy
- intersection
- intersects
- visible
- project
- projectInto

- Exports
- Credits

- Author
- Copyright
- License

# Rectangle

Rectangles in 3d space

PhilipRBrenan@yahoo.com, 2004, Perl License

## Synopsis

Example t/rectangle.t

     #_ Rectangle __________________________________________________________
     # Test 3d rectangles
     # philiprbrenan@yahoo.com, 2004, Perl License
     #______________________________________________________________________

     use Math::Zap::Rectangle;
     use Math::Zap::Vector;
     use Test::Simple tests=>3;

     my ($a, $b, $c, $d) =
      (vector(0,    0, +1),
       vector(0, -1.9, -1),
       vector(0, -2.0, -1),
       vector(0, -2.1, -1)
      );

     my $r = rectangle
      (vector(-1,-1, 0),
       vector( 2, 0, 0),
       vector( 0, 2, 0)
      );

     ok($r->intersects($a, $b) == 1);
     ok($r->intersects($a, $c) == 1);
     ok($r->intersects($a, $d) == 0);

## Description

Rectangles in 3d space

     package Math::Zap::Rectangle;
     $VERSION=1.03;
     use Math::Zap::Vector check=>'vectorCheck';
     use Math::Zap::Matrix new3v=>'matrixNew3v';
     use Carp;

## Constructors

### new

Create a rectangle from 3 vectors:

     a position of any corner
     b first side
     c second side.

Note that vectors b,c must be at right angles to each other.

     sub new($$$)
      {my ($a, $b, $c) = vectorCheck(@_);
       $b->dot($c) == 0 or confess 'non rectangular rectangle specified';
       bless {a=>$a, b=>$b, c=>$c};
      }

### rectangle

Create a rectangle from 3 vectors - synonym for new.

     sub rectangle($$$) {new($_[0],$_[1],$_[2])};

## Methods

### check

Check its a rectangle

     sub check(@)
      {for my $r(@_)
        {confess "$r is not a rectangle" unless ref($r) eq __PACKAGE__;
        }
       return (@_)
      }

### is

Test its a rectangle

     sub is(@)
      {for my $r(@_)
        {return 0 unless ref($r) eq __PACKAGE__;
        }
       'rectangle';
      }

### a,b,c

Components of rectangle

     sub a($) {my ($r) = check(@_); $r->{a}}
     sub b($) {my ($r) = check(@_); $r->{b}}
     sub c($) {my ($r) = check(@_); $r->{c}}

### clone

Create a rectangle from another rectangle

     sub clone($)
      {my ($r) = check(@_); # Rectangles
       bless {a=>$r->a, b=>$r->b, c=>$r->c};
      }

### accuracy

Get/Set accuracy for comparisons

     my $accuracy = 1e-10;

     sub accuracy
      {return $accuracy unless scalar(@_);
       $accuracy = shift();
      }

### intersection

Intersect line between two vectors with plane defined by a rectangle

     r rectangle
     a start vector
     b end vector

Solve the simultaneous equations of the plane defined by the rectangle and the line between the vectors:

       ra+l*rb+m*rc         = a+(b-a)*n
     =>ra+l*rb+m*rc+n*(a-b) = a-ra

Note: no checks (yet) for line parallel to plane.

     sub intersection($$$)
      {my ($r)     =       check(@_[0..0]); # Rectangles
       my ($a, $b) = vectorCheck(@_[1..2]); # Vectors

       $s = matrixNew3v($r->b, $r->c, $a-$b)/($a-$r->a);
      }

### intersects

# Test whether a line between two vectors intersects a rectangle # Note: no checks (yet) for line parallel to plane.

     sub intersects($$$)
      {my ($r)     =       check(@_[0..0]); # Rectangles
       my ($a, $b) = vectorCheck(@_[1..2]); # Vectors

       my $s = $r->intersection($a, $b);
       return 1 if $s->x >=0 and $s->x < 1 and
                   $s->y >=0 and $s->y < 1 and
                   $s->z >=0 and $s->z < 1;
       0;
      }

### visible

# Visibility of a rectangle r hid by other rectangles R from a view # point p. # Rectangle r is divided up into I*J sub rectangles: each sub rectangle # is tested for visibility from point p via the intervening rectangles.

     sub visible($$@)
      {my ($p)     = vectorCheck(@_[0.. 0]);    # Vector
       my ($I, $J) =            (@_[1.. 2]);    # Number of divisions
       my ($r, @R) =       check(@_[3..scalar(@_)-1]);  # Rectangles

       my $v;
       $v->{r} = $r;                              # Save rectangle data
       $v->{I} = $I;                              #
       $v->{J} = $J;                              #

       for      my $i(1..$I)                      # Along one edge
        {L: for my $j(1..$J)                      # Along the other edge
          {my $c = $r->a+($r->b)*(($i-1/2)/$I)    # Test point
                        +($r->c)*(($j-1/2)/$J);

           for my $R(@R)                          # Each intervening rectangle
            {my ($x, $y, $z) = ($c->x, $c->y, $c->z);
             my $in = $R->intersects($p, $c);
             next L if $in;                       # Solid, intersected
            }
           $v->{v}{$i}{$j} = 1;
          }
        }
       $v;
      }

### project

# Project rectangle r onto rectangle R from a point p

     sub project($$$)
      {my ($p)     = vectorCheck(@_[0.. 0]);    # Vector
       my ($r, $R) =            (@_[1.. 2]);    # Rectangles

       my $A = $r->a;                             # Main  corner of r
       my $B = $r->a+$r->b;                       # One   corner of r
       my $C = $r->a+$r->c;                       # Other corner of r

       my $a = $R->intersection($p, $A);          # Main  corner of r on R
       my $b = $R->intersection($p, $B);          # One   corner of r on R
       my $c = $R->intersection($p, $C);          # Other corner of r on R

       $aR = $p+($A-$p)*$a->z;                    # Coordinates of main  corner of r on R
       $bR = $p+($B-$p)*$b->z;                    # Coordinates of one   corner of r on R
       $cR = $p+($C-$p)*$c->z;                    # Coordinates of other corner of r on R
       print "a=$aR\n";
       print "b=$bR\n";
       print "c=$cR\n";

       rectangle($aR, $bR, $cR);
      }

### projectInto

# Project rectangle r into rectangle R from a point p

     sub projectInto($$$)
      {my ($r, $R) =            (@_[0..1]);    # Rectangles
       my ($p)     = vectorCheck(@_[2..2]);    # Vector

       my $A = $r->a;                             # Main     corner of r
       my $B = $r->a+$r->b;                       # One      corner of r
       my $C = $r->a+$r->c;                       # Other    corner of r
       my $D = $r->a+$r->b+$r->c;                 # Opposite corner of r

       my $a = $R->intersection($p, $A);          # Main     corner of r on R
       my $b = $R->intersection($p, $B);          # One      corner of r on R
       my $c = $R->intersection($p, $C);          # Other    corner of r on R
       my $d = $R->intersection($p, $D);          # Opposite corner of r on R

       ($a, $b, $d, $c);
      }

## Exports

Export rectangle

     use Math::Zap::Exports qw(
       rectangle ($$$)
      );

     #_ Rectangle __________________________________________________________
     # Package loaded successfully
     #______________________________________________________________________

     1;

## Credits

### Author

philiprbrenan@yahoo.com

### Copyright

philiprbrenan@yahoo.com, 2004

### License

Perl License.