Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
263 changes: 263 additions & 0 deletions content/tutorials/howtos/convert-flowdir.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
---
title: "How to convert flow direction between different encodings in GRASS"
author: "Huidae Cho"
date: 2022-03-25
date-modified: today
format:
html:
toc: true
toc-depth: 2
code-tools: true
code-copy: true
code-fold: false
html-math-method: katex
theme:
- cosmo
categories: [bash, beginner]
linkcolor: green
urlcolor: green
citecolor: green
highlight-style: github
# engine: knitr
execute:
eval: false
---
# Introduction

This document shows how to convert flow direction encodings between several formats in GRASS. Each section displays:

- **Figure Left:** Input encoding
- **Equation:** Conversion formula
- **Figure Right:** Output encoding
- **GRASS Command**

---

## 1. Degree to 45degree

::: columns
:::: {.column width="20%"}
![](images/degree.svg){width=80%}
::::

:::: {.column width="60%"}
$$D = \frac{d}{45}$$
::::

:::: {.column width="20%"}
![](images/45degree.svg){width=80%}
::::
:::
```bash
r.mapcalc "45degree = int(degree / 45)"
```

## 2. 45degree to Degree

::: columns
:::: {.column width="20%"}
![](images/45degree.svg){width=80%}
::::

:::: {.column width="60%"}
$$d = 45 \times |D|$$
::::

:::: {.column width="20%"}
![](images/degree.svg){width=80%}
::::
:::
```bash
r.mapcalc "degree = abs(45degree) * 45"
```

## 3. Degree to Power2

::: columns
:::: {.column width="20%"}
![](images/degree.svg){width=80%}
::::

:::: {.column width="60%"}
$$p = 2^{8 - \frac{d}{45}}$$
::::

:::: {.column width="20%"}
![](images/power2.svg){width=80%}
::::
:::
```bash
r.mapcalc "power2 = 2^(8 - degree / 45)"
```
---

## 4. Power2 to Degree

::: columns
:::: {.column width="20%"}
![](images/power2.svg){width=80%}
::::

:::: {.column width="60%"}
$$d = 45 \times (8 - \log_2 p)$$
::::

:::: {.column width="20%"}
![](images/degree.svg){width=80%}
::::
:::
```bash
r.mapcalc "degree = 45 * int(8 - log(power2, 2))"
```

## 5. Degree to TauDEM

::: columns
:::: {.column width="20%"}
![](images/degree.svg){width=80%}
::::

:::: {.column width="60%"}
$$t = 1 + \left( \frac{d}{45} \mod 8 \right)$$
::::

:::: {.column width="20%"}
![](images/taudem.svg){width=80%}
::::
:::
```bash
r.mapcalc "taudem = 1 + (degree / 45) % 8"
```

## 6. TauDEM to Degree

::: columns
:::: {.column width="20%"}
![](images/taudem.svg){width=80%}
::::

