---
name: r.geomorphon
description: Calculates geomorphons (terrain forms) and associated geometry using machine vision approach.
keywords: [ raster, geomorphons, terrain patterns, machine vision geomorphometry ]
---

# r.geomorphon

Calculates geomorphons (terrain forms) and associated geometry using machine vision approach.

=== "Command line"

    **r.geomorphon**
    [**-me**]
    **elevation**=*name*
    [**forms**=*name*]
    [**ternary**=*name*]
    [**positive**=*name*]
    [**negative**=*name*]
    [**intensity**=*name*]
    [**exposition**=*name*]
    [**range**=*name*]
    [**variance**=*name*]
    [**elongation**=*name*]
    [**azimuth**=*name*]
    [**extend**=*name*]
    [**width**=*name*]
    **search**=*integer*
    **skip**=*integer*
    **flat**=*float*
    **dist**=*float*
    [**comparison**=*string*]
    [**coordinates**=*east,north*]
    [**profiledata**=*name*]
    [**profileformat**=*string*]
    [**--overwrite**]
    [**--verbose**]
    [**--quiet**]
    [**--qq**]
    [**--ui**]

    Example:

    ```sh
    r.geomorphon elevation=name search=3 skip=0 flat=1 dist=0
    ```

=== "Python (grass.tools)"

    *grass.tools.Tools.r_geomorphon*(**elevation**,
        **forms**=*None*,
        **ternary**=*None*,
        **positive**=*None*,
        **negative**=*None*,
        **intensity**=*None*,
        **exposition**=*None*,
        **range**=*None*,
        **variance**=*None*,
        **elongation**=*None*,
        **azimuth**=*None*,
        **extend**=*None*,
        **width**=*None*,
        **search**=*3*,
        **skip**=*0*,
        **flat**=*1*,
        **dist**=*0*,
        **comparison**=*"anglev1"*,
        **coordinates**=*None*,
        **profiledata**=*None*,
        **profileformat**=*None*,
        **flags**=*None*,
        **overwrite**=*None*,
        **verbose**=*None*,
        **quiet**=*None*,
        **superquiet**=*None*)

    Example:

    ```python
    tools = Tools()
    tools.r_geomorphon(elevation="name", search=3, skip=0, flat=1, dist=0)
    ```

    This grass.tools API is experimental in version 8.5 and expected to be stable in version 8.6.

=== "Python (grass.script)"

    *grass.script.run_command*("***r.geomorphon***",
        **elevation**,
        **forms**=*None*,
        **ternary**=*None*,
        **positive**=*None*,
        **negative**=*None*,
        **intensity**=*None*,
        **exposition**=*None*,
        **range**=*None*,
        **variance**=*None*,
        **elongation**=*None*,
        **azimuth**=*None*,
        **extend**=*None*,
        **width**=*None*,
        **search**=*3*,
        **skip**=*0*,
        **flat**=*1*,
        **dist**=*0*,
        **comparison**=*"anglev1"*,
        **coordinates**=*None*,
        **profiledata**=*None*,
        **profileformat**=*None*,
        **flags**=*None*,
        **overwrite**=*None*,
        **verbose**=*None*,
        **quiet**=*None*,
        **superquiet**=*None*)

    Example:

    ```python
    gs.run_command("r.geomorphon", elevation="name", search=3, skip=0, flat=1, dist=0)
    ```

## Parameters

