I'm applying lasnormalize with catalog_apply in lidR with opt_chunk_buffer set to 20 metres. I do not remove the buffer explicitly and the normalized las files, which are returned, include the hits from the buffer (i.e. my resulting las files now extend 20 metres beyond their original extent). I had interpreted the lidR manual that buffer removal is automatic - but maybe I need to remove the buffer with code? Many thanks for clarifying.

ctg <- readLAScatalog("J:/2019/LAS")

normF = function(chunk)
  las = readLAS(chunk)
  if (is.empty(las)) return(NULL)

  # skip las files that do not have ground hits
  ground <- lasfilter(las, Classification == 2)
  if (is.empty(ground))

  lasNorm <- lasnormalize(las, algorithm = knnidw(k = 10, p = 2), na.rm = FALSE, use_class = c(2L, 9L))

  # This is the line needed, as identified in the answer below...
  lasNorm <- lasfilter (lasNorm, buffer == 0)


opt_filter(ctg) <- "-drop_withheld -drop_overlap -drop_z_below 0"
opt_chunk_buffer(ctg) <- 20
opt_output_files(ctg) <- ("J:/2019/LAS_normalized/{ORIGINALFILENAME}_norm")
mylasCatalogueNorm <- catalog_apply(ctg, normF)

1 Answer 1


The manual of catalog_apply explicitly states that there is no mechanism to automatically remove the buffer

Edge artifacts

It is important to take precautions to avoid 'edge artifacts' [...]. The LAScatalog processing engine provides internal tools to load buffered data 'on-the-fly'. However, there is no mechanism to remove the results computed in the buffered area since this task depends on the output of the user-defined function. The user must take care of this task (see examples) to prevent unexpected output with duplicated entries or conflict between values computed twice.

There is an example for your case in this vignette. You can simply remove the point tagged as 'buffer'

las <- lasfilter(las, buffer == 0)  

The documentation of catalog_apply() helps to understand why it works

Buffered data

The LAS objects read by the user function have a special attribute called 'buffer' that indicates, for each point, if it comes from a buffered area or not. Points from non-buffered areas have a 'buffer' value of 0, while points from buffered areas have a 'buffer' value of 1, 2, 3 or 4, where 1 is the bottom buffer and 2, 3 and 4 are the left, top and right buffers, respectively. This allows for filtering of buffer points if required.

For this kind of question I strongly recommend to have a look the the lidR source code. It can help a lot.e.g. l187-205

  • 1
    I added this line in the code, right after the '''lasnormalize''' in the function to make it work: '''lasNorm <- lasfilter (lasNorm, buffer == 0)''' (thanks, I see where I misinterpreted the manual on p. 64, but the section on edge artifacts now makes it clear)
    – Ray J
    Commented Mar 9, 2020 at 16:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.