File Coverage

blib/lib/Math/Zap/Rectangle.pm
Criterion Covered Total %
statement 33 82 40.2
branch 3 12 25.0
condition 8 15 53.3
subroutine 12 18 66.6
pod 14 14 100.0
total 70 141 49.6


line stmt bran cond sub pod time code
1            
2             =head1 Rectangle
3            
4             Rectangles in 3d space
5            
6             PhilipRBrenan@yahoo.com, 2004, Perl License
7            
8            
9             =head2 Synopsis
10            
11             Example t/rectangle.t
12            
13             #_ Rectangle __________________________________________________________
14             # Test 3d rectangles
15             # philiprbrenan@yahoo.com, 2004, Perl License
16             #______________________________________________________________________
17            
18             use Math::Zap::Rectangle;
19             use Math::Zap::Vector;
20             use Test::Simple tests=>3;
21            
22             my ($a, $b, $c, $d) =
23             (vector(0, 0, +1),
24             vector(0, -1.9, -1),
25             vector(0, -2.0, -1),
26             vector(0, -2.1, -1)
27             );
28            
29             my $r = rectangle
30             (vector(-1,-1, 0),
31             vector( 2, 0, 0),
32             vector( 0, 2, 0)
33             );
34            
35             ok($r->intersects($a, $b) == 1);
36             ok($r->intersects($a, $c) == 1);
37             ok($r->intersects($a, $d) == 0);
38            
39            
40            
41            
42             =head2 Description
43            
44             Rectangles in 3d space
45            
46             =cut
47            
48            
49             package Math::Zap::Rectangle;
50             $VERSION=1.07;
51 1     1   1157 use Math::Zap::Vector check=>'vectorCheck';
  1         3  
  1         38  
52 1     1   721 use Math::Zap::Matrix new3v=>'matrixNew3v';
  1         3  
  1         32  
53 1     1   5 use Carp;
  1         2  
  1         1503  
54            
55            
56             =head2 Constructors
57            
58            
59             =head3 new
60            
61             Create a rectangle from 3 vectors:
62            
63             a position of any corner
64             b first side
65             c second side.
66            
67             Note that vectors b,c must be at right angles to each other.
68            
69             =cut
70            
71            
72 1     1 1 34 sub new($$$)
73             {my ($a, $b, $c) = vectorCheck(@_);
74 1 50       8 $b->dot($c) == 0 or confess 'non rectangular rectangle specified';
75 1         11 bless {a=>$a, b=>$b, c=>$c};
76             }
77            
78            
79             =head3 rectangle
80            
81             Create a rectangle from 3 vectors - synonym for L.
82            
83             =cut
84            
85            
86 1     1 1 6 sub rectangle($$$) {new($_[0],$_[1],$_[2])};
87            
88            
89             =head2 Methods
90            
91            
92             =head3 check
93            
94             Check its a rectangle
95            
96             =cut
97            
98            
99 15 50       120 sub check(@)
100 15     15 1 27 {for my $r(@_)
101             {confess "$r is not a rectangle" unless ref($r) eq __PACKAGE__;
102             }
103 15         32 return (@_)
104             }
105            
106            
107             =head3 is
108            
109             Test its a rectangle
110            
111             =cut
112            
113            
114 0 0       0 sub is(@)
115 0     0 1 0 {for my $r(@_)
116             {return 0 unless ref($r) eq __PACKAGE__;
117             }
118 0         0 'rectangle';
119             }
120            
121            
122             =head3 a,b,c
123            
124             Components of rectangle
125            
126             =cut
127            
128            
129 3     3 1 15 sub a($) {my ($r) = check(@_); $r->{a}}
  3         13  
130 3     3 1 9 sub b($) {my ($r) = check(@_); $r->{b}}
  3         20  
131 3     3 1 9 sub c($) {my ($r) = check(@_); $r->{c}}
  3         17  
