I would like to create a raster where each cell contains the vertical distance to the nearest water (a decent approximation would be acceptable). The problem is that I'm not sure how to go about it.

Current approach:

I've looked through the documentation for my GIS (I'm using Grass 6.4 if that matters). And I can't find any direct way to perform this calculation. I've also searched the web without luck.

So I dreamed up the following:

  • convert my water vector to a water raster (1=water, null=everything else)
  • replace the 1s in the water raster with the altitude above sea level
  • perform "neighborhood" (moving window) analysis. Calculate the average altitude of water for a 100 meter radius for every cell in my region (ignoring nulls)
  • repeat the above with 100m, 200m, 300m, ..., 2000m. One raster for each distance.
  • using r.grow.distance calculate the distance between each cell and it's nearest water
  • then, using map algebra, I look at the distance to nearest water for each cell and its own altitude and subtract the average altitude of water for the appropriately distanced raster.

The problems with my method:

  • It is very computationally demanding. I am working at a 10m resolution and I need to perform this modelling on around 60 million cells. I've been creating rasters on a fast desktop for days and days and I'm not even close to finished.

  • At small radii, the calculation seems reasonable. If the distance to nearest water is 75 meters and I use a 100 m average altitude to water, the approximation is pretty good. But if the distance to nearest water is 1875 meters and I use the 1900 meter raster I will be averaging in the altitude to water of many cells far removed from the nearest water to my cell. The results are dissatisfying. I considered using some kind of smoothing process for the final raster but I wonder if there is a completely different approach that I am not seeing.

I've been reading about predictive modeling projects where vertical distance to nearest water is a one of the inputs to the model so I know it can be done but I'm just not sure how.

I'd appreciate any help I can get with this problem. Thanks.

  • 1
    In arcgis you could use the euclidean allocation function + some map algebra. I know you don't have that software but maybe there's a source for the calculation? Apr 18, 2011 at 5:29
  • @BlindJesse has a good solution if "nearest" truly means that, rather than strictly downstream to the nearest water. It's a simple workflow: attribute the water grid with the elevations. Round them to whole numbers so you can apply Euclidean allocation. Subtract the DEM from that, then take the absolute value of that difference. Done.
    – whuber
    Apr 16, 2015 at 17:21

2 Answers 2


Perform a hydrologic analysis on your data. Taking your first step of water bodies as a raster, you can then use that as a sinks raster. I'll specify the rest of this analysis in terms of GRASS as you mentioned that's the GIS system you're using:

Set up r.watershed (documentation) with the elevation data layer you'd like to analyze and the sinks raster you generated in the first step:

r.watershed elev=input_dem depression=input_sinks basin=output_basins \ 
  stream=output_streams threshold=1000

Where threshold is something appropriate for the scale of your data-- this should give you a map of each watershed: if you subtract that elevation from all the cells in that basin, you should get the vertical distance to the nearest water. You may need to iterate over smaller regions than your full raster to get good performance. You might find these tutorials (1, 2) also helpful in understanding how to use the command.

Mike helpfully mentioned an addon called r.watershed.distance which can be used to calculate this all in one go:

r.stream.distance -o dir=dirs stream=streams dem=elev \ 
  distance=distance_outlets  elevation=elevation_outlets

Which will result in an output close to what you're interested in: http://grass.osgeo.org/grass-wiki/images/Distance_outlets.png

This example was taken from the R.stream.* page, you can download the extension itself from the addon page.

  • 4
    There are a few gems in GRASS for hydrological sciences, such as r.stream.distance (based on r.watershed) that calculates downslope distance and downslope elevation difference to stream or outlet cells
    – Mike T
    Apr 18, 2011 at 9:06
  • Thank-you. I've been pulling my hair out on this one. r.stream.distance looks perfect. I'll install it tomorrow. Apr 19, 2011 at 4:18
  • I have thought of one issue with this technique: if you have a waterbody in an adjacent but close basin, it won't give you the distance to it going 'uphill' over the ridge first. It'd still be possible, but a bit more tricky to implement.
    – scw
    Apr 19, 2011 at 17:52

If you use free SAGA GIS (http://www.saga-gis.org/), you have some interesting options to calculate vertical distance to river. I recommend the algorithms, both on the toolbox cold "Terrain Analysis - channels": "overland flow distance to channel network" and "vertical distance to channel network". Each one has a different approach.

The "overland flow distance to channel network", in SAGA GIS requires an hydrological consistent DEM, but the "vertical distance to channel network" does not need it. The r.stream.distance in GRASS needs a flow direction raster that usually is extracted from a hydrological consistent DEM, too.

It is interesting to note that some papers recommend that, to calculate the vertical distance to rivers, deepening the drainage is better than feeling the sinks of the DEM, in order to make the DEM as hydrological consistent (see it here: http://www.lerf.eco.br/img/publicacoes/2011_0811%20Height%20Above%20the%20Nearest%20Drainage%20a%20hydrologically%20relevant%20new%20terrain%20model.pdf). That is because the sink filling option may change a lot the original raster. Another option, possible in the r.stream.distance in Grass is to enter a flow direction raster from a hydrological consistent DEM, while entering the original elevation raster as DEM.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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