=== "Command line"

    **elevation**=*name* **[required]**  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input elevation raster map  
    **forms**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Most common geomorphic forms  
    **ternary**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Code of ternary patterns  
    **positive**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Code of binary positive patterns  
    **negative**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Code of binary negative patterns  
    **intensity**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing mean relative elevation of the form  
    **exposition**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing maximum difference between extend and central cell  
    **range**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing difference between max and min elevation of the form extend  
    **variance**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing variance of form boundary  
    **elongation**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing local elongation  
    **azimuth**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing local azimuth of the elongation  
    **extend**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing local extend (area) of the form  
    **width**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing local width of the form  
    **search**=*integer* **[required]**  
    &nbsp;&nbsp;&nbsp;&nbsp;Outer search radius  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *3*  
    **skip**=*integer* **[required]**  
    &nbsp;&nbsp;&nbsp;&nbsp;Inner search radius  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0*  
    **flat**=*float* **[required]**  
    &nbsp;&nbsp;&nbsp;&nbsp;Flatness threshold (degrees)  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *1*  
    **dist**=*float* **[required]**  
    &nbsp;&nbsp;&nbsp;&nbsp;Flatness distance, zero for none  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0*  
    **comparison**=*string*  
    &nbsp;&nbsp;&nbsp;&nbsp;Comparison mode for zenith/nadir line-of-sight search  
    &nbsp;&nbsp;&nbsp;&nbsp;Allowed values: *anglev1, anglev2, anglev2_distance*  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *anglev1*  
    **coordinates**=*east,north*  
    &nbsp;&nbsp;&nbsp;&nbsp;Coordinates to profile  
    **profiledata**=*name*  
    &nbsp;&nbsp;&nbsp;&nbsp;Profile output file name ("-" for stdout)  
    **profileformat**=*string*  
    &nbsp;&nbsp;&nbsp;&nbsp;Profile output format  
    &nbsp;&nbsp;&nbsp;&nbsp;Allowed values: *json, yaml, xml*  
    **-m**  
    &nbsp;&nbsp;&nbsp;&nbsp;Use meters to define search units (default is cells)  
    **-e**  
    &nbsp;&nbsp;&nbsp;&nbsp;Use extended form correction  
    **--overwrite**  
    &nbsp;&nbsp;&nbsp;&nbsp;Allow output files to overwrite existing files  
    **--help**  
    &nbsp;&nbsp;&nbsp;&nbsp;Print usage summary  
    **--verbose**  
    &nbsp;&nbsp;&nbsp;&nbsp;Verbose module output  
    **--quiet**  
    &nbsp;&nbsp;&nbsp;&nbsp;Quiet module output  
    **--qq**  
    &nbsp;&nbsp;&nbsp;&nbsp;Very quiet module output  
    **--ui**  
    &nbsp;&nbsp;&nbsp;&nbsp;Force launching GUI dialog

=== "Python (grass.tools)"

    **elevation** : str | np.ndarray, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input elevation raster map  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, raster, *name*  
    **forms** : str | type(np.ndarray) | type(np.array) | type(gs.array.array), *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Most common geomorphic forms  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **ternary** : str | type(np.ndarray) | type(np.array) | type(gs.array.array), *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Code of ternary patterns  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **positive** : str | type(np.ndarray) | type(np.array) | type(gs.array.array), *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Code of binary positive patterns  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **negative** : str | type(np.ndarray) | type(np.array) | type(gs.array.array), *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Code of binary negative patterns  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **intensity** : str | type(np.ndarray) | type(np.array) | type(gs.array.array), *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing mean relative elevation of the form  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **exposition** : str | type(np.ndarray) | type(np.array) | type(gs.array.array), *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing maximum difference between extend and central cell  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **range** : str | type(np.ndarray) | type(np.array) | type(gs.array.array), *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing difference between max and min elevation of the form extend  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **variance** : str | type(np.ndarray) | type(np.array) | type(gs.array.array), *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing variance of form boundary  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **elongation** : str | type(np.ndarray) | type(np.array) | type(gs.array.array), *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing local elongation  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **azimuth** : str | type(np.ndarray) | type(np.array) | type(gs.array.array), *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing local azimuth of the elongation  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **extend** : str | type(np.ndarray) | type(np.array) | type(gs.array.array), *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing local extend (area) of the form  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **width** : str | type(np.ndarray) | type(np.array) | type(gs.array.array), *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing local width of the form  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **search** : int, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Outer search radius  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *3*  
    **skip** : int, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Inner search radius  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0*  
    **flat** : float, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Flatness threshold (degrees)  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *1*  
    **dist** : float, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Flatness distance, zero for none  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0*  
    **comparison** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Comparison mode for zenith/nadir line-of-sight search  
    &nbsp;&nbsp;&nbsp;&nbsp;Allowed values: *anglev1, anglev2, anglev2_distance*  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *anglev1*  
    **coordinates** : tuple[float, float] | list[float] | str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Coordinates to profile  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, coords, *east,north*  
    **profiledata** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Profile output file name ("-" for stdout)  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, file, *name*  
    **profileformat** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Profile output format  
    &nbsp;&nbsp;&nbsp;&nbsp;Allowed values: *json, yaml, xml*  
    **flags** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Allowed values: *m*, *e*  
    &nbsp;&nbsp;&nbsp;&nbsp;**m**  
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Use meters to define search units (default is cells)  
    &nbsp;&nbsp;&nbsp;&nbsp;**e**  
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Use extended form correction  
    **overwrite** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Allow output files to overwrite existing files  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **verbose** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Verbose module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **quiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **superquiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Very quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  

    Returns:

    **result** : grass.tools.support.ToolResult | np.ndarray | tuple[np.ndarray] | None  
    If the tool produces text as standard output, a *ToolResult* object will be returned. Otherwise, `None` will be returned. If an array type (e.g., *np.ndarray*) is used for one of the raster outputs, the result will be an array and will have the shape corresponding to the computational region. If an array type is used for more than one raster output, the result will be a tuple of arrays.

    Raises:

    *grass.tools.ToolError*: When the tool ended with an error.

