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   25068 use strict;
  6         10  
  6         203  
2 6     6   28 use warnings;
  6         8  
  6         234  
3             package Math::Shape::Circle;
4             $Math::Shape::Circle::VERSION = '0.13';
5 6     6   87 use 5.008;
  6         26  
  6         199  
6 6     6   28 use Carp;
  6         6  
  6         364  
7 6     6   489 use Math::Shape::Vector;
  6         9  
  6         149  
8 6     6   753 use Math::Shape::Rectangle;
  6         7  
  6         2115  
9              
10             # ABSTRACT: a 2d circle
11              
12              
13             sub new {
14 14 50   14 1 62 croak 'incorrect number of args' unless @_ == 4;
15 14         23 my ($class, $x, $y, $r) = @_;
16 14         50 bless { center => Math::Shape::Vector->new($x, $y),
17             radius => $r,
18             }, $class;
19             }
20              
21              
22             sub collides
23             {
24 81     81 1 103 my ($self, $other_obj) = @_;
25              
26 81 100       568 if ($other_obj->isa('Math::Shape::Circle'))
    100          
    100          
    100          
    100          
    50          
27             {
28 8         28 my $center = $self->{center}->subtract_vector($other_obj->{center});
29 8 100       24 $center->length <= $self->{radius} + $other_obj->{radius} ? 1 : 0;
30             }
31             elsif ($other_obj->isa('Math::Shape::Vector'))
32             {
33 41         89 my $center = $self->{center}->subtract_vector($other_obj);
34 41 100       85 $center->length <= $self->{radius} ? 1 : 0;
35             }
36             elsif ($other_obj->isa('Math::Shape::Line'))
37             {
38 7         28 my $center = $self->{center}->subtract_vector($other_obj->{base});
39 7         24 my $project = $center->project($other_obj->{direction});
40              
41 7         22 my $base_vector = $other_obj->{base}->add_vector($project);
42 7         25 $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       19 return 1 if $self->collides($other_obj->{start});
48 4 50       8 return 1 if $self->collides($other_obj->{end});
49              
50             # test collision of nearest point on LineSegment with circle
51 4         9 my $d = $other_obj->{end}->subtract_vector($other_obj->{start});
52 4         9 my $lc = $self->{center}->subtract_vector($other_obj->{start});
53 4         9 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         36 my $clamped_vector = $other_obj->clamp($self->{center});
64              
65 12         33 $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         26 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         21 my $distance = $self->{center}->subtract_vector($other_obj->{center});
75 6         21 $distance = $distance->rotate(- $other_obj->{rotation});
76 6         25 my $center = $distance->add_vector($other_obj->{half_extend});
77 6         25 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__