File Coverage

blib/lib/Algorithm/BreakOverlappingRectangles.pm
Criterion Covered Total %
statement 71 103 68.9
branch 9 20 45.0
condition n/a
subroutine 17 22 77.2
pod 4 6 66.6
total 101 151 66.8


line stmt bran cond sub pod time code
1             package Algorithm::BreakOverlappingRectangles;
2              
3 1     1   23290 use strict;
  1         3  
  1         45  
4 1     1   6 use warnings;
  1         3  
  1         76  
5              
6             BEGIN {
7 1     1   2 our $VERSION = '0.01';
8              
9 1         10 require XSLoader;
10 1         740 XSLoader::load('Algorithm::BreakOverlappingRectangles', $VERSION);
11             }
12              
13              
14 1     1   11 use constant X0 => 0;
  1         2  
  1         94  
15 1     1   4 use constant Y0 => 1;
  1         2  
  1         40  
16 1     1   4 use constant X1 => 2;
  1         2  
  1         29  
17 1     1   4 use constant Y1 => 3;
  1         1  
  1         54  
18              
19             our $verbose = 0;
20              
21 1     1   4 use constant NVSIZE => length pack F => 1.0;
  1         1  
  1         66  
22 1     1   4 use constant IDOFFSET => NVSIZE * 4;
  1         1  
  1         711  
23              
24             sub new {
25 5     5 1 106559 my $class = shift;
26 5         53 my $self = { rects => [],
27             name2id => {},
28             names => [],
29             n => 0 };
30 5         53 bless $self, $class;
31             }
32              
33             sub add_rectangle {
34 1005     1005 1 21570 my ($self, $x0, $y0, $x1, $y1, @names) = @_;
35              
36 1005 100       2163 ($x0, $x1) = ($x1, $x0) if $x0 > $x1;
37 1005 100       2177 ($y0, $y1) = ($y1, $y0) if $y0 > $y1;
38              
39 1005         1059 my @ids;
40 1005         1320 for (@names) {
41 1005         2038 my $id = $self->{name2id}{$_};
42 1005 50       1787 unless (defined $id) {
43 1005         915 $id = $self->{name2id}{$_} = @{$self->{names}};
  1005         3853  
44 1005         1043 push @{$self->{names}}, $_;
  1005         2165  
45             }
46 1005         2189 push @ids, $id;
47             }
48              
49 1005         1350 push @{$self->{rects}}, pack 'F4L*' => $x0, $y0, $x1, $y1, @ids;
  1005         3483  
50 1005         1433 delete $self->{broken};
51 1005         2894 ++($self->{n});
52             }
53              
54             sub _do_break {
55 5     5   8 my $self = shift;
56 5         1604547 _break_rectangles $self->{rects};
57 5         60 $self->{broken} = 1;
58 5         31 $self->{iter} = 0;
59             }
60              
61             * _brute_force_break = \&_brute_force_break_xs;
62              
63             sub dump {
64 0     0 0 0 my $self = shift;
65 0 0       0 $self->_do_break unless $self->{broken};
66 0         0 for (@{$self->{rects}}) {
  0         0  
67 0         0 my ($x0, $y0, $x1, $y1, @ids) = unpack 'F4L*' => $_;
68 0         0 my @names = map $self->{names}[$_], @ids;
69             # my @names = @ids;
70 0         0 print "[$x0 $y0 $x1 $y1 | @names]\n";
71             }
72              
73 0         0 print "$self->{n} rectangles broken into ".(scalar @{$self->{rects}})."\n";
  0         0  
74              
75             }
76              
77             sub dump_stats {
78 0     0 0 0 my $self = shift;
79 0 0       0 $self->_do_break unless $self->{broken};
80 0         0 print "$self->{n} rectangles broken into ".(scalar @{$self->{rects}})."\n";
  0         0  
81             }
82              
83             sub get_rectangles {
84 0     0 1 0 my $self = shift;
85 0 0       0 $self->_do_break unless $self->{broken};
86 0         0 my $names = $self->{names};
87 0         0 map {
88 0         0 my @a = unpack "F4I*" => $_;
89 0         0 $a[$_] = $names->[$a[$_]] for (4..$#a);
90 0         0 \@a;
91 0         0 } @{$self->{rects}}
92             }
93              
94              
95             sub get_rectangles_as_array_ref {
96 5     5 1 77 my $self = shift;
97 5         55 tie my @iter, 'Algorithm::BreakOverlappingRectangles::Iterator', $self;
98 5         20 return \@iter;
99             }
100              
101             package Algorithm::BreakOverlappingRectangles::Iterator;
102              
103 1     1   8 use base 'Tie::Array';
  1         2  
  1         1403  
104              
105             sub TIEARRAY {
106 5     5   15 my ($class, $abor) = @_;
107 5         33 my $self = bless \$abor, $class;
108             }
109              
110             sub FETCH {
111 121167     121167   31949277 my ($self, $index) = @_;
112 121167         130288 my $abor = $$self;
113 121167 50       249382 $abor->_do_break unless $abor->{broken};
114 121167         236098 my $r = $abor->{rects}[$index];
115 121167 50       233585 if (defined $r) {
116             # print ".";
117 121167         148637 my $names = $abor->{names};
118 121167         678476 my ($x0, $y0, $x1, $y1, @ids) = unpack 'F4I*' => $r;
119 121167         2973306 return [$x0, $y0, $x1, $y1, map($names->[$_], @ids)];
120             }
121             ()
122 0         0 }
123              
124             sub EXISTS {
125 0     0   0 my ($self, $index) = @_;
126 0         0 my $abor = $$self;
127 0 0       0 $abor->_do_break unless $abor->{broken};
128 0         0 my $rects = $abor->{rects};
129 0         0 return (@$rects > $index);
130             }
131              
132             sub FETCHSIZE {
133 120946     120946   1974714 my ($self) = @_;
134 120946         138439 my $abor = $$self;
135 120946 100       244723 $abor->_do_break unless $abor->{broken};
136 120946         150202 my $rects = $abor->{rects};
137 120946         280190 return scalar(@$rects);
138             }
139              
140             sub PUSH {
141 0     0     my $self = shift;
142 0           $self->[0] = 0;
143 0           my $abor = $$self;
144 0           $abor->add_rectangle(@$_) for (@_);
145 0           1;
146             }
147              
148              
149             1;
150              
151             __END__