=== "Python (grass.script)"

    **elevation** : str, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input elevation raster map  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, raster, *name*  
    **forms** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Most common geomorphic forms  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **ternary** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Code of ternary patterns  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **positive** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Code of binary positive patterns  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **negative** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Code of binary negative patterns  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **intensity** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing mean relative elevation of the form  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **exposition** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing maximum difference between extend and central cell  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **range** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing difference between max and min elevation of the form extend  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **variance** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing variance of form boundary  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **elongation** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing local elongation  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **azimuth** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing local azimuth of the elongation  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **extend** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing local extend (area) of the form  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **width** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Rasters containing local width of the form  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, raster, *name*  
    **search** : int, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Outer search radius  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *3*  
    **skip** : int, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Inner search radius  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0*  
    **flat** : float, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Flatness threshold (degrees)  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *1*  
    **dist** : float, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Flatness distance, zero for none  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0*  
    **comparison** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Comparison mode for zenith/nadir line-of-sight search  
    &nbsp;&nbsp;&nbsp;&nbsp;Allowed values: *anglev1, anglev2, anglev2_distance*  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *anglev1*  
    **coordinates** : tuple[float, float] | list[float] | str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Coordinates to profile  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, coords, *east,north*  
    **profiledata** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Profile output file name ("-" for stdout)  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, file, *name*  
    **profileformat** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Profile output format  
    &nbsp;&nbsp;&nbsp;&nbsp;Allowed values: *json, yaml, xml*  
    **flags** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Allowed values: *m*, *e*  
    &nbsp;&nbsp;&nbsp;&nbsp;**m**  
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Use meters to define search units (default is cells)  
    &nbsp;&nbsp;&nbsp;&nbsp;**e**  
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Use extended form correction  
    **overwrite** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Allow output files to overwrite existing files  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **verbose** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Verbose module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **quiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **superquiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Very quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*

## DESCRIPTION

*r.geomorphon* calculates terrain forms using machine-vison technique
called geomorphons.

### What is geomorphon

![What is geomorphon](geomorphon.png)

Geomorphon is a new concept of presentation and analysis of terrain
forms. This concept utilises 8-tuple pattern of the visibility
neighbourhood and breaks well known limitation of standard calculus
approach where all terrain forms cannot be detected in a single window
size. The pattern arises from a comparison of a focus pixel with its
eight neighbors starting from the one located to the east and continuing
counterclockwise producing ternary operator. For example, a tuple
{+,-,-,-,0,+,+,+} describes one possible pattern of relative measures
{higher, lower, lower, lower, equal, higher, higher, higher} for pixels
surrounding the focus pixel. It is important to stress that the
visibility neighbors are **not necessarily an immediate neighbors** of
the focus pixel in the grid, but the pixels determined from **the
line-of-sight** principle along the eight principal directions. This
principle relates surface relief and horizontal distance by means of
so-called zenith and nadir angles along the eight principal compass
directions. The ternary operator converts the information contained in
all the pairs of zenith and nadir angles into the ternary pattern
(8-tuple). The result depends on the values of two parameters: search
radius (L) and relief threshold (d). The search radius is the maximum
allowable distance for calculation of zenith and nadir angles. The
relief threshold is a minimum value of difference between LOSs angle
(zenith and nadir) that is considered significantly different from the
horizon. Two lines-of-sight are necessary due to zenith LOS only, does
not detect positive forms correctly.

