The Perl Toolchain Summit 2025 Needs You: You can help 🙏 Learn more

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 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

$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"

rectangle ($$$)
);
#_ Rectangle __________________________________________________________
# Package loaded successfully
#______________________________________________________________________
1;

Credits

Author

philiprbrenan@yahoo.com

philiprbrenan@yahoo.com, 2004

License

Perl License.