The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

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.07;
 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

philiprbrenan@yahoo.com, 2004

License

Perl License.