There are 3\*\*8 = 6561 possible ternary patterns (8-tuples). By
removing all patterns that are the result of either rotation or
reflection of other patterns, a set of 498 patterns remains, referred to
as geomorphons. This is a comprehensive and exhaustive set of idealized
landforms that are independent of the size, relief, and orientation of
the actual landform.

Form recognition depends on two free parameters: **Search radius** and
**flatness threshold**. Using larger values of L and is tantamount to
terrain classification from a higher and wider perspective, whereas
using smaller values of L and is tantamount to terrain classification
from a local point of view. A character of the map depends on the value
of L. Using small value of L results in the map that correctly
identifies landforms if their size is smaller than L; landforms having
larger sizes are broken down into components. Using larger values of L
allows simultaneous identification of landforms on variety of sizes in
expense of recognition smaller, second-order forms. There are two
additional parameters: **skip radius** used to eliminate impact of small
irregularities. On the contrary **flatness distance** eliminates the
impact of very high distance (in meters) of search radius which may not
detect elevation difference if this is at very far distance. Important
especially with low resolution DEMS.

## OPTIONS

**-m**  
All distance parameters (search, skip, flat distances) are supplied as
meters instead of cells (default). To avoid situation when supplied
distances is smaller than one cell program first check if supplied
distance is longer than one cell in both NS and WE directions. For
LatLong projection only NS distance checked, because in latitude angular
unit comprise always bigger or equal distance than longitude one. If
distance is supplied in cells, For all projections is recalculated into
meters according formula:
`number_of_cells*resolution_along_NS_direction`. It is important if
geomorphons are calculated for large areas in LatLong projection.

**elevation**  
Digital elevation model. Data can be of any type and any projection.
During calculation DEM is stored as floating point raster.

**search**  
Determines length on the geodesic distances in all eight directions
where line-of-sight is calculated. To speed up calculation is determines
only these cells which centers falls into the distance.

**skip**  
Determines length on the geodesic distances at the beginning of
calculation all eight directions where line-of-sight is yet calculated.
To speed up calculation this distance is always recalculated into number
of cell which are skipped at the beginning of every line-of-sight and is
equal in all direction. This parameter eliminates forms of very small
extend, smaller than skip parameter.

**flat**  
The difference (in degrees) between zenith and nadir line-of-sight which
indicate flat direction. If higher threshold produce more flat maps. If
resolution of the map is low (more than 1 km per cell) threshold should
be very small (much smaller than 1 degree) because on such distance 1
degree of difference means several meters of high difference.

**dist**  
Flat distance. This is additional parameter defining the distance above
which the threshold starts to decrease to avoid problems with
pseudo-flat line-of-sights if real elevation difference appears on the
distance where its value is higher (TO BE CORRECTED).

**comparison**  
Comparison mode for zenith/nadir line-of-sight search. "anglev1" is the
original r.geomorphon comparison mode. "anglev2" is an improved mode,
which better handles angle thresholds and zenith/nadir angles that are
exactly equal. "anglev2_distance" in addition to that takes the
zenith/nadir distances into account when the angles are exactly equal.

**forms**  
Returns geomorphic map with 10 most popular terrestrial forms. Legend
for forms, its definition by the number of *+* and *-* and its idealized
visualisation are presented at the image.

### Forms represented by geomorphons

![forms legend](legend.png)

**ternary**  
returns code of one of 498 unique ternary patterns for every cell. The
code is a decimal representation of 8-tuple minimalised patterns written
in ternary system. Full list of patterns is available in source code
directory as patterns.txt. This map can be used to create alternative
form classification using supervised approach.

**positive** and **negative**  
returns codes binary patterns for zenith (positive) and nadir (negative)
line of sights. The code is a decimal representation of 8-tuple
minimalised patterns written in binary system. Full list of patterns is
available in source code directory as patterns.txt.

**coordinates**  
The central point of a single geomorphon to profile. The central point
must be within the computational region, which should be large enough to
accommodate the search radius. Setting the region larger than that will
not produce more accurate data, but in the current implementation will
slow the computation down. For the best results remember to align the
region to the raster cells. Profiling is mutually exclusive with any
raster outputs, but other parameters and flags (such as **elevation**,
**search**, **comparison**, **-m** and **-e**) work as usual.

**profiledata**  
The output file name for the complete profile data, "-" means to write
to the standard output. The data is in a machine-readable format and it
includes assorted values describing the computation context and
parameters, as well as its intermediate and final results.

