line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Geo::ShapeFile::Point; |
2
|
|
|
|
|
|
|
# TODO - add dimension operators (to specify if 2 or 3 dimensional point) |
3
|
2
|
|
|
2
|
|
13
|
use strict; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
57
|
|
4
|
2
|
|
|
2
|
|
10
|
use warnings; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
57
|
|
5
|
2
|
|
|
2
|
|
1143
|
use Math::Trig 1.04; |
|
2
|
|
|
|
|
29910
|
|
|
2
|
|
|
|
|
294
|
|
6
|
2
|
|
|
2
|
|
20
|
use Carp; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
231
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = '3.03'; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
use overload |
11
|
2
|
|
|
|
|
15
|
'==' => 'eq', |
12
|
|
|
|
|
|
|
'eq' => 'eq', |
13
|
|
|
|
|
|
|
'""' => 'stringify', |
14
|
|
|
|
|
|
|
'+' => \&add, |
15
|
|
|
|
|
|
|
'-' => \&subtract, |
16
|
|
|
|
|
|
|
'*' => \&multiply, |
17
|
|
|
|
|
|
|
'/' => \÷, |
18
|
|
|
|
|
|
|
fallback => 1, |
19
|
2
|
|
|
2
|
|
15
|
; |
|
2
|
|
|
|
|
4
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
my %config = ( |
22
|
|
|
|
|
|
|
comp_includes_z => 1, |
23
|
|
|
|
|
|
|
comp_includes_m => 1, |
24
|
|
|
|
|
|
|
); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
sub new { |
27
|
83413
|
|
|
83413
|
1
|
155754
|
my $proto = shift; |
28
|
83413
|
|
33
|
|
|
191428
|
my $class = ref($proto) || $proto; |
29
|
|
|
|
|
|
|
|
30
|
83413
|
|
|
|
|
244622
|
my $self = {@_}; |
31
|
|
|
|
|
|
|
|
32
|
83413
|
|
|
|
|
115252
|
bless $self, $class; |
33
|
|
|
|
|
|
|
|
34
|
83413
|
|
|
|
|
220598
|
return $self; |
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub _var { |
38
|
107360
|
|
|
107360
|
|
139113
|
my $self = shift; |
39
|
107360
|
|
|
|
|
134379
|
my $var = shift; |
40
|
|
|
|
|
|
|
|
41
|
107360
|
100
|
|
|
|
158761
|
if (@_) { |
42
|
10098
|
|
|
|
|
24710
|
return $self->{$var} = shift; |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
else { |
45
|
97262
|
|
|
|
|
177533
|
return $self->{$var}; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# these could be factory generated |
50
|
48490
|
|
|
48490
|
1
|
2738800
|
sub X { shift()->_var('X', @_); } |
51
|
48490
|
|
|
48490
|
1
|
144930
|
sub Y { shift()->_var('Y', @_); } |
52
|
7791
|
|
|
7791
|
1
|
14699
|
sub Z { shift()->_var('Z', @_); } |
53
|
2589
|
|
|
2589
|
1
|
5602
|
sub M { shift()->_var('M', @_); } |
54
|
|
|
|
|
|
|
|
55
|
0
|
|
|
0
|
1
|
0
|
sub x_min { $_[0]->_var('X'); } |
56
|
0
|
|
|
0
|
1
|
0
|
sub x_max { $_[0]->_var('X'); } |
57
|
0
|
|
|
0
|
1
|
0
|
sub y_min { $_[0]->_var('Y'); } |
58
|
0
|
|
|
0
|
1
|
0
|
sub y_max { $_[0]->_var('Y'); } |
59
|
0
|
|
|
0
|
1
|
0
|
sub z_min { $_[0]->_var('Z'); } |
60
|
0
|
|
|
0
|
1
|
0
|
sub z_max { $_[0]->_var('Z'); } |
61
|
0
|
|
|
0
|
1
|
0
|
sub m_min { $_[0]->_var('M'); } |
62
|
0
|
|
|
0
|
1
|
0
|
sub m_max { $_[0]->_var('M'); } |
63
|
|
|
|
|
|
|
|
64
|
16984
|
|
|
16984
|
1
|
41765
|
sub get_x { $_[0]->{X} } |
65
|
16984
|
|
|
16984
|
1
|
54747
|
sub get_y { $_[0]->{Y} } |
66
|
0
|
|
|
0
|
1
|
0
|
sub get_z { $_[0]->{Z} } |
67
|
0
|
|
|
0
|
1
|
0
|
sub get_m { $_[0]->{M} } |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
sub import { |
71
|
4
|
|
|
4
|
|
145
|
my $self = shift; |
72
|
4
|
|
|
|
|
13
|
my %args = @_; |
73
|
|
|
|
|
|
|
|
74
|
4
|
|
|
|
|
136
|
foreach(keys %args) { $config{$_} = $args{$_}; } |
|
0
|
|
|
|
|
0
|
|
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub eq { |
78
|
8
|
|
|
8
|
0
|
1296
|
my $left = shift; |
79
|
8
|
|
|
|
|
12
|
my $right = shift; |
80
|
|
|
|
|
|
|
|
81
|
8
|
100
|
66
|
|
|
34
|
if ($config{comp_includes_z} && (defined $left->Z || defined $right->Z)) { |
|
|
|
33
|
|
|
|
|
82
|
1
|
50
|
33
|
|
|
14
|
return 0 unless defined $left->Z && defined $right->Z; |
83
|
1
|
50
|
|
|
|
4
|
return 0 unless $left->Z == $right->Z; |
84
|
|
|
|
|
|
|
} |
85
|
8
|
100
|
66
|
|
|
25
|
if ($config{comp_includes_m} && (defined $left->M || defined $right->M)) { |
|
|
|
33
|
|
|
|
|
86
|
3
|
50
|
33
|
|
|
23
|
return 0 unless defined $left->M && defined $right->M; |
87
|
3
|
50
|
|
|
|
16
|
return 0 unless $left->M == $right->M; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
8
|
|
33
|
|
|
19
|
return ($left->X == $right->X && $left->Y == $right->Y); |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub stringify { |
94
|
107
|
|
|
107
|
0
|
2955
|
my $self = shift; |
95
|
|
|
|
|
|
|
|
96
|
107
|
|
|
|
|
197
|
my @foo = (); |
97
|
107
|
|
|
|
|
223
|
foreach(qw/X Y Z M/) { |
98
|
428
|
100
|
|
|
|
976
|
if(defined $self->$_()) { |
99
|
230
|
|
|
|
|
508
|
push @foo, "$_=" . $self->$_(); |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
} |
102
|
107
|
|
|
|
|
886
|
my $r = 'Point(' . join(',', @foo) . ')'; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub distance_from { |
106
|
0
|
|
|
0
|
1
|
0
|
my ($p1, $p2) = @_; |
107
|
|
|
|
|
|
|
|
108
|
0
|
|
|
|
|
0
|
my $dp = $p2->subtract($p1); |
109
|
0
|
|
|
|
|
0
|
return sqrt ( ($dp->X ** 2) + ($dp->Y **2) ); |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
0
|
|
|
0
|
0
|
0
|
sub distance_to { distance_from(@_); } |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
sub angle_to { |
115
|
8
|
|
|
8
|
1
|
32
|
my ($p1, $p2) = @_; |
116
|
|
|
|
|
|
|
|
117
|
8
|
|
|
|
|
23
|
my $dp = $p2->subtract ($p1); |
118
|
|
|
|
|
|
|
|
119
|
8
|
|
|
|
|
19
|
my $x_off = $dp->get_x; |
120
|
8
|
|
|
|
|
18
|
my $y_off = $dp->get_y; |
121
|
|
|
|
|
|
|
|
122
|
8
|
100
|
100
|
|
|
33
|
return 0 if !($x_off || $y_off); |
123
|
|
|
|
|
|
|
|
124
|
7
|
|
|
|
|
49
|
my $bearing = 90 - Math::Trig::rad2deg (Math::Trig::atan2 ($y_off, $x_off)); |
125
|
7
|
100
|
|
|
|
194
|
if ($bearing < 0) { |
126
|
2
|
|
|
|
|
4
|
$bearing += 360; |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
7
|
|
|
|
|
25
|
return $bearing; |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
|
132
|
0
|
|
|
0
|
0
|
0
|
sub add { _mathemagic('add', @_); } |
133
|
8
|
|
|
8
|
0
|
21
|
sub subtract { _mathemagic('subtract', @_); } |
134
|
0
|
|
|
0
|
0
|
0
|
sub multiply { _mathemagic('multiply', @_); } |
135
|
0
|
|
|
0
|
0
|
0
|
sub divide { _mathemagic('divide', @_); } |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
sub _mathemagic { |
138
|
8
|
|
|
8
|
|
19
|
my ($op, $l, $r, $reverse) = @_; |
139
|
|
|
|
|
|
|
|
140
|
8
|
50
|
|
|
|
24
|
if ($reverse) { # put them back in the right order |
141
|
0
|
|
|
|
|
0
|
($l, $r) = ($r, $l); |
142
|
|
|
|
|
|
|
} |
143
|
8
|
|
|
|
|
13
|
my ($left, $right); |
144
|
|
|
|
|
|
|
|
145
|
8
|
50
|
|
|
|
35
|
if (UNIVERSAL::isa($l, 'Geo::ShapeFile::Point')) { $left = 'point'; } |
|
8
|
|
|
|
|
14
|
|
146
|
8
|
50
|
|
|
|
22
|
if (UNIVERSAL::isa($r, 'Geo::ShapeFile::Point')) { $right = 'point'; } |
|
8
|
|
|
|
|
14
|
|
147
|
|
|
|
|
|
|
|
148
|
8
|
50
|
|
|
|
27
|
if ($l =~ /^[\d\.]+$/) { $left = 'number'; } |
|
0
|
|
|
|
|
0
|
|
149
|
8
|
50
|
|
|
|
20
|
if ($r =~ /^[\d\.]+$/) { $right = 'number'; } |
|
0
|
|
|
|
|
0
|
|
150
|
|
|
|
|
|
|
|
151
|
8
|
50
|
|
|
|
25
|
unless ($left) { croak "Couldn't identify $l for $op"; } |
|
0
|
|
|
|
|
0
|
|
152
|
8
|
50
|
|
|
|
23
|
unless ($right) { croak "Couldn't identify $r for $op"; } |
|
0
|
|
|
|
|
0
|
|
153
|
|
|
|
|
|
|
|
154
|
8
|
|
|
|
|
63
|
my $function = '_' . join '_', $op, $left, $right; |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
croak "Don't know how to $op $left and $right" |
157
|
8
|
50
|
|
|
|
13
|
if !defined &{$function}; |
|
8
|
|
|
|
|
40
|
|
158
|
|
|
|
|
|
|
|
159
|
8
|
|
|
|
|
13
|
do { |
160
|
2
|
|
|
2
|
|
2909
|
no strict 'refs'; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
1618
|
|
161
|
8
|
|
|
|
|
29
|
return $function->($l, $r); |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub _add_point_point { |
166
|
0
|
|
|
0
|
|
0
|
my ($p1, $p2) = @_; |
167
|
|
|
|
|
|
|
|
168
|
0
|
|
|
|
|
0
|
my $z; |
169
|
0
|
0
|
0
|
|
|
0
|
if(defined($p2->Z) && defined($p1->Z)) { $z = ($p2->Z + $p1->Z); } |
|
0
|
|
|
|
|
0
|
|
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
Geo::ShapeFile::Point->new( |
172
|
0
|
|
|
|
|
0
|
X => ($p2->X + $p1->X), |
173
|
|
|
|
|
|
|
Y => ($p2->Y + $p1->Y), |
174
|
|
|
|
|
|
|
Z => $z, |
175
|
|
|
|
|
|
|
); |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
sub _add_point_number { |
179
|
0
|
|
|
0
|
|
0
|
my ($p1, $n) = @_; |
180
|
|
|
|
|
|
|
|
181
|
0
|
|
|
|
|
0
|
my $z; |
182
|
0
|
0
|
|
|
|
0
|
if (defined($p1->Z)) { $z = ($p1->Z + $n); } |
|
0
|
|
|
|
|
0
|
|
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
Geo::ShapeFile::Point->new( |
185
|
0
|
|
|
|
|
0
|
X => ($p1->X + $n), |
186
|
|
|
|
|
|
|
Y => ($p1->Y + $n), |
187
|
|
|
|
|
|
|
Z => $z, |
188
|
|
|
|
|
|
|
); |
189
|
|
|
|
|
|
|
} |
190
|
0
|
|
|
0
|
|
0
|
sub _add_number_point { add_point_number(@_); } |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
sub _subtract_point_point { |
193
|
8
|
|
|
8
|
|
18
|
my($p1, $p2) = @_; |
194
|
|
|
|
|
|
|
|
195
|
8
|
|
|
|
|
11
|
my $z; |
196
|
8
|
50
|
33
|
|
|
18
|
if(defined($p2->Z) && defined($p1->Z)) { $z = ($p2->Z - $p1->Z); } |
|
0
|
|
|
|
|
0
|
|
197
|
|
|
|
|
|
|
|
198
|
8
|
|
|
|
|
24
|
my $result = Geo::ShapeFile::Point->new( |
199
|
|
|
|
|
|
|
X => ($p1->X - $p2->X), |
200
|
|
|
|
|
|
|
Y => ($p1->Y - $p2->Y), |
201
|
|
|
|
|
|
|
Z => $z, |
202
|
|
|
|
|
|
|
); |
203
|
8
|
|
|
|
|
25
|
return $result; |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
sub _subtract_point_number { |
207
|
0
|
|
|
0
|
|
|
my($p1, $n) = @_; |
208
|
|
|
|
|
|
|
|
209
|
0
|
|
|
|
|
|
my $z; |
210
|
0
|
0
|
|
|
|
|
if (defined $p1->Z) { |
211
|
0
|
|
|
|
|
|
$z = ($p1->Z - $n); |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
Geo::ShapeFile::Point->new( |
215
|
0
|
|
|
|
|
|
X => ($p1->X - $n), |
216
|
|
|
|
|
|
|
Y => ($p1->Y - $n), |
217
|
|
|
|
|
|
|
Z => $z, |
218
|
|
|
|
|
|
|
); |
219
|
|
|
|
|
|
|
} |
220
|
0
|
|
|
0
|
|
|
sub _subtract_number_point { _subtract_point_number(reverse @_); } |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
sub _multiply_point_point { |
223
|
0
|
|
|
0
|
|
|
my ($p1, $p2) = @_; |
224
|
|
|
|
|
|
|
|
225
|
0
|
|
|
|
|
|
my $z; |
226
|
0
|
0
|
0
|
|
|
|
if (defined $p2->Z and defined $p1->Z) { |
227
|
0
|
|
|
|
|
|
$z = $p2->Z * $p1->Z; |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
Geo::ShapeFile::Point->new( |
231
|
0
|
|
|
|
|
|
X => ($p2->X * $p1->X), |
232
|
|
|
|
|
|
|
Y => ($p2->Y * $p1->Y), |
233
|
|
|
|
|
|
|
Z => $z, |
234
|
|
|
|
|
|
|
); |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
sub _multiply_point_number { |
237
|
0
|
|
|
0
|
|
|
my($p1, $n) = @_; |
238
|
|
|
|
|
|
|
|
239
|
0
|
|
|
|
|
|
my $z; |
240
|
0
|
0
|
|
|
|
|
if (defined $p1->Z) { |
241
|
0
|
|
|
|
|
|
$z = $p1->Z * $n; |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
Geo::ShapeFile::Point->new( |
245
|
0
|
|
|
|
|
|
X => ($p1->X * $n), |
246
|
|
|
|
|
|
|
Y => ($p1->Y * $n), |
247
|
|
|
|
|
|
|
Z => $z, |
248
|
|
|
|
|
|
|
); |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
0
|
|
|
0
|
|
|
sub _multiply_number_point { _multiply_point_number(reverse @_); } |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
sub _divide_point_point { |
254
|
0
|
|
|
0
|
|
|
my($p1, $p2) = @_; |
255
|
|
|
|
|
|
|
|
256
|
0
|
|
|
|
|
|
my $z; |
257
|
0
|
0
|
0
|
|
|
|
if (defined $p2->Z and defined $p1->Z) { |
258
|
0
|
|
|
|
|
|
$z = $p1->Z / $p2->Z; |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
Geo::ShapeFile::Point->new( |
262
|
0
|
|
|
|
|
|
X => ($p1->X / $p2->X), |
263
|
|
|
|
|
|
|
Y => ($p1->Y / $p2->Y), |
264
|
|
|
|
|
|
|
Z => $z, |
265
|
|
|
|
|
|
|
); |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
sub _divide_point_number { |
269
|
0
|
|
|
0
|
|
|
my ($p1, $n) = @_; |
270
|
|
|
|
|
|
|
|
271
|
0
|
|
|
|
|
|
my $z; |
272
|
0
|
0
|
|
|
|
|
if (defined $p1->Z) { |
273
|
0
|
|
|
|
|
|
$z = $p1->Z / $n; |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
Geo::ShapeFile::Point->new( |
277
|
0
|
|
|
|
|
|
X => ($p1->X / $n), |
278
|
|
|
|
|
|
|
Y => ($p1->Y / $n), |
279
|
|
|
|
|
|
|
Z => $z, |
280
|
|
|
|
|
|
|
); |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
|
283
|
0
|
|
|
0
|
|
|
sub _divide_number_point { divide_point_number(reverse @_); } |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
1; |
286
|
|
|
|
|
|
|
__END__ |