Hi Martin,
I have a lidar dataset that is composed of 4 billion classified (ground vs. non-ground) points and currently partitioned into 105 separate 1000 x 1000 m tiles. I would like to try using LAStools (i.e., lastile vs. lasclip vs. las2las) to retile the entire dataset using a 500 x 500 m tile size and user-defined grid origin. Ideally, I would like the tiling procedure to follow a consistent boundary logic where points are included in a tile: IF (pt_x >= x_min & pt_x < x_max & pt_y >= y_min & pt_y < y_max), so that no lidar points will be duplicated or excluded from the dataset. The tiles should also be temporally buffered by some small margin (10 to 25 m) to avoid edge artifacts when normalizing laser elevations to heights above the ground surface using lasheight. Finally, I’ll want to remove the buffer from the tiles containing laser heights so that I can compute a broad range of gridded vegetation metrics using existing software. Could you please let me know the most efficient way to do this with LAStools.
Best regards and many thanks,
Gordon
Hi Martin,
Thank you for the helpful response. The one detail that did not appear was how to invoke a user-defined origin. It is often the case that gridded lidar data will be spatially integrated with other types of remotely sensed data (digital colour photography, satellite imagery, radar, etc.). Therefore, it is helpful that for a lidar analyst to generate a grid that shares the same origin point and cell size as the other spatial datasets (i.e., grid cells from disparate dataset will overlay perfectly upon one another). Is it possible to input a specific grid origin in lastile or is it arbitrarily defined by the bounding box (range rectangle) the entire dataset?
I’ll happily report any success or failure with the workflow you kindly supplied. I would also license LAStools for any type of production work. This effort is purely to see how easily I can accomplish the task with LAStools. Your efforts are greatly appreciated.
Thanks,
Gordon
Hi Martin,
A user-defined grid origin (ll_x, ll_y) would simply provide a predetermined starting point to build a tiling scheme that would cover the (x,y)-dimensions of the entire lidar dataset. The benefit here (assuming that lidar points will be used to generate gridded surfaces; e.g., vegetation metrics) is that all lidar-derived grid cells (pixels), once mosaicked, will sit directly upon other existing GIS raster layers or remotely sensed imagery without having to resample any of the datasets. Starting the tiling scheme on the lower left-hand corner of the point cloud bounding box does not allow the flexibility required to spatially integrate lidar-derived gridded data with other raster datasets unless grid-cell resampling takes place. I wrote a R program last evening that builds a tiling scheme with a user-defined origin (see below). The lidar point cloud would still fall entirely within the bounds of this tiling scheme; however, the resultant grid cells (pixels) would now assume the correct position according to the other datasets with which they will be spatially integrated with. Please let me know if this still does not make sense to you.
Thanks,
Gordon
# This R program builds a lidar tiling scheme in shape file format.
# load libraries.
library(shapefiles)
# set input parameters.
# range rectangle of tiling grid.
x_min = 1063323.805
y_min = 490409.75
x_max = 1086323.805
y_max = 508909.75
# tile size
tile_size = 500
buffer = 10
# number of columns and rows in tiling scheme.
num_col = ceiling(x_max - x_min)/tile_size
num_row = ceiling(y_max - y_min)/tile_size
# create data table to store coordinates of polygon vertices.
dd = data.frame(matrix(0, nrow = (5 * num_col * num_row), ncol= 3))
names(dd) = c("Id", "X", "Y")
# create data table to store table attributes.
ddTable = data.frame(matrix(0, nrow = (num_col * num_row), ncol = 11))
names(ddTable) = c("Id", "Block_id","buffer", "ll_x", "ll_y", "ul_x", "ul_y", "ur_x", "ur_y", "lr_x", "lr_y")
# loop through grid and assign xy coordinates for vertices, block_id, and tile_id.
tile_num = 0
row_id = 0
for (i in 1:num_col){
for (j in 1:num_row){
# compute table values.
# sequential tile number.
tile_num = tile_num + 1
# concatentate tile id.
tile_id = paste("chm_", i - 1, "_", j - 1, sep="")
# compute vertices of key points.
# lower left corner.
ll_x = x_min + ((i - 1) * tile_size) - buffer
ll_y = y_min + ((j - 1) * tile_size) - buffer
# upper left corner.
ul_x = ll_x
ul_y = ll_y + tile_size + 2 * buffer
# upper right corner.
ur_x = ul_x + tile_size + 2 * buffer
ur_y = ul_y
# lower right corner.
lr_x = ur_x
lr_y = ll_y
# load data in matrices for points.
for (k in 1:5){
row_id = row_id + 1
if (k == 1){
dd$Id[row_id] = tile_num
dd$X[row_id] = ll_x
dd$Y[row_id] = ll_y
} else if (k == 2){
dd$Id[row_id] = tile_num
dd$X[row_id] = ul_x
dd$Y[row_id] = ul_y
} else if (k == 3){
dd$Id[row_id] = tile_num
dd$X[row_id] = ur_x
dd$Y[row_id] = ur_y
} else if (k == 4){
dd$Id[row_id] = tile_num
dd$X[row_id] = lr_x
dd$Y[row_id] = lr_y
} else if (k == 5){
dd$Id[row_id] = tile_num
dd$X[row_id] = ll_x
dd$Y[row_id] = ll_y
}
}
# load data matrices for attribute table.
ddTable$Id[tile_num] = tile_num
ddTable$Block_id[tile_num] = tile_id
ddTable$buffer[tile_num] = buffer
# range rectangle for each tile
ddTable$ll_x[tile_num] = ll_x
ddTable$ll_y[tile_num] = ll_y
ddTable$ul_x[tile_num] = ul_x
ddTable$ul_y[tile_num] = ul_y
ddTable$ur_x[tile_num] = ur_x
ddTable$ur_y[tile_num] = ur_y
ddTable$lr_x[tile_num] = lr_x
ddTable$lr_y[tile_num] = lr_y
}
}
# create shape file.
ddShapefile = convert.to.shapefile(dd, ddTable, "Id", 5)
write.shapefile(ddShapefile, "e:\\temp\\bb_analysis_grid_10m_buffer", arcgis=F)
Hi Martin,Does this same logic apply for the "-inside_rectangle" option for las2las and las2txt?ie: IF (pt_x >= x_min & pt_x < x_max & pt_y >= y_min & pt_y < y_max)RegardsAndrew
http://rapidlasso.comhttp://facebook.com/LAStools
Be social with LAStools at
http://twitter.com/LAStools
http://linkedin.com/groups/LAStools-4408378
Manage your settings at
http://groups.google.com/group/lastools/subscribe
--
Download LAStools at
http://lastools.org
http://rapidlasso.com
Be social with LAStools at
http://facebook.com/LAStools
http://twitter.com/LAStools
http://linkedin.com/groups/LAStools-4408378
Manage your settings at
http://groups.google.com/group/lastools/subscribe
--
Download LAStools at
http://lastools.org