Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 720eee3

Browse files
committed
Approximations
1 parent 26ffea0 commit 720eee3

File tree

4 files changed

+121
-14
lines changed

4 files changed

+121
-14
lines changed

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@ See: [http://www2.jpl.nasa.gov/srtm/](http://www2.jpl.nasa.gov/srtm/).
66

77
## Usage:
88

9-
>>> import srtm
10-
>>> elevation_data = srtm.get_data()
11-
>>> print 'CGN Airport elevation (meters):', elevation_data.get_elevation(50.8682, 7.1377)
9+
import srtm
10+
elevation_data = srtm.get_data()
11+
print 'CGN Airport elevation (meters):', elevation_data.get_elevation(50.8682, 7.1377)
12+
13+
With get\_elevation() an elevation of the the nearest location found in the SRTM data will be given.
14+
If you need an approximation based on nearby locations, you can use:
15+
16+
elevation_data.get_elevation(50.8682, 7.1377, approximate=True)
1217

1318
You can create elevation images with:
1419

srtm/data.py

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def __init__(self, srtm1_files, srtm3_files, files_directory):
5252

5353
self.files = {}
5454

55-
def get_elevation(self, latitude, longitude):
55+
def get_elevation(self, latitude, longitude, approximate=None):
5656
geo_elevation_file = self.get_file(float(latitude), float(longitude))
5757

5858
mod_logging.debug('File for ({0}, {1}) -> {2}'.format(
@@ -61,7 +61,10 @@ def get_elevation(self, latitude, longitude):
6161
if not geo_elevation_file:
6262
return None
6363

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)
6568

6669
def get_file(self, latitude, longitude):
6770
"""
@@ -79,7 +82,7 @@ def get_file(self, latitude, longitude):
7982
if not data:
8083
return None
8184

82-
result = GeoElevationFile(file_name, data)
85+
result = GeoElevationFile(file_name, data, self)
8386
self.files[file_name] = result
8487
return result
8588

@@ -195,7 +198,12 @@ def get_image(self, size, latitude_interval, longitude_interval, max_elevation,
195198
return image
196199

197200
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+
"""
199207

200208
file_name = None
201209
url = None
@@ -205,9 +213,10 @@ class GeoElevationFile:
205213

206214
data = None
207215

208-
def __init__(self, file_name, data):
216+
def __init__(self, file_name, data, geo_elevation_data):
209217
""" Data is a raw file contents of the file. """
210218

219+
self.geo_elevation_data = geo_elevation_data
211220
self.file_name = file_name
212221

213222
self.parse_file_name_starting_position()
@@ -219,19 +228,66 @@ def __init__(self, file_name, data):
219228

220229
self.square_side = int(square_side)
221230

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+
"""
223236
if not (self.latitude <= latitude < self.latitude + 1):
224237
raise Exception('Invalid latitude %s for file %s' % (latitude, self.file_name))
225238
if not (self.longitude <= longitude < self.longitude + 1):
226239
raise Exception('Invalid longitude %s for file %s' % (longitude, self.file_name))
227240

228241
points = self.square_side ** 2
229242

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
233258

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
235291

236292
def get_elevation_from_row_and_column(self, row, column):
237293
i = row * (self.square_side) + column

srtm/utils.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17+
import math as mod_math
18+
19+
ONE_DEGREE = 1000. * 10000.8 / 90.
20+
21+
def distance(latitude_1, longitude_1, latitude_2, longitude_2):
22+
"""
23+
Distance between two points.
24+
"""
25+
26+
coef = mod_math.cos(latitude_1 / 180. * mod_math.pi)
27+
x = latitude_1 - latitude_2
28+
y = (longitude_1 - longitude_2) * coef
29+
30+
return mod_math.sqrt(x * x + y * y) * ONE_DEGREE
31+
1732
def get_color_between(color1, color2, i):
1833
""" i is a number between 0 and 1, if 0 then color1, if 1 color2, ... """
1934
if i <= 0:

test.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def test_invalit_coordinates_for_file(self):
8383
message = str(e)
8484
self.assertEquals('Invalid longitude 1 for file N47E013.hgt', message)
8585

86-
def test_invalit_file(self):
86+
def test_invalid_file(self):
8787
geo_elevation_data = mod_srtm.get_data()
8888
geo_file = geo_elevation_data.get_file(-47.0, -13.99)
8989
self.assertEquals(None, geo_file)
@@ -97,3 +97,34 @@ def test_coordinates_in_file(self):
9797
self.assertEquals(geo_file.get_elevation(47, 13),
9898
geo_file.get_elevation(47, 13))
9999

100+
def test_without_approximation(self):
101+
geo_elevation_data = mod_srtm.get_data()
102+
103+
self.assertEquals(geo_elevation_data.get_elevation(47.1, 13.1, approximate=False),
104+
geo_elevation_data.get_elevation(47.1, 13.1))
105+
106+
# SRTM elevations are always integers:
107+
elevation = geo_elevation_data.get_elevation(47.1, 13.1)
108+
self.assertTrue(int(elevation) == elevation)
109+
110+
def test_with_approximation(self):
111+
geo_elevation_data = mod_srtm.get_data()
112+
113+
self.assertNotEquals(geo_elevation_data.get_elevation(47.1, 13.1, approximate=True),
114+
geo_elevation_data.get_elevation(47.1, 13.1))
115+
116+
# When approximating a random point, it probably won't be a integer:
117+
elevation = geo_elevation_data.get_elevation(47.1, 13.1, approximate=True)
118+
self.assertTrue(int(elevation) != elevation)
119+
120+
def test_approximation(self):
121+
# TODO(TK) Better tests for approximation here:
122+
geo_elevation_data = mod_srtm.get_data()
123+
elevation_without_approximation = geo_elevation_data.get_elevation(47, 13)
124+
elevation_with_approximation = geo_elevation_data.get_elevation(47, 13, approximate=True)
125+
126+
print elevation_without_approximation
127+
print elevation_with_approximation
128+
129+
self.assertNotEquals(elevation_with_approximation, elevation_without_approximation)
130+
self.assertTrue(abs(elevation_with_approximation - elevation_without_approximation) < 30)

0 commit comments

Comments
 (0)