Skip to content

Commit b569c75

Browse files
committed
Fixes for #107 and #109
1 parent e78e919 commit b569c75

17 files changed

+398
-81
lines changed

.DS_Store

0 Bytes
Binary file not shown.

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
[package]
33
name = "whitebox_tools"
4-
version = "1.3.1"
4+
version = "1.4.0"
55
authors = ["John Lindsay <jlindsay@uoguelph.ca>"]
66
description = "A library for analyzing geospatial data."
77
keywords = ["geospatial", "GIS", "remote sensing", "geomatics", "image processing", "lidar", "spatial analysis"]

readme.txt

+6-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ for more details.
5656
* Release Notes: *
5757
******************
5858

59-
Version 1.4.0 (03-09-2020)
59+
Version 1.4.0 (04-09-2020)
6060
- Added the TimeInDaylight model tool for modelling the proportion of daytime that a location is not in shadow.
6161
- Added the MapOffTerrainObjects tool.
6262
- Added the FilterRasterFeaturesByArea tool.
@@ -68,6 +68,11 @@ Version 1.4.0 (03-09-2020)
6868
- The Resample tool has been modified so that it does not require a 'destination' raster. Instead,
6969
it will create a new output raster either based on a user-specified target cell resolution or
7070
an optional base raster, much like the vector-to-raster conversion tools.
71+
- Tools that input a z_factor conversion no longer override user input with geographic coordinates
72+
(see issue #113).
73+
- The StreamLinkIdentifier tool now outputs a 32-bit integer format, increasing the maximum allowable
74+
number of streams (see issue #110).
75+
- Fixed a bug with cubic-convolution and bilinear resampling in the Mosaic tool (see issue #109).
7176

7277
Version 1.3.1 (23-07-2020)
7378
- Added the HypsometricallyTintedHillshade tool to create hypsometric tinted hillshades.

src/tools/image_analysis/mosaic.rs

+15-23
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
This tool is part of the WhiteboxTools geospatial analysis library.
33
Authors: Dr. John Lindsay
44
Created: 02/01/2018
5-
Last Modified: 02/01/2018
5+
Last Modified: 03/09/2020
66
License: MIT
77
*/
88

@@ -535,22 +535,20 @@ impl WhiteboxTool for Mosaic {
535535
let ret = tree
536536
.locate_all_at_point(&[x[col as usize], y[row as usize]])
537537
.collect::<Vec<_>>();
538+
539+
let mut flag = true;
538540
for a in 0..ret.len() {
539541
i = ret[a].data;
540-
// row_src = inputs[i].get_row_from_y(y[row as usize]);
541-
// col_src = inputs[i].get_column_from_x(x[col as usize]);
542+
if !flag {
543+
break;
544+
}
545+
542546
row_src = (inputs[i].configs.north - y[row as usize])
543547
/ inputs[i].configs.resolution_y;
544548
col_src = (x[col as usize] - inputs[i].configs.west)
545549
/ inputs[i].configs.resolution_x;
546-
547550
origin_row = row_src.floor() as isize;
548551
origin_col = col_src.floor() as isize;
549-
550-
// z = inputs[i].get_value(origin_row, origin_col);
551-
552-
// if origin_row < 0 || origin_col < 0 { break; }
553-
// if origin_row > inputs[i].configs.rows as isize || origin_col > inputs[i].configs.columns as isize { break; }
554552
sum_dist = 0f64;
555553
for n in 0..num_neighbours {
556554
row_n = origin_row + shift_y[n];
@@ -566,8 +564,7 @@ impl WhiteboxTool for Mosaic {
566564
neighbour[n][1] = 0f64;
567565
} else {
568566
data[col as usize] = neighbour[n][0];
569-
// flag = false;
570-
break;
567+
flag = false;
571568
}
572569
}
573570

@@ -577,9 +574,7 @@ impl WhiteboxTool for Mosaic {
577574
z += (neighbour[n][0] * neighbour[n][1]) / sum_dist;
578575
}
579576
data[col as usize] = z;
580-
581-
// flag = false;
582-
break;
577+
flag = false;
583578
}
584579
}
585580
}
@@ -633,19 +628,18 @@ impl WhiteboxTool for Mosaic {
633628
let ret = tree
634629
.locate_all_at_point(&[x[col as usize], y[row as usize]])
635630
.collect::<Vec<_>>();
631+
let mut flag = true;
636632
for a in 0..ret.len() {
637633
i = ret[a].data;
638-
// if !flag {
639-
// break;
640-
// }
634+
if !flag {
635+
break;
636+
}
641637
row_src = (inputs[i].configs.north - y[row as usize])
642638
/ inputs[i].configs.resolution_y;
643639
col_src = (x[col as usize] - inputs[i].configs.west)
644640
/ inputs[i].configs.resolution_x;
645641
origin_row = row_src.floor() as isize;
646642
origin_col = col_src.floor() as isize;
647-
// if origin_row < 0 || origin_col < 0 { break; }
648-
// if origin_row > inputs[i].configs.rows as isize || origin_col > inputs[i].configs.columns as isize { break; }
649643
sum_dist = 0f64;
650644
for n in 0..num_neighbours {
651645
row_n = origin_row + shift_y[n];
@@ -661,8 +655,7 @@ impl WhiteboxTool for Mosaic {
661655
neighbour[n][1] = 0f64;
662656
} else {
663657
data[col as usize] = neighbour[n][0];
664-
break;
665-
// flag = false;
658+
flag = false;
666659
}
667660
}
668661

@@ -672,8 +665,7 @@ impl WhiteboxTool for Mosaic {
672665
z += (neighbour[n][0] * neighbour[n][1]) / sum_dist;
673666
}
674667
data[col as usize] = z;
675-
break;
676-
// flag = false;
668+
flag = false;
677669
}
678670
}
679671
}

src/tools/lidar_analysis/lidar_dsm.rs

+52
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,58 @@ use std::sync::Arc;
2121
use std::{env, f64, fs, path, thread};
2222
// use rayon::prelude::*;
2323

24+
/// This tool creates a digital surface model (DSM) from a LiDAR point cloud. A DSM reflects the elevation of the tops
25+
/// of all off-terrain objects (i.e. non-ground features) contained within the data set. For example, a DSM will model
26+
/// the canopy top as well as building roofs. This is in stark contrast to a bare-earth digital elevation model (DEM),
27+
/// which models the ground surface without off-terrain objects present. Bare-earth DEMs can be derived from LiDAR data
28+
/// by interpolating last-return points using one of the other LiDAR interpolators (e.g. `LidarTINGridding`). The algorithm
29+
/// used for interpolation in this tool is based on gridding a triangulation (TIN) fit to top-level points in the
30+
/// input LiDAR point cloud. All points in the input LiDAR data set that are below other neighbouring points, within
31+
/// a specified search radius (`--radius`), and that have a large inter-point slope, are filtered out. Thus, this tool
32+
/// will remove the ground surface beneath as well as any intermediate points within a forest canopy, leaving only the
33+
/// canopy top surface to be interpolated. Similarly, building wall points and any ground points beneath roof overhangs
34+
/// will also be remove prior to interpolation. Note that because the ground points beneath overhead wires and utility
35+
/// lines are filtered out by this operation, these features tend to be appear as 'walls' in the output DSM. If these
36+
/// points are classified in the input LiDAR file, you may wish to filter them out before using this tool (`FilterLidarClasses`).
37+
///
38+
/// The following images show the differences between creating a DSM using the `LidarDigitalSurfaceModel`
39+
/// and by interpolating first-return points only using the `LidarTINGridding` tool respectively. Note, the images show
40+
/// `TimeInDaylight`, which is a more effective way of hillshading DSMs than the traditional `Hillshade` method. Compare
41+
/// how the DSM created `LidarDigitalSurfaceModel` tool (above) has far less variability in areas of tree-cover, more
42+
/// effectively capturing the canopy top. As well, notice how building rooftops are more extensive and straighter in
43+
/// the `LidarDigitalSurfaceModel` DSM image. This is because this method eliminates ground returns beneath roof overhangs
44+
/// before the triangulation operation.
45+
///
46+
/// ![](../../doc_img/DSM.png)
47+
///
48+
/// ![](../../doc_img/FirstReturnTIN.png)
49+
///
50+
/// The user must specify the grid resolution of the output raster (`--resolution`), and optionally, the name of the
51+
/// input LiDAR file (`--input`) and output raster (`--output`). Note that if an input LiDAR file (`--input`) is not
52+
/// specified by the user, the tool will search for all valid LiDAR (*.las, *.zlidar) contained within the current
53+
/// working directory. This feature can be very useful when you need to interpolate a DSM for a large number of LiDAR
54+
/// files. Not only does this batch processing mode enable the tool to run in a more optimized parallel manner, but it
55+
/// will also allow the tool to include a small buffer of points extending into adjacent tiles when interpolating an
56+
/// individual file. This can significantly reduce edge-effects when the output tiles are later mosaicked together.
57+
/// When run in this batch mode, the output file (`--output`) also need not be specified; the tool will instead create
58+
/// an output file with the same name as each input LiDAR file, but with the .tif extension. This can provide a very
59+
/// efficient means for processing extremely large LiDAR data sets.
60+
///
61+
/// Users may also exclude points from the interpolation if they fall below or above the minimum (`--minz`) or
62+
/// maximum (`--maxz`) thresholds respectively. This can be a useful means of excluding anomalously high or low
63+
/// points. Note that points that are classified as low points (LAS class 7) or high noise (LAS class 18) are
64+
/// automatically excluded from the interpolation operation.
65+
///
66+
/// Triangulation will generally completely fill the convex hull containing the input point data. This can sometimes
67+
/// result in very long and narrow triangles at the edges of the data or connecting vertices on either side of void
68+
/// areas. In LiDAR data, these void areas are often associated with larger waterbodies, and triangulation can result
69+
/// in very unnatural interpolated patterns within these areas. To avoid this problem, the user may specify a the
70+
/// maximum allowable triangle edge length (`max_triangle_edge_length`) and all grid cells within triangular facets
71+
/// with edges larger than this threshold are simply assigned the NoData values in the output DSM. These NoData areas
72+
/// can later be better dealt with using the `FillMissingData` tool after interpolation.
73+
///
74+
/// # See Also
75+
/// `LidarTINGridding`, `FilterLidarClasses`, `FillMissingData`, `TimeInDaylight`
2476
pub struct LidarDigitalSurfaceModel {
2577
name: String,
2678
description: String,

src/tools/lidar_analysis/lidar_idw_interpolation.rs

+34
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,40 @@ use std::sync::mpsc;
2525
use std::sync::{Arc, Mutex};
2626
use std::thread;
2727

28+
/// This tool interpolates LiDAR files using [inverse-distance weighting](https://en.wikipedia.org/wiki/Inverse_distance_weighting)
29+
/// (IDW) scheme. The user must specify the value of the IDW weight parameter (`--weight`). The output grid can be
30+
/// based on any of the stored LiDAR point parameters (`--parameter`), including elevation
31+
/// (in which case the output grid is a digital elevation model, DEM), intensity, class, return number, number of
32+
/// returns, scan angle, RGB (colour) values, and user data values. Similarly, the user may specify which point
33+
/// return values (`--returns`) to include in the interpolation, including all points, last returns (including single
34+
/// return points), and first returns (including single return points).
35+
///
36+
/// The user must specify the grid resolution of the output raster (`--resolution`), and optionally, the name of the
37+
/// input LiDAR file (`--input`) and output raster (`--output`). Note that if an input LiDAR file (`--input`) is not
38+
/// specified by the user, the tool will search for all valid LiDAR (*.las, *.zlidar) contained within the current
39+
/// working directory. This feature can be very useful when you need to interpolate a DEM for a large number of LiDAR
40+
/// files. Not only does this batch processing mode enable the tool to run in a more optimized parallel manner, but it
41+
/// will also allow the tool to include a small buffer of points extending into adjacent tiles when interpolating an
42+
/// individual file. This can significantly reduce edge-effects when the output tiles are later mosaicked together.
43+
/// When run in this batch mode, the output file (`--output`) also need not be specified; the tool will instead create
44+
/// an output file with the same name as each input LiDAR file, but with the .tif extension. This can provide a very
45+
/// efficient means for processing extremely large LiDAR data sets.
46+
///
47+
/// Users may excluded points from the interpolation based on point classification values, which follow the LAS
48+
/// classification scheme. Excluded classes are specified using the `--exclude_cls` parameter. For example,
49+
/// to exclude all vegetation and building classified points from the interpolation, use --exclude_cls='3,4,5,6'.
50+
/// Users may also exclude points from the interpolation if they fall below or above the minimum (`--minz`) or
51+
/// maximum (`--maxz`) thresholds respectively. This can be a useful means of excluding anomalously high or low
52+
/// points. Note that points that are classified as low points (LAS class 7) or high noise (LAS class 18) are
53+
/// automatically excluded from the interpolation operation.
54+
///
55+
/// The tool will search for the nearest input LiDAR point to each grid cell centre, up to a maximum search distance
56+
/// (`--radius`). If a grid cell does not have a LiDAR point within this search distance, it will be assigned the
57+
/// NoData value in the output raster. In LiDAR data, these void areas are often associated with larger waterbodies.
58+
/// These NoData areas can later be better dealt with using the `FillMissingData` tool after interpolation.
59+
///
60+
/// # See Also
61+
/// `LidarTINGridding`, `LidarNearestNeighbourGridding`, `LidarTINGridding`
2862
pub struct LidarIdwInterpolation {
2963
name: String,
3064
description: String,

0 commit comments

Comments
 (0)