SRTM & Ordnance Survey Elevation Data in PHP
This page is about how to use PHP code to read elevation data from two freely-available data sources:
- 90m 5x5 degree SRTM GeoTIFF data files (version 4)
- 50m UK Ordnance Survey Land-Form PANORAMA® NTF data files
Download the code here (latest bugfix version 22-Oct-2014)
Elevation data is already available from a number of online sources, so why bother rolling your own code? The answer is that most (all?) online elevation resources restrict the number of data requests you can make. So to get the flexibility to do whatever you like with the data as often as you like you will need to read the raw data files yourself.
I expect the main use for the code will be to generate spot elevation data or profile charts for hiking or cycling. So here's a demo:
- Using a mouse? Move it over the map to see the elevation for the mouse position
- Click or tap any two points on the map to generate a profile image under the map
|Data type (choose either):||CGIAR-CSI SRTM|
|Mouseover demo||Elevation (m)|
|Mouse click demo||Lat / Northing||Long / Easting|
Which data set to use? For most cases probably the SRTM data is the best bet. SRTM data was obtained using the NASA Space Shuttle and provides a 90m data grid data for most of the world. My code expects to see Version 4.1 data files in the 5x5 degree GeoTIFF format. This means that the UK is covered using just 6 files (around 412MB in total). Or 5 files if you don't mind chopping off a very small chunk of Cornwall!
UK users may prefer the OS Land-Forma PANORAMA NTF data available from the Ordnance Survey. This data (around 570MB in total) provides a 50m data grid for the UK and is the same data as used for OS maps. Be warned that there are occasional gaps in the data on incomplete contour lines or sheer cliffs. This can be seen in the demo above where the graph occasionally drops to zero over certain areas. This only seems to occur in exceptionally sheer locations so is unlikely to be an issue for a typical hike or bike ride.
You will need:
- A web site running PHP 5
- A mapping API - I use OS OpenSpace maps, but the principles are the same for other mapping APIs
- Elevation data for your area of interest as described above - note that the OS data MUST remain in the default tree structure exactly as downloaded (i.e. in directories 'hp', 'ht', 'hu' etc.)
- My PHP code - this page plus all associated files in a ZIP file above
- If you want to display graphs, then a package such as jpGraph
The code can:
- Return the elevation for the data point closest to the parameter coordinates
- Return a bilinear interpolation of the four elevation data points which surround the parameter coordinates - this is arguably more accurate and smoother for graphs but is more expensive
- Return an array of elevations (closest point or interpolated) given an array of coordinates
- Return an array of elevations (closest point or interpolated) from calculated intermediate locations every 90m (SRTM) or 50m (OS) distance between two or more coordinates
- Return the total distance, total ascent and total descent between two or more coordinates
Both classes automatically work out which data file to read and then use file pointer arithmetic to jump to the data offset address. This means that - unlike ASCII file parsing or reading from a database - the code uses hardly any system resources and is very fast.
If you try the demo at silly small scales, it will be slow but will work eventually. The slowness is mostly the graph library - the elevation data itself is returned pretty much instantly for anything under a thousand or so coordinate pairs.
Using the code
It's pretty straightforward:
require_once 'SRTMGeoTIFFReader.php'; $dataReader = new SRTMGeoTIFFReader("/path/to/GeoData"); // where GeoData is the directory containing your SRTM data files // get single elevation $lat = 53.073997; $lon = -4.095965; $elevation = $dataReader->getElevation($lat, $lon); // get an array of elevations for each of the supplied coordinate pairs $locations = array($lat0, $lon0, ... $latN, $lonN); $elevations = $dataReader->getMultipleElevations( $locations, $addIntermediateLatLons, $interpolate ); // - $addIntermediateLatLons is a bool which will fill in the gaps // between two given points as per the demo // - $interpolate is a bool which if set to true gives smoother graphs // but may be noticeably slower for large numbers of coordinate pairs
Ordnance Survey code
require_once 'OSNTFReader.php'; $dataReader = new OSNTFReader("path/to/OSNTFdata"); // where OSNTFdata is the directory containing the directories // holding the .ntf data files in the default structure // exactly as downloaded from OS // get single elevation $e = 261550; // an OS easting value $n = 354515; // an OS northing value $elevation = $dataReader->getElevation($e, $n); // get an array of elevations for each of the supplied coordinate pairs $locations = array($e0, $n0, ... $eN, $nN); $elevations = $dataReader->getMultipleElevations( $locations, $addIntermediateLatLons, $interpolate );
There are also some common useful utility methods and properties:
// get ascent and descent in meters $hills = $dataReader->getAscentDescent(); $ascent = $hills["ascent"]; $descent = $hills["descent"]; // get the total distance between the points in kilometers $distance = $dataReader->getTotalDistance(); // optionally show verbose errors for debugging purposes (default: false) $dataReader->showErrors = true; // optionally change max number of allowed input locations (default: 5000) $dataReader->maxPoints = 20000;
There's some other test stuff in there if you dig around - it's fairly liberally commented mainly so that I can work out how it all works again in 6 months time. You might need to allow a few nights to fully grok the data structures and pointer arithmetic :-)
If you want to hack the GeoTIFF files, then the TIFF section of the AWare Systems site is a great resource. Their free TIFF Tag Viewer (Windows only) will also help you to dig around in the data files.
If you want to hack the OS data then the excellent OS PDF entitled Land-Form PANORAMA User guide and technical specification is a must-have resource.
This code is given as public domain freeware. There is no licence of any kind - use it as you like. An acknowledgement or an email would be nice but it isn't required.
Any bugs reports, suggestions or code improvements would be very welcome - please email me at firstname.lastname@example.org.
22-Oct-2011 - Thanks are due to Bert Hulsmans who reported a bug in the SRTM code, now fixed.