:::: {.column width="60%"}
$$d = 45 \times \left\{ \begin{array}{ll} t-1 & \text{if } t-1 > 0 \\ 8 & \text{otherwise} \end{array} \right.$$
::::

:::: {.column width="20%"}
![](images/degree.svg){width=80%}
::::
:::
```bash
r.mapcalc "degree = 45 * if(taudem - 1, taudem - 1, 8)"
```

## 7. 45degree to Power2

::: columns
:::: {.column width="20%"}
![](images/45degree.svg){width=80%}
::::

:::: {.column width="60%"}
$$p = 2^{8 - |D|}$$
::::

:::: {.column width="20%"}
![](images/power2.svg){width=80%}
::::
:::
```bash
r.mapcalc "power2 = 2^(8 - abs(45degree))"
```

## 8. Power2 to 45degree

::: columns
:::: {.column width="20%"}
![](images/power2.svg){width=80%}
::::

:::: {.column width="60%"}
$$D = 8 - \log_2 p$$
::::

:::: {.column width="20%"}
![](images/45degree.svg){width=80%}
::::
:::
```bash
r.mapcalc "45degree = int(8 - log(power2, 2))"
```

## 9. 45degree to TauDEM

::: columns
:::: {.column width="20%"}
![](images/45degree.svg){width=80%}
::::

:::: {.column width="60%"}
$$t = 1 + (|D| \mod 8)$$
::::

:::: {.column width="20%"}
![](images/taudem.svg){width=80%}
::::
:::
```bash
r.mapcalc "taudem = 1 + abs(45degree) % 8"
```

## 10. TauDEM to 45degree

::: columns
:::: {.column width="20%"}
![](images/taudem.svg){width=80%}
::::

:::: {.column width="60%"}
$$D = \left\{\begin{array}{ll} t-1 & \text{if } t-1 > 0 \\ 8 & \text{otherwise} \end{array} \right.$$
::::

:::: {.column width="20%"}
![](images/45degree.svg){width=80%}
::::
:::
```bash
r.mapcalc "45degree = if(taudem - 1, taudem - 1, 8)"
```

## 11. Power2 to TauDEM

::: columns
:::: {.column width="20%"}
![](images/power2.svg){width=80%}
::::

:::: {.column width="60%"}
$$t = 1 + \left[ (8 - \log_2 p) \mod 8 \right]$$
::::

:::: {.column width="20%"}
![](images/taudem.svg){width=80%}
::::
:::
```bash
r.mapcalc "taudem = 1 + (8 - log(power2, 2)) % 8"
```

## 12. TauDEM to Power2

::: columns
:::: {.column width="20%"}
![](images/taudem.svg){width=80%}
::::

:::: {.column width="60%"}
$$p = 2^{(9 - t) \mod 8}$$
::::

:::: {.column width="20%"}
![](images/power2.svg){width=80%}
::::
:::
```bash
r.mapcalc "power2 = 2^((9 - taudem) % 8)"
```
34 changes: 34 additions & 0 deletions content/tutorials/howtos/create-empty-vector-map.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: "How to create an empty vector map in GRASS"
author: "Huidae Cho"
date: 2022-03-25
date-modified: today
format:
html:
toc: true
toc-depth: 2
code-tools: true
code-copy: true
code-fold: false
html-math-method: katex
theme:
- cosmo
categories: [beginner]
linkcolor: green
urlcolor: green
citecolor: green
highlight-style: github
# engine: knitr
execute:
eval: false
---


[`v.edit`](https://grass.osgeo.org/grass-stable/manuals/v.edit.html) can create an empty vector map, but it does not create an attribute table.

```bash
# Create an empty vector map
v.edit map=new_map tool=create
# Add a new table
v.db.addtable map=new_map columns="value double"
```
78 changes: 78 additions & 0 deletions content/tutorials/howtos/delineate-stream-networks.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
title: "How to delineate stream networks in GRASS"
author: "Huidae Cho"
date: 2022-03-25
date-modified: today
format:
html:
toc: true
toc-depth: 2
code-tools: true
code-copy: true
code-fold: false
html-math-method: katex
theme:
- cosmo
categories: [bash, beginner]
linkcolor: green
urlcolor: green
citecolor: green
highlight-style: github
# engine: knitr
execute:
eval: false
---
# 1. Identifying stream networks without calculating hydrologic parameters

Extract streams using the A* algorithm with a threshold value of 50,000 cells for stream generation:

```bash
# accumulation=flow_accum is optional
r.stream.extract elevation=elevation threshold=50,000 stream_vector=streams accumulation=flow_accum
```

Figure 1 shows a stream network vector map created using [r.stream.extract](https://grass.osgeo.org/grass-stable/manuals/r.stream.extract.html). The stream vector properly represents flow directions.

![Figure 1: Stream networks generated using r.stream.extract. The red and blue lines represent the stream vector and flow directions, respectively. The underlying raster map is flow accumulation.](images/r.stream.extract.webp)

---

# 2. Delineating watersheds and identifying stream networks from the same source of elevation data

Calculate flow direction and accumulation, and delineate basins in the raster format:

```bash
r.watershed -a elevation=elevation threshold=50,000 accumulation=flow_accum basin=basins
```

Extract streams from the flow accumulation raster map from [r.watershed](https://grass.osgeo.org/grass-stable/manuals/r.watershed.html) so that the stream network output matches the watershed output from [r.watershed](https://grass.osgeo.org/grass-stable/manuals/r.watershed.html):

```bash
r.stream.extract elevation=elevation accumulation=flow_accum threshold=50,000 stream_vector=streams
```

---

# 3. Delineating stream networks from a flow direction map

[r.accumulate](https://grass.osgeo.org/grass-stable/manuals/addons/r.accumulate.html) takes a flow direction map and delineates stream networks using a threshold:

```bash
r.accumulate direction=drain_directions threshold=50000 stream=streams
```

---

# 4. How not to delineate stream networks

[r.watershed](https://grass.osgeo.org/grass-stable/manuals/r.watershed.html) generates a stream raster map and you may be tempted to simply convert this stream raster map to vector to identify stream networks:

```bash
r.watershed -a elevation=elevation threshold=50,000 stream=streams
r.thin input=streams output=streams_thinned
r.to.vect input=streams_thinned output=streams type=line
```

However, there are two problems with this method. First, the output stream vector map does not guarantee the correct directionality of stream paths. Second, if there are raster cell clumps in the stream raster map, stream loops may be generated or even incorrect stream paths can be obtained. An example is shown in Figure 2. Note that the stream vector does not fully agree with flow directions. Compare this output to Figure 1.

![Figure 2: Stream networks generated using r.watershed, r.thin, and r.to.vect. The red and blue lines represent the stream vector and flow directions, respectively. The underlying raster map is flow accumulation.](images/r.watershed.webp)
Loading
Loading