(if the else) + (if then else)
. Since even the test clause of an if-then-else is an expression, you can also replace that with another if-then-else. Example: if (if i1 > 0 then 1 else i2) then i2 else 1 + i3
i1 + null
will always be null since something +
null is always null.isNull( expression )
or expression1 ? expression2
:isNull( expression )
evaluates the expression and results 1 if the expression
evaluates to null, and 0 otherwise.expression1 ? expression2
evaluates the expression1
and, if the result is non-null, returns that value. Otherwise, it evaluates expression2
and returns the resulting value as its own result.(if (i1/3 > 9) then i2 else 1 + i3) + 10
:i1
is null, i1/3
is also null, and i1/3 > 9
also becomes null. Therefore, the if-then-else test is null and the entire if-then-else is null. ( (if (i1/3 > 9) then i2 else 1 + i3) + 10 ) ? 20
– Note that we are using the operator ?
now:i1
is null, i1/3
is also null, and i1/3 > 9
also becomes null. Therefore, the if-then-else test is null and the entire if-then-else is null. null ? 20
, since the if then else + 10
is null, and the result is 20.
The null evaluation mechanism allows us to write short expressions like i1 + 10
to add 10 to every valid cell of the i1
map, or i1 * i2
to multiply two maps. If one of the map cells is null, the result is null, so in the last example, we are basically just multiplying the corresponding cells where the two values are valid: everything else will be null.
If we want to treat all null values as values 1s, in the previous expression, we can write (i1 ? 1) * (i2 ? 1)
. We can also use the more complicated form using the if-then-else to achieve the same result such as (if isNull(i1) then 1 else i1) * (if isNull(i2) then 1 else i2)
, or even
if isNull(i1) and isNull(i2) then 1 else if not isNull(i1) and not isNull(i2) then i1*i2 else if not isNull(i1) and isNull(i2) then i1 else i2
If you need to retrieve the number corresponding to an image null value, you can use the null( iX )
expression. For instance, null(i1)
returns the number corresponding to the null value of image i1
. So if, so some reason, you need to retrieve the image value or its corresponding numeric null value, you can use i1 ? null(i1)
or if isnull(i1) then null(i1) then i1
. Note that null(i1)
is very different from expression null
, since null(i1)
always returns a valid numeric value and null
returns a special construct that, if not contained, invalidates the expression evaluation producing null as a result.
Lets assume that we want to replace all occurrences of a given valid value in a image with some other valid valid: if i1 = 2 then 10 else i1
. Since we are not explicitly guarding the if-then-else test against null, the expression is internally equivalent to if isNull(i1) then null else if i1 = 2 then 10 else i1
. So, simply using the most compact if-then-else definition works as expected.
Now, lets assume the we want do combine two images, a landscape map and road map, as a single map, where roads in the road map are represent by the value 1 and everything else is represented using the null value. Assuming the i1
is the landscape map and i2
is the road map, we might be tempted to write an expression as if i2 = 1 then 1 else i1
. Unfortunately that is not going to work, since the expression is internally equivalent to if isNull(i2) then null else if i2 = 1 then 1 else i1
(we not guarding against null values). As you can see, all occurrences of null values on the road map will be replicated in the output map.
So, the proper way of doing the calculation is using a isNull( iX )
to protect the if-then-else test against the null: if not isNull(i2) and i2 = 1 then 1 else i2
. Now we only test for the value in the road map if we are sure that value is not going to contaminate the whole if-then-else, turning the result into null.