@@ -52,7 +52,7 @@ def __init__(self, srtm1_files, srtm3_files, files_directory):
52
52
53
53
self .files = {}
54
54
55
- def get_elevation (self , latitude , longitude ):
55
+ def get_elevation (self , latitude , longitude , approximate = None ):
56
56
geo_elevation_file = self .get_file (float (latitude ), float (longitude ))
57
57
58
58
mod_logging .debug ('File for ({0}, {1}) -> {2}' .format (
@@ -61,7 +61,10 @@ def get_elevation(self, latitude, longitude):
61
61
if not geo_elevation_file :
62
62
return None
63
63
64
- return geo_elevation_file .get_elevation (float (latitude ), float (longitude ))
64
+ return geo_elevation_file .get_elevation (
65
+ float (latitude ),
66
+ float (longitude ),
67
+ approximate )
65
68
66
69
def get_file (self , latitude , longitude ):
67
70
"""
@@ -79,7 +82,7 @@ def get_file(self, latitude, longitude):
79
82
if not data :
80
83
return None
81
84
82
- result = GeoElevationFile (file_name , data )
85
+ result = GeoElevationFile (file_name , data , self )
83
86
self .files [file_name ] = result
84
87
return result
85
88
@@ -195,7 +198,12 @@ def get_image(self, size, latitude_interval, longitude_interval, max_elevation,
195
198
return image
196
199
197
200
class GeoElevationFile :
198
- """ Contains data from a single Shuttle elevation file. """
201
+ """
202
+ Contains data from a single Shuttle elevation file.
203
+
204
+ This class hould not be instantiated without its GeoElevationData because
205
+ it may need elevations from nearby files.
206
+ """
199
207
200
208
file_name = None
201
209
url = None
@@ -205,9 +213,10 @@ class GeoElevationFile:
205
213
206
214
data = None
207
215
208
- def __init__ (self , file_name , data ):
216
+ def __init__ (self , file_name , data , geo_elevation_data ):
209
217
""" Data is a raw file contents of the file. """
210
218
219
+ self .geo_elevation_data = geo_elevation_data
211
220
self .file_name = file_name
212
221
213
222
self .parse_file_name_starting_position ()
@@ -219,19 +228,66 @@ def __init__(self, file_name, data):
219
228
220
229
self .square_side = int (square_side )
221
230
222
- def get_elevation (self , latitude , longitude ):
231
+ def get_elevation (self , latitude , longitude , approximate = None ):
232
+ """
233
+ If approximate is True then only the points from SRTM grid will be
234
+ used, otherwise a basic aproximation of nearby points will be calculated.
235
+ """
223
236
if not (self .latitude <= latitude < self .latitude + 1 ):
224
237
raise Exception ('Invalid latitude %s for file %s' % (latitude , self .file_name ))
225
238
if not (self .longitude <= longitude < self .longitude + 1 ):
226
239
raise Exception ('Invalid longitude %s for file %s' % (longitude , self .file_name ))
227
240
228
241
points = self .square_side ** 2
229
242
230
- pdb .set_trace ()
231
- row = int (mod_math .floor ((self .latitude + 1 - latitude ) * float (self .square_side - 1 )))
232
- column = int (mod_math .floor ((longitude - self .longitude ) * float (self .square_side - 1 )))
243
+ row = mod_math .floor ((self .latitude + 1 - latitude ) * float (self .square_side - 1 ))
244
+ column = mod_math .floor ((longitude - self .longitude ) * float (self .square_side - 1 ))
245
+
246
+ if approximate :
247
+ return self .approximation (latitude , longitude )
248
+ else :
249
+ return self .get_elevation_from_row_and_column (int (row ), int (column ))
250
+
251
+ def approximation (self , latitude , longitude ):
252
+ """
253
+ Dummy approximation with nearest points. The nearest the neighbour the
254
+ more important will be its elevation.
255
+ """
256
+ d = 1. / self .square_side
257
+ d_meters = d * mod_utils .ONE_DEGREE
233
258
234
- return self .get_elevation_from_row_and_column (row , column )
259
+ # Since the less the distance => the more important should be the
260
+ # distance of the point, we'll use d-distance as importance coef
261
+ # here:
262
+ importance_1 = d_meters - mod_utils .distance (latitude + d , longitude , latitude , longitude )
263
+ elevation_1 = self .geo_elevation_data .get_elevation (latitude + d , longitude , approximate = False )
264
+
265
+ importance_2 = d_meters - mod_utils .distance (latitude - d , longitude , latitude , longitude )
266
+ elevation_2 = self .geo_elevation_data .get_elevation (latitude - d , longitude , approximate = False )
267
+
268
+ importance_3 = d_meters - mod_utils .distance (latitude , longitude + d , latitude , longitude )
269
+ elevation_3 = self .geo_elevation_data .get_elevation (latitude , longitude + d , approximate = False )
270
+
271
+ importance_4 = d_meters - mod_utils .distance (latitude , longitude - d , latitude , longitude )
272
+ elevation_4 = self .geo_elevation_data .get_elevation (latitude , longitude - d , approximate = False )
273
+ # TODO(TK) Check if coordinates inside the same file, and only the decide if to xall
274
+ # self.geo_elevation_data.get_elevation or just self.get_elevation
275
+
276
+ # Normalize importance:
277
+ sum_importances = float (importance_1 + importance_2 + importance_3 + importance_4 )
278
+
279
+ # Check normallization:
280
+ assert abs (importance_1 / sum_importances + \
281
+ importance_2 / sum_importances + \
282
+ importance_3 / sum_importances + \
283
+ importance_4 / sum_importances - 1 ) < 0.000001
284
+
285
+ result = importance_1 / sum_importances * elevation_1 + \
286
+ importance_2 / sum_importances * elevation_2 + \
287
+ importance_3 / sum_importances * elevation_3 + \
288
+ importance_4 / sum_importances * elevation_4
289
+
290
+ return result
235
291
236
292
def get_elevation_from_row_and_column (self , row , column ):
237
293
i = row * (self .square_side ) + column
0 commit comments