rlidarlidr

How to modify height value of building class within LAScatalog


I am working with a collection of classified LAZ files located over an urban area. I would like to create a canopy height model (CHM) for the urban tree extent. Filtering out and only keeping ground and tree classified points, the resulting CHM has some artifacts created during triangulation due to the missing points. I address this by retaining all the building points and modifying their heights to be 0. Working with a single LAZ file this is simple:

# Read
las<-readLAS("path/to/file.laz")

# Filter points
las<-filter_poi(las,las$Classification  %in% c(6,5,2))

# Normalize
las<-normalize_height(las,tin(),use_class=c(2L))

# Modify building height
las_buildings<-filter_poi(las,las$Classification %in% c(6))
las_buildings$Z<-0
las_trees_ground<-filter_poi(las,las$Classification %in% c(5,2))
las<-rbind(las_buildings,las_trees_ground)

# Create chm
chm<-rasterize_canopy(las,0.5,pitfree(subcircle=0.5))

However, doing this while working with a LAScatalog is unclear to me. This is what I have so far:

# Load laz catalog
ctg<-readLAScatalog("path/to/")

# Create buffer
opt_chunk_buffer(ctg)<-50

# Filter points
opt_filter(ctg)<-"-keep_first -keep_class 6 -keep_class 5 -keep_class 2"

# Normalize heights
opt_output_files(ctg)<-paste0(tempdir(),"/{*}_norm")
ctg_norm<-normalize_height(ctg,tin())

# How to change building height to 0 ???

# Create CHM
opt_output_files(ctg_norm)<-paste0(tempdir(),"/{*}_chm")
chm<-rasterize_canopy(ctg_norm,0.5,pitfree(subcircle=0.5),pkg="terra")
terra::writeRaster(chm,"chm.tif")

Any guidance on how I can achieve this would be very much appreciated.


Solution

  • Ok, after doing more reading I found the catalog_map function, which applies a custom function to the catalog.

    Here is my solution:

    # Function to change heights
    myfun <- function(las) {
      las_buildings<-filter_poi(las,las$Classification %in% c(6))
      las_buildings$Z<-0
      las_trees_ground<-filter_poi(las,las$Classification %in% c(5,2))
      output<-rbind(las_buildings,las_trees_ground)
      return(output)
    }
    
    # Change building height
    ctg_norm<-catalog_map(ctg_norm,myfun)