If you are viewing this file on CRAN, please checkthe latestnews on GitHub where the formatting is also better
nanoflann for knn computation. Numerous functionsare faster.readLAScatalog with a VPC files parse absolutepaths with “/” instead of “\” properly.plot() withcolor = "Classification" is now as fast as plotting otherattributesconnected_components() gained an argumentconnectivityv4.2.0 brings new tools for terrestrial data (TLS,MLS):
connected_components() toperform clustering.knn_distance() to measurethe average distance between a point and its neighborhood.SparsePartition3D for TLS data, optimized for memoryusage.readALS() andreadTLS(), which replace the overly complex and rarely usedreadALSLAS(),readTLSLAS(),readUAVLAS(), and related functions.readLAS() automatically detects if the point cloudis TLS or ALS.readALS() andreadTLS() shouldbe preferred in order to avoid false positive. The print function wasupdated to display what lidar type is registered.readALScatalog() andreadTLScatalog() to replace the complex and less-usedreadALSLAScatalog(),readTLSLAScatalog(),readUAVLAScatalog(), and related functions.readLAScatalog() also detects if the point cloud is TLS orALS.fit_circle() using aRANSAC-based approach.height_above_ground()remove_noise()add_circle3d()knn() andknnx()for point clouds.barycenter_per_voxel(),lowest_attribute_per_voxel() andhighest_attribute_per_voxel() fordecimate_points()crs(),is.empty(),andarea() functions, which now inherit fromterra, avoiding conflicts withterra.readLAScatalog()to skip corrupted files.homogenize()pitfill_stonge2008 was bugged with non squarerasters du to rows-columns inversionpoint_in_triangle() to enhance the quality of Delaunaytriangulation interpolations and prevent local NAs.decimate_points() function with therandom() method now preserves the original pointorder.random_per_voxel algorithm, whichwas previously not functioning as intended.readLAScatalog() whensp was missing.boost forpoint_in_polygon() (issue #763).point_metrics() function due to CRAN policy changes that nolonger permit the use of some internal functions critical to thisfunction (issue #764).readLAScatalog() was not working if packageraster was not installed.stars package makesrasterize_terrain() extremely slow and blow up the RAMmemorycatalog_intersects() support aSpatExtentlidR can fully works withoutrasteranssplmf() with a fixed windows isnow 20 times faster.point_eigenvalues gained an argumentcoeff to return the principal component coefficientspitfill_stonge2008(). See references.readLAScatalog can read a virtual point cloud file(.vpc)Following the retirement ofrgdal andsp weremoved the dependence tosp and the strong dependence toraster:
bbox inherited fromspraster is now only suggested andlidR no longer depends on it.extent was removed in consequenceof (3) because it was inherited fromraster and returned anobjectExtent fromraster.crs,crs<-,projection,projection<-,wktandarea inherited fromraster are nowgeneric. This may create clash with theraster package butanywayraster should no longer be used.silva2016 can load (not too big) ondisk chm on thefly.rasterize_terrain() works in parallel withres = <SpatRaster>.plot(las, mapview = TRUE).plot(las, breaks = <vector>) now works with a vectorof custom break points.crown_metrics now always remove invalid polygons ifany.readMSLAS can now be written properly withwriteLAS.readMSLAS accepts only two files.readMSLAS convertsScanAngleRank toScanAngle.add_lasnir().rgl::rgl.* byrgl::*3d functions#651readLAS no longer checks for attribute namesvalidity as they are necessarily correct#659plot_metrics() no longer fails with a single plot#664unormalize_height() removes extra_bytes in VLR.print(las) works even when the CRS is not recognized bysf.dsmtin andpitfree gain an argumenthighest. This option was enabled by default in previousreleases. There is now an option to disable it.normalize_height() andsegment_trees work inparallel withSpatRaster.crown_metrics() now triggers a warning when invalidgeometries are created anddelineate_crowns() remove thesegeometries before to convert tosp.crown_metrics() now works withfunc = NULL andaLAScatalog.*_metrics() functions always returnedNAs forlastofmany.dalponte2016 doc updated to useterra.plot(ctg, chunk = TRUE) does not fail if aninvalid output file template is registered#537locate_trees() throws an informative error ifcalled with an on-disk raster. The former error was cryptic. If theraster is small enough it is loaded on-the-fly.merge_spatial() with RGB andSpatRaster was not working properly#545st_area() better estimates the area of smallpoint-clouds and is fasterinterpret_waveform#549.plot_metrics() returns NA if 0 points available#551.rasterize_canopy may generate error or messed-up CHM#552.print() andst_area() were notworking for point cloud with no CRStrack_sensor() does not fail with aLAScatalog when no sensor position is found. It alsotriggers a warning.#556.rasterize_terrain() now works with aLAScatalog andshape = sfc_object#558.catalog_retile() now works when some tiles areempty#563.crown_metrics() messed up tree IDs with a hullgeometry#554.merge_spatial() crops large vectors to the extentof the point cloud before to perform the merge. This has forconsequences to sometime transform polygons into multipolygons. Whenpolygons and multipolygons were mixed the functions stopped with anerror. It now works.normalize_height() now sets the Z offset to 0#571.We are currently developing rlas 1.6.0 that uses the ALTREP frameworkto load compact representation of non populated attributes. For exampleUserData is usually populated with zeros (not populated).Yet it takes 32 bits per point to store each 0. With rlas 1.6.0 it willonly uses 644 bits no matter the number of points loaded for nonpopulated attributes. This applies to each attribute populated with asingle repeated value. This allows for saving approximately 30% ofmemory usage depending on the number of non-populated attributes thatare present in the file. rlas 1.6.0 is compatible will all versions oflidR but lidR 4.0.1 introduced some internal optimization, internalfixes and new functions to fully take advantage of rlas 1.6.0. lidRv<= 4.0.0 will work with rlas 1.6.0 but won’t take advantage of thenew compression feature.
the functionLAS() no longer calldata.table::setDT() if the input is already adata.table. Indeeddata.table::setDT()materializes the compressed ALTREP vectors and this is not what we want.One consequence of this change is thatreadLAS() nowpreserve the ALTREPness (i.e. the compression) of the output ofrlas::read.las().
Subsetting aLAS object no longer calldata.table native subset. We previously used something likelas@data[indx] to subset the point cloud. Sadlydata.table tries to materialized the ALTREPed vectorwhenever it can. We implemented internally asmart_subset()function that subset and preserves the compression of the vectors. Oneconsequence of such change is that allfilter_*() andclip_*() functions preserve the compression of thepoint-cloud if any.
las_check() has been slightly modified to ensure itdoes not materialize ALTREPed object. One side effect oflas_check() was to decompress the point cloud unexpectedly.Such a pity! We also changelas_check() to printinformation about the compression.
We changed the way*_metrics() functions evaluatesthe user defined expression because we found that it had the side effectof materializing all the attributes instead of materializing only thoseneeded. For examplepixel_metrics(las, mean(Z)) only needsthe attribute Z. No need to allocate and copy memory forIntensity,ScanAngle and so on. In previousversion all attributes where inspected with the side effect tomaterialize all compressed vectors. The*_metrics()functions now properly detect which attributes are actually necessaryfor the evaluation offunc. Two consequences:(1)*_metrics() functions are 20 to 40% faster, (2) thecompression is preserved if no compressed attribute is used in theevaluation and e.g. pixel_metrics(las, mean(UserData))uncompresses onlyUserData.
New functionslas_is_compressed() that tells whichattributes are compressed andlas_size() that returns thetrue size of aLAS objects taking into account thecompression.las_size() should returns something similar topryr::object_size() but different toobject.size() that is not ALTREP aware. We also changed theprint function so it useslas_size() insteadofobject.size().
On overall lidR’s functions are expected to almost never decompress aLAS object. However other R packages and R functions may do it. Forexampledata.table::print do materializes the ALTREPvectors.base::range() too but notbase::mean() orbase::var().
las@data# Full decompression (print data.table)range(las$Userdata)# Decompression of UserDatalas@data[2, UserData:=1]# Decompression of UserDatalas@data[1:10]# Full decompressionrgdal andrgeos will be retired on Jan 1st2024. see twitter(https://twitter.com/RogerBivand/status/1407705212538822656),youtube, or seethe respective package descriptions on CRAN. Packagesraster andsp are based onrgdal/rgeos andlidR was based onraster andsp because it was created beforesf,terra andstars. This meansthat sooner or laterlidR will run into trouble (actuallyit is more or less already the case). Consequently, we modernizedlidR by moving tosf,terra/stars and we are no longer depending onsp andraster (see alsoOlder R SpatialPackage for more insight). It is time for everybody to stop usingsp andraster and to embracesfandstars/terra.
In version 4lidR now no longer usessp, itusessf and it no longer usesraster. It isnow raster agnostic and works transparently with rasters fromraster,terra andstars. Thesetwo changes meant we had to rewrite a large portion of the code base,which implies few backward incompatibilities. The backwardincompatibilities are very small compared to the huge internal changeswe implemented in the foundations of the code and should not even bevisible for most users.
lidR no longer loadsraster andsp. To manipulateRaster* andSpatial* objects returned by lidR users need to loadsp andraster with:r library(sp) library(raster) library(lidR)
The formal classLAS no longer inherits the classSpatial fromsp. It means, among other things,that aLAS object no longer has a slot@proj4string with aCRS fromsp,or a slot@bbox. The CRS is now stored in the slot@crs in acrs object fromsf.Former functionscrs() andprojection()inherited fromraster are backward compatible and return aCRS or aproj4string fromsp.However code that accesses these slots manually are no longer valid (butnobody was supposed to do that anyway because it was the purpose of thefunctionprojection()):r las@proj4string # No longer works las@bbox # No longer works inherits(las, "Spatial") # Now returns FALSE
The formal classLAScatalog no longer inherits theclassSpatialPolygonDataFrame fromsp. Itmeans, among other things, that aLAScatalog object nolonger has a slot@proj4string, or@bbox, or@polygons. The slot@data is preserved andcontains ansf,data.frame instead of adata.frame allowing backward compatibility of data accessto be maintained. The syntaxctg$attribute is the way toaccess data, but statement likectg@data$attribute arebackward compatible. However, code that accesses other slots manually isno longer valid, like for theLAS class:r ctg@proj4string # No longer works ctg@bbox # No longer works ctg@polygons # No longer works inherits(ctg, "Spatial") # Now returns FALSE
sp::spplot() no longer works on aLAScatalog because aLAScatalog is no longer aSpatialPolygonDataFramer spplot(ctg, "Max.Z") # becomes plot(ctg["Max.Z"])
raster::projection() no longer works onLAS* objects because they no longer inheritSpatial. Moreover,lidR no longerDepends onraster which means thatraster::projection() andlidR::projection canmask each other. Users should usest_crs() preferentially.To useprojection users can either loadrasterbeforelidR or calllidR::projection() withthe explicit namespace.
library(lidR)projection(las)# workslibrary(raster)projection(las)# no longer worksSerializedLAS/LAScatalog objects (i.e. stored in.rds or.Rdata files) saved withlidR v3.x.y are no longer compatible withlidR v4.x.y. Indeed, the structure of aLAS/LAScatalog object is now different mainly because theslot@crs replaces the slot@proj4string.Users may get errors when using e.g. readRDS(las.rds) toload back an R object. However we put safeguards in place so, inpractice, it should be backward compatible transparently, and evenrepaired automatically in some circumstances. Consequently we are notsure it is a backward incompatibility because we handled and fixed allwarnings and errors we found. In the worst case it is possible to repairaLAS object v3 with:r las <- LAS(las)
track_sensor() is not backward compatible because itis a very specific function used by probably just 10 people in theworld. We chose not to rename it. It now returns ansfobject instead of aSpatialPointsDataFrame.
Former functions that returnSpatial* objects frompackagesp should no longer be used. It is time foreverybody to embracesf. However, these functions are stillinlidR for backward compatibility. They won’t be removedexcept if packagesp is removed from CRAN. It might happenon Jan 1st 2024, it might happen later. We do not know. New functionsreturnsf orsfc objects. Old functions arenot documented so new users won’t be able to use them.
tree_metrics() anddelineate_crowns() arereplaced by a single functioncrown_metrics() that has thesame functionality, and more.find_trees() is replaced bylocate_trees().Older functions that returnRaster* objects from theraster package should no longer be used. It is time foreverybody to embraceterra/stars. However, these functionsare still inlidR for backward compatibility. They won’t beremoved except if packageraster is removed from CRAN. Newfunctions return either aRaster*, aSpatRaster, or astars object, according touser preference.
grid_metrics() is replaced bypixel_metrics()grid_terrain(),grid_canopy(),grid_density() are replaced byrasterize_terrain(),rasterize_canopy(),rasterize_density()New functions are mostly convenient features that simplify someworkflow aspects without introducing a lot of brand new functionalitythat did not already exist inlidR v3.
New geometry functionsst_convex_hull() andst_concave_hull() that returnsfc
New modern functionsst_area(),st_bbox(),st_transform() andst_crs() inherited fromsf forLAS* objects.
New convenient functionsnrow(),ncol(),dim(),names() inheritedfrombase forLAS* objects
New operators$,[[,$<- and[[<- onLASheader.The following are now valid statements:r header[["Version Major"]] header[["Z scale factor"]] <- 0.001
Operators$,[[,$<-and[[<- onLAS can now access theLASheader metadata. The following are now valid statements:r las[["Version Major"]] las[["Z scale factor"]] <- 0.001
RStudio now supports auto completion for operator$inLAS objects. Yay!
New functionstemplate_metrics(),hexagon_metrics(),polygon_metrics() thatextend the concept of metrics further to any kind of template.
Functions that used to accept spatial vector or spatial raster asinput now consistently accept any ofSpatial*,sf,sfc,Raster*,SpatRaster andstars objects. This includemerge_spatial(),normalize_intensity(),normalize_height(),rasterize_*(),segment_trees(),plot_dtm3d() and severalothers. We plan to supportSpatVector in futurereleases.
Every function that supports a raster as input now accept an“on-disk” raster fromraster,terra andstars i.e. a raster not loaded in memory. This includesrasterization functions, individual tree segmentation functions,merge_spatial and others, in particularplot_dtm3d() andadd_dtm3d() that nowdownsample on-disk rasters on-the-fly to display very large DTMs.On-disk rasters were already generally supported in previous versionsbut not every function was properly optimized to handle suchobjects.
All the functions that return a raster(pixel_metrics() andrasterize_*()) are rasteragnostic and can return rasters fromraster,terra orstars. They have an argumentpkg = "raster|terra|stars" to choose. The default isterra but this can be changed globally using:r options(lidR.raster.default = "stars")
New functioncatalog_map() that simplifiescatalog_apply() to a large degree. Yet it is not asversatile ascatalog_apply() but well suits around 80% ofuse cases. Applying a user-defined function to a collection of LAS filesis now as simple as:r my_fun <- function(las, ...) { # do something with the point cloud return(something) } res <- catalog_map(ctg, my_fun, param1 = 2, param2 = 5)
Operator[ onLAS object has beenoverloaded to clip a point-cloud using abbox or asfcr sub <- las[sfc]
rasterize_terrain() accepts ansfc asargument to force interpolation within a defined area.
normalize_height() now always interpolates allpoints. It is no longer possible to get an error that some points cannotbe interpolated. The problem of interpolating the DTM where there is nodata is still present but we opted for a nearest neighbour approach witha warning instead of a failure. This prevents the method from failingafter hours of computation for special cases somewhere in the filecollection. This also means we removed thena.rm optionthat is no longer relevant.
New functionsheader(),payload(),phb(),vlr(),evlr() to get thecorresponding data from aLAS object.
New algorithmshp_hline andshp_vlineforsegment_shapes()#499
New algorithmmcc for groundclassification.
The bounding box of the CHM computed withrastertize_canopy() orgrid_canopy() is nolonger affected by thesubcircle tweak. See#518.
readLAS() can now read two or more files that do nothave the same point format (see#508)
plot() forLAS gains argumentspal,breaks andnbreaks similartosf. Argumentstrim andcolorPalette are deprecated
classify_*,rasterize_*,*_metrics,segment_* andnormalize_* were grouped.