r3.mapcalc(1)

okay bestie, sit down, hydrate, because we're reading the GRASS GIS User's Manual page for r3.mapcalc and it is a whole journey ๐Ÿฆ‹ this is part 1, so grab a snack, we're going in ๐Ÿ’–


โœจ NAME โœจ

r3.mapcalc โ€” Raster map calculator. that's it. that's the name. short, sweet, devastating. ๐Ÿ’…


๐ŸŽ€ KEYWORDS ๐ŸŽ€

raster, algebra


๐ŸŒˆ SYNOPSIS ๐ŸŒˆ

r3.mapcalc
r3.mapcalc --help
r3.mapcalc [-sl]  [expression=string]   [region=string]   [file=name]
[seed=integer]   [--overwrite]  [--help]  [--verbose]  [--quiet]  [--ui]

๐Ÿšฉ Flags

  • -s โ€” generate random seed. heads up bestie, the result is non-deterministic, so like, don't expect the same thing twice ๐ŸŽฒ
  • -l โ€” list input and output maps. love that for us, receipts please ๐Ÿงพ
  • --overwrite โ€” lets output files overwrite existing files. use with intent, okay? ๐Ÿ˜ญ
  • --help โ€” print usage summary. the classic. ๐Ÿซถ
  • --verbose โ€” verbose module output. give us everything โœจ
  • --quiet โ€” quiet module output. shhh ๐Ÿคซ
  • --ui โ€” force launching GUI dialog. for the girlies who love a window ๐ŸชŸ

๐Ÿ“ Parameters

  • expression=string โ€” expression to evaluate. this is the main character here ๐Ÿ‘‘
  • region=string โ€” the computational region that should be used.
    • options: current, intersect, union
    • default: current
    • current: uses the current region of the mapset ๐ŸŒธ
    • intersect: computes the intersection region between all input maps and uses the smallest resolution โœ‚๏ธ
    • union: computes the union extent of all map regions and uses the smallest resolution ๐Ÿค
  • file=name โ€” file containing expression(s) to evaluate ๐Ÿ“„
  • seed=integer โ€” seed for the rand() function ๐ŸŽฐ

๐Ÿ’– DESCRIPTION ๐Ÿ’–

so what does it even do?? r3.mapcalc performs arithmetic on raster map layers. new raster map layers can be created which are arithmetic expressions involving existing raster map layers, integer or floating point constants, and functions. basically it's a calculator but the numbers are maps and the vibe is immaculate ๐Ÿ”ฅ

๐Ÿงฎ Program use

r3.mapcalc expressions have the form:

result = expression

where result is the name of a raster map layer to contain the result of the calculation, and expression is any legal arithmetic expression involving existing raster map layers (except result itself, no self-referencing bestie ๐Ÿ’€), integer or floating point constants, and functions known to the calculator. parentheses are allowed in the expression and may be nested to any depth. result will be created in the user's current mapset. ๐Ÿ 

as expression= is the first option, it is the default. this means that passing an expression on the command line is possible as long as the expression is quoted and a space is included before the first = sign. example (foo is the resulting map):

r3.mapcalc "foo = 1"

or:

r3.mapcalc 'foo = 1'

an unquoted expression (i.e. split over multiple arguments) won't work, nor will omitting the space before the = sign:

r3.mapcalc 'foo=1'
Sorry, <foo> is not a valid parameter
the space before = is NOT optional and the shell will humble you about it. no cap. ๐Ÿ˜ญ

if no options are given, it manufactures "file=-" (which reads from stdin), so you can continue to use e.g.:

r3.mapcalc < file

or:

r3.mapcalc <<EOF
foo = 1
EOF

but unless you need compatibility with previous versions, use file= explicitly, e.g.:

r3.mapcalc file=file

or:

r3.mapcalc file=- <<EOF
foo = 1
EOF

the formula entered to r3.mapcalc by the user is recorded both in the result map title (which appears in the category file for result) and in the history file for result. it's giving receipts, it's giving accountability ๐Ÿงš

