License Information

Use of this function requires a license for Whitebox Workflows for Python Professional (WbW-Pro). Please visit www.whiteboxgeo.com to purchase a license.

Description

The ModifyLidar tool can be used to alter the properties of points within a LiDAR point cloud. The user provides a statement (statement) containing one or more expressions, separated by semicolons (;). The expressions are evaluated for each point within the input LiDAR file (input). Expressions assign altered values to the properties of points in the output file (output), based on any mathematically defined expression that may include the various properties of individual points (e.g. coordinates, intensity, return attributes, etc) or some file-level properties (e.g. min/max coordinates). As a basic example, the following statement:

x = x + 1000.0 could be used to translate the point cloud 1000 x-units (note, the increment operator could be used as a simpler equivalent, x += 1000.0).

Note that if the user does not specify the optional input LiDAR file, the tool will search for all valid LiDAR (.las, .laz, *.zlidar) files contained within the current working directory. This feature can be useful for processing a large number of LiDAR files in batch mode. When this batch mode is applied, the output file names will be the same as the input file names but with a '_modified' suffix added to the end.

Expressions may contain any of the following point-level or file-level variables:

Variable NameDescriptionType
**Point-level properties**
xThe point x coordinatefloat
yThe point y coordinatefloat
zThe point z coordinatefloat
xyAn x-y coordinate tuple, (x, y)(float, float)
xyzAn x-y-z coordinate tuple, (x, y, z)(float, float, float)
intensityThe point intensity valueint
retThe point return numberint
nretThe point number of returnsint
is_onlyTrue if the point is an only return (i.e. ret == nret == 1), otherwise falseBoolean
is_multipleTrue if the point is a multiple return (i.e. nret > 1), otherwise falseBoolean
is_earlyTrue if the point is an early return (i.e. ret == 1), otherwise falseBoolean
is_intermediateTrue if the point is an intermediate return (i.e. ret > 1 && ret < nret), otherwise falseBoolean
is_lateTrue if the point is a late return (i.e. ret == nret), otherwise falseBoolean
is_firstTrue if the point is a first return (i.e. ret == 1 && nret > 1), otherwise falseBoolean
is_lastTrue if the point is a last return (i.e. ret == nret && nret > 1), otherwise falseBoolean
classThe class value in numeric form, e.g. 0 = Never classified, 1 = Unclassified, 2 = Ground, etc.int
is_noiseTrue if the point is classified noise (i.e. class == 7class == 18), otherwise falseBoolean
is_syntheticTrue if the point is synthetic, otherwise falseBoolean
is_keypointTrue if the point is a keypoint, otherwise falseBoolean
is_withheldTrue if the point is withheld, otherwise falseBoolean
is_overlapTrue if the point is an overlap point, otherwise falseBoolean
scan_angleThe point scan angleint
scan_directionTrue if the scanner is moving from the left towards the right, otherwise falseBoolean
is_flightline_edgeTrue if the point is situated along the filightline edge, otherwise falseBoolean
user_dataThe point user dataint
point_source_idThe point source IDint
scanner_channelThe point scanner channelint
timeThe point GPS time, if it exists, otherwise 0float
rgbA red-green-blue tuple (r, g, b) if it exists, otherwise (0,0,0)(int, int, int)
nirThe point near infrared value, if it exists, otherwise 0int
pt_numThe point number within the input fileint
**File-level properties (invariant)**
n_ptsThe number of points within the fileint
min_xThe file minimum x valuefloat
mid_xThe file mid-point x valuefloat
max_xThe file maximum x valuefloat
min_yThe file minimum y valuefloat
mid_yThe file mid-point y valuefloat
max_yThe file maximum y valuefloat
min_zThe file minimum z valuefloat
mid_zThe file mid-point z valuefloat
max_zThe file maximum z valuefloat
x_scale_factorThe file x scale factorfloat
y_scale_factorThe file y scale factorfloat
z_scale_factorThe file z scale factorfloat
x_offsetThe file x offsetfloat
y_offsetThe file y offsetfloat
z_offsetThe file z offsetfloat

Most of the point-level properties above are modifiable, however some are not. The complete list of modifiable point attributes include, x, y, z, xy, xyz, intensity, ret, nret, class, user_data, point_source_id, scanner_channel, scan_angle, time, rgb, nir, is_synthetic, is_keypoint, is_withheld, and is_overlap. The immutable properties include is_only, is_multiple, is_early, is_intermediate, is_late, is_first, is_last, is_noise, and pt_num. Of the file-level properties, the modifiable properties include the x_scale_factor, y_scale_factor, z_scale_factor, x_offset, y_offset, and z_offset.

In addition to the point properties defined above, if the user applies the lidar_eigenvalue_features tool on the input LiDAR file, the modify_lidar tool will automatically read in the additional *.eigen file, which include the eigenvalue-based point neighbourhood measures, such as lambda1, lambda2, lambda3, linearity, planarity, sphericity, omnivariance, eigentropy, slope, and residual. See the lidar_eigenvalue_features documentation for details on each of these metrics describing the structure and distribution of points within the neighbourhood surrounding each point in the LiDAR file.

Expressions may use any of the standard mathematical operators, +, -, *, /, % (modulo), ^ (exponentiation), comparison operators, <, >, <=, >=, == (equality), != (inequality), and logical operators, && (Boolean AND),

to must be a modifiable point-level property (see table above). That is, expressions should take the form
(Boolean OR). Expressions must evaluate to an assignment operation, where the variable that is assigned

