line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package GPS::Track::Point; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
779261
|
use Moo; |
|
2
|
|
|
|
|
6952
|
|
|
2
|
|
|
|
|
9
|
|
4
|
2
|
|
|
2
|
|
1685
|
use Scalar::Util qw/blessed/; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
96
|
|
5
|
2
|
|
|
2
|
|
546
|
use Geo::Distance; |
|
2
|
|
|
|
|
13790
|
|
|
2
|
|
|
|
|
149
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use overload |
8
|
1
|
|
|
1
|
|
6
|
'!=' => sub { !shift->equals(shift) }, |
9
|
2
|
|
|
2
|
|
17
|
'==' => \= |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
21
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
has ["lon", "lat", "ele", "spd", "bpm", "cad" ] => ( |
12
|
|
|
|
|
|
|
is => "rw", |
13
|
|
|
|
|
|
|
default => undef |
14
|
|
|
|
|
|
|
); |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
has "time" => ( |
17
|
|
|
|
|
|
|
is => "rw", |
18
|
|
|
|
|
|
|
default => undef, |
19
|
|
|
|
|
|
|
isa => sub { |
20
|
|
|
|
|
|
|
my $val = shift; |
21
|
|
|
|
|
|
|
die "Not a DateTime object!" if(defined($val) && !$val->isa("DateTime")); |
22
|
|
|
|
|
|
|
} |
23
|
|
|
|
|
|
|
); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
has "geoDistance" => ( |
26
|
|
|
|
|
|
|
is => "ro", |
27
|
|
|
|
|
|
|
default => sub { return Geo::Distance->new(); }, |
28
|
|
|
|
|
|
|
); |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub distanceTo { |
31
|
10
|
|
|
10
|
1
|
6848
|
my $self = shift; |
32
|
10
|
|
|
|
|
24
|
my $other = shift; |
33
|
|
|
|
|
|
|
|
34
|
10
|
|
|
|
|
21
|
my $otherLon = undef; |
35
|
10
|
|
|
|
|
20
|
my $otherLat = undef; |
36
|
|
|
|
|
|
|
|
37
|
10
|
100
|
|
|
|
50
|
if(blessed($other)) { |
38
|
6
|
100
|
|
|
|
39
|
unless($other->isa("GPS::Track::Point")) { |
39
|
1
|
|
|
|
|
14
|
die "\$other is not a GPS::Track::Point!"; |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
5
|
|
|
|
|
19
|
$otherLon = $other->lon; |
43
|
5
|
|
|
|
|
15
|
$otherLat = $other->lat; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
else { |
46
|
4
|
100
|
|
|
|
19
|
unless(ref($other) eq "HASH") { |
47
|
1
|
|
|
|
|
25
|
die "\$other is not a HASH reference!"; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
3
|
|
|
|
|
9
|
$otherLon = $other->{lon}; |
51
|
3
|
|
|
|
|
9
|
$otherLat = $other->{lat}; |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
8
|
100
|
|
|
|
45
|
die "\$other is missing a 'lon' value!" unless(defined $otherLon); |
55
|
6
|
100
|
|
|
|
40
|
die "\$other is missing a 'lat' value!" unless(defined $otherLat); |
56
|
|
|
|
|
|
|
|
57
|
4
|
100
|
|
|
|
52
|
die "\$self is missing a 'lon' value!" unless(defined $self->lon); |
58
|
3
|
100
|
|
|
|
22
|
die "\$self is missing a 'lat' value!" unless(defined $self->lat); |
59
|
|
|
|
|
|
|
|
60
|
2
|
|
|
|
|
19
|
return $self->geoDistance->distance("meter", $self->lon, $self->lat, $otherLon, $otherLat); |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub equals { |
64
|
9
|
|
|
9
|
1
|
174
|
my $self = shift; |
65
|
9
|
|
|
|
|
19
|
my $other = shift; |
66
|
|
|
|
|
|
|
|
67
|
9
|
100
|
66
|
|
|
87
|
unless(blessed($other) && $other->isa("GPS::Track::Point")) { |
68
|
1
|
|
|
|
|
14
|
die "First argument not a GPS::Track::Point!"; |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
8
|
|
|
|
|
22
|
my $equal = 1; |
72
|
|
|
|
|
|
|
|
73
|
8
|
|
|
|
|
24
|
foreach my $attr ($self->attributes) { |
74
|
32
|
|
|
|
|
225
|
my $me = $self->$attr(); |
75
|
32
|
|
|
|
|
212
|
my $other = $other->$attr(); |
76
|
|
|
|
|
|
|
|
77
|
32
|
|
100
|
|
|
139
|
my $bothDefined = defined($me) && defined($other); |
78
|
32
|
|
|
|
|
66
|
my $onlyOneDefined = defined($me) ^ defined($other); |
79
|
|
|
|
|
|
|
|
80
|
32
|
100
|
100
|
|
|
148
|
if($onlyOneDefined || ($bothDefined && $me != $other)) { |
|
|
|
100
|
|
|
|
|
81
|
4
|
|
|
|
|
9
|
$equal = 0; |
82
|
4
|
|
|
|
|
11
|
last; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
8
|
|
|
|
|
67
|
return $equal; |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
sub toString { |
89
|
1
|
|
|
1
|
1
|
18
|
my $self = shift; |
90
|
1
|
|
|
|
|
4
|
my @parts; |
91
|
1
|
|
|
|
|
5
|
foreach my $attr ($self->attributes) { |
92
|
7
|
|
|
|
|
50
|
my $value = $self->$attr(); |
93
|
7
|
100
|
|
|
|
44
|
push(@parts, "$attr=" . (defined($value) ? $value : "undef")); |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
1
|
|
|
|
|
12
|
return join(" ", @parts); |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
sub toHash { |
99
|
4
|
|
|
4
|
1
|
28
|
my $self = shift; |
100
|
4
|
|
|
|
|
8
|
my $data = {}; |
101
|
|
|
|
|
|
|
|
102
|
4
|
|
|
|
|
12
|
foreach my $attr ($self->attributes) { |
103
|
28
|
|
|
|
|
156
|
my $value = $self->$attr(); |
104
|
28
|
100
|
|
|
|
81
|
if(defined($value)) { |
105
|
14
|
|
|
|
|
20
|
$data->{$attr} = $value; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
4
|
|
|
|
|
24
|
return $data; |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub attributes { |
113
|
13
|
|
|
13
|
0
|
49
|
return qw/lon lat time ele spd cad bpm/; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
1; |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
__END__ |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=head1 NAME |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
GPS::Track::Point - Represent a Point of a GPS::Track |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=head1 SYNOPSIS |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# Construct an empty point |
127
|
|
|
|
|
|
|
my $point = GPS::Track::Point->new(); |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
# Construct a simple point |
130
|
|
|
|
|
|
|
my $point = GPS::Track::Point->new(lon => 12, lat => 13, ele => 8848); |
131
|
|
|
|
|
|
|
my $point = GPS::Track::Point->new( { lon => 12, lat => 13 } ); # Hashref Construction supported too |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
my $pointsEqual = $pointA == $pointB; # Watch out for floating point troubles! |
134
|
|
|
|
|
|
|
my $distance = $pointA->distanceTo($pointB); |
135
|
|
|
|
|
|
|
my $distance = $pointaA->distanceTo( { lon => 12, lat => 13 } ); |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=head1 DESCRIPTION |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
C<GPS::Track::Point> is a thin module representing a Point as parsed by L<GPS::Track>. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=head2 lon |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
my $lon = $point->lon; |
146
|
|
|
|
|
|
|
$point = $point->lon(48); |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=head2 lat |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
my $lat = $point->lat; |
151
|
|
|
|
|
|
|
$point = $point->lat(9); |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=head2 time |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
Accepts/Returns a L<DateTime>-Object or undef (if no time information is present) |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
my $time = $point->time; |
158
|
|
|
|
|
|
|
my $point = $point->time(DateTime->now()); |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=head2 ele |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
my $ele = $point->ele; |
163
|
|
|
|
|
|
|
$point = $point->ele(8848); |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=head2 spd |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
The speed at this point, measured in meter per second. |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
my $spd = $point->spd; |
170
|
|
|
|
|
|
|
my $point = $point->spd(10); |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=head2 cad |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
my $cad = $point->cad; |
175
|
|
|
|
|
|
|
$point = $point->cad(75); |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=head2 bpm |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
my $bpm = $point->bpm; |
180
|
|
|
|
|
|
|
$point = $point->bpm(180); |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
=head1 METHODS |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=head2 distanceTo($otherPoint) |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
Return the 2D distance to the other point in meters. |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
Dies if one of the points is missing lon/lat. |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
my $distance = $pointA->distanceTo($pointB); |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=head2 distanceTo( { lon => X, lat => Y } ) |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
Shorthand method to get the 2D distance to a known lon-lat-pair. |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
my $distance = $pointA->distanceTo( { lon => 12, lat => 6 } ); |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=head2 equals($otherPoint) |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
Compares to point object attribute by attribute. |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
Equal means, that ALL atributes of both points are equal in the sense of perl. You may experience troubles with floating point precision! |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
Return 1 for equal points, otherwise 0. |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
my $equal = $pointA->equals($pointB); |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=head2 toHash() |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
Convert the point to a plain hash ref. Only C<defined> attributes are included as keys in the hash. |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
my $point = GPS::Track::Point->new(lon => 1, lat => 2); |
213
|
|
|
|
|
|
|
my $ref = $point->toHash(); |
214
|
|
|
|
|
|
|
# { lon => 1, lat => 2 } |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=head2 toString() |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
Converts the point to a string representation. |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
my $point = GPS::Trakc::Point->new(lon => 1, lat => 2, ele => 8848); |
221
|
|
|
|
|
|
|
say $point->toString(); |
222
|
|
|
|
|
|
|
# lon=1 lat=2 ele=8848 time=undef cad=undef bpm=undef spd=undef |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=head1 OPERATORS |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=head2 == |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
Shorthand operator to call L</"equals-otherPoint"> on $pointA with $pointB as argument. |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
my $areEqual = $pointA == $pointB; |
231
|
|
|
|
|
|
|
# Equivalent to $pointA->equals($pointB); |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
=cut |