# Import libraries
import os
import sys
import subprocess
from pathlib import Path
# Find GRASS Python packages
sys.path.append(
subprocess.check_output("grass", "--config", "python_path"],
[=True
text
).strip()
)
# Import GRASS packages
import grass.script as gs
import grass.jupyter as gj
# Create a temporary folder
import tempfile
= tempfile.TemporaryDirectory()
temporary
# Create a project in the temporary directory
=temporary.name, name="xy")
gs.create_project(path
# Start GRASS in this project
= gj.init(Path(temporary.name, "xy")) session
Earthworks: Basics
Learn the basics of terrain modeling with r.earthworks. This tool uses cut and fill operations to transform topography. Cut operations subtract from a topographic surface, while fill operations add to the topography. Transformations are based on proposed local topographic extrema, i.e. high points and low points. These extrema can be set with coordinates, rasters, vector points, or vector lines. In GRASS raster and vector data can be drawn with the raster digitizer and vector digitizer. Transformations are a function of the existing elevation, change in vertical distance, and change in slope over horizontal distance. Vertical distance is calculated as the difference between proposed local extrema and a topographic datum, while change in slope is a function of growth and decay applied to horizontal change in distance. This tutorial covers:
- Cut operations
- Fill operations
- Cut & fill operations
- Random operations
This tutorial can be run as a computational notebook. Learn how to work with notebooks with the tutorial Get started with GRASS & Python in Jupyter Notebooks.
Setup
Project
Start a GRASS session in a new project with a Cartesian (XY) coordinate system.
grass --tmp-project XY
Installation
Install r.earthworks with g.extension.
g.extension extension=r.earthworks
# Install extension
"g.extension", extension="r.earthworks") gs.run_command(
Region
Use g.region to set the extent and resolution of the computational region. Create a region starting at the origin and extending two hundred units north and eight hundred units east. Use the raster calculator r.mapcalc to generate a flat terrain with an constant elevation of zero.
g.region n=200 e=800 s=0 w=0 res=1
r.mapcalc expression="elevation = 0"
# Set region
"g.region", n=200, e=800, s=0, w=0, res=1)
gs.run_command(
# Generate base elevation
"elevation = 0") gs.mapcalc(
Fill Operations
Use a fill operation to model a peak from a set of x- and y-coordinates with r.earthworks. These coordinates represents a local topographic maxima, i.e. a high point. The algorithm will fill locally up to that point, then the slopes will fall off at a given rate of decay. Set coordinates
to a pair of x- and y-coordinates. Use the z
parameter to set a z-coordinate for the top of the peak. Optionally use the flat
parameter to create a plateau at the top of the peak. Using the default linear growth and decay function \(z = z_0 - r \sqrt{\Delta x^2 + \Delta y^2}\), set the rate
to 0.5 to model a 50 percent slope.
r.earthworks elevation=elevation earthworks=peak operation=fill coordinates=400,100 z=25 flat=25 rate=0.5
# Model earthworks
gs.run_command("r.earthworks",
="elevation",
elevation="peak",
earthworks="fill",
operation=[400, 100],
coordinates=25,
z=25,
flat=0.5
rate
)
# Visualize
= gj.Map(width=800)
m map="peak")
m.d_rast(="peak", color="white", at=(5, 95, 1, 3))
m.d_legend(raster m.show()
Cut Operations
Use a cut operation to model a pit from a set of x- and y-coordinates with r.earthworks. Set a z-coordinate for the bottom of the pit. These coordinates represents a local topographic minima, i.e. a low point. The algorithm will cut locally down to that point, then the slopes will climb at a given rate of growth.
r.earthworks elevation=elevation earthworks=pit operation=cut coordinates=400,100 z=-25 flat=25 rate=0.5
# Model earthworks
gs.run_command("r.earthworks",
="elevation",
elevation="pit",
earthworks="cut",
operation=[400, 100],
coordinates=-25,
z=25,
flat=0.5
rate
)
# Visualize
= gj.Map(width=800)
m map="pit")
m.d_rast(="pit", color="black", at=(5, 95, 1, 3))
m.d_legend(raster m.show()
Cut & Fill Operations
Use cut and fill operations to model a pit and a peak from two sets of x- and y-coordinates with r.earthworks. Set a z-coordinate for the bottom of the pit and another z-coordinate for the top of the peak.
r.earthworks elevation=elevation earthworks=pit_and_peak operation=cutfill coordinates=350,100,450,100 z=-25,25 flat=25 rate=0.5
# Model earthworks
gs.run_command("r.earthworks",
="elevation",
elevation="pit_and_peak",
earthworks="cutfill",
operation=[350, 100, 450, 100],
coordinates=[-25, 25],
z=25,
flat=0.5
rate
)
# Visualize
= gj.Map(width=800)
m map="pit_and_peak")
m.d_rast(="pit_and_peak", color="black", at=(5, 95, 1, 3))
m.d_legend(raster m.show()
Random Operations
Randomness
Model a set of random peaks by generating a random surface, sampling random points, and then filling on those points. First generate a random surface with r.surf.random. Set a seed
for reproducible results or set flags="s"
for a random seed. Then randomly sample 50 cells from the random surface r.random. Use a fill operation to model random peaks with r.earthworks. Set input raster to the random cells.
r.surf.random out=surface min=0 max=25 seed=2
r.random input=surface npoints=50 raster=random seed=7
r.earthworks elevation=elevation earthworks=earthworks operation=fill raster=random rate=0.25 flat=25
# Generate random surface
"r.surf.random", out="surface", min=0, max=25, seed=2)
gs.run_command(
# Sample random points
gs.run_command("r.random",
input="surface",
=50,
npoints="random",
raster=7
seed
)
# Model earthworks
gs.run_command("r.earthworks",
="elevation",
elevation="earthworks",
earthworks="fill",
operation="random",
raster=0.25,
rate=25
flat
)
# Visualize
= gj.Map(width=800)
m map="earthworks")
m.d_rast(="earthworks", digits=0, at=(5, 95, 1, 3))
m.d_legend(raster m.show()
Visualization
Compute contours for earthworks with r.contour.
r.contour input=earthworks output=contours step=2
# Derive contours
"r.contour", input="earthworks", output="contours", step=2)
gs.run_command(
# Visualize Contours
= gj.Map(width=800)
m map="contours")
m.d_vect( m.show()