## 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 FilterLidar tool is a very powerful tool for filtering points within a LiDAR point cloud based on point properties. Complex filter statements (`statement`) can be used to include or exclude points in the output file (`output`).

Note that if the user does not specify the optional input LiDAR file (`input`), 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 '_filtered' suffix added to the end.

Points are either included or excluded from the output file by creating conditional filter statements. Statements must be valid Rust syntax and evaluate to a Boolean. Any of the following variables are acceptable within the filter statement:

| Variable Name | Description
x | The point x coordinate
y | The point y coordinate
z | The point z coordinate
intensity | The point intensity value
ret | The point return number
nret | The point number of returns
is_only | True if the point is an only return (i.e. ret == nret == 1), otherwise false
is_multiple | True if the point is a multiple return (i.e. nret > 1), otherwise false
is_early | True if the point is an early return (i.e. ret == 1), otherwise false
is_intermediate | True if the point is an intermediate return (i.e. ret > 1 && ret < nret), otherwise false
is_late | True if the point is a late return (i.e. ret == nret), otherwise false
is_first | True if the point is a first return (i.e. ret == 1 && nret > 1), otherwise false
is_last | True if the point is a last return (i.e. ret == nret && nret > 1), otherwise false
class | The class value in numeric form, e.g. 0 = Never classified, 1 = Unclassified, 2 = Ground, etc.
is_noise | True if the point is classified noise (i.e. class == 7 | class == 18), otherwise false
is_synthetic | True if the point is synthetic, otherwise false
is_keypoint | True if the point is a keypoint, otherwise false
is_withheld | True if the point is withheld, otherwise false
is_overlap | True if the point is an overlap point, otherwise false
scan_angle | The point scan angle
scan_direction | True if the scanner is moving from the left towards the right, otherwise false
is_flightline_edge | True if the point is situated along the filightline edge, otherwise false
user_data | The point user data
point_source_id | The point source ID
scanner_channel | The point scanner channel
time | The point GPS time, if it exists, otherwise 0
red | The point red value, if it exists, otherwise 0
green | The point green value, if it exists, otherwise 0
blue | The point blue value, if it exists, otherwise 0
nir | The point near infrared value, if it exists, otherwise 0
pt_num | The point number within the input file
n_pts | The number of points within the file
min_x | The file minimum x value
mid_x | The file mid-point x value
max_x | The file maximum x value
min_y | The file minimum y value
mid_y | The file mid-point y value
max_y | The file maximum y value
min_z | The file minimum z value
mid_z | The file mid-point z value
max_z | The file maximum z value
dist_to_pt | The distance from the point to a specified xy or xyz point, e.g. dist_to_pt(562500, 4819500) or dist_to_pt(562500, 4819500, 320)
dist_to_line | The distance from the point to the line passing through two xy points, e.g. dist_to_line(562600, 4819500, 562750, 4819750)
dist_to_line_seg | The distance from the point to the line segment defined by two xy end-points, e.g. dist_to_line_seg(562600, 4819500, 562750, 4819750)
within_rect | 1 if the point falls within the bounds of a 2D or 3D rectangle, otherwise 0. Bounds are defined as within_rect(ULX, ULY, LRX, LRY) or within_rect(ULX, ULY, ULZ, LRX, LRY, LRZ)

In addition to the point properties defined above, if the user applies the lidar_eigenvalue_features tool on the input LiDAR file, the filter_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.

Statements can be as simple or complex as desired. For example, to filter out all points that are classified noise (i.e. class numbers 7 or 18):

`!is_noise` The following is a statement to retain only the late returns from the input file (i.e. both last and single returns):

`ret == nret` Notice that equality uses the `==` symbol an inequality uses the `!=` symbol. As an equivalent to the above statement, we could have used the `is_late` point property:

`is_late` If we want to remove all points outside of a range of xy values:

`x >= 562000 && x <= 562500 && y >= 4819000 && y <= 4819500` Notice how we can combine multiple constraints using the `&&` (logical AND) and `||` (logical OR) operators. As an alternative to the above statement, we could have used the `within_rect` function:

`within_rect(562000, 4819500, 562500, 4819000)` If we want instead to exclude all of the points within this defined region, rather than to retain them, we simply use the `!` (logial NOT):

`!(x >= 562000 && x <= 562500 && y >= 4819000 && y <= 4819500)` or, simply:

`!within_rect(562000, 4819500, 562500, 4819000)` If we need to find all of the ground points within 150 m of (562000, 4819500), we could use:

`class == 2 && dist_to_pt(562000, 4819500) <= 150.0` The following statement outputs all non-vegetation classed points in the upper-right quadrant:

`!(class == 3 && class != 4 && class != 5) && x < min_x + (max_x - min_x) / 2.0 && y > max_y - (max_y - min_y) / 2.0` As demonstrated above, the filter_lidar tool provides an extremely flexible, powerful, and easy means for retaining and removing points from point clouds based on any of the common LiDAR point attributes.

## See Also

filter_lidar_classes, filter_lidar_scan_angles, modify_lidar, erase_polygon_from_lidar, clip_lidar_to_polygon, sort_lidar, lidar_eigenvalue_features

## Function Signature

`def filter_lidar(self, statement: str, input_lidar: Optional[Lidar]) -> Optional[Lidar]: ...`

## Project Links

WbW Homepage User Manual Support WbW