I have two modified las files, which came from the same original las file. One of the files (file A) was produced using normalize_height() and the other (file B) was produced using normalize_intensity(). So the two las files come from the same parent las file, only they have normalized heights and normalized intensities respectively. I would like to copy the normalized intensity values from file B to file A. Is there a way to this with add_attribute() while ensuring that each point get's the correct normalized intensity value? Should both files first be sorted or something like that?

UPDATE: It seems that normalize_height() removes a few points from file A, making a match without filtering file B impossible...

add_lasattribute(norm_las, rc_las@data$Intensity, "CorrectedIntensity", "intensity values as a result of range correction")
#> Error in `[[<-.data.frame`(`*tmp*`, name, value = c(13L, 13L, 161L, 150L,  : 
  replacement has 28380609 rows, data has 28380265
#>[1] 28380265
#>[1] 28380609

1 Answer 1


The point ordering is expected to be preserved. Unless you explicitly discarded / rearranged / split some points the following should work.

las2$Intensity = las1$Intensity

But you could also chain the operations. normalize_intensity() should come first because it requires absolute elevations:

las = normalize_intensity(las, ...)
las = normalize_height(las, ...)

normalize_height() discards some points only if na.rm = TRUE. If for some reason you have already normalized and discarded some points you can always perform a join with data.table native syntax

# simulate intensity normalized dataset
LASfile <- system.file("extdata", "Megaplot.laz", package="lidR")
las1 = readLAS(LASfile)
las1$Intensity = as.integer(runif(npoints(las1), 0,500))

# Simulate height normalized dataset with missing points
las2 = readLAS(LASfile, filter = "-keep_random_fraction 0.98")

# join on XY ReturnNumber (and/or gpstime) 
joined = las1@data[, .(X,Y,ReturnNumber, Intensity)][las2@data[, .(X,Y,ReturnNumber)], on = .(X,Y,ReturnNumber)]

# Update intensity
las2$Intensity = joined$Intensity
  • Chaining is definitely the more simple approach. The reason for this question is that I have a large set of files which have already been height normalized. I was hoping to save some processing time by avoiding reapplying normalize_height()... But since I didn't run this function with na.rm = FALSE I think my only choice is to re-run normalize_height(). Do you agree?
    – Lucas
    Commented Nov 16, 2020 at 15:57
  • Actually, I ran the old lasnormalize() function with default parameters for na.rm. So it is likely that the few hundred points that were removed were "degenerated" right? I don't think there is any way around this.
    – Lucas
    Commented Nov 16, 2020 at 16:01
  • Degenerated points are not expected to be removed. No point is expected to be removed actually. If you have fewer points after normalization you either found a bug of forgot that you performed some extra post-processing
    – JRR
    Commented Nov 16, 2020 at 16:18
  • The documentation for the Wdegenerated parameter under the normalize_height() documentation implies that degenerated points are removed.
    – Lucas
    Commented Nov 16, 2020 at 16:22
  • 1
    Exact, my bad. You can indeed use gpstime and/or return number
    – JRR
    Commented Nov 16, 2020 at 16:39

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.