File Coverage

blib/lib/Math/Shape/Circle.pm
Criterion Covered Total %
statement 47 48 97.9
branch 21 24 87.5
condition 2 3 66.6
subroutine 8 8 100.0
pod 2 2 100.0
total 80 85 94.1


line stmt bran cond sub pod time code
1 6     6   15679 use strict;
  6         14  
  6         177  
2 6     6   20 use warnings;
  6         8  
  6         230  
3             package Math::Shape::Circle;
4             $Math::Shape::Circle::VERSION = '0.14';
5 6     6   84 use 5.008;
  6         19  
  6         183  
6 6     6   23 use Carp;
  6         14  
  6         341  
7 6     6   385 use Math::Shape::Vector;
  6         8  
  6         108  
8 6     6   768 use Math::Shape::Rectangle;
  6         8  
  6         2311  
9              
10             # ABSTRACT: a 2d circle
11              
12              
13             sub new {
14 14 50   14 1 67 croak 'incorrect number of args' unless @_ == 4;
15 14         22 my ($class, $x, $y, $r) = @_;
16 14         47 bless { center => Math::Shape::Vector->new($x, $y),
17             radius => $r,
18             }, $class;
19             }
20              
21              
22             sub collides
23             {
24 81     81 1 106 my ($self, $other_obj) = @_;
25              
26 81 100       577 if ($other_obj->isa('Math::Shape::Circle'))
    100          
    100          
    100          
    100          
    50          
27             {
28 8         27 my $center = $self->{center}->subtract_vector($other_obj->{center});
29 8 100       17 $center->length <= $self->{radius} + $other_obj->{radius} ? 1 : 0;
30             }
31             elsif ($other_obj->isa('Math::Shape::Vector'))
32             {
33 41         88 my $center = $self->{center}->subtract_vector($other_obj);
34 41 100       78 $center->length <= $self->{radius} ? 1 : 0;
35             }
36             elsif ($other_obj->isa('Math::Shape::Line'))
37             {
38 7         25 my $center = $self->{center}->subtract_vector($other_obj->{base});
39 7         20 my $project = $center->project($other_obj->{direction});
40              
41 7         18 my $base_vector = $other_obj->{base}->add_vector($project);
42 7         21 $self->collides($base_vector);
43             }
44             elsif ($other_obj->isa('Math::Shape::LineSegment'))
45             {
46             # test collision of both LineSegment start/end points
47 7 100       16 return 1 if $self->collides($other_obj->{start});
48 4 50       10 return 1 if $self->collides($other_obj->{end});
49              
50             # test collision of nearest point on LineSegment with circle
51 4         11 my $d = $other_obj->{end}->subtract_vector($other_obj->{start});
52 4         11 my $lc = $self->{center}->subtract_vector($other_obj->{start});
53 4         10 my $p = $lc->project($d);
54 4         17 my $nearest = $other_obj->{start}->add_vector($p);
55              
56 4 100 66     8 $self->collides($nearest)
57             && $p->length <= $d->length
58             && 0 <= $p->dot_product($d)
59             ? 1 : 0;
60             }
61             elsif ($other_obj->isa('Math::Shape::Rectangle'))
62             {
63 12         29 my $clamped_vector = $other_obj->clamp($self->{center});
64              
65 12         22 $self->collides($clamped_vector);
66             }
67             elsif ($other_obj->isa('Math::Shape::OrientedRectangle'))
68             {
69             # transform OrientedRectangle into Rectangle
70 6         21 my $r_size = $other_obj->{half_extend}->multiply(2);
71 6         22 my $lr = Math::Shape::Rectangle->new(0, 0, $r_size->{x}, $r_size->{y});
72              
73             # transform $self into local Circle in coordinates of other_obj
74 6         16 my $distance = $self->{center}->subtract_vector($other_obj->{center});
75 6         19 $distance = $distance->rotate(- $other_obj->{rotation});
76 6         21 my $center = $distance->add_vector($other_obj->{half_extend});
77 6         17 my $lc = Math::Shape::Circle->new($center->{x}, $center->{y}, $self->{radius});
78              
79             # check local objects collide
80 6         12 $lc->collides($lr);
81             }
82             else
83             {
84 0           croak 'collides must be called with a Math::Shape::Vector library object';
85             }
86             }
87             1;
88              
89             __END__