Skip to content

v4.0.1

Compare
Choose a tag to compare
@Jean-Romain Jean-Romain released this 04 May 08:28
· 180 commits to master since this release

lidR v4.0.1 (Release date: 2022-05-03)

  • Fix: plot(ctg, chunk = TRUE) does not fail if an invalid output file template is registered #537
  • Enhance: locate_trees() throws an informative error if called with an on-disk raster. The former error was cryptic. If the raster is small enough it is loaded on-the-fly.
  • Fix: merge_spatial() with RGB and SpatRaster was not working properly #545
  • Enhance: st_area() better estimates the area of small point-clouds and is faster
  • Fix: #548
  • Enhance: Scale factors are better estimated in interpret_waveform #549.
  • Fix: plot_metrics() returns NA if 0 points available #551.
  • Fix: floating point accuracy error with rasterize_canopy may generate error or messed-up CHM #552.
  • Fix: print() and st_area() were not working for point cloud with no CRS
  • Fix: track_sensor() does not fail with a LAScatalog when no sensor position is found. It also triggers a warning. #556.
  • Fix: The LAScatalog processing engine works with a single file #558.
  • Fix: rasterize_terrain() now works with a LAScatalog and shape = sfc_object #558.
  • Fix: catalog_retile() now works when some tiles are empty #563.
  • Fix: crown_metrics() messed up tree IDs with a hull geometry #554.
  • Fix: merge_spatial() crops large vectors to the extent of the point cloud before to perform the merge. This has for consequences to sometime transform polygons into multipolygons. When polygons and multipolygons were mixed the functions stopped with an error. It now works.
  • Fix: normalize_height() now sets the Z offset to 0 #571.
  • Fix: smaller rasters stored on-disk are better handled and loaded if needed

Changes related to rlas 1.6.0

We are currently developing rlas 1.6.0 that uses the ALTREP framework to load compact representation of non populated attributes. For example UserData is usually populated with zeros (not populated). Yet it takes 32 bits per point to store each 0. With rlas 1.6.0 it will only uses 644 bits no matter the number of points loaded for non populated attributes. This applies to each attribute populated with a single repeated value. This allows for saving approximately 30% of memory usage depending on the number of non-populated attributes that are present in the file. rlas 1.6.0 is compatible will all versions of lidR but lidR 4.0.1 introduced some internal optimization, internal fixes and new functions to fully take advantage of rlas 1.6.0. lidR v<= 4.0.0 will work with rlas 1.6.0 but won't take advantage of the new compression feature.

  1. the function LAS() no longer call data.table::setDT() if the input is already a data.table. Indeed data.table::setDT() materializes the compressed ALTREP vectors and this is not what we want. One consequence of this change is that readLAS() now preserve the ALTREPness (i.e. the compression) of the output of rlas::read.las().

  2. Subsetting a LAS object no longer call data.table native subset. We previously used something like las@data[indx] to subset the point cloud. Sadly data.table tries to materialized the ALTREPed vector whenever it can. We implemented internally a smart_subset() function that subset and preserves the compression of the vectors. One consequence of such change is that all filter_*() and clip_*() functions preserve the compression of the point-cloud if any.

  3. las_check() has been slightly modified to ensure it does not materialize ALTREPed object. One side effect of las_check() was to decompress the point cloud unexpectedly. Such a pity! We also change las_check() to print information about the compression.

  4. We changed the way *_metrics() functions evaluates the user defined expression because we found that it had the side effect of materializing all the attributes instead of materializing only those needed. For example pixel_metrics(las, mean(Z)) only needs the attribute Z. No need to allocate and copy memory for Intensity, ScanAngle and so on. In previous version all attributes where inspected with the side effect to materialize all compressed vectors. The *_metrics() functions now properly detect which attributes are actually necessary for the evaluation of func. Two consequences: (1)*_metrics() functions are 20 to 40% faster, (2) the compression is preserved if no compressed attribute is used in the evaluation and e.g. pixel_metrics(las, mean(UserData)) uncompresses only UserData.

  5. New functions las_is_compressed() that tells which attributes are compressed and las_size() that returns the true size of a LAS objects taking into account the compression. las_size() should returns something similar to pryr::object_size() but different to object.size() that is not ALTREP aware. We also changed the print function so it uses las_size() instead of object.size().

On overall lidR's functions are expected to almost never decompress a LAS object. However other R packages and R functions may do it. For example data.table::print do materializes the ALTREP vectors. base::range() too but not base::mean() or base::var().

las@data                    # Full decompression (print data.table)
range(las$Userdata)         # Decompression of UserData
las@data[2, UserData := 1]  # Decompression of UserData
las@data[1:10]              # Full decompression