Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I want to asign a specific long/lat position on a map the elevation from SRTM3 data files, but have no idea how to find the specific value. So I want some example of how I can find in N50E14.hgt elevation to 50°24'58.888"N, 14°55'11.377"E. Thanks so much.

share|improve this question
1  
What software are you using? There are some notes on the .hgt file format in the SRTM documentation, but a specific step-by-step answer depends on the software you have available. –  anoved Dec 11 '12 at 20:50
1  
I have no software, i am c# programmer and i am writting my own application. I am able to asign long/lat to every pixel and now i want to search elevation to each point. Best data format should be something like CSV file. So in one row i can found longitude;latitude;altitude. I have searched SRTM documentation, but i still can't imagine how can i provide data mining on the file. –  Martin Ševic Dec 11 '12 at 21:08

3 Answers 3

up vote 7 down vote accepted

Data format

I'll take it as a little exercise in how to program a data reader. Have a look at the documentation:

SRTM data are distributed in two levels: SRTM1 (for the U.S. and its territories and possessions) with data sampled at one arc-second intervals in latitude and longitude, and SRTM3 (for the world) sampled at three arc-seconds.

Data are divided into one by one degree latitude and longitude tiles in "geographic" projection, which is to say a raster presentation with equal intervals of latitude and longitude in no projection at all but easy to manipulate and mosaic.

File names refer to the latitude and longitude of the lower left corner of the tile - e.g. N37W105 has its lower left corner at 37 degrees north latitude and 105 degrees west longitude. To be more exact, these coordinates refer to the geometric center of the lower left pixel, which in the case of SRTM3 data will be about 90 meters in extent.

Height files have the extension .HGT and are signed two byte integers. The bytes are in Motorola "big-endian" order with the most significant byte first, directly readable by systems such as Sun SPARC, Silicon Graphics and Macintosh computers using Power PC processors. DEC Alpha, most PCs and Macintosh computers built after 2006 use Intel ("little-endian") order so some byte-swapping may be necessary. Heights are in meters referenced to the WGS84/EGM96 geoid. Data voids are assigned the value -32768.

How to proceed

For your position, 50°24'58.888"N 14°55'11.377"E, you already found the correct tile, N50E14.hgt. Let's find out which pixel you are interested in. First latitude, 50°24'58.888"N:

24'58.888" = (24 * 60)" + 58.888" = 1498.888"

arc seconds. Divided by three and rounded to the closest integer gives a grid row of 500. The same calculation for longitude results in grid column 1104.

The quickstart documentation lacks information about how rows and columns are organized in the file, but in the full documentation it is stated that

The data are stored in row major order (all the data for row 1, followed by all the data for row 2, etc.)

The first row in the file is very likely the northernmost one, i.e. if we are interested in row 500 from the lower edge, we actually have to look at row

1201 - 500 = 701

from the start if the file. Our grid cell is number

(1201 * 700) + 1104 = 841804

from the start of the file (i.e. skip 700 rows, and in the 701st one take sample 1104). Two bytes per sample means we have to skip the first 1683606 bytes in the file and then read two bytes in order to get our grid cell. The data is big-endian, which means that you need to swap the two bytes on e.g. Intel platforms.

Sample program

A simplistic Python program to retrieve the right data would look like this (see the docs for use of the struct module):

import struct

def get_sample(filename, n, e):
    i = 1201 - int(round(n / 3, 0))
    j = int(round(e / 3, 0))
    with open(filename, "rb") as f:
        f.seek(((i - 1) * 1201 + (j - 1)) * 2)  # go to the right spot,
        buf = f.read(2)  # read two bytes and convert them:
        val = struct.unpack('>h', buf)  # ">h" is a signed two byte integer
        if not val == -32768:  # the not-a-valid-sample value
            return val
        else:
            return None

if __name__ == "__main__":
    n = 24 * 60 + 58.888
    e = 55 * 60 + 11.377
    tile = "N50E14.hgt"  # Or some magic to figure it out from position
    print get_sample(tile, n, e)

Note that efficient data retrieval would have to look a little more sophisticated (e.g. not opening the file for each and every sample).

Alternatives

You could also use a program which can read the .hgt files out of the box. But that is boring.

share|improve this answer
    
Beat me to it, and with more detail to boot! –  anoved Dec 11 '12 at 21:54
    
Nice explain, love you. Thanks for your help. All of you guys. –  Martin Ševic Dec 11 '12 at 22:06
    
+1 Yes, the rows are ordered from north to south. This is clear as soon as you map one of the files. Also, consider obtaining heights via bilinear interpolation among the four cell centers surrounding the location. –  whuber Dec 11 '12 at 22:14

If you do use QGIS, check if the python plugin "Point Sampling Tool" is installed. You'll find it at -> Enhancements (Python) -> Analyse.

Select your point layer of the required positions, then start the PST, choose the hgt (or whatever raster/polygone file) and choose a new point shape for output.

Thats all :-)

  Chris
share|improve this answer

Chris' answer indicates it is straightforward to sample points from a layer in QGIS.

However, since your reply to my comment clarifies you are writing your own program to read elevation values from the .hgt files, have another look at the Quickstart PDF in the SRTM docs. It explains how the elevation data is stored. To summarize:

  • SRTM3 files contain a sequence of big-endian integer values.
  • Each integer value represents an elevation "in meters referenced to the WGS84/EGM96 geoid", except for values of -32768, which indicate no-data pixels.
  • There are 1201 lines of 1201 samples, so there should be 1442401 integer values altogether.

You say you can convert between lon/lat coordinates and pixels, so getting the elevation is a matter of reading the integer value from the appropriate offset in the file. Given pixel coordinates x and y relative to the upper left corner of the scene, that's basically offset = (y * 1201) + x. Pixel 0,0 is the first integer in the file and pixel 1200,1200 is the last integer in the file.

share|improve this answer
    
This is correct, but is missing a few crucial details provided by bhell's answer, including that the coordinates are associated with cell centers. Thus, for instance, the upper left corner of N50E014.hgt is actually located at longitude 13.99958 E, latitude 51.00042 N. –  whuber Dec 11 '12 at 22:18

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.