High-Level Interface

LASDatasets.jl provides a number of high-level functions to easily manipulate your LAS data.

LAS Datasets

A LASDataset is a wrapper around data from a LAS file that acts as an interface to read, write and modify your LAS data. In general, a LAS file will have the following contents:

  • File Header: contains metadata about the file contents and byte layout
  • VLRs: Variable length records of data that appear before the point records
  • User-defined bytes: Additional bytes included after the last VLR and before the first point record
  • LAS point records: data assigned to each point in the point cloud (following a specific format specified in the header)
  • EVLRs : Extended VLRs that come after the point records (allows larger data payloads)

These are contained in a LASDataset as follows

LASDatasets.LASDatasetType
struct LASDataset

A wrapper around a LAS dataset. Contains point cloud data in tabular format as well as metadata and VLR's/EVLR's

  • header::LasHeader: The header from the LAS file the points were extracted from

  • pointcloud::TypedTables.FlexTable: Point cloud data stored in a Tabular format for convenience

  • vlrs::Vector{LasVariableLengthRecord}: Collection of Variable Length Records from the LAS file

  • evlrs::Vector{LasVariableLengthRecord}: Collection of Extended Variable Length Records from the LAS file

  • user_defined_bytes::Vector{UInt8}: Extra user bytes packed between the Header block and the first VLR of the source LAS file

  • unit_conversion::StaticArraysCore.SVector{3, Float64}: Unit conversion factors applied to each axis when the dataset is ingested. This is reversed when you save the dataset to keep header/coordinate system information consistent

source

You can query the contents of your LASDataset by using the following functions:

LASDatasets.get_vlrsFunction
get_vlrs(las::LASDataset) -> Vector{LasVariableLengthRecord}

Extract the set of Variable Length Records from a LASDataset las

source
LASDatasets.get_evlrsFunction
get_evlrs(
    las::LASDataset
) -> Vector{LasVariableLengthRecord}

Extract the set of Extended Variable Length Records from a LASDataset las

source

Reading

To read the entire contents of a LAS or LAZ file, you can use the load_las function. This returns a LASDataset with all the properties listed above. You also have the option of only loading certain point fields.

# read the full dataset
las = load_las("example.las")

# only extract position and classification
las = load_las("example.las", [:position, :classification])

Note that when reading data, the position units for your points are automatically converted to metres provided they are specified correctly in an OGC Coordinate System WKT string. If not, you can still manually specify what units you would like to convert from (note that they must match the unit naming convention given by OGC WKTs), e.g.

las = load_las("example.las"; convert_x_y_units = "us-ft")
LASDatasets.load_lasFunction
load_las(file_name::AbstractString; ...) -> LASDataset
load_las(
    file_name::AbstractString,
    fields;
    kwargs...
) -> LASDataset

Load a LAS dataset from a source file

Arguments

  • file_name : Name of the LAS file to extract data from
  • fields : Name of the LAS point fields to extract as columns in the output data. If set to nothing, ingest all available columns. Default DEFAULT_LAS_COLUMNS
source

You can also choose to just load the points themselves (in tabular format), header or VLRs rather than the whole datsset by using the following functions:

LASDatasets.load_pointcloudFunction
load_pointcloud(
    file_name::AbstractString;
    ...
) -> TypedTables.FlexTable
load_pointcloud(
    file_name::AbstractString,
    fields::Union{Nothing, AbstractVector{Symbol}};
    kwargs...
) -> TypedTables.FlexTable

Ingest LAS point data in a tabular format

source

Writing

You can write the contents of your LASDataset to a file by using the save_las function. Note that this takes either a LASDataset on its own or a tabular point cloud with (E)VLRs and user-defined bytes supplied separately.

LASDatasets.save_lasFunction
save_las(
    file_name::AbstractString,
    pointcloud::AbstractVector{<:NamedTuple};
    vlrs,
    evlrs,
    user_defined_bytes,
    scale,
    kwargs...
)

Saves a pointcloud to LAS or LAZ. The appropriate LAS version and point format is inferred from the contents of your point cloud

Arguments

  • file_name : Name of the LAS file to save the data into
  • pointcloud : Point cloud data in a tabular format

