File Coverage

blib/lib/Math/Shape/Circle.pm
Criterion Covered Total %
statement 46 47 97.8
branch 21 24 87.5
condition 2 3 66.6
subroutine 8 8 100.0
pod 2 2 100.0
total 79 84 94.0


line stmt bran cond sub pod time code
1 6     6   20495 use strict;
  6         12  
  6         152  
2 6     6   28 use warnings;
  6         11  
  6         255  
3             package Math::Shape::Circle;
4             $Math::Shape::Circle::VERSION = '0.15';
5 6     6   102 use 5.008;
  6         26  
6 6     6   28 use Carp;
  6         9  
  6         380  
7 6     6   545 use Math::Shape::Vector;
  6         17  
  6         141  
8 6     6   1448 use Math::Shape::Rectangle;
  6         12  
  6         3052  
9              
10             # ABSTRACT: a 2d circle
11              
12              
13             sub new {
14 14 50   14 1 70 croak 'incorrect number of args' unless @_ == 4;
15 14         35 my ($class, $x, $y, $r) = @_;
16 14         55 bless { center => Math::Shape::Vector->new($x, $y),
17             radius => $r,
18             }, $class;
19             }
20              
21              
22             sub collides
23             {
24 81     81 1 136 my ($self, $other_obj) = @_;
25              
26 81 100       651 if ($other_obj->isa('Math::Shape::Circle'))
    100          
    100          
    100          
    100          
    50          
27             {
28 8         80 my $center = $self->{center}->subtract_vector($other_obj->{center});
29 8 100       30 $center->length <= $self->{radius} + $other_obj->{radius} ? 1 : 0;
30             }
31             elsif ($other_obj->isa('Math::Shape::Vector'))
32             {
33 41         117 my $center = $self->{center}->subtract_vector($other_obj);
34 41 100       114 $center->length <= $self->{radius} ? 1 : 0;
35             }
36             elsif ($other_obj->isa('Math::Shape::Line'))
37             {
38 7         29 my $center = $self->{center}->subtract_vector($other_obj->{base});
39 7         26 my $project = $center->project($other_obj->{direction});
40              
41 7         21 my $base_vector = $other_obj->{base}->add_vector($project);
42 7         32 $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       23 return 1 if $self->collides($other_obj->{start});
48 4 50       13 return 1 if $self->collides($other_obj->{end});
49              
50             # test collision of nearest point on LineSegment with circle
51 4         13 my $d = $other_obj->{end}->subtract_vector($other_obj->{start});
52 4         15 my $lc = $self->{center}->subtract_vector($other_obj->{start});
53 4         20 my $p = $lc->project($d);
54 4         17 my $nearest = $other_obj->{start}->add_vector($p);
55              
56 4 100 66     11 $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         45 my $clamped_vector = $other_obj->clamp($self->{center});
64              
65 12         36 $self->collides($clamped_vector);
66             }
67             elsif ($other_obj->isa('Math::Shape::OrientedRectangle'))
68             {
69             # transform OrientedRectangle into Rectangle
70 6         24 my $r_size = $other_obj->{half_extend}->multiply(2);
71 6         24 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         25 my $distance = $self->{center}->subtract_vector($other_obj->{center});
75 6         24 $distance = $distance->rotate(- $other_obj->{rotation});
76 6         25 my $center = $distance->add_vector($other_obj->{half_extend});
77 6         22 my $lc = Math::Shape::Circle->new($center->{x}, $center->{y}, $self->{radius});
78              
79             # check local objects collide
80 6         17 $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__