r.drain(1grass)

๐Ÿ’ง r.drain ๐Ÿ’ง

okay bestie, welcome to r.drain from the GRASS User's Manual โ€” it's the module that traces a flow through an elevation model or a cost surface on a raster map. it's giving main character hydrology energy and honestly? obsessed. ๐ŸŒŠ

๐Ÿท๏ธ KEYWORDS ๐Ÿท๏ธ

raster, hydrology, cost surface


โœจ SYNOPSIS โœจ

r.drain
r.drain --help
r.drain [-cand] input=name  [direction=name]  output=name  [drain=name]
[start_coordinates=east,north[,east,north,...]]
[start_points=name[,name,...]]   [--overwrite]  [--help]  [--verbose]
[--quiet]  [--ui]

๐ŸŽ€ Flags ๐ŸŽ€

  • -c โ€” copies the input cell values straight onto the output, verbatim, no glow-up. โœจ
  • -a โ€” accumulates the input values as you go along the path, like a running total bestie ๐Ÿ’œ
  • -n โ€” counts cell numbers along the path, numerically, one by one ๐Ÿ”ข
  • -d โ€” says "bestie, the input raster map is a cost surface", which means the direction surface must also be specified. no exceptions. periodt.
  • --overwrite โ€” lets output files overwrite files that already exist, lowkey dangerous but okay ๐Ÿ’€
  • --help โ€” prints the usage summary, iykyk
  • --verbose โ€” verbose module output, she's chatty ๐ŸŒธ
  • --quiet โ€” quiet module output, she's mysterious ๐Ÿคซ
  • --ui โ€” forces the GUI dialog to launch

๐Ÿฆ‹ Parameters ๐Ÿฆ‹

  • input=name [required] โ€” the name of the input elevation or cost surface raster map. you NEED this one, no cap.
  • direction=name โ€” the name of the input movement direction map that goes with the cost surface. direction is in degrees CCW from east. โญ
  • output=name [required] โ€” the name for the output raster map ๐Ÿ’–
  • drain=name โ€” the name for the output drain vector map. recommended for a cost surface made using knight's move.
  • start_coordinates=east,north[,east,north,...] โ€” coordinates of the starting point(s) (E,N) ๐Ÿ“
  • start_points=name[,name,...] โ€” name of the starting vector points map(s)

๐ŸŒˆ DESCRIPTION ๐ŸŒˆ

okay so here's the tea ๐Ÿต โ€” r.drain traces a flow through a least-cost path in an elevation model or a cost surface. for cost surfaces you HAVE to give a movement direction map with the direction option and the -d flag so it can trace a flow path following the directions you gave. and guess what bestie, you can generate that movement direction map with r.walk, r.cost, r.slope.aspect or r.watershed โ€” as long as the direction is in degrees, measured counterclockwise from east. ๐Ÿ’…

the output raster map is gonna show one or more least-cost paths between each user-provided location(s) and the minima (low category values) in the raster input map. if you use the -d flag, the output least-cost paths get found using the direction raster map. by default, the output is an integer CELL map with category 1 along the least cost path, and null cells everywhere else. it's giving โœจminimalโœจ.

so, the flags, because this is the part where u need to lock in ๐Ÿ”’:

  • with -c (copy), the input raster map cell values are copied verbatim along the path.
  • with -a (accumulate), the accumulated cell value from the starting point up to the current cell gets written on output.
  • with either -c or -a, the output map is created with the same cell type as the input raster map (integer, float or double).
  • with -n (number), the cells are numbered consecutively from the starting point to the final point.
โš ๏ธ tbh the -c, -a, and -n flags are mutually incompatible. pick one, bestie, you can't have all three, that's not how this works ๐Ÿ˜ญ

for an elevation surface, the path is calculated by choosing the steeper "slope" between adjacent cells. and the slope calculation accurately accounts for the variable scale in lat-lon projections โ€” she did her homework. ๐Ÿ“š

for a cost surface, the path is calculated by following the movement direction surface back to the start point you gave in r.walk or r.cost. the path search stops as soon as it hits a region border or a neighboring NULL cell, because in those cases the direction can not be determined (the path could continue outside the current region). ๐Ÿ’€

the start_coordinates parameter is made of map E and N grid coordinates of a starting point. each x,y pair is the easting and northing (respectively) of a starting point from which a least-cost corridor will be developed. the start_points parameter can take multiple vector maps containing additional starting points. you can input up to 1024 starting points from a combination of the start_coordinates and start_points parameters. that's a lot of starting points bestie, go off ๐Ÿ‘‘

๐Ÿงš Explanation of output values ๐Ÿงš

consider this glow-up of an example โœจ:

Input:                          Output:
  ELEVATION SURFACE               LEAST COST PATH
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 19. 20. 18. 19. 16. 15. 15.    .   .   .   .   .   .   .   .
. .  ---  . . . . . . . . . .    . . . . . . . . . . . . . . .
. 20| 19| 17. 16. 17. 16. 16.    .   . 1 . 1 . 1 .   .   .   .
. .  ---  . . . . . . . . . .    . . . . . . . . . . . . . . .
. 18. 18. 24. 18. 15. 12. 11.    .   .   .   .   . 1 .   .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 22. 16. 16. 18. 10. 10. 10.    .   .   .   .   . 1 .   .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 17. 15. 15. 15. 10. 8 . 8 .    .   .   .   .   .   . 1 .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 24. 16. 8 . 7 . 8 . 0 . 12.    .   .   .   .   .   . 1 .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 17. 9 . 8 . 7 . 8 . 6 . 12.    .   .   .   .   .   .   .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .

the user-provided starting location in the above example is the boxed 19 in the left-hand map. the path in the output shows the least-cost corridor for moving from the starting box to the lowest (smallest) possible point. this is the path a raindrop would take in this landscape. ๐ŸŒง๏ธ iconic honestly


with the -c (copy) flag, you get this:

Input:                          Output:
  ELEVATION SURFACE               LEAST COST PATH
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 19. 20. 18. 19. 16. 15. 15.    .   .   .   .   .   .   .   .
. .  ---  . . . . . . . . . .    . . . . . . . . . . . . . . .
. 20| 19| 17. 16. 17. 16. 16.    .   . 19. 17. 16.   .   .   .
. .  ---  . . . . . . . . . .    . . . . . . . . . . . . . . .
. 18. 18. 24. 18. 15. 12. 11.    .   .   .   .   . 15.   .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 22. 16. 16. 18. 10. 10. 10.    .   .   .   .   . 10.   .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 17. 15. 15. 15. 10. 8 . 8 .    .   .   .   .   .   . 8 .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 24. 16. 8 . 7 . 8 . 0 .12 .    .   .   .   .   .   . 0 .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 17. 9 . 8 . 7 . 8 . 6 .12 .    .   .   .   .   .   .   .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
note that the last 0 will not be put in the null values map. ๐Ÿซถ

with the -a (accumulate) flag, you get this:

Input:                          Output:
  ELEVATION SURFACE               LEAST COST PATH
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 19. 20. 18. 19. 16. 15. 15.    .   .   .   .   .   .   .   .
. .  ---  . . . . . . . . . .    . . . . . . . . . . . . . . .
. 20| 19| 17. 16. 17. 16. 16.    .   . 19. 36. 52.   .   .   .
. .  ---  . . . . . . . . . .    . . . . . . . . . . . . . . .
. 18. 18. 24. 18. 15. 12. 11.    .   .   .   .   . 67.   .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 22. 16. 16. 18. 10. 10. 10.    .   .   .   .   . 77.   .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 17. 15. 15. 15. 10. 8 . 8 .    .   .   .   .   .   . 85.   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 24. 16. 8 . 7 . 8 . 0 .12 .    .   .   .   .   .   . 85.   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 17. 9 . 8 . 7 . 8 . 6 .12 .    .   .   .   .   .   .   .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .

with the -n (number) flag, you get this:

Input:                          Output:
  ELEVATION SURFACE               LEAST COST PATH
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 19. 20. 18. 19. 16. 15. 15.    .   .   .   .   .   .   .   .
. .  ---  . . . . . . . . . .    . . . . . . . . . . . . . . .
. 20| 19| 17. 16. 17. 16. 16.    .   . 1 . 2 . 3 .   .   .   .
. .  ---  . . . . . . . . . .    . . . . . . . . . . . . . . .
. 18. 18. 24. 18. 15. 12. 11.    .   .   .   .   . 4 .   .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 22. 16. 16. 18. 10. 10. 10.    .   .   .   .   . 5 .   .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 17. 15. 15. 15. 10. 8 . 8 .    .   .   .   .   .   . 6 .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 24. 16. 8 . 7 . 8 . 0 .12 .    .   .   .   .   .   . 7 .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .
. 17. 9 . 8 . 7 . 8 . 6 .12 .    .   .   .   .   .   .   .   .
. . . . . . . . . . . . . . .    . . . . . . . . . . . . . . .

with the -d (direction) flag, the direction raster is used for the input, rather than the elevation surface. the output is then created according to one of the -can flags. ๐Ÿ’…

the directions are recorded as degrees CCW from East:

       112.5     67.5         i.e. a cell with the value 135
157.5  135   90  45   22.5    means the next cell is to the North-West
       180   x   0
202.5  225  270  315  337.5
       247.5     292.5

๐Ÿ“ NOTES ๐Ÿ“

okay important stuff, don't skip this part ๐Ÿซฃ

if no direction input map is given, r.drain currently finds only the lowest point (the cell having the smallest category value) in the input file that can be reached through directly adjacent cells that are less than or equal in value to the cell reached immediately prior to it; therefore, it will not necessarily reach the lowest point in the input file. it currently finds pits in the data, rather than the lowest point in the entire input map. you can use the r.fill.dir, r.terraflow, and r.basins.fill modules to fill in subbasins before you process with r.drain. ๐Ÿ•ณ๏ธ

