lidR
not compiled with OpenMP support (i.e. on MacOS)Fix segfault on Windows 64 bits when constructing a proj4 from some specific modern WTK strings using doCheckCRSArgs = FALSE
. #323 sp #75
Fix wrong gpstime matching in lasrangecorrection()
at the edge of flightlines #327.
Fix error when building the clusters with a partial processing and a realignment #332.
Fix error in lasclip()
and lasmergespatial()
with sf
objects when the coordinates are not stored in a column named geometry
. Thank to Michael Koontz in #335.
lasrangecorrection()
no longer mess-up the original sensor data. See #336
Enhancements made here and there to improve the support of the CRS when reading and checking a LAS file.
crs not found
message is no longer displayed when building a LAS object. This message appeared with an update of rgdal
or sp
. It is now gone.
sensor_tracking()
now throws an error for the invalid case reported in #327
lascheck()
now reports problems for invalid data reported in #327
grid_metrics()
returns a raster full of NAs instead of failing if a RasterLayer
is given as a layout but this layer does not encompase the point cloud
opt_output_file()
now applies tilde-expansion to the path.
When processing by file with an raster output, automatic chunk extension to match with a raster resolution now perform a tighter extension.
This fix breaks backward compatibility. In catalog_apply()
if automerge = TRUE
and the output contains a list
of strings the list was expected to be merged into a character vector. But actually, the raw list was returned, which was not the intended behavior. This appends with Spatial*
and sf
objects and with data.frame
. This bug should not have affected too many people.
```r opt_output_files(ctg) <- paste0(tempdir(), "/{ORIGINALFILENAME}") option <- list(automerge = TRUE) ret <- catalog_apply(ctg, sptest, .options = option) # now returns a vector print(ret)
```
When using a grid_*
function with a RasterLayer
used as layout, if the layout was not empty or full of NAs, the values of the layout were transferred to the NA cells of the output #318.
lascheck()
no longer warns about "proj4string found but no CRS in the header". This was a false positive. Overall, CRS are better checked.
opt_output_files()
now prints a message when using the ORIGINALFILENAME
template with a chunk size that is not 0 to inform users that it does not make sense.
```r opt_chunk_size(ctg) <- 800 opt_output_files(ctg) <- "{ORIGINALFILENAME}"
```
Internally when building the chunks an informative error is now thrown when using the ORIGINALFILENAME
template with a chunk size that is not 0 to inform users that it does not make sense instead of the former uninformative error, Error in eval(parse(text = text, keep.source = FALSE), envir) : objet 'ORIGINALFILENAME' not found
.
```r
```
When using a "by file" processing strategy + a buffer around each file, up to 9 files may be read. Internally the chunks (LAScluster
) are now built in such a way that the first file read is the main one (and not one of the "buffer file"). This way, if the 9 files do not have the same scales and the same offsets, the main file has precedence over the other ones when rescaling and re-offsetting on-the-fly. This reduces the risk of incompatibilities and preserves the original pattern when processing a LAScatalog.
grid_metrics()
now constructs a RasterBrick
in a better way and this reduces the risk of bugs with users' functions that sometimes return 0 length objects. The RasterBrick
will now be properly filled with NAs
.
lascheck()
now reports information if some points are flagged 'withheld', 'synthetic' or 'keypoint'.
We moved the internal logic of chunk realignment with a raster from catalog_apply()
to the internal function catalog_makecluster()
. This simplifies the source code, make it easier to maintain and test and will enable us to provide access, at the user level, to more internal functions in future releases.
We introduced a bug in v2.2.0 in the catalog processing engine. Empty chunks triggered and error i[1] is 1 which is out of range [1,nrow=0]
internally. It now works again.
Fix heap-buffer-overflow in lasrangecorrection()
when throwing an error about invalid range.
lasunormalize()
now update the header.
imager
was used to drive the mcwatershed()
algorithm. imager
is an orphaned package that generated a warning on CRAN. Consequently mcwatershed()
has been removed. In attempt to provide an informative message to users, the function still exists but generates an error. Anyway this method was weak and buggy and it was a good reason to remove it...
In version 2.2.0 we missed to put the parameter r
in point_metrics()
. It is not yet supported but will be.
catalog_apply()
the options automerge
now supports automerging of sf
and data.frame
objects.catalog_sapply()
strictly equivalent to catalog_apply()
but with the option automerge = TRUE
enforced to simplify the output whenever it is possible.In the catalog processing engine, the graphical progression map is now able to plot the actual shape of the chunks. In the case of lasclip
it means that discs and polygons are displayed instead of bounding boxes.
Multi-layers VRTs are returned as RasterBrick
instead of RasterStack
for consistency with in memory raster that are returns as RasterBrick
.
grid_
functions now try to preserve the layer names when returning a VRT built from files written on disk. This works only with file formats that support to store layer name (e.g. not GTiff
).
There are now more than 900 unit tests for a coverage of 91%.
Fix access to not mapped memory in one unit test (consequentless for users).
In lasclip()
the template XCENTER
actually gave the Y coordinate. It is now the correct X coordinate of the center of the clipped region.
In lasclip()
the template YCENTER
was not actually defined. It is now the correct Y coordinate of the center of the clipped region.
Fix heap-buffer-overflow in lasrangecorrection()
. The range was likely to be badly computed for points that have a gpstime later than the last sensor position
LAScatalog processing engine:
catalog_apply()
gains an option automerge = TRUE
. catalog_apply()
used to return a list
that had to be merged by the user. This new option allows for automatic merging. This is a fail-safe feature. In the worst case, if the user-defined function returns a non-supported list of objects that cannot be merged it falls back to the former behavior i.e. it returns a list
. Thus there is no risk associated with adding the option automerge = TRUE
but by defaut it is set to FALSE
for retrocompatibility. This might be switched to TRUE
in future releases.
opt_output_file()
now interprets *
as {ORIGINALFILENAME}
for shorter syntax. The following is now accepted:
```R opt_output_file(ctg) <- "/home/user/data/norm/_norm" # {} is valid as well
opt_output_file(ctg) <- "/home/user/data/norm/{ORIGINALFILENAME}_norm" ``` * The engine now supports "alternative directories". This is a very specific and undocumented feature useful in a single case of remote computing. More details on the wiki page.
r
ctg = readLAScatalog("~/folder/LASfiles/")
ctg@input_options$alt_dir = c("/home/Alice/data/", "/home/Bob/remote/project1/data/")
* LAScatalog modification constraints are now relaxed. It is now possible to add or modify an attribute if this attribute has a name that is not reserved.
```r ctg$newattr <- 1 # is now allowed ctg$GUID <- TRUE # is still forbidden
``
* The engine supports partial processing. It is possible to flag some files that will, or will not, be processed. These files are not removed from the LAScatalog. They are used to load a buffer, if required, for the files that are actually processed. To activate this option a new boolean attribute named
processed` can be added in the catalog.
r
ctg$processed <- TRUE
ctg$processed[3:5] <- FALSE
3D rendering:
colorPalette
of the function plot()
for LAS
objects is now set to "auto"
by default. This allows for this argument to not be specified even when plotting an attribute other than Z, and having an appropriate color palette by default. More interestingly, it will automatically apply a nice color scheme to the point cloud with the attribute 'Classification' following the ASPRS specifications. See #275.R
plot(las)
plot(las, color = "Intensity")
plot(las, color = "ReturnNumber")
plot(las, color = "Classification")
* In plot.lasmetrics3d()
the parameter trim
is now set to Inf
by default.
New function point_metrics()
- very similar to grid_metrics()
but at the point level. The 'metrics' family is now complete. cloud_metrics()
computes user-defined metrics at the point cloud level. grid_metrics()
and hexbin_metrics()
compute user-defined metrics at the pixel level. voxel_metrics
computes user-defined metrics at the voxel level. point_metrics()
computes user-defined metrics at the point level.
lasnormalize()
:
use_class
to control the points used as ground.lasnormalize()
can take forever to run (see #295)).New function sensor_tracking()
to retrieve the position of the sensor in the sky.
New function lasrangecorrection()
to normalize intensity using the sensor position (range correction)
catalog_select
now also allows files to process to be flagged interactively:
r
ctg <- catalog_select(ctg, method = "flag_processed")
ctg <- catalog_select(ctg, method = "flag_unprocessed")
grid_terrain()
use_class
to control which points are considered as ground pointsLAScatalog
it now uses the filter -keep_class
by default respecting the classes given in use_class
.LAS()
now rounds the values to 2 digits if no header is provided to fit with the default header automatically generated. This ensures that a perfectly valid LAS
object is built out of external data. This change is made by reference, meaning that the original dataset is also rounded.
r
pts <- data.frame(X = runif(10), Y = runif(10), Z = runif(10))
las <- LAS(pts) # 'las' contains rounded values but 'pts' as well to avoid data copying
lasmetrics()
is deprecated. All las*
functions return LAS
objects except lasmetrics()
. For consistency across the package lasmetrics()
becomes cloud_metrics()
.
grid_metrics3d()
and grid_hexametrics()
are deprecated. They are renamed voxel_metrics()
and hexbin_metrics()
for naming consistency.
The example dataset Topography.laz
is now larger and include attributes gpstime, PointSourceID and some classified lakes.
Internally the package used a QuadTree as spatial index in versions <= 2.1.3. Spatial index has been rewritten and changed for a grid partition which is twice as fast as the former QuadTree. This change provides a significant boost (i.e. up to two times faster) to many algorithms of the package that rely on a spatial index. This includes lmf()
, shp_*()
, wing2015()
, pmf()
, lassmooth()
, tin()
, pitfree()
. Benchmark on a Intel Core i7-5600U CPU @ 2.60GHz × 2.
```r
set_lidr_threads(n) tree_detection(las, lmf(3))
lassnags(las, wing2015(neigh_radii = nr, BBPRthrsh_mat = bbpr_th))
lasdetectshape(las3, shp_plane())
```
Internally the Delaunay triangulation has been rewritten with boost
instead of relying on the geometry
package. The Delaunay triangulation and the rasterization of the Delaunay triangulation are now written in C++ providing an important speed-up (up to three times faster) to tin()
, dsmtin()
and pitfree()
. However, for this to work, the point cloud must be converted to integers. This implies that the scale factors and offset in the header must be properly populated, which might not be the case if users have modified these values manually or if using a point cloud coming from a format other than las/laz. Benchmark on an Intel Core i7-5600U CPU @ 2.60GHz × 2.
```r
set_lidr_threads(n) grid_terrain(las, 0.5, tin())
grid_canopy(las, res = 0.5, dsmtin())
grid_canopy(las, res = 0.5, pitfree(c(0,2,5,10,15), c(0, 1.5)))
```
There are more than 100 new unit tests in testthat
. The coverage increased from 68 to 87%.
The vignette named Speed-up the computations on a LAScatalog gains a section about the possible additional speed-up using the argument select
from readLAS()
.
The vignette named LAScatalog formal class gains a section about partial processing.
Harmonization and review of the sections 'Supported processing options' in the man pages.
Several minor fixes in lascheck()
for very improbable cases of LAS
objects likely to have been modified manually.
Fix colorization of boolean data when plotting an object of class lasmetrics3d
(returned by voxel_metrics()
) #289
The LAScatalog engine now calls raster::writeRaster()
with NAflag = -999999
because it seems that the default -Inf
generates a lot of trouble on windows when building a virtual raster mosaic with gdalUtils::gdalbuildvrt()
.
plot.LAS()
better handles the case when coloring with an attribute that has only two values: NA
and one other value.
lasclip()
was not actually able to retrieve the attributes of the Spatial*DataFrame
or sf
equivalent when using opt_output_file(ctg) <- "/dir/{PLOTID}"
.
opt_stop_early()
was not actually working as expected. The processing was aborted without logs. It now prevent the catalog processing engine to stop
even when an error occurs.
In tree_detection()
if no tree is found (e.g. in a lake) the function crashed. It now returns an empty SpatialPointDataFrame
.
The argument keep_lowest
in grid_terrain
returned dummy output full of NAs because NAs have the precedence on actual numbers.
grid_terrain()
gains an argument full_raster = FALSE
.
lasnormalize()
gains an argument ...
to tune raster::extract()
and use, for example, method = "bilinear"
.
In lasground()
if last_returns = TRUE
and the LAS
is not properly populated i.e. no last return, the classification was not actually computed. The expected behavior was to use all the points. This is now the case.
lasclip()
is now able to clip into a LAS
objects using SpatialPoints
or sf POINT
. It previously worked only into LAScatalog
objects.
lasaddextrabyte_manual()
was not actually working because the type
was not converted to a numeric value according to the LAS specifications.
Fix double precision floating point error in grid_*
function in some specific cases. This fix affect also highest()
and other raster-based algorithms #273.
lasreoffset()
now checks for integer overflow and throws an error in case of invalid user request #274.
Tolerance for internal point_in_triangle()
have been increased to fix double precision error in rasterization of a triangulation. This fixes some rare NA
s in pitfree()
, dsmtin()
and tin()
.
The NAs are now correctly interpreted when writing a GDAL virtual raster #283.
Fix lasmergespatial()
with 'on disk' rasters #285.
Fix pitfree()
with a single triangle case #288.
pitfree()
handles more errors and fails more nicely in some specific cases #286.New functions lasrescale()
and lasreoffset()
to modify the scale factors and the offsets. The functions update the header and recompute the coordinates to get the proper rounded values in accordance with the new header.
readLAS()
throw (again) warnings for invalid files such as files with invalid scale factors, invalid bounding box, invalid attributes ReturnNumber and so on.
readLAScatalog()
is 60% faster
The progress bar of the LAScatalog processing engine has been removed in non interactive sessions and replaced by regular but more informative prints. This allows to track the state of the computation with a stream redirection to a file when running a script remotely for example.
R -f script.R &> log.txt &
Fix an infinite loop in the knn search when k > number of points. This bug may affect lasdetectectshape()
, wing2012()
and other functions that rely on a knn search.
Using remote futures now works for any function that supports a LAScatalog
input. Previously remote evaluation of futures failed because of the presence of return()
statement in the code future#333
r
plan(remote, workers = "132.203.41.25")
lasclipCircle()
behaves identically for LAS
and LAScatalog
object. It now returns the points that are strictly inside the circle. Previously for LAS
objects it also returned the point belonging on the disc.
The bounding box is updated after lastransform()
#270
The offsets are updated after lastransform()
to prevent integer overflow when writing the point cloud in .las
files #272
Removed deprecated C++ functions std::bind2nd
as requested by CRAN.
#266 lasmetrics
has now a dispatch to LAS
and LAScluster
cluster objects. It means that lasmetrics
can be used with catalog_apply
in some specific cases where it has a meaning (see also #266):
r
opt_chunk_buffer(ctg) <- 0
opt_chunk_size(ctg) <- 0
opt_filter(ctg) <- "-keep_first"
opt_output_files(new_ctg) <- ""
output <- catalog_apply(new_ctg, lasmetrics, func = .stdmetrics)
output <- data.table::rbindlist(output)
lastrees()
now uses S3 dispatcher system. When trying to use it with a LAScatalog
object, user will have a standard R message to state that LAScatalog
is not supported instead of an uninformative message that state that 'no slot of name "header" for this object of class "LAScatalog"'
Internal code has been modified to drastically reduce probability of name intersection in catalog_apply()
. For example, the use of a function that have a parameter p
in catalog_apply()
failed because of partial matching between the true argument p
and the internal argument processing_option
.
lasfilterdecimate()
with algorithm highest()
is now more than 20 times faster. lasfiltersurfacepoints()
, being a proxy of this algorithm, had the same speed-up
plot
for LAS
objects gained the pan capability.
grid_metrics
when used with a parallelized plan (tree_metrics()
was also affected).Several algorithms are now natively parallelized at the C++ level with OpenMP
. This has for consequences for speed-up of some computations by default but implies visible changes for users. For more details see help("lidR-parallelism")
. The following only explains how to modify code to restore the exact former behavior.
In versions < 2.1.0
the catalog processing engine has R-based parallelism capabilities using the future
package. The addition of C++-based parallelism introduced additional complexity. To prevent against nested parallelism and give the user the ability to use either R-based or C++-based parallelism (or a mix of the two), the function opt_cores()
is no longer supported. If used it generates a message and does nothing. The strategy used to process the tiles in parallel must now be explicitly declared by users. This is anyway how it should have been designed from the beginning! For users, restoring the exact former behavior implies only one change.
In versions < 2.1.0
the following was correct:
library(lidR)
ctg <- catalog("folder/")
opt_cores(ctg) <- 4L
hmean <- grid_metrics(ctg, mean(Z))
In versions >= 2.1.0
this must be explicitly declared with the future
package:
library(lidR)
library(future)
plan(multisession)
ctg <- catalog("folder/")
hmean <- grid_metrics(ctg, mean(Z))
readLAS()
:
lascheck()
and print()
were updated to work correctly with these formats (#204)readLASheader()
to read the header of a file in a LASheader
object.Coordinate Reference System:
wkt()
to store a WKT CRS in a LAS 1.4 file. This function is the twin of epsg()
to store CRS. It updates the proj4string
and the header of the LAS object. This function is not expected to be used by users. Users must prefer the new function projection()
instead.projection<-
that updates both the slot proj4string
and the header with an EPSG code or a WKT string from a proj4string
or a sp:CRS
object. This function supersedes epsg()
and wkt()
that are actually only useful internally and in specific cases. The vignette LAS-class
has been updated accordingly.r
projection(las) <- projection(raster)
LAScatalog processing engine:
An error occurred when processing the chunk 190. Try to load this chunk with:
chunk <- readRDS("/tmp/RtmpAlHUux/chunk190.rds")
las <- readLAS(chunk)
grid_metrics()
:
stdshapemetrics()
and lazy coding .stdshapemetrics
to compute eigenvalue-related features (#217).filter
in grid_metrics()
. This argument enables users to compute metrics on a subset of selected points such as "first returns", for example, without creating a copy of the point cloud. Such an argument is expected to be added later in several other functions.r
hmean <- grid_metrics(las, ~mean(Z), 20, filter = ~ReturnNumber == 1)
New functions lasdetectshape()
for water and human-made structure detection with three algorithms shp_plane()
, shp_hplane()
, shp_line()
.
plot()
:
plot()
gained an argument axis = TRUE
to display axis.plot()
gained an argument legend = TRUE
to display color gradient legend (#224).tree_hull()
:
func
to compute metrics for each tree, like tree_metrics()
r
convhulls <- tree_hulls(las, func = ~list(imean = mean(Intensity)))
Miscellaneous tools:
area()
has been extended to LASheader
objects.npoints()
and density()
available for LAS
, LASheader
and LAScatalog
objects that return what users may expect.```r las <- readLAS("file.las", filter = "-keep_first") header <- readLASheader(file) ctg <- catalog("folder/")
npoints(las) #> [1] 55756 npoints(header) #> [1] 81590 npoints(ctg) #> [1] 1257691
density(las) #> [1] 1.0483 density(header) #> [1] 1.5355 density(ctg) #> [1] 1.5123 ```
Several functions are natively parallelized at the C++ level with OpenMP. See help("lidR-parallelism")
for more details.
New function catalog_select
for interactive tile selection.
lasground
have lost the argument last_returns
for a more generic argument filter
. Retro-compatibility as been preserved by interpreting adding an ellipsis.
grid_metrics()
, grid_metrics3d()
, tree_metrics()
, tree_hull()
, grid_hexametrics()
and lasmetrics()
expect a formula as input. Users should not write grid_metrics(las, mean(Z))
but grid_metrics(las, ~mean(Z))
. The first syntax is still valid, for now.
The argument named field
in tree_metrics()
is now named attribute
for consistency with all other functions.
The documentation of supported options in tree_*()
functions was incorrect and has been fixed.
readLAScatalog()
replaces catalog()
. catalog()
is soft-deprecated.
#264 grid_terrain
now filter degenerated ground points.
#238 fix a floating point precision error in p2r
algorithm.
readLAS(f, select = "xyzi")
) the header is updated to remove the non-loaded extrabytes. This fixes the issue #234 and enables LAS objects to be written without updating the header manually.li2012()
the doc states that If R = 0 all the points are automatically considered as
local maxima and the search step is skipped (much faster). This is now true.lasmergespatial
used with a SpatialPolygonDataFrame
when the bounding boxes do not match the full search was performed uselessly. Now the function exits early without searching anything.tsearch
that searches in a triangulation is 25% faster giving a small speed-up to pitfree()
and tin()
algorithms.lasmergespatial
used with a SpatialPolygonDataFrame
the function checks the bounding box of the polygon to speed-up the computation with complex polygons.?lidR
page to the manual.li2012()
the doc states that If R = 0 all the points are automatically considered as local maxima and the search step is skipped (much faster). This is now true.lasmergespatial
with a SpatialPolygonDataFrame
when the bounding boxes do not match instead of exiting early without searching anything the full search was performed uselessly.grid_*()
functions return consistently a RasterLayer
if there is a single layer. virtual raster mosaic were returned as RasterStack
no matter the number of layers.lasmergespatial()
wrongly copied shapefile attributes to each point when the parameter attribute
was the name of an attribute of the shapefile.laspulse()
, lasflightline()
, lasscanline()
were broken since v2.0.0.lasmergespatial()
and lasclip()
loose precision when extracting polygons due to missing digits in the WKT string used to rebuild the polygons at C++ level.catalog
has been slightly modified in prevision of the release of the package rlas 1.3.0
to preserve future compatibility. This is invisible for the users.lasnormalize
gained a parameter na.rm = TRUE
chunk_pattern = TRUE
: object 'ctg' not found.tin()
and knnidw()
were inverted.keep_lowest
in grid_terrain
.> 2.0
are incompatible with versions 1.x.y
?The lidR package versions 1 were mainly built upon "personal R scripts" I wrote 3 years ago. These scripts were written for my own use at a time when the lidR package was much smaller (both in term of code and users). The lidR package became a relatively large framework built on top of an unstructured base so it became impossible to develop it further. Many features and functions were missing because the way lidR was built did not allow them to be written. The new release (lidR version 2) breaks the former code to build a more robust, more consistent and more scalable framework that is intended and expected to continue for years without the need to break anything more in the future.
Old binaries can still be found here for 6 months:
lidR as a GIS tool
lidR versions 1 was not a GIS tool. For example, rasterization functions such as grid_metrics()
or grid_canopy()
returned a data.frame
. Tree tops extraction with tree_detection()
also returned a data.frame
. Tree segmentation with lastrees()
accepted RasterLayer
or data.frame
as input in a very inconsistent way. Moreover, the CRS of the point cloud was useless and never propagated to the outputs because outputs were not spatial objects.
lidR version 2 consistently uses Raster*
and Spatial*
objects everywhere. Rasterization functions such as grid_metrics()
or grid_canopy()
return Raster*
objects. Tree tops extraction returns SpatialPointDataFrame
objects. Tree segmentation methods accept SpatialPointDataFrame
objects only in a consistent way across functions. The CRS of the point cloud is always propagated to the outputs. LAS
objects are Spatial
objects. LAScatalog
objects are SpatialPolygonDataFrame
objects. In short, lidR version 2 is now a GIS tool that is fully compatible with the R ecosystem.
No longer any update by reference
Several lidR functions used to update objects by reference. In lidR versions 1 the user wrote: lasnormalize(las)
instead of las2 <- lasnormalize(las1)
. This used to make sense in R < 3.1 but now the gain is no longer as relevant because R makes shallow copies instead of deep copies.
To simplfy, let's assume that we have a 1 GB data.frame
that stores the point cloud. In R < 3.1 las2
was a copy of las1
i.e. las1
+ las2
= 2GB . This is why we made functions that worked by reference that implied no copy at all. This was memory optimized but not common or traditional in R. The question of memory optimization is now less relevant since R >= 3.1. In the previous example las2
is no longer a deep copy of las1
, but a shallow copy. Thus lidR now consistently uses the traditional syntax y <- f(x)
.
Algorithm dispatch
The frame of lidR versions 1 was designed at a time when there were fewer algorithms. The increasing number of algorithms led to inconsistent ways to dispatch algorithms. For example:
grid_canopy()
implemented one algorithm and a second function grid_tincanopy()
was created to implement another algorithm. With two functions the switch was possible by using two different names (algorithms dispatched by names).grid_tincanopy()
actually implemented two algorithms in one function. The switch was possible by changing the input parameters in the function (algorithm dispatched by input).lastrees()
had several variants that provided access to several algorithms: lastrees_li()
, lastrees_dalpontes()
, lastrees_watershed()
, and so on. With several functions the switch was possible by using several different names (algorithms dispatched by names).tree_detection
did not have several variants, thus it was impossible to introduce a new algorithm (no dispatch at all).lidR version 2 comes with a flexible and scalable dispatch method that unifies all the former functions. For example, grid_canopy()
is the only function to make a CHM. There is no longer the need for a second function grid_tincanopy()
. grid_canopy()
unifies the two functions by accepting as input an algorithm for a digital surface model:
chm = grid_canopy(las, res = 1, algo = pitfree())
chm = grid_canopy(las, res = 1, algo = p2r(0.2))
The same idea drives several other functions including lastrees
, lassnags
, tree_detection
, grid_terrain
, lasnormalize
, and so on. Examples:
ttops = tree_detection(las, algo = lmf(5))
ttops = tree_detection(las, algo = lidRplugins::multichm(1,2))
lastrees(las, algo = li2012(1.5, 2))
lastrees(las, algo = watershed(chm))
lasnormalize(las, algo = tin())
lasnormalize(las, algo = knnidw(k = 10))
This allows lidR
to be extended with new algorithms without any restriction either in lidR or even from third-party tools. Also, how lidR functions are used is now more consistent across the package.
LAScatalog processing engine
lidR versions 1 was designed to run algorithms on medium-sized point clouds loaded in memory but not to run algorithms over a set of files covering wide areas. In addition, lidR 1 had a poorly and inconsistently designed engine to process catalogs of las files. For example:
LAScatalog
but not multipart-polygons or polygons with holes. This was only possible with LAS
objects i.e loaded in memory (inconsistent behaviors within a function).grid_metrics()
on a LAScatalog
i.e. over a wide area not loaded in memory, but not lasnormalize
, lasground
or tree_detection
(inconsistent behavior across the functions).lidR version 2 comes with a powerful and scalable catalog processing engine. Almost all the lidR functions can be used seamlessly with either LAS
or LAScatalog
objects. The following chunks of code are now possible:
ctg = catalog("folfer/to/las/file")
opt_output_file(ctg) <- "folder/to/normalized/las/files/{ORIGINALFILENAME}_normalized"
new_ctg = lasnormalize(ctg, algo = tin())
LAS class
LAS
class is now a Spatial
object or, more technically, it inherits a Spatial
object.Spatial
object, a LAS
object no longer has a @crs
slot. It has now a slot @proj4string
that is accessible with the functions raster::projection
or sp::proj4string
Spatial
object, a LAS
object inherits multiple functions from raster
and sp
, such $
and [[
accessors or raster::extent
, sp::bbox
, raster::projection
, and so on. However, the replacement method $<-
, [[<-
have restricted capabilities to ensure a LAS
object cannot be modified in a way that implies loosening the properties of the LAS specifications.LAS
objects with 0 points are now allowed. This has repercussions for several functions including lasfilter
, lasclip
, and readLAS
that do not return NULL
for empty data but a LAS
object with 0 points. This new behavior has been introduced to fix the old inconsistent behavior of functions that return either LAS
or NULL
objects. LAS
objects are always returned.LAScatalog class
LAScatalog
class is now a SpatialPolygonsDataFrame
or, more technically, it inherits a SpatialPolygonsDataFrame
.SpatialPolygonsDataFrame
object, a LAScatalog
no longer has a @crs
slot. It has now a slot @proj4string
that is accessible with the functions raster::projection
or sp::proj4string
.SpatialPolygonsDataFrame
a LAScatalog
can be plotted with sp::spplot()
.@cores
, @by_file
, @buffer
, and so on. They are replaced by more generic and scalable slots @processing_options
, @output_options
, @clustering_options
and @input_options
that are list of options classified by their main roles.by_file
, progress
, tiling_size
, buffer
were replaced by opt_chunk_size
, opt_chunk_buffer
, opt_progress
, and so on. These allow for a consistent set of functions that do not overlap with functions from raster
or sp
.sp
functions.readLAS
readLAS
no longer supports option PFC
. Users must use the functions laspulse
, lasflightlines
manually.lasclip
lasclip
now works both with a LAS
object and a LAScatalog
object in a seamless and consistent way. There are no longer any differences between the capabilities of the LAS
version or the LAScatalog
one.lasclip
support many geometries including multipart polygons and polygons with holes, both with a LAS
object and a LAScatalog
object.inside
has been removed for consistency because it cannot be safely supported both on LAS
and LAScatalog
.ofile
has been removed for consistency and this option in now managed by the LAScatalog
processing engine. For example, one can extract ground inventories and write them in laz
files automatically named after their center coordinates like this:ctg = catalog(folder)
output_files(ctg) <- "path/to/a/file_{XCENTER}_{YCENTER}"
laz_compression(ctg) <- TRUE
new_ctg = lasclipCircle(ctg, xc,yc, r)
lasclip
does not return NULL
anymore for empty queries but an empty LAS
object.lasclipRectangle
returns the same output both with a LAS
and a LAScatalog
. With a LAS
the rectangle is now closed on the bottom and the left and open on the right and the top.catalog_queries
catalog_queries
has been removed because it is superseded by lasclip
.lasnormalize
lasnormalize()
no longer updates the original object by reference.copy = TRUE
that is now meaningless.lasnormalize()
now relies on lidR algorithms dispatch (see also the main new features above).lasnormalize()
can be applied on a LAScatalog
to write a new normalized catalog using the catalog processing engine (see also the main new features above).lasclassify
lasclassify()
is now named lasmergespatial()
to free the name lasclassify
that should be reserved for other usage.lasmergespatial()
no longer updates the original object by reference.RasterLayer
, preserves the data type of the RasterLayer
. This also fixes the fact that lastrees()
used to classify the tree with double
instead of int
.tree_detection
tree_detection()
now relies on the new dispatch method (see also the main new features above).lmf
has user-defined variable-sized search windows and two possible search window shapes (square or disc).manual
algorithm for manual correction of tree detection.tree_detection
algorithms are seamlessly useable with a LAScatalog
object by using the catalog processing engine (see also the main new features above). Thus, the following just works:ctg <- catalog(folder)
ttop <- tree_detection(ctg, lmf(5))
lmf
algorithm, when used with a RasterLayer
as input, expects parameters given in the units of the map and no longer in pixels.tree_detection()
function consistently returns a SpatialPointsDataFrame
whatever the algorithm.tree_detection()
function based on a CHM no longer support a lasmetric
object as input. Anyway, this class no longer exists.tree_metrics
tree_metrics()
returns a SpatialPointsDataFrame
.tree_metrics()
is seamlessly useable with a LAScatalog
using the catalog processing engine (see also the main new features above). Thus, this just works if the las file has extra bytes attributes that store the tree ids:ctg <- catalog(folder)
metrics <- tree_metrics(ctg, list(`Mean I` = mean(Intensity)))
lastrees
lastrees()
now relies on the new algorithms dispatch method (see also the main new features above).mcwatershed
algorithm that implements a marker-controlled watershed.grid_metrics
grid_metrics()
as well as other grid_*
functions consistently return a RasterLayer
or a RasterBrick
instead of a data.table
.splitlines
has been removed. grid_metrics()
used to return a data.table
because of the splitlines
option and lidR was built on top of that feature from the very beginning. Now lidR consistently usessp
and raster
and this option is no longer supported.grid_terrain
grid_terrain()
now relies on the new algorithms dispatch method (see also the main new features above).grid_terrain()
consistently returns a RasterLayer
instead of a data.table
, whatever the algorithm used.grid_canopy
grid_canopy()
now relies on the new algorithms dispatch method (see also the main new features above). It unifies the former functions grid_canopy()
and grid_tincanopy()
.grid_canopy()
consistently returns a RasterLayer
instead of a data.table
, whatever the algorithm used.grid_tincanopy
grid_tincanopy()
has been removed. Digital Surface Models are consistently driven by the function grid_canopy()
and the lidR algorithm dispatch engine. The algorithms that replaced grid_tincanopy()
are dsmtin
and pitfree
.grid_hexametrics
grid_metrics
, the parameter splitlines
has been removed.hexbin
object or a list of hexbin
objects and no longer data.table
objects.grid_catalog
grid_catalog()
has been removed. The new LAScatalog
processing engine means that this function is no longer useful.class lasmetrics
data.table
with a class lasmetrics
no longer exists. It has been consistently replaced by RasterLayer
and RasterBrick
everywhere.as.raster
no longer exists because it used to convert lasmetrics
into RasterLayer
and RasterStack
.as.spatial
no longer converts lasmetrics
to SpatialPixelsDataFrame
but still converts LAS
to SpatialPointsDataFrame
.plot.lasmetrics
has been removed obviously.lasroi
lasoi()
has been removed. It was not useful and 'buggy'. It might be reintroduced later in lasclipManual
.lascolor
lascolor()
has been removed. It was one of the first functions of the package and is no longer useful because plot()
has enhanced capabilities.lasfilterdecimate
highest
available in lasfilterdecimate()
. This supersedes the function lasfiltersurfacepoints()
.lassnags
lassnags()
now relies on the new algorithms dispatch method (see also the main new features above).lasnsnags()
can be applied on a LAScatalog
to write a new catalog using the catalog processing engine (see also the main new features above).lidr_options
lidr_option()
has been removed. The options are now managed by regular R base options with function options()
. Available lidR options are named with the prefix lidR
.Example files
proj4string
.MixedConifers.laz
contains the segmented trees in extra bytes 0.plot
plot()
for LAS
objects supports RGB
as a color attribute.color
supports lazy evaluation. This syntax is correct: plot(las, color = Classification)
.clear_artifact = TRUE
shifts the point cloud to (0,0) and reduces the display artifact due to the use of floating point in rgl
.add_treetops3d
, add_dtm3d
and plot_dtm3d
add elements in the point cloud.trim
does not trim on a percentile of values but on the values themselves.Coordinate reference system
epsg()
.lastranform
that returns transformed coordinates of a LAS
object using the CRS argument.New functions
lasfilterduplicates
lascheck
lasvoxelize
point_in_polygon
algorithm relies on boost
and drastically simplifies the former code of lasmergespatial()
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.