**profileformat**  
Format of the profile data: "json", "yaml" or "xml".

*NOTE: parameters below are experimental. The usefulness of these
parameters are currently under investigation.*

**intensity**  
returns average difference between central cell of geomorphon and eight
cells in visibility neighbourhood. This parameter shows local (as is
visible) exposition/abasement of the form in the terrain.

**range**  
returns difference between minimum and maximum values of visibility
neighbourhood.

**variance**  
returns variance (difference between particular values and mean value)
of visibility neighbourhood.

**extend**  
returns area of the polygon created by the 8 points where line-of-sight
cuts the terrain (see image in description section).

**azimuth**  
returns orientation of the polygon constituting geomorphon. This
orientation is currently calculated as a orientation of least square fit
line to the eight verticles of this polygon.

**elongation**  
returns proportion between sides of the bounding box rectangle
calculated for geomorphon rotated to fit least square line.

**width**  
returns length of the shorter side of the bounding box rectangle
calculated for geomorphon rotated to fit least square line.

## NOTES

From computational point of view there are no limitations of input DEM
and free parameters used in calculation. However, in practice there are
some issues on DEM resolution and search radius. Low resolution DEM
especially above 1 km per cell requires smaller than default flatness
threshold. On the other hand, only forms with high local elevation
difference will be detected correctly. It results from fact that on very
high distance (of order of kilometers or higher) even relatively high
elevation difference will be recognized as flat. For example at the
distance of 8 km (8 cells with 1 km resolution DEM) an relative
elevation difference of at least 136 m is required to be noticed as
non-flat. Flatness distance threshold may be helpful to avoid this
problem.

## EXAMPLES

### Geomorphon calculation: extraction of terrestrial landforms

Geomorphon calculation example using the EU DEM 25m:

```sh
g.region raster=eu_dem_25m -p
r.geomorphon elevation=eu_dem_25m forms=eu_dem_25m_geomorph

# verify terrestrial landforms found in DEM
r.category eu_dem_25m_geomorph
 1  flat
 2  peak
 3  ridge
 4  shoulder
 5  spur
 6  slope
 7  hollow
 8  footslope
 9  valley
 10 pit
```

![Geomorphon calculation example using the EU DEM 25m (with search=11)](r_geomorphon.png)

### Extraction of peaks

Using the resulting terrestrial landforms map, single landforms can be
extracted, e.g. the peaks, and converted into a vector point map:

```sh
r.mapcalc expression="eu_dem_25m_peaks = if(eu_dem_25m_geomorph == 2, 1, null())"
r.thin input=eu_dem_25m_peaks output=eu_dem_25m_peaks_thinned
r.to.vect input=eu_dem_25m_peaks_thinned output=eu_dem_25m_peaks type=point
v.info input=eu_dem_25m_peaks
```

![Extraction of peaks from EU DEM 25m (with search=11)](r_geomorphon_peaks.png)

## REFERENCES

- Stepinski, T., Jasiewicz, J., 2011, Geomorphons - a new approach to
  classification of landform, in : Eds: Hengl, T., Evans, I.S., Wilson,
  J.P., and Gould, M., Proceedings of Geomorphometry 2011, Redlands,
  109-112
  ([PDF](https://www.geomorphometry.org/uploads/pdf/pdf2011/StepinskiJasiewicz2011geomorphometry.pdf))
- Jasiewicz, J., Stepinski, T., 2013, Geomorphons - a pattern
  recognition approach to classification and mapping of landforms,
  Geomorphology, vol. 182, 147-156 (DOI:
  [10.1016/j.geomorph.2012.11.005](https://doi.org/10.1016/j.geomorph.2012.11.005))

## SEE ALSO

*[r.param.scale](r.param.scale.md)*

## AUTHORS

Jarek Jasiewicz, Tomek Stepinski (merit contribution)

## SOURCE CODE

Available at: [r.geomorphon source code](https://github.com/OSGeo/grass/tree/main/raster/r.geomorphon)
([history](https://github.com/OSGeo/grass/commits/main/raster/r.geomorphon))  
Latest change: Monday Nov 17 13:07:11 2025 in commit [66c1733](https://github.com/OSGeo/grass/commit/66c1733a055484761c1c25bdec937ebf0b31f00e)