pt_variable = .... Other assignment operators are also possible (at least for numeric non-tuple properties), such as the increment (=+) operator (e.g. x += 1000.0) and the decrement (-=) operator (e.g. y -= 1000.0). Expressions may use a number of built-in mathematical functions, including:

Function NameDescriptionExample
ifPerforms an if(CONDITION, TRUE, FALSE) operation, return either the value of TRUE or FALSE depending on CONDITION`ret = if(ret==0, 1, ret)`
absReturns the absolute value of the argument`value = abs(x - mid_x)`
minReturns the minimum of the arguments`value = min(x, y, z)`
maxReturns the maximum of the arguments`value = max(x, y, z)`
floorReturns the largest integer less than or equal to a number`x = floor(x)`
roundReturns the nearest integer to a number. Rounds half-way cases away from 0.0`x = round(x)`
ceilReturns the smallest integer greater than or equal to a number`x = ceil(x)`
clampForces a value to fall within a specified range, defined by a minimum and maximum`z = clamp(min_z+10.0, z, max_z-20.0)`
intReturns the integer equivalent of a number`intensity = int(z)`
floatReturns the float equivalent of a number`z = float(intensity)`
to_radiansConverts a number in degrees to radians`val = to_radians(scan_angle)`
to_degreesConverts a number in radians to degrees`scan_angle = int(to_degrees(val))`
distReturns the distance between two points defined by two n-length tuples`d = dist(xy, (mid_x, mid_y))` or `d = dist(xyz, (mid_x, mid_y, mid_z))`
rotate_ptRotates an x-y point by a certain angle, in degrees`xy = rotate_pt(xy, 45.0)` or `orig_pt = (1000.0, 1000.0); xy = rotate_pt(xy, 45.0, orig_pt)`
math::lnReturns the natural logarithm of the number`z = math::ln(z)`
math::logReturns the logarithm of the number with respect to an arbitrary base`z = math::log(z, 10)`
math::log2Returns the base 2 logarithm of the number`z = math::log2(z)`
math::log10Returns the base 10 logarithm of the number`z = math::log10(z)`
math::expReturns e^(number), (the exponential function)`z = math::exp(z)`
math::powRaises a number to the power of the other number`z = math::pow(z, 2.0)`
math::sqrtReturns the square root of a number. Returns NaN for a negative number`z = math::sqrt(z, 2.0)`
math::cosComputes the cosine of a number (in radians)`z = math::cos(to_radians(z))`
math::sinComputes the sine of a number (in radians)`z = math::sin(to_radians(z))`
math::tanComputes the tangent of a number (in radians)`z = math::tan(to_radians(z))`
math::acosComputes the arccosine of a number. The return value is in radians in the range [0, pi] or NaN if the number is outside the range [-1, 1]`z = math::acos(z)`
math::asinComputes the arcsine of a number. The return value is in radians in the range [0, pi] or NaN if the number is outside the range [-1, 1]`z = math::asin(z)`
math::atanComputes the arctangent of a number. The return value is in radians in the range [0, pi] or NaN if the number is outside the range [-1, 1]`z = math::atan(z)`
randReturns a random value between 0 and 1, with an optional seed value`rgb = (int(255.0 * rand()), int(255.0 * rand()), int(255.0 * rand()))`
helmert_transformationPerforms a Helmert transformation on a point using a 7-parameter transform`xyz = helmert_transformation(xyz, −446.448, 125.157, −542.06, 20.4894, −0.1502, −0.247, −0.8421 )`

The hyperbolic trigonometric functions are also available for use in expression building, as is math::atan2 and the mathematical constants pi and e.

You may use if operations within statements to implement a conditional modification of point properties. For example, the following expression demonstrates how you could modify a point's RGB colour based on its classification, assign ground points (class 2) in the output file a green colour:

rgb = if(class==2, (0,255,0), rgb) To colour all points within 50 m of the tile mid-point red and all other points blue:

rgb = if(dist(xy, (mid_x, mid_y))<50.0, (255,0,0), (0,0,255)) if operations may also be nested to create more complex compound conditional point modification. For example, in the following statement, we assign first-return points red (255,0,0) and last-return points green (0,255,0) colours and white (255,255,255) to all other points (intermediate-returns and only-returns):

rgb = if(is_first, (255,0,0), if(is_last, (0,255,0), (255,255,255))) Here we use an if expression to re-classify points above an elevation of 1000.0 as high noise (class 18):

class = if(z>1000.0, 18, class) Expressions may be strung together within statements using semicolons (;), with each expression being evaluated individually. When this is the case, at least one of the expressions must assign a value to one of the variant point properties (see table above). The following statement demonstrates multi-expression statements, in this case to swap the x and y coordinates in a LiDAR file:

new_var = x; x = y; y = new_var The rand function, used with the seeding option, can be useful when assigning colours to points based on common point properties. For example, to assign a point a random RGB colour based on its point_source_id (Note, for many point clouds, this operation will assign each flightline a unique colour; if flightline information is not stored in the file's point_source_id attribute, one could use the recover_flightline_info tool to calculate this data.):

rgb=(int(255 * rand(point_source_id)), int(255 * rand(point_source_id+1)), int(255 * rand(point_source_id+2))) This expression-based approach to modifying point properties provides a great deal of flexibility and power to the processing of LiDAR point cloud data sets.

See Also

filter_lidar, sort_lidar, lidar_eigenvalue_features

Project Links

WbW Homepage User Manual Support WbW