๐Ÿšจ r.drain will not give sane results at the region boundary. on outer rows and columns bordering the edge of the region, the flow direction is always directly out of the map. in this case, you could try adjusting the region extents slightly with g.region to allow additional outlet paths for r.drain. bestie pls check ur region, i'm begging ๐Ÿ™

๐ŸŒˆ EXAMPLES ๐ŸŒˆ

โœจ Path to the lowest point โœจ

okay so bestie, in this example we compute drainage paths from two given points, following decreasing elevation values all the way down to the lowest point ๐Ÿ’ง We're using the full North Carolina sample dataset, periodt.

First, we create the two points from a text file using the v.in.ascii module (the text file here is CSV and we're using unix here-file syntax with EOF โ€” in the GUI you just type the values directly into the parameter input, no biggie):

v.in.ascii input=- output=start format=point separator=comma <<EOF
638667.15686275,220610.29411765
638610.78431373,220223.03921569
EOF

Now we compute the drainage path ๐Ÿฆ‹:

r.drain input=elev_lid792_1m output=drain_path drain=drain start_points=start

Before we visualize the result, we set a color table for the elevation we're using, and we create a shaded relief map โœจ:

r.colors map=elev_lid792_1m color=elevation
r.relief input=elev_lid792_1m output=relief

Finally we visualize all the input and output data ๐Ÿ‘‘:

d.shade shade=relief color=elev_lid792_1m
d.vect map=drain_path color=0:0:61 width=4 legend_label="drainage paths"
d.vect map=start color=none fill_color=224:0:0 icon=basic/circle size=15 legend_label=origins
d.legend.vect -b

Figure: Drainage paths from two points flowing into the points with lowest values โ€” it's giving โœจartโœจ, fr fr.


๐ŸŽ€ Path following directions ๐ŸŽ€

To continue flow even after it hits a depression, we need to supply a direction raster map which will tell the r.drain module how to continue from the depression ๐Ÿ•ณ๏ธโžก๏ธ To get these directions, we use the r.watershed module:

r.watershed elevation=elev_lid792_1m accumulation=accum drainage=drain_dir

The directions are categorical, and we convert them to degrees using raster algebra ๐Ÿงฎ:

r.mapcalc "drain_deg = if(drain_dir != 0, 45. * abs(drain_dir), null())"

Together with directions, we need to provide the r.drain module with cost values. We don't have any cost to assign to specific cells, so we create a constant surface ๐ŸŒŠ:

r.mapcalc "const1 = 1"

Now we're ready to compute the drainage paths ๐Ÿ’… We're using the two points from the previous example:

r.drain -d input=const1 direction=drain_deg output=drain_path_2 drain=drain_2 start_points=start

We visualize the result in the same way as in the previous example.

Figure: Drainage paths from two points where directions from r.watershed were used โ€” iconic behavior honestly ๐Ÿ˜Œ


โš ๏ธ KNOWN ISSUES โš ๏ธ

Sometimes, when the differences among integer cell category values in the r.cost cumulative cost surface output are small, this cumulative cost output cannot accurately be used as input to r.drain โ€” and r.drain will output bad results ๐Ÿ’€ Yeah. Not the vibe.

This problem can be circumvented by making the differences between cell category values in the cumulative cost output bigger. It is recommended that if the output from r.cost is to be used as input to r.drain, the user multiply the r.cost input cost surface map by the value of the map's cell resolution, before running r.cost.

This can be done using r.mapcalc. The map resolution can be found using g.region. ๐Ÿซถ

And the good news? This problem doesn't arise with floating point maps. Slay. โœจ


๐Ÿ‘€ SEE ALSO ๐Ÿ‘€

  • g.region
  • r.cost
  • r.fill.dir
  • r.basins.fill
  • r.watershed
  • r.terraflow
  • r.mapcalc
  • r.walk

the way this is literally the whole friend group ๐Ÿฅน go say hi to all of them


๐Ÿ’– AUTHORS ๐Ÿ’–

  • Completely rewritten by Roger S. Miller, 2001
  • July 2004 at WebValley 2004, error checking and vector points added by Matteo Franchi (Liceo Leonardo Da Vinci, Trento) and Roberto Flor (ITC-irst, Trento, Italy)

๐Ÿงš SOURCE CODE ๐Ÿงš

Available at: r.drain source code (history)

Latest change: Saturday Oct 25 22:50:58 2025 in commit: ee87f21833475fd40805f58d1702f7d64478a27b

Main index | Raster index | Topics index | Keywords index | Graphical index | Full index


okay that's the whole page bestie, you ate that ๐Ÿ“ this was GRASS 8.5.0 Reference Manual, r.drain(1grass), ยฉ 2003-2026 GRASS Development Team, and yeah โ€” you're officially a drainage path main character now ๐Ÿ‘‘๐Ÿ’œ

๐Ÿ“ฆ where this page comes from