line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Geo::Elevation::HGT; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
52734
|
use 5.010; |
|
1
|
|
|
|
|
3
|
|
4
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
17
|
|
5
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
20
|
|
6
|
1
|
|
|
1
|
|
402
|
use POSIX (); |
|
1
|
|
|
|
|
5046
|
|
|
1
|
|
|
|
|
24
|
|
7
|
1
|
|
|
1
|
|
6
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
578
|
|
8
|
|
|
|
|
|
|
# set the version for version checking |
9
|
|
|
|
|
|
|
our $VERSION = '0.08'; |
10
|
|
|
|
|
|
|
# file-private lexicals |
11
|
|
|
|
|
|
|
my $grid_size; # .hgt grid size = 3601x3601 for 1-minute DEMs or 7201x7201 for 0.5-minute DEMs or 1201x1201 for 3-minute DEMs |
12
|
|
|
|
|
|
|
my @DEMnames; |
13
|
|
|
|
|
|
|
my @default_DEMs; |
14
|
|
|
|
|
|
|
my @want_DEMnames; |
15
|
|
|
|
|
|
|
my $status_descr; |
16
|
|
|
|
|
|
|
my $url; |
17
|
|
|
|
|
|
|
my $folder; |
18
|
|
|
|
|
|
|
my $cache_folder; |
19
|
|
|
|
|
|
|
my $debug; |
20
|
|
|
|
|
|
|
my $bicubic; |
21
|
|
|
|
|
|
|
my $bicubic_current; |
22
|
|
|
|
|
|
|
my $bicubic_mixed; |
23
|
|
|
|
|
|
|
my $switch; |
24
|
|
|
|
|
|
|
my $cache; |
25
|
|
|
|
|
|
|
my $fail; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub new { |
28
|
0
|
|
|
0
|
1
|
|
my ($class, %params) = @_; |
29
|
0
|
|
|
|
|
|
%params = ( |
30
|
|
|
|
|
|
|
url => "https://elevation-tiles-prod.s3.amazonaws.com/skadi", # info at https://registry.opendata.aws/terrain-tiles/ |
31
|
|
|
|
|
|
|
folder => "https://elevation-tiles-prod.s3.amazonaws.com/skadi", |
32
|
|
|
|
|
|
|
cache_folder => "", |
33
|
|
|
|
|
|
|
debug => 0, |
34
|
|
|
|
|
|
|
bicubic => 0, |
35
|
|
|
|
|
|
|
bicubic_current => 0, |
36
|
|
|
|
|
|
|
bicubic_mixed => 0, |
37
|
|
|
|
|
|
|
%params |
38
|
|
|
|
|
|
|
); |
39
|
0
|
|
|
|
|
|
my $self = {}; |
40
|
0
|
|
|
|
|
|
while ( my($key,$value) = each %params ) { |
41
|
0
|
|
|
|
|
|
$self->{$key} = $value; |
42
|
|
|
|
|
|
|
} |
43
|
0
|
|
|
|
|
|
bless $self, $class; |
44
|
0
|
|
|
|
|
|
return $self; |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub get_elevation_batch_hgt { |
48
|
0
|
|
|
0
|
1
|
|
my ($self, $batch_latlon) = @_; |
49
|
0
|
|
|
|
|
|
my @elegeh; |
50
|
0
|
|
|
|
|
|
for my $latlon ( @$batch_latlon ) { |
51
|
0
|
|
|
|
|
|
my ($lat, $lon) = @$latlon; |
52
|
0
|
|
|
|
|
|
push (@elegeh, $self->get_elevation_hgt ($lat, $lon)); |
53
|
|
|
|
|
|
|
} |
54
|
0
|
|
|
|
|
|
return \@elegeh; |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
sub get_elevation_hgt { |
58
|
0
|
|
|
0
|
1
|
|
my ($self, $lat, $lon) = @_; |
59
|
0
|
|
|
|
|
|
$folder = $self->{folder}; |
60
|
0
|
|
|
|
|
|
$url = $self->{url}; |
61
|
0
|
|
|
|
|
|
$cache_folder = $self->{cache_folder}; |
62
|
0
|
|
|
|
|
|
$debug = $self->{debug}; |
63
|
0
|
|
|
|
|
|
$bicubic = $self->{bicubic}; |
64
|
0
|
|
|
|
|
|
$bicubic_current = $self->{bicubic_current}; |
65
|
0
|
|
|
|
|
|
$bicubic_mixed = $self->{bicubic_mixed}; |
66
|
0
|
|
|
|
|
|
$status_descr = "Memory"; |
67
|
0
|
0
|
|
|
|
|
say STDERR "get_elevation_hgt" if $debug; |
68
|
0
|
0
|
|
|
|
|
say STDERR " Parameters: folder=>'$folder', url=>'$url', cache_folder=>'$cache_folder', debug=>$debug, bicubic=>$bicubic" if $debug; |
69
|
0
|
0
|
|
|
|
|
say STDERR " Input lat lon: $lat $lon" if $debug; |
70
|
0
|
|
|
|
|
|
my $flat = POSIX::floor $lat; |
71
|
0
|
|
|
|
|
|
my $flon = POSIX::floor $lon; |
72
|
0
|
0
|
|
|
|
|
my $ns = $flat < 0 ? "S" : "N"; |
73
|
0
|
0
|
|
|
|
|
my $ew = $flon < 0 ? "W" : "E"; |
74
|
0
|
|
|
|
|
|
my $lt = sprintf ("%02s", abs($flat)); |
75
|
0
|
|
|
|
|
|
my $ln = sprintf ("%03s", abs($flon)); |
76
|
0
|
|
|
|
|
|
my $DEMname = "$ns$lt$ew$ln"; |
77
|
0
|
0
|
|
|
|
|
say STDERR " Tile lat lon: $flat $flon" if $debug; |
78
|
|
|
|
|
|
|
# read DEM unless already defined |
79
|
0
|
0
|
0
|
|
|
|
say STDERR " Using DEM in memory: '$flat $flon'" if ($debug and defined $self->{DEMs}{$DEMname}{DEM}); |
80
|
0
|
|
0
|
|
|
|
$self->{DEMs}{$DEMname}{DEM} //= $self->_readDEM($DEMname); # //= Logical Defined-Or Assignment Operator |
81
|
0
|
|
|
|
|
|
my $dem = $self->{DEMs}{$DEMname}{DEM}; |
82
|
0
|
0
|
|
|
|
|
say STDERR " Status: $status_descr" if $debug; |
83
|
0
|
|
|
|
|
|
$self->{lat} = $lat; |
84
|
0
|
|
|
|
|
|
$self->{lon} = $lon; |
85
|
0
|
|
|
|
|
|
$self->{status_descr} = $status_descr; |
86
|
0
|
|
|
|
|
|
$self->{switch} = $switch; |
87
|
0
|
|
|
|
|
|
$self->{cache} = $cache; |
88
|
0
|
|
|
|
|
|
$self->{fail} = $fail; |
89
|
0
|
|
|
|
|
|
$self->{DEMname} = $DEMname; |
90
|
0
|
0
|
|
|
|
|
if (ref($dem) eq "") { |
91
|
0
|
0
|
|
|
|
|
say STDERR " No data in DEM: '$flat $flon' returning elevation 0" if $debug; |
92
|
0
|
|
|
|
|
|
$self->{grid_size} = 0; |
93
|
0
|
|
|
|
|
|
$self->{elevation} = 0; |
94
|
0
|
|
|
|
|
|
return $self->{elevation}; |
95
|
|
|
|
|
|
|
} |
96
|
0
|
|
|
|
|
|
$grid_size = sqrt (length ($$dem)/2); # grid size of DEM |
97
|
0
|
0
|
0
|
|
|
|
unless ($grid_size == 3601 or $grid_size == 7201 or $grid_size == 1201) { |
|
|
|
0
|
|
|
|
|
98
|
0
|
|
|
|
|
|
croak "Unknown tile format for '$self->{DEMs}{$DEMname}{DEMpath}': grid size is '$grid_size', should be 3601 or 7201 or 1201"; |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
# the DEMs start in the NW corner with $grid_size - 1 intervals |
101
|
0
|
|
|
|
|
|
my $ilat = (1 - ($lat - $flat)) * ($grid_size - 1); |
102
|
0
|
|
|
|
|
|
my $ilon = ($lon - $flon) * ($grid_size - 1); |
103
|
0
|
0
|
|
|
|
|
say STDERR " Grid size lat lon: $grid_size $ilat $ilon" if $debug; |
104
|
0
|
|
|
|
|
|
$self->{grid_size} = $grid_size; |
105
|
0
|
0
|
|
|
|
|
$self->{elevation} = $bicubic ? _interpolate_bicubic ($dem, $ilat, $ilon) : _interpolate_bilinear ($dem, $ilat, $ilon); |
106
|
0
|
|
|
|
|
|
return $self->{elevation}; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub _interpolate_bicubic { |
110
|
1
|
|
|
1
|
|
6
|
use List::Util qw( min max ); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
888
|
|
111
|
0
|
|
|
0
|
|
|
my ($f, $x, $y) = @_; |
112
|
0
|
|
|
|
|
|
my $x1 = POSIX::floor $x; |
113
|
0
|
|
|
|
|
|
my $x2 = POSIX::ceil $x; |
114
|
0
|
|
|
|
|
|
my $x0 = max ($x1-1, 0); |
115
|
0
|
|
|
|
|
|
my $x3 = min ($x2+1, $grid_size-1); |
116
|
0
|
|
|
|
|
|
my $y1 = POSIX::floor $y; |
117
|
0
|
|
|
|
|
|
my $y2 = POSIX::ceil $y; |
118
|
0
|
|
|
|
|
|
my $y0 = max ($y1-1, 0); |
119
|
0
|
|
|
|
|
|
my $y3 = min ($y2+1, $grid_size-1); |
120
|
|
|
|
|
|
|
|
121
|
0
|
|
|
|
|
|
my $f00 = unpack ("s>*", substr ($$f, 2*($x0*$grid_size+$y0), 2)); # unpack signed big-endian 16-bit integer to elevation value |
122
|
0
|
|
|
|
|
|
my $f01 = unpack ("s>*", substr ($$f, 2*($x0*$grid_size+$y1), 2)); # unpack signed big-endian 16-bit integer to elevation value |
123
|
0
|
|
|
|
|
|
my $f02 = unpack ("s>*", substr ($$f, 2*($x0*$grid_size+$y2), 2)); # unpack signed big-endian 16-bit integer to elevation value |
124
|
0
|
|
|
|
|
|
my $f03 = unpack ("s>*", substr ($$f, 2*($x0*$grid_size+$y3), 2)); # unpack signed big-endian 16-bit integer to elevation value |
125
|
|
|
|
|
|
|
|
126
|
0
|
|
|
|
|
|
my $f10 = unpack ("s>*", substr ($$f, 2*($x1*$grid_size+$y0), 2)); # unpack signed big-endian 16-bit integer to elevation value |
127
|
0
|
|
|
|
|
|
my $f11 = unpack ("s>*", substr ($$f, 2*($x1*$grid_size+$y1), 2)); # unpack signed big-endian 16-bit integer to elevation value |
128
|
0
|
|
|
|
|
|
my $f12 = unpack ("s>*", substr ($$f, 2*($x1*$grid_size+$y2), 2)); # unpack signed big-endian 16-bit integer to elevation value |
129
|
0
|
|
|
|
|
|
my $f13 = unpack ("s>*", substr ($$f, 2*($x1*$grid_size+$y3), 2)); # unpack signed big-endian 16-bit integer to elevation value |
130
|
|
|
|
|
|
|
|
131
|
0
|
|
|
|
|
|
my $f20 = unpack ("s>*", substr ($$f, 2*($x2*$grid_size+$y0), 2)); # unpack signed big-endian 16-bit integer to elevation value |
132
|
0
|
|
|
|
|
|
my $f21 = unpack ("s>*", substr ($$f, 2*($x2*$grid_size+$y1), 2)); # unpack signed big-endian 16-bit integer to elevation value |
133
|
0
|
|
|
|
|
|
my $f22 = unpack ("s>*", substr ($$f, 2*($x2*$grid_size+$y2), 2)); # unpack signed big-endian 16-bit integer to elevation value |
134
|
0
|
|
|
|
|
|
my $f23 = unpack ("s>*", substr ($$f, 2*($x2*$grid_size+$y3), 2)); # unpack signed big-endian 16-bit integer to elevation value |
135
|
|
|
|
|
|
|
|
136
|
0
|
|
|
|
|
|
my $f30 = unpack ("s>*", substr ($$f, 2*($x3*$grid_size+$y0), 2)); # unpack signed big-endian 16-bit integer to elevation value |
137
|
0
|
|
|
|
|
|
my $f31 = unpack ("s>*", substr ($$f, 2*($x3*$grid_size+$y1), 2)); # unpack signed big-endian 16-bit integer to elevation value |
138
|
0
|
|
|
|
|
|
my $f32 = unpack ("s>*", substr ($$f, 2*($x3*$grid_size+$y2), 2)); # unpack signed big-endian 16-bit integer to elevation value |
139
|
0
|
|
|
|
|
|
my $f33 = unpack ("s>*", substr ($$f, 2*($x3*$grid_size+$y3), 2)); # unpack signed big-endian 16-bit integer to elevation value |
140
|
|
|
|
|
|
|
|
141
|
0
|
0
|
|
|
|
|
say STDERR " Grid corners: ($x0,$y0) ($x1,$y1) ($x2,$y2) ($x3,$y3)" if $debug; |
142
|
|
|
|
|
|
|
# say STDERR " Elevation at corners: $f11 $f21 $f12 $f22" if $debug; |
143
|
0
|
0
|
|
|
|
|
say STDERR " Elevation at corners: $f00 $f01 $f02 $f03" if $debug; |
144
|
0
|
0
|
|
|
|
|
say STDERR " Elevation at corners: $f10 $f11 $f12 $f13" if $debug; |
145
|
0
|
0
|
|
|
|
|
say STDERR " Elevation at corners: $f20 $f21 $f22 $f23" if $debug; |
146
|
0
|
0
|
|
|
|
|
say STDERR " Elevation at corners: $f30 $f31 $f32 $f33" if $debug; |
147
|
|
|
|
|
|
|
# Bicubic interpolation as per https://www.paulinternet.nl/?page=bicubic |
148
|
|
|
|
|
|
|
# using the simplifying fact that ($x2-$x1)==1 and ($y2-$y1)==1 |
149
|
0
|
|
|
|
|
|
my $xx = $x - $x1; |
150
|
0
|
|
|
|
|
|
my $yy = $y - $y1; |
151
|
0
|
|
|
|
|
|
my $f0 = _bicubic ($f00, $f01, $f02, $f03, $yy); |
152
|
0
|
|
|
|
|
|
my $f1 = _bicubic ($f10, $f11, $f12, $f13, $yy); |
153
|
0
|
|
|
|
|
|
my $f2 = _bicubic ($f20, $f21, $f22, $f23, $yy); |
154
|
0
|
|
|
|
|
|
my $f3 = _bicubic ($f30, $f31, $f32, $f33, $yy); |
155
|
0
|
0
|
|
|
|
|
say STDERR " bicubic interpolated elevation: "._bicubic ($f0, $f1, $f2, $f3, $xx) if $debug; |
156
|
0
|
|
|
|
|
|
return _bicubic ($f0, $f1, $f2, $f3, $xx); |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
sub _bicubic { |
160
|
0
|
|
|
0
|
|
|
my ($f0, $f1, $f2, $f3, $x) = @_; |
161
|
0
|
0
|
|
|
|
|
if ($bicubic_current) { |
|
|
0
|
|
|
|
|
|
162
|
0
|
|
|
|
|
|
return $f1 + $x*($f1 - $f0 + $x*(2.0*$f0 - 5.0*$f1 + 4.0*$f2 - $f3 + $x*(3.0*($f1 - $f2) + $f3 - $f0))); # use slope of a line between the previous and the «current» point as the derivative at a point, that is (p1-p0) and (p3-p2) |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
elsif ($bicubic_mixed) { |
165
|
0
|
|
|
|
|
|
return $f1 + 0.75 * $x*($f2 - $f0 + $x*(2.0*$f0 - 5.0*$f1 + 4.0*$f2 - $f3 + $x*(3.0*($f1 - $f2) + $f3 - $f0))); # use «current» and «next» point «mixed» slope |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
else { |
168
|
0
|
|
|
|
|
|
return $f1 + 0.5 * $x*($f2 - $f0 + $x*(2.0*$f0 - 5.0*$f1 + 4.0*$f2 - $f3 + $x*(3.0*($f1 - $f2) + $f3 - $f0))); # use slope of a line between the previous and the «next» point as the derivative at a point, that is (p2-p0)/2 and (p3-p1)/2 |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
sub _interpolate_bilinear { |
173
|
0
|
|
|
0
|
|
|
my ($f, $x, $y) = @_; |
174
|
0
|
|
|
|
|
|
my $x1 = POSIX::floor $x; |
175
|
0
|
|
|
|
|
|
my $x2 = POSIX::ceil $x; |
176
|
0
|
|
|
|
|
|
my $y1 = POSIX::floor $y; |
177
|
0
|
|
|
|
|
|
my $y2 = POSIX::ceil $y; |
178
|
0
|
|
|
|
|
|
my $f11 = unpack ("s>*", substr ($$f, 2*($x1*$grid_size+$y1), 2)); # unpack signed big-endian 16-bit integer to elevation value |
179
|
0
|
|
|
|
|
|
my $f21 = unpack ("s>*", substr ($$f, 2*($x2*$grid_size+$y1), 2)); # unpack signed big-endian 16-bit integer to elevation value |
180
|
0
|
|
|
|
|
|
my $f12 = unpack ("s>*", substr ($$f, 2*($x1*$grid_size+$y2), 2)); # unpack signed big-endian 16-bit integer to elevation value |
181
|
0
|
|
|
|
|
|
my $f22 = unpack ("s>*", substr ($$f, 2*($x2*$grid_size+$y2), 2)); # unpack signed big-endian 16-bit integer to elevation value |
182
|
0
|
0
|
|
|
|
|
say STDERR " Grid corners: ($x1,$y1) ($x2,$y1) ($x1,$y2) ($x2,$y2)" if $debug; |
183
|
0
|
0
|
|
|
|
|
say STDERR " Elevation at corners: $f11 $f21 $f12 $f22" if $debug; |
184
|
|
|
|
|
|
|
# bilinear interpolation as per https://github.com/racemap/elevation-service/blob/master/hgt.js |
185
|
|
|
|
|
|
|
# using the simplifying fact that ($x2-$x1)==1 and ($y2-$y1)==1 |
186
|
0
|
|
|
|
|
|
my $xx = $x - $x1; |
187
|
0
|
|
|
|
|
|
my $yy = $y - $y1; |
188
|
0
|
|
|
|
|
|
my $f1 = _avg ($f11, $f21, $xx); |
189
|
0
|
|
|
|
|
|
my $f2 = _avg ($f12, $f22, $xx); |
190
|
0
|
0
|
|
|
|
|
say STDERR " bilinear interpolated elevation: "._avg ($f1, $f2, $yy) if $debug; |
191
|
0
|
|
|
|
|
|
return _avg ($f1, $f2, $yy); |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
sub _avg { |
195
|
0
|
|
|
0
|
|
|
my ($f1, $f2, $x) = @_; |
196
|
0
|
|
|
|
|
|
return $f1 + ($f2 - $f1) * $x; |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
sub _readDEM { |
200
|
1
|
|
|
1
|
|
1157
|
use IO::Uncompress::AnyUncompress qw(anyuncompress $AnyUncompressError); |
|
1
|
|
|
|
|
66880
|
|
|
1
|
|
|
|
|
106
|
|
201
|
1
|
|
|
1
|
|
1161
|
use HTTP::Tiny; |
|
1
|
|
|
|
|
27942
|
|
|
1
|
|
|
|
|
464
|
|
202
|
0
|
|
|
0
|
|
|
my ($self, $DEMname) = @_; |
203
|
0
|
|
|
|
|
|
my $nslt = substr($DEMname,0,3); |
204
|
0
|
|
|
|
|
|
my $path_to_hgt_gz = "$nslt/$DEMname.hgt.gz"; |
205
|
0
|
|
|
|
|
|
$switch = 0; |
206
|
0
|
|
|
|
|
|
$cache = 0; |
207
|
0
|
|
|
|
|
|
$fail = 0; |
208
|
0
|
|
|
|
|
|
@default_DEMs = ("$path_to_hgt_gz", "$DEMname.zip"); |
209
|
0
|
|
|
|
|
|
@want_DEMnames = ("$DEMname.hgt.gz", "$DEMname.zip"); |
210
|
0
|
|
|
|
|
|
my $dem; |
211
|
0
|
0
|
|
|
|
|
$status_descr = -d $folder ? "Folder" : "Url"; |
212
|
0
|
0
|
|
|
|
|
my $path = -d $folder ? _findDEM ($folder) : "$folder/$path_to_hgt_gz"; |
213
|
0
|
0
|
|
|
|
|
if (-e $path) { |
214
|
0
|
0
|
|
|
|
|
say STDERR " Reading DEM '$path'" if $debug; |
215
|
0
|
|
|
|
|
|
$self->{DEMs}{$DEMname}{DEMpath}=$path; |
216
|
0
|
0
|
|
|
|
|
anyuncompress $path => \$dem or croak "anyuncompress failed on '$path': $AnyUncompressError"; |
217
|
0
|
|
|
|
|
|
return \$dem; |
218
|
|
|
|
|
|
|
} |
219
|
0
|
0
|
|
|
|
|
unless ($path =~ m/^https?:\/\//) { |
220
|
0
|
0
|
|
|
|
|
say STDERR " DEM '$path' not found -> switch to '$url'" if $debug; |
221
|
0
|
|
|
|
|
|
$status_descr .= "->Switch"; |
222
|
0
|
|
|
|
|
|
$switch = 1; |
223
|
|
|
|
|
|
|
} |
224
|
0
|
0
|
|
|
|
|
my $cache_path = $cache_folder ne "" ? _findDEM ($cache_folder) : undef; |
225
|
0
|
0
|
0
|
|
|
|
if (defined $cache_path and -e $cache_path) { |
226
|
0
|
0
|
|
|
|
|
say STDERR " Reading DEM from cache '$cache_path'" if $debug; |
227
|
0
|
|
|
|
|
|
$self->{DEMs}{$DEMname}{DEMpath}=$cache_path; |
228
|
0
|
|
|
|
|
|
$status_descr .= "->Cached"; |
229
|
0
|
|
|
|
|
|
$cache = 1; |
230
|
0
|
0
|
|
|
|
|
anyuncompress $cache_path => \$dem or croak "anyuncompress failed on '$cache_path': $AnyUncompressError"; |
231
|
0
|
|
|
|
|
|
return \$dem; |
232
|
|
|
|
|
|
|
} |
233
|
0
|
|
|
|
|
|
$path = "$url/$path_to_hgt_gz"; |
234
|
0
|
0
|
|
|
|
|
say STDERR " Getting DEM '$path'" if $debug; |
235
|
0
|
0
|
|
|
|
|
$status_descr .= "->Url" unless ($status_descr eq "Url"); |
236
|
0
|
|
|
|
|
|
my $response = HTTP::Tiny->new->get($path); # get gzip archive file .hgt.gz |
237
|
0
|
0
|
|
|
|
|
unless ($response->{success}) { |
238
|
|
|
|
|
|
|
# no success |
239
|
0
|
|
|
|
|
|
carp " DEM '$path'- $response->{status} $response->{reason}. All of its elevations will read as 0"; |
240
|
0
|
|
|
|
|
|
$status_descr .= "->Failed"; |
241
|
0
|
|
|
|
|
|
$fail = 1; |
242
|
0
|
|
|
|
|
|
return 0; |
243
|
|
|
|
|
|
|
} |
244
|
0
|
0
|
0
|
|
|
|
if ($cache_folder ne "" and -d $cache_folder) { |
245
|
0
|
0
|
|
|
|
|
unless (-d "$cache_folder/$nslt") {mkdir "$cache_folder/$nslt", 0755} |
|
0
|
|
|
|
|
|
|
246
|
0
|
0
|
|
|
|
|
open my $file_handle, '>', "$cache_path" or croak "'$cache_path' error opening: $!"; |
247
|
0
|
|
|
|
|
|
binmode $file_handle; |
248
|
0
|
|
|
|
|
|
print $file_handle $response->{content}; |
249
|
0
|
|
|
|
|
|
close $file_handle; |
250
|
0
|
|
|
|
|
|
$status_descr .= "->Saved"; |
251
|
0
|
0
|
|
|
|
|
say STDERR " Saved DEM cache file '$cache_path'" if $debug; |
252
|
|
|
|
|
|
|
} |
253
|
0
|
|
|
|
|
|
$self->{DEMs}{$DEMname}{DEMpath}=$path; |
254
|
0
|
0
|
|
|
|
|
anyuncompress \$response->{content} => \$dem or croak "anyuncompress failed on '$path': $AnyUncompressError"; |
255
|
0
|
|
|
|
|
|
return \$dem; |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
sub _findDEM { |
259
|
1
|
|
|
1
|
|
8
|
use File::Find; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
199
|
|
260
|
0
|
|
|
0
|
|
|
my ($folder) = @_; |
261
|
0
|
|
|
|
|
|
for my $default (@default_DEMs) { |
262
|
0
|
0
|
0
|
|
|
|
say STDERR " Found default DEM '$folder/$default'" if ($debug and -e "$folder/$default"); |
263
|
0
|
0
|
|
|
|
|
return "$folder/$default" if (-e "$folder/$default"); |
264
|
|
|
|
|
|
|
} |
265
|
0
|
|
|
|
|
|
splice (@DEMnames,0); |
266
|
0
|
|
|
|
|
|
find(\&_wanted, $folder); |
267
|
0
|
0
|
0
|
|
|
|
say STDERR " Found wanted DEM '$DEMnames[0]'" if ($debug and defined $DEMnames[0]); |
268
|
0
|
|
0
|
|
|
|
return $DEMnames[0] // "$folder/$default_DEMs[0]"; |
269
|
|
|
|
|
|
|
} |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
sub _wanted { |
272
|
1
|
|
|
1
|
|
13
|
use List::Util 'any'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
119
|
|
273
|
0
|
|
|
0
|
|
|
my $filename = $_; |
274
|
0
|
0
|
|
0
|
|
|
push (@DEMnames, $File::Find::name) if any {$_ =~ m/^$filename$/i} @want_DEMnames; # add file to list if matched |
|
0
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
1; # End of Geo::Elevation::HGT |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
__END__ |