r-lidar / lidR

Airborne LiDAR data manipulation and visualisation for forestry application
https://CRAN.R-project.org/package=lidR
GNU General Public License v3.0
582 stars 130 forks source link

Access Violation in writeLAS #709

Open AMarthaller opened 12 months ago

AMarthaller commented 12 months ago

I'm trying to add a point index to my las file, so I can coordinate points between tools. writeLAS is causing an AV and R.exe is shutting down.

las <- readLAS(...)
data_length <- nrow(las@data)
indices <- seq(data_length)
las <- add_lasattribute(las, x = indices, name = "Index", desc = "Unique point identifier")
writeLAS(las, ...)

My overall goal is to be able to edit point clouds in other tools like cloud compare, then bring this back into lidR and use that data to aid in classification. e.g. isolate a building in cloud compare, classify those points in lidR.

Something like:

las <- classify_poi(las, 6L, 'Index in OtherLas Indices') # pseudo.

I tried using just XYZ to line things up, but I think the round trip through cloud compare might be causing small changes in XYZ that don't compare well even with tolerance.

Jean-Romain commented 12 months ago

I confirm a memory access violation. MRE:

library(lidR)

f <- system.file("extdata", "Megaplot.laz", package="lidR")
las <- readLAS(f)
data_length <- nrow(las@data)
indices <- seq(data_length)
las <- add_lasattribute(las, x = indices, name = "Index", desc = "Unique point identifier")

g = tempfile(fileext = ".las")
writeLAS(las, g)

las2 = readLAS(g)

In Rstudio, no crash but the data is corrupted

las@data[,c(1:3,17)]
              X       Y     Z Index
    1: 684992.2 5018007 17.30     1
    2: 684992.6 5018006 17.03     2
    3: 684993.0 5018005 16.14     3
    4: 684993.1 5018006 11.10     4
    5: 684993.2 5018001 17.58     5
   ---                             
81586: 684945.1 5018004  2.45 81586
81587: 684944.3 5018007 13.20 81587
81588: 684946.4 5018005  2.40 81588
81589: 684947.4 5018006  0.00 81589
81590: 684947.2 5018007  0.86 81590

las2@data[,c(1:3,17)]
              X       Y     Z Index
    1: 684992.2 5018007 17.30     1
    2: 684992.6 5018006 17.03     0
    3: 684993.0 5018005 16.14     0
    4: 684993.1 5018006 11.10     0
    5: 684993.2 5018001 17.58     0
   ---                             
81586: 684945.1 5018004  2.45     0
81587: 684944.3 5018007 13.20     0
81588: 684946.4 5018005  2.40     0
81589: 684947.4 5018006  0.00     0
81590: 684947.2 5018007  0.86     0

When using reprex it crashes.

Jean-Romain commented 11 months ago

Investigation notes to myself.

Using rlas it works

  f <- system.file("extdata", "example.las", package="rlas")
  g <- tempfile(fileext = ".las")
  e <- 1:30

  # Read a file
  dat <- rlas::read.las(f)
  hea <- rlas::read.lasheader(f)

  # Add extra bytes
  hea <- rlas::header_add_extrabytes(hea, data = e, name = "Index", desc = "Unique point identifier")
  dat$Index <- e

  # write
  rlas::write.las(g, hea, dat)

  # read back
  las2 = rlas::read.las(g)

Using lidR it fails

  f <- system.file("extdata", "example.las", package="rlas")
  g <- tempfile(fileext = ".las")
  e <- 1:30

  las <- lidR::readLAS(f)
  las <- lidR::add_lasattribute(las, x = e, name = "Index", desc = "Unique point identifier")
  lidR::writeLAS(las, g)
  las3 = lidR::readLAS(g)

Despite the header are identical. Valgrind reports:

==325076== Conditional jump or move depends on uninitialised value(s)
==325076==    at 0x23038098: RLASExtrabyteAttributes::set_attribute(int, LASpoint*) (in /home/jr/R/x86_64-pc-linux-gnu-library/4.3/rlas/libs/rlas.so)