Keyword Arguments

  • vlrs : Collection of Variable Length Records to write to the LAS file, default LasVariableLengthRecord[]
  • evlrs : Collection of Extended Variable Length Records to write to the LAS file, default LasVariableLengthRecord[]
  • user_defined_bytes : Any user-defined bytes to write in between the VLRs and point records, default UInt8[]
  • scale : Scaling factor applied to points on writing, default LASDatasets.POINT_SCALE

save_las(
    file_name,
    pointcloud;
    vlrs,
    evlrs,
    user_defined_bytes,
    scale,
    kwargs...
)

defined at /home/runner/work/LASDatasets.jl/LASDatasets.jl/src/write.jl:18.

source

For example, if you have the whole dataset:

save_las("my_las.las", las)

Alternatively, if you just have the point cloud data as a Table:

using StaticArrays
using TypedTables

pc = Table(position = rand(SVector{3, Float64}, 10), classification = rand(UInt8, 10))
save_las("my_las.las", pc)

Note that when you supply just the point cloud outside of a LASDataset, LASDatasets.jl will automatically construct the appropriate header for you so you don't need to worry about the specifics of appropriate point formats etc.

Modifying LAS Contents

You can modify point fields in your LASDataset by adding new columns or merging in values from an existing vector. Additionally, you can add and remove points from a dataset. When adding points, the user is responsible for correctly setting the appropriate fields (e.g. synthetic flags).

LASDatasets.add_column!Function
add_column!(
    las::LASDataset,
    column::Symbol,
    values::AbstractArray{T, 1}
)

Add a column with name column and set of values to a las dataset

source
LASDatasets.merge_column!Function
merge_column!(
    las::LASDataset,
    column::Symbol,
    values::AbstractVector
) -> Any

Merge a column with name column and a set of values into a las dataset

source
LASDatasets.add_points!Function
add_points!(
    las::LASDataset,
    points::AbstractVector{<:NamedTuple}
)

Add a collection of points to a LASDataset, las. Updates header information to ensure dataset consistency

source
LASDatasets.remove_points!Function
remove_points!(
    las::LASDataset,
    idxs::Union{AbstractUnitRange, AbstractVector{<:Integer}}
)

Remove a set of points stored at indices idxs from a las dataset. Updates header information to ensure consistency

source

For example, if you want to add a set of synthetic points to your dataset, you can run:

las = load_las("my_las.las")
# note - we need to set a synthetic column here for the existing points before we append points with this field
add_column!(las, :synthetic, falses(number_of_points(las)))
synthetic_points = Table(position = rand(SVector{3, Float64}, 5), classification = rand(UInt8, 5), synthetic = trues(5))
add_points!(las, synthetic_points)

You can remove points from your data using the remove_points! function and specifying the indices of the points you wish to delete (these will be indexing into the list of points in order). E.g.

remove_points!(las, 11:15)

Note that you can also modify the contents of your points by acting directly on the tabular pointcloud data. Note: this should not be used to add/remove points or point fields, since this will cause a conflict between the data in your points and the file header. Intended use is for operations that preserve the number of points and the existing fields. For example:

pc = get_pointcloud(las)

# shuffle the order of the points based on point positions
pc = pc[sortperm(pc.position)]

# set all classifications to 0
pc.classification .= 0

You can also add or remove (E)VLRs using the following functions, and set an existing (E)VLR as superseded if it's an old copy of a record.

LASDatasets.add_vlr!Function
add_vlr!(
    las::LASDataset,
    vlr::LasVariableLengthRecord
) -> Union{Nothing, Int64}

Add a vlr into the set of VLRs in a LAS dataset las. Note that this will modify the header content of las, including updating its LAS version to v1.4 if vlr is extended

source
LASDatasets.remove_vlr!Function
remove_vlr!(
    las::LASDataset,
    vlr::LasVariableLengthRecord
) -> Union{Nothing, Int64}

Remove a vlr from set of VLRs in a LAS dataset las. Note that this will modify the header content of las

source
LASDatasets.set_superseded!Function
set_superseded!(vlr::LasVariableLengthRecord) -> UInt16

Mark a VLR as "superseded", meaning it has been replaced by a newer record when modifying the LAS file. Note: The LAS spec only allows for 1 superseded record per LAS file

source
set_superseded!(
    las::LASDataset,
    vlr::LasVariableLengthRecord
) -> UInt16

Mark a VLR vlr as superseded in a dataset las

source