some characters have special meaning to the command shell. if the user is entering input to r3.mapcalc on the command line, expressions should be enclosed within single quotes. see NOTES, below. (yes bestie, NOTES is coming, we're just not there yet ๐Ÿซ )

โž— Operators and order of precedence

the following operators are supported:

  • - โ€” negation ยท Arithmetic ยท precedence 12
  • ~ โ€” one's complement ยท Bitwise ยท precedence 12
  • ! โ€” not ยท Logical ยท precedence 12
  • ^ โ€” exponentiation ยท Arithmetic ยท precedence 11
  • % โ€” modulus ยท Arithmetic ยท precedence 10
  • / โ€” division ยท Arithmetic ยท precedence 10
  • * โ€” multiplication ยท Arithmetic ยท precedence 10
  • + โ€” addition ยท Arithmetic ยท precedence 9
  • - โ€” subtraction ยท Arithmetic ยท precedence 9
  • << โ€” left shift ยท Bitwise ยท precedence 8
  • >> โ€” right shift ยท Bitwise ยท precedence 8
  • >>> โ€” right shift (unsigned) ยท Bitwise ยท precedence 8
  • > โ€” greater than ยท Logical ยท precedence 7
  • >= โ€” greater than or equal ยท Logical ยท precedence 7
  • < โ€” less than ยท Logical ยท precedence 7
  • <= โ€” less than or equal ยท Logical ยท precedence 7
  • == โ€” equal ยท Logical ยท precedence 6
  • != โ€” not equal ยท Logical ยท precedence 6
  • & โ€” bitwise and ยท Bitwise ยท precedence 5
  • | โ€” bitwise or ยท Bitwise ยท precedence 4
  • && โ€” logical and ยท Logical ยท precedence 3
  • &&& โ€” logical and[1] ยท Logical ยท precedence 3
  • || โ€” logical or ยท Logical ยท precedence 2
  • ||| โ€” logical or[1] ยท Logical ยท precedence 2
  • ?: โ€” conditional ยท Logical ยท precedence 1

(modulus is the remainder upon division) ๐Ÿฐ

[1] the &&& and ||| operators handle null values differently to other operators. see the section entitled NULL support below for more details. ๐Ÿ‘€

the operators are applied from left to right, with those of higher precedence applied before those with lower precedence. division by 0 and modulus by 0 are acceptable and give a NULL result โ€” yes really, no crash, just vibes โœจ. the logical operators give a 1 result if the comparison is true, 0 otherwise. binary. periodt. ๐Ÿ’…

๐Ÿ—บ๏ธ 3D Grid names

anything in the expression which is not a number, operator, or function name is taken to be a 3D grid name. examples:

volume
x3
3d.his

most GRASS raster map layers and 3D grids meet this naming convention. however, if a 3D grid has a name which conflicts with the above rule, it should be quoted. for example, the expression

x = a-b

would be interpreted as: x equals a minus b, whereas

x = "a-b"

would be interpreted as: x equals the 3D grid named a-b. see how much the quotes are doing?? the quotes are the whole plot twist ๐ŸŽญ

also

x = 3107

would create x filled with the number 3107, while

x = "3107"

would copy the 3D grid 3107 to the 3D grid x. literally the same characters, completely different outcome. iykyk ๐Ÿ˜Œ

quotes are not required unless the 3D grid names look like numbers or contain operators, OR unless the program is run non-interactively. examples given here assume the program is run interactively. see NOTES, below. (again with the NOTES, we get it, it's coming ๐Ÿ“)

r3.mapcalc will look for the 3D grids according to the user's current mapset search path. it is possible to override the search path and specify the mapset from which to select the 3D grid. this is done by specifying the 3D grid name in the form:

name@mapset

for example, the following is a legal expression:

result = x@PERMANENT / y@SOILS

the mapset specified does not have to be in the mapset search path. (this method of overriding the mapset search path is common to all GRASS commands, not just r3.mapcalc.) so like, it's a GRASS-wide thing, not a r3.mapcalc exclusive. we're just the ones talking about it rn ๐Ÿซถ

๐ŸงŠ The neighborhood modifier

3D grids are data base files stored in voxel format, i.e., three-dimensional matrices of float/double values. in r3.mapcalc, 3D grids may be followed by a neighborhood modifier that specifies a relative offset from the current cell being evaluated. the format is map[r,c,d], where r is the row offset, c is the column offset and d is the depth offset. for example, map[1,2,3] refers to the cell one row below, two columns to the right and 3 levels below of the current cell, map[-3,-2,-1] refers to the cell three rows above, two columns to the left and one level below of the current cell, and map[0,1,0] refers to the cell one column to the right of the current cell. this syntax permits the development of neighborhood-type filters within a single 3D grid or across multiple 3D grids. it's giving spatial awareness ๐Ÿง โœจ

๐ŸŽ€ Functions

the functions currently supported are listed in the table below. the type of the result is indicated in the last column. F means that the functions always results in a floating point value, I means that the function gives an integer result, and * indicates that the result is float if any of the arguments to the function are floating point values and integer if all arguments are integer. ๐Ÿ‘‘


ok so bestie, here's the โœจfull function menuโœจ โ€” every single one, no skipping, I promise. The type column at the end is the vibe: F means float, I means integer, and * means it depends on what u feed it (more on that in a sec, iykyk).

๐Ÿงฎ functions

  • abs(x) โ€” hands u the absolute value of x ๐Ÿ’… type *
  • acos(x) โ€” inverse cosine of x (and yes, the result comes out in degrees) โœจ type F
  • asin(x) โ€” inverse sine of x (result is in degrees, no cap) type F
  • atan(x) โ€” inverse tangent of x (in degrees) type F
  • atan(x,y) โ€” inverse tangent of y/x (still degrees, slay) type F
  • ceil(x) โ€” the smallest integral value that's not less than x type *
  • cos(x) โ€” cosine of x (and x is in degrees here, not radians, ok?) type F
  • double(x) โ€” converts x to double-precision floating point type F
  • eval([x,y,...,]z) โ€” evaluates the values of the listed exprs, then passes the results to z ๐Ÿซถ
  • exp(x) โ€” the exponential function of x type F
  • exp(x,y) โ€” x to the power y type F
  • float(x) โ€” converts x to single-precision floating point type F
  • floor(x) โ€” the largest integral value not greater than x type *
  • graph(x,x1,y1[x2,y2..]) โ€” converts the x to a y based on points in a graph ๐Ÿ“ˆ type F
  • graph2(x,x1[,x2,..],y1[,y2..]) โ€” the alternative form of graph() type F
  • if โ€” decision options, the whole lil family ๐Ÿ’– type *
    • if(x) โ€” 1 if x is not zero, 0 otherwise
    • if(x,a) โ€” a if x is not zero, 0 otherwise
    • if(x,a,b) โ€” a if x is not zero, b otherwise
    • if(x,a,b,c) โ€” a if x > 0, b if x is zero, c if x < 0
  • int(x) โ€” converts x to integer [ truncates, it's giving brutal honesty ] type I
  • isnull(x) โ€” checks if x = NULL
  • log(x) โ€” natural log of x type F
  • log(x,b) โ€” log of x base b type F
  • max(x,y[,z...]) โ€” the largest value of all the ones listed type *
  • median(x,y[,z...]) โ€” the median value of those listed type *
  • min(x,y[,z...]) โ€” the smallest value of those listed type *
  • mod(x,y) โ€” returns the modulus (aka the remainder) of x/y type *
  • mode(x,y[,z...]) โ€” the mode value of those listed type *
  • nmax(x,y[,z...]) โ€” largest value of those listed, but it excludes the NULLs ๐Ÿ™ˆ type *
  • nmedian(x,y[,z...]) โ€” median value of those listed, NULLs excluded type *
  • nmin(x,y[,z...]) โ€” smallest value of those listed, NULLs excluded type *
  • nmode(x,y[,z...]) โ€” mode value of those listed, NULLs excluded type *
  • not(x) โ€” 1 if x is zero, 0 otherwise
  • pow(x,y) โ€” x to the power y type *
  • rand(a,b) โ€” a random value x where a <= x < b ๐ŸŽฒ type *
  • round(x) โ€” rounds x to the nearest integer type I
  • round(x,y) โ€” rounds x to the nearest multiple of y
  • round(x,y,z) โ€” rounds x to the nearest y*i+z for some integer i
  • sin(x) โ€” sine of x (x is in degrees) type F
  • sqrt(x) โ€” square root of x type F
  • tan(x) โ€” tangent of x (x is in degrees) type F
  • xor(x,y) โ€” exclusive-or (XOR) of x and y type I

๐Ÿ‘‘ internal variables

  • row() โ€” current row of the moving window type I
  • col() โ€” current col of the moving window type I
  • depth() โ€” returns the current depth type I
  • nrows() โ€” number of rows in the computation region type I
  • ncols() โ€” number of columns in the computation region type I
  • ndepths() โ€” number of depth levels in the computation region type I
  • x() โ€” current x-coordinate of the moving window type F
  • y() โ€” current y-coordinate of the moving window type F
  • z() โ€” returns the current z value type F
  • ewres() โ€” current east-west resolution type F
  • nsres() โ€” current north-south resolution type F
  • tbres() โ€” current top-bottom resolution type F
  • area() โ€” area of the current cell in square meters type F
  • null() โ€” the NULL value
heads up bestie: row(), col() and depth() all start their indexing at 1. Not zero. One. Remember it, it'll get u every time ๐Ÿ’€

๐ŸŒˆ Floating point values in the expression

Floating point numbers are 100% allowed in the expression. A floating point number is just a number that contains a decimal point:

2.3   12.0   12.   .81

Floating point values get handled in a special way and honestly it's iconic. With arithmetic and logical operators, if either operand is float, the other one gets converted to float, and the result of the operation is float. Which means โ€” and this is the part people get wrong โ€” dividing integers gives u a (truncated) integer, while dividing floats gives u an accurate floating point value โœจ. And with functions of type * (peep the table above ๐Ÿ‘€), the result is float if any argument is float, and integer otherwise.

Note: if u calculate with integer numbers, the resulting map will be integer. If u want a float result, just add the decimal point to the integer number(s). That's it, that's the whole trick ๐Ÿ’…

If u want floating point division, at least one of the arguments has to be a floating point value. Multiplying one of them by 1.0 will produce a floating-point result, and so will using float():

r3.mapcalc "ratio = float(soil.4 - soil.3) / soil.3)"

๐Ÿฆ‹ NULL support

  • Division by zero should result in NULL.
  • Modulus by zero should result in NULL.
  • NULL-values in any arithmetic or logical operation should result in NULL. (however, &&& and ||| are treated specially, as described below ๐Ÿ‘‡).
  • The &&& and ||| operators observe the following axioms even when x is NULL:
x &&& false == false
false &&& x == false
x ||| true == true
true ||| x == true
  • NULL-values in function arguments should result in NULL (however, if(), eval() and isnull() are treated specially, as described below ๐Ÿ‘‡).
  • The eval() function always returns its last argument.
  • The situation for if() is:
if(x)
    NULL if x is NULL; 0 if x is zero; 1 otherwise
if(x,a)
    NULL if x is NULL; a if x is non-zero; 0 otherwise
if(x,a,b)
    NULL if x is NULL; a if x is non-zero; b otherwise
if(x,n,z,p)
    NULL if x is NULL; n if x is negative;
z if x is zero; p if x is positive
  • The (new) function isnull(x) returns: 1 if x is NULL; 0 otherwise. The (new) function null() (which has no arguments) returns an integer NULL.
  • Non-NULL, but invalid, arguments to functions should result in NULL.

Examples:

log(-2)
sqrt(-2)
pow(a,b) where a is negative and b is not an integer

NULL support: Please note that any math performed with NULL cells always results in a NULL value for these cells ๐Ÿซ . If u want to replace a NULL cell on-the-fly, use the isnull() test function inside an if-statement.

Example: the user wants the NULL-valued cells to be treated like zeros. To add maps A and B (where B contains NULLs) to get a map C, the user can use a construction like:

C = A + if(isnull(B),0,B)

๐ŸŽ€ NULL and conditions

For the one argument form:

if(x) = NULL        if x is NULL
if(x) = 0        if x = 0
if(x) = 1        otherwise (i.e. x is neither NULL nor 0).

For the two argument form:

if(x,a) = NULL        if x is NULL
if(x,a) = 0        if x = 0
if(x,a) = a        otherwise (i.e. x is neither NULL nor 0).

For the three argument form:

if(x,a,b) = NULL    if x is NULL
if(x,a,b) = b        if x = 0
if(x,a,b) = a        otherwise (i.e. x is neither NULL nor 0).

For the four argument form:

if(x,a,b,c) = NULL    if x is NULL
if(x,a,b,c) = a        if x > 0
if(x,a,b,c) = b        if x = 0
if(x,a,b,c) = c        if x < 0

More generally, all operators and most functions return NULL if any of their arguments are NULL.

The functions if(), isnull() and eval() are the exceptions ๐Ÿ‘‘. The function isnull() returns 1 if its argument is NULL and 0 otherwise. If the user wants the opposite, the ! operator, e.g. "!isnull(x)" must be used.

All forms of if() return NULL if the first argument is NULL. The 2, 3 and 4 argument forms of if() return NULL if the "selected" argument is NULL, e.g.:

if(0,a,b) = b    regardless of whether a is NULL
if(1,a,b) = a    regardless of whether b is NULL

eval() always returns its last argument, so it only returns NULL if the last argument is NULL.

Note: the user cannot test for NULL using the == operator, as that returns NULL if either or both arguments are NULL. i.e. if x and y are both NULL, then "x == y" and "x != y" are both NULL rather than 1 and 0 respectively. ๐Ÿ’€

The behaviour makes sense if the user considers NULL as representing an unknown quantity. E.g. if x and y are both unknown, then the values of "x == y" and "x != y" are also unknown; if they both have unknown values, the user doesn't know whether or not they both have the same value ๐Ÿงš

๐Ÿ“ NOTES ๐Ÿ“


๐Ÿ’ป Usage from command line

okay bestie, listen up, because this part is important. If you're typing your expression straight onto the command line, you gotta be careful โ€” some characters mean stuff to the UNIX shell. Which ones? Among others:

  • *
  • (
  • )
  • >
  • &
  • |

so the move is to wrap your expression in single quotes, like:

'result = volume * 2'

because without the quotes, that * (which the shell thinks is its business, not yours) would get messed with, and r3.mapcalc would see something totally different from a *. no cap. ๐Ÿ™ˆ


๐Ÿ” Multiple computations

general vibe: it's lowkey preferable to do as much as you can inside each single r3.mapcalc command, using multi-line input. one command, many lines, main character energy. โœจ


๐Ÿ•ฐ๏ธ Backwards compatibility

for backwards compatibility with GRASS 6, if you give no options at all, it manufactures file=- for you (which reads from stdin), so you can keep doing stuff like:

r3.mapcalc < file

or:

r3.mapcalc <<EOF
foo = 1
EOF

but โ€” and I mean this lovingly โ€” unless you actually need compatibility with previous GRASS GIS versions, just use file= explicitly, like we said above. ๐Ÿ’…

Also: when the map name contains uppercase letter(s) or a dot, which aren't allowed in module option names, the r3.mapcalc command is still valid without quotes:

r3.mapcalc volume_A=1
r3.mapcalc volume.1=1

However, this syntax is not recommended โ€” quotes, as stated above, are more safe. Using quotes is both backwards compatible and valid in the future. so like, just use quotes? ๐Ÿซถ


โŒจ๏ธ Interactive input in command line

for formulas the user enters from standard input (not from the command line), there's a line continuation feature now. If you slap a backslash at the end of an input line, r3.mapcalc assumes the formula keeps going on the next input line. There is no limit to the possible number of input lines, or to the length of a formula. iconic. ๐Ÿ‘‘

If the r3.mapcalc formula you entered is very long, the map title will contain only some of it โ€” but most (if not all) of the formula will be placed into the history file for the result map. so it's not lost, bestie, it's just shy. ๐ŸŽ€

โš ๏ธ When the user enters input to r3.mapcalc non-interactively on the command line, the program will not warn you about overwriting existing map layers. So you gotta take care to assign program outputs raster map names that don't already exist in your current mapsets. be careful out there. ๐Ÿ˜ญ

๐ŸŽญ 3D GRID MASK handling

r3.mapcalc follows the common GRASS behavior of raster MASK handling, so the MASK is only applied when reading an existing GRASS raster map. This implies that, for example, the command:

r3.mapcalc "volume_amplified = volume * 3"

creates a map that respects the masked pixels if MASK is active. slay. โœจ

However, when creating a map which is not based on any map โ€” like a map from a constant:

r3.mapcalc "volume_const = 200.0"

the created raster map is limited only by a computation region but it is not affected by an active MASK. This is expected, because (as we just said) MASK is only applied when reading, not when writing a raster map.

If in this case you do want the MASK applied, use an if() statement that includes the MASK, e.g.:

r3.mapcalc "volume_const = if(MASK, 200.0, null())"

When testing MASK related expressions, keep in mind that when MASK is active you don't see data in masked areas even if they are not NULL. See r.mask for details. ๐Ÿฆ‹


๐ŸŽฒ Random number generator initialization

The pseudo-random number generator used by the rand() function can be initialised to a specific value using the seed option. This can be used to replicate a previous calculation. ๐Ÿ”

Alternatively, it can be initialised from the system time and the PID using the -r flag. This should result in a different seed being used each time. ๐ŸŽฐ

In either case, the seed will be written to the map's history, and can be seen using r.info.

If you want other people to be able to verify your results, it's preferable to use the seed option to supply a seed which is either specified in the script or generated from a deterministic process such as a pseudo-random number generator given an explicit seed.

๐Ÿ’€ Note that the rand() function will generate a fatal error if neither the seed option nor the -s flag are given. not a vibe. so don't forget it.

๐ŸŒˆ EXAMPLES ๐ŸŒˆ

To compute the average of two 3D grids a and b:

ave = (a + b)/2

To form a weighted average:

ave = (5*a + 3*b)/8.0

To produce a binary representation of the 3D grid a so that category 0 remains 0 and all other categories become 1:

mask = a != 0

This could also be accomplished by:

mask = if(a)

To mask 3D grid b by 3D grid a:

result = if(a,b)

To change all values below 5 to NULL, keep value otherwise:

newmap = if(map < 5, null(), map)

The graph() function allows users to specify a x-y conversion using pairs of x,y coordinates. In some situations a transformation from one value to another is not easily established mathematically, but can be represented by a 2-D graph and then linearly interpolated. The graph() function provides the opportunity to accomplish this. An x-axis value is provided to the graph function along with the associated graph represented by a series of x,y pairs. The x values must be monotonically increasing (each larger than or equal to the previous). The graph function linearly interpolates between pairs. Any x value lower the lowest x value (i.e. first) will have the associated y value returned. Any x value higher than the last will similarly have the associated y value returned. Consider the request:

newmap = graph(map, 1,10, 2,25, 3,50)

X (map) values supplied and y (newmap) values returned:

  • 0, 10
  • 1, 10
  • 1.5, 17.5
  • 2.9, 47.5
  • 4, 50
  • 100, 50

๐Ÿ’€ KNOWN ISSUES ๐Ÿ’€

  • The result variable on the left hand side of the equation should not appear in the expression on the right hand side.
mymap = if( mymap > 0, mymap, 0)
  • Any maps generated by a r3.mapcalc command only exist after the entire command has completed. All maps are generated concurrently, row-by-row (i.e. there is an implicit "for row in rows {...}" around the entire expression). Thus the #, @, and [ ] operators cannot be used on a map generated within same r3.mapcalc command run.
newmap = oldmap * 3.14
othermap = newmap[-1, 0] / newmap[1, 0]
  • Continuation lines must end with a \ and have no trailing white space (blanks or tabs). If the user does leave white space at the end of continuation lines, the error messages produced by r3.mapcalc will be meaningless and the equation will not work as the user intended. This is particularly important for the eval() function. ๐Ÿ™ˆ
  • Currently, there is no comment mechanism in r3.mapcalc. Perhaps adding a capability that would cause the entire line to be ignored when the user inserted a # at the start of a line as if it were not present, would do the trick.
  • The function should require the user to type "end" or "exit" instead of simply a blank line. This would make separation of multiple scripts separable by white space.
  • r3.mapcalc does not print a warning in case of operations on NULL cells. It is left to the user to utilize the isnull() function.

๐Ÿ“š REFERENCES ๐Ÿ“š

  • r.mapcalc: An Algebra for GIS and Image Processing, by Michael Shapiro and Jim Westervelt, U.S. Army Construction Engineering Research Laboratory (March/1991).
  • Performing Map Calculations on GRASS Data: r.mapcalc Program Tutorial, by Marji Larson, Michael Shapiro and Scott Tweddale, U.S. Army Construction Engineering Research Laboratory (December 1991)
  • Neteler, M. (2001): Volume modelling of soils using GRASS GIS 3D tools. - in: Brovelli, M. (ed.)(2001): The Geomatics Workbook N. 2. Politecnico di Milano, Italy (ISSN 1591-092X) (PDF)

๐Ÿ‘€ SEE ALSO ๐Ÿ‘€

  • g.region
  • r3.colors
  • r.mapcalc

๐Ÿ’– AUTHORS ๐Ÿ’–

  • Tomas Paudits & Jaro Hofierka, funded by GeoModel s.r.o., Slovakia tpaudits@mailbox.sk, hofierka@geomodel.sk
  • Glynn Clements

๐Ÿ”— SOURCE CODE ๐Ÿ”—

Available at: r3.mapcalc source code (history)

Accessed: Saturday Jan 17 05:40:51 2026

Main index | 3D raster index | Topics index | Keywords index | Graphical index | Full index

ยฉ 2003-2025 GRASS Development Team, GRASS GIS 8.4.2 Reference Manual


and that's a wrap, bestie!! ๐ŸŽ€ this whole thing lives in the <b>GRASS 8.4.2</b> reference manual, it's the <b>r3.mapcalc(1)</b> page, and it got accessed on <b>Saturday Jan 17 05:40:51 2026</b>. go make some 3D grids, you absolute legend. ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from