r-lidar / rlas

R package to read and write las and laz files used to store LiDAR data
https://cran.r-project.org/package=rlas
GNU General Public License v3.0
34 stars 14 forks source link

read.las segfault with "-keep_class" when greater than 31 #26

Closed Buckmaster7 closed 5 years ago

Buckmaster7 commented 5 years ago

Edit: issue moved from lidR to rlas

First off thank you for this very helpful package. I'm not sure this is a bug or a known issue but...

I frequently use LAS files with classification numbers greater than 31. When I use readLAS with a -keep_class filter greater than 31 I get a massive failure (R studio closes and must restart). To clarify this is an example of the code that causes the massive failure:

read.las("File_123.las", filter = "-keep_class 186")  

This same line of code works fine if the -keep_class number is <= 31. It would be great if this very helpful code would work for higher classification numbers.

Jean-Romain commented 5 years ago

We must consider two things here. One comes from you, the other one comes from LASlib or rlas

Firstly, a classification above 31 does not exist. The classification attribute is stored on 5 bits and thus the maximum classification value is 2⁵-1 = 31 (see ASPRS LAS specification).

What is the expected behavior of -keep_class 186? It should either return 0 point or throw an error but it will never return points with a class equal to 186 because this class cannot even be stored in the file.

That being said it did not return 0 point or throw an error. The behavior was a segfault. This is not a bug in lidR but in LASlib the C++ library that read las files internally via my rlas package .

Let test what happens with lastools

las2las -i input.las -o output.las -keep_class 186 
ERROR: cannot keep classification 186 because it is larger than 31

It means either that:

Anyway this is a bug with the package rlas not lidR. I move this issue to the correct repo.

Jean-Romain commented 5 years ago

After reading the source code the good answer is: rlas does not catch this error.

Bug confirmed. Thank you for reporting.

Buckmaster7 commented 5 years ago

Thanks Jean-Romain for getting back so quickly! I’m new to R and new to reporting on message boards so I hope my message made sense. Happy New Year

Jean-Romain commented 5 years ago

Bug fixed. Now fails with an error:

library(rlas)
lazfile <- system.file("extdata", "example.laz", package="rlas")
lasdata <- read.las(lazfile, filter = "-keep_class 333")
#> ERROR: cannot keep classification 333 because it is larger than 31
#> Error in C_reader(ifiles, ofile, select, filter, filter_wkt) : 
#>   Filter error see message above. 
Jean-Romain commented 5 years ago

Are you using LAS 1.4 file format with point format 6? In that case class 186 exist. rlas now support LAS 1.4. See #27 . But anyway filter = "-keep_class 186" is not supported.

Buckmaster7 commented 5 years ago

Yes – you are correct, that appears to be directly related as to why I ran into problems. This is a bit of a learning process for me although I’ve worked several times with LAS point cloud files I never clued into the limits on the classification codes. Although R is a bit of a steep learning curve for me (I’m a SAS guy), I thoroughly enjoy using the tools you have developed. They are lightning fast - especially compared to working with the point cloud in ARCGIS. Thanks again!

Jean-Romain commented 5 years ago

They are lightning fast - especially compared to working with the point cloud in ARCGIS

That makes me happy. I'm working hard on speed improvement. I'm glad to know that I beat ARCGIS :wink:

Jean-Romain commented 5 years ago

If you are working with LAS 1.4 and format > 6, digging int the source code of LAS lib I found -keep_extended_class and -drop_extended_class

rlas::read.las("las14_prf6.las", filter = "-keep_extended_class 186")

And actually it is documented in rlas:::lasfilterusage :wink:

Buckmaster7 commented 5 years ago

Awesome! Thanks for that – I’ll give that a try.

Jean-Romain commented 5 years ago

Yes but be careful, the current released version of rlas only has a partial support of LAS1.4 files. Thus the filter will work but the data actually read will not be correct. Update to rlas 1.3.0

devtools::install_github("Jean-Romain/rlas")

To support LAS 1.4 as well as LAS <= 1.3 in a consistent way I introduced a minor incompatibility with lidR 2.0.0. So you must also install lidR 2.0.1 to do not encounter any crash.

devtools::install_github("Jean-Romain/lidR")