File Coverage

blib/lib/Imager/LineTrace/Algorithm.pm
Criterion Covered Total %
statement 83 83 100.0
branch 36 38 94.7
condition 20 21 95.2
subroutine 4 4 100.0
pod 0 1 0.0
total 143 147 97.2


line stmt bran cond sub pod time code
1             package Imager::LineTrace::Algorithm;
2 2     2   1272 use 5.008001;
  2         8  
  2         96  
3 2     2   12 use strict;
  2         15  
  2         73  
4 2     2   11 use warnings;
  2         4  
  2         1635  
5              
6             # コード中のコメントは、左下を原点として記述している
7             sub search {
8 16     16 0 22590 my ( $pixels_ref, $opt ) = @_;
9 16 50       64 my $ignore = ( exists $opt->{ignore} ) ? $opt->{ignore} : 0;
10 16 50       45 my $limit = ( exists $opt->{limit} ) ? $opt->{limit} : 1024;
11              
12 16         21 my $w = scalar(@{$pixels_ref->[0]});
  16         34  
13 16         29 my $h = scalar(@{$pixels_ref});
  16         27  
14              
15 16         173 my @figures = ();
16 16         27 my $y0 = 0;
17 16         41 foreach my $point_number (1..$limit) {
18 35         61 my ( $x, $y ) = ( -1, -1 );
19              
20 35         103 for (my $iy=$y0; $iy<$h; $iy++) {
21 54         68 my $i = 0;
22             #say "iy = $iy";
23 54         58 foreach my $val (@{$pixels_ref->[$iy]}) {
  54         143  
24 114 100       223 if ( $val != $ignore ) {
25             #say "here!!!!!!!!!!!!!";
26 19         26 $x = $i;
27 19         22 $y = $iy;
28 19         34 last;
29             }
30 95         153 $i++;
31             }
32              
33 54 100       137 last if 0 <= $y;
34 35         93 $y0 = $iy + 1;
35             }
36              
37 35 100       76 if ( $y < 0 ) {
38 16         29 last;
39             }
40              
41 19         28 my $x0 = $x;
42 19         21 my $y0 = $y;
43 19         33 my $trace_value = $pixels_ref->[$y][$x];
44              
45             # 探索開始点は図形の左下なので、
46             # 上方向と繋がってなければ閉じていないと判断できる
47 19         26 my $is_close = 0;
48 19 100 100     90 if ( $x0 < ($w - 1) and $y0 < ($h - 1) ) {
49 9 100 100     58 if ( $pixels_ref->[$y][$x + 1] == $trace_value
50             and $pixels_ref->[$y + 1][$x] == $trace_value ) {
51 2         5 $is_close = 1;
52             }
53             }
54              
55 19 100       46 if ( $is_close ) {
56             # 最後の探索が開始点に到達できるように残しておく
57             }
58             else {
59             # 閉じた図形ではないので、探索済みの処理をする
60 17         30 $pixels_ref->[$y][$x] = $ignore;
61             }
62              
63 19         46 my @points = ( [$x, $y] );
64 19         32 my $search_comp = 0;
65 19         48 while ( not $search_comp ) {
66 33         41 my $number_of_points = scalar( @points );
67              
68             # 右方向に探索
69 33 100 100     136 if ( ($x + 1) < $w and $pixels_ref->[$y][$x + 1] == $trace_value ) {
70 10         32 while ( $pixels_ref->[$y][$x + 1] == $trace_value ) {
71 20         21 $x++;
72 20         31 $pixels_ref->[$y][$x] = $ignore;
73 20 100       79 last if $w <= ($x + 1);
74             }
75              
76 10         24 push @points, [ $x, $y ];
77             }
78              
79             # 上方向に探索
80 33 100 100     129 if ( ($y + 1) < $h and $pixels_ref->[$y + 1][$x] == $trace_value ) {
81 7         38 while ( $pixels_ref->[$y + 1][$x] == $trace_value ) {
82 14         16 $y++;
83 14         26 $pixels_ref->[$y][$x] = $ignore;
84 14 100       52 last if $h <= ($y + 1);
85             }
86              
87 7         18 push @points, [ $x, $y ];
88             }
89              
90             # 左方向に探索
91 33 100 100     139 if ( 0 < ($x - 1) and $pixels_ref->[$y][$x - 1] == $trace_value ) {
92 2         9 while ( $pixels_ref->[$y][$x - 1] == $trace_value ) {
93 4         6 $x--;
94 4         6 $pixels_ref->[$y][$x] = $ignore;
95 4 100       15 last if ($x - 1) < 0;
96             }
97              
98 2         5 push @points, [ $x, $y ];
99             }
100              
101             # 下方向に探索
102 33 100 100     120 if ( 0 < ($y - 1) and $pixels_ref->[$y - 1][$x] == $trace_value ) {
103 2         5 while ( $pixels_ref->[$y - 1][$x] == $trace_value ) {
104 4         5 $y--;
105 4         6 $pixels_ref->[$y][$x] = $ignore;
106 4 100       13 last if ($y - 1) < 0;
107             }
108              
109 2         4 push @points, [ $x, $y ];
110             }
111              
112             # 探索前と頂点を比較することで完了したか判定
113 33 100       85 if ( $number_of_points == scalar(@points) ) {
114 20 100       37 if ( $is_close ) {
115 2         7 my ( $p1, $p2 ) = @points[0,-1];
116 2 100 66     11 if ( $p1->[0] == $p2->[0] and $p1->[1] == $p2->[1] ) {
117             # 開始点と終点が同じなので、終点を取り除いて探索終了
118 1         5 pop @points;
119 1         5 $search_comp = 1;
120             }
121             else {
122             # 閉じていないことが判明したので、開始点から再探索
123 1         2 $is_close = 0;
124 1         3 @points = reverse @points;
125 1         3 $pixels_ref->[$y0][$x0] = $ignore;
126 1         3 ( $x, $y ) = ( $x0, $y0 );
127             }
128             }
129             else {
130 18         51 $search_comp = 1;
131             }
132             }
133             }
134              
135 19         104 push @figures, +{
136             points => \@points,
137             is_closed => $is_close,
138             value => $trace_value
139             };
140             }
141              
142 16         53 return \@figures;
143             }
144              
145             1;
146             __END__