132            
133            
134             =head3 clone
135            
136             Create a rectangle from another rectangle
137            
138             =cut
139            
140            
141 0     0 1 0 sub clone($)
142             {my ($r) = check(@_); # Rectangles
143 0         0 bless {a=>$r->a, b=>$r->b, c=>$r->c};
144             }
145            
146            
147             =head3 accuracy
148            
149             Get/Set accuracy for comparisons
150            
151             =cut
152            
153            
154             my $accuracy = 1e-10;
155            
156             sub accuracy
157 0 0   0 1 0 {return $accuracy unless scalar(@_);
158 0         0 $accuracy = shift();
159             }
160            
161            
162             =head3 intersection
163            
164             Intersect line between two vectors with plane defined by a rectangle
165            
166             r rectangle
167             a start vector
168             b end vector
169            
170             Solve the simultaneous equations of the plane defined by the
171             rectangle and the line between the vectors:
172            
173             ra+l*rb+m*rc = a+(b-a)*n
174             =>ra+l*rb+m*rc+n*(a-b) = a-ra
175            
176             Note: no checks (yet) for line parallel to plane.
177            
178             =cut
179            
180            
181 3     3 1 16 sub intersection($$$)
182             {my ($r) = check(@_[0..0]); # Rectangles
183 3         101 my ($a, $b) = vectorCheck(@_[1..2]); # Vectors
184            
185 3         13 $s = matrixNew3v($r->b, $r->c, $a-$b)/($a-$r->a);
186             }
187            
188            
189             =head3 intersects
190            
191             # Test whether a line between two vectors intersects a rectangle
192             # Note: no checks (yet) for line parallel to plane.
193            
194             =cut
195            
196            
197 3     3 1 18 sub intersects($$$)
198             {my ($r) = check(@_[0..0]); # Rectangles
199 3         224 my ($a, $b) = vectorCheck(@_[1..2]); # Vectors
200            
201 3         12 my $s = $r->intersection($a, $b);
202 3 50 33     37 return 1 if $s->x >=0 and $s->x < 1 and
      66        
      66        
      66        
      33        
203             $s->y >=0 and $s->y < 1 and
204             $s->z >=0 and $s->z < 1;
205 1         8 0;
206             }
207            
208            
209             =head3 visible
210            
211             # Visibility of a rectangle r hid by other rectangles R from a view
212             # point p.
213             # Rectangle r is divided up into I*J sub rectangles: each sub rectangle
214             # is tested for visibility from point p via the intervening rectangles.
215            
216             =cut
217            
218            
219 0     0 1   sub visible($$@)
220             {my ($p) = vectorCheck(@_[0.. 0]); # Vector
221 0           my ($I, $J) = (@_[1.. 2]); # Number of divisions
222 0           my ($r, @R) = check(@_[3..scalar(@_)-1]); # Rectangles
223            
224 0           my $v;
225 0           $v->{r} = $r; # Save rectangle data
226 0           $v->{I} = $I; #
227 0           $v->{J} = $J; #
228            
229 0           for my $i(1..$I) # Along one edge
  0            
230 0           {L: for my $j(1..$J) # Along the other edge
231             {my $c = $r->a+($r->b)*(($i-1/2)/$I) # Test point
232             +($r->c)*(($j-1/2)/$J);
233            
234 0           for my $R(@R) # Each intervening rectangle
  0            
235             {my ($x, $y, $z) = ($c->x, $c->y, $c->z);
236 0           my $in = $R->intersects($p, $c);
237 0 0         next L if $in; # Solid, intersected
238             }
239 0           $v->{v}{$i}{$j} = 1;
240             }
241             }
242 0           $v;
243             }
244            
245            
246             =head3 project
247            
248             # Project rectangle r onto rectangle R from a point p
249            
250             =cut
251            
252            
253 0     0 1   sub project($$$)
254             {my ($p) = vectorCheck(@_[0.. 0]); # Vector
255 0           my ($r, $R) = (@_[1.. 2]); # Rectangles
256            
257 0           my $A = $r->a; # Main corner of r
258 0           my $B = $r->a+$r->b; # One corner of r
259 0           my $C = $r->a+$r->c; # Other corner of r
260            
261 0           my $a = $R->intersection($p, $A); # Main corner of r on R
262 0           my $b = $R->intersection($p, $B); # One corner of r on R
263 0           my $c = $R->intersection($p, $C); # Other corner of r on R
264            
265 0           $aR = $p+($A-$p)*$a->z; # Coordinates of main corner of r on R
266 0           $bR = $p+($B-$p)*$b->z; # Coordinates of one corner of r on R
267 0           $cR = $p+($C-$p)*$c->z; # Coordinates of other corner of r on R
268 0           print "a=$aR\n";
269 0           print "b=$bR\n";
270 0           print "c=$cR\n";
271            
272 0           rectangle($aR, $bR, $cR);
273             }
274            
275            
276             =head3 projectInto
277            
278             # Project rectangle r into rectangle R from a point p
279            
280             =cut
281            
282            
283 0     0 1   sub projectInto($$$)
284             {my ($r, $R) = (@_[0..1]); # Rectangles
285 0           my ($p) = vectorCheck(@_[2..2]); # Vector
286            
287 0           my $A = $r->a; # Main corner of r
288 0           my $B = $r->a+$r->b; # One corner of r
289 0           my $C = $r->a+$r->c; # Other corner of r
290 0           my $D = $r->a+$r->b+$r->c; # Opposite corner of r
291            
292 0           my $a = $R->intersection($p, $A); # Main corner of r on R
293 0           my $b = $R->intersection($p, $B); # One corner of r on R
294 0           my $c = $R->intersection($p, $C); # Other corner of r on R
295 0           my $d = $R->intersection($p, $D); # Opposite corner of r on R
296            
297 0           ($a, $b, $d, $c);
298             }
299            
300            
301             =head2 Exports
302            
303             Export L
304            
305             =cut
306            
307            
308 1         5 use Math::Zap::Exports qw(
309             rectangle ($$$)
310 1     1   8 );
  1         2  
311            
312             #_ Rectangle __________________________________________________________
313             # Package loaded successfully
314             #______________________________________________________________________
315            
316             1;
317            
318            
319             =head2 Credits
320            
321             =head3 Author
322            
323             philiprbrenan@yahoo.com
324            
325             =head3 Copyright
326            
327             philiprbrenan@yahoo.com, 2004
328            
329             =head3 License
330            
331             Perl License.
332            
333            
334             =cut