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.LASDataset
— Typestruct 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 frompointcloud::TypedTables.FlexTable
: Point cloud data stored in a Tabular format for conveniencevlrs::Vector{LasVariableLengthRecord}
: Collection of Variable Length Records from the LAS fileevlrs::Vector{LasVariableLengthRecord}
: Collection of Extended Variable Length Records from the LAS fileuser_defined_bytes::Vector{UInt8}
: Extra user bytes packed between the Header block and the first VLR of the source LAS fileunit_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
You can query the contents of your LASDataset
by using the following functions:
LASDatasets.get_header
— Functionget_header(las::LASDataset) -> LasHeader
Extract the header information from a LASDataset
las
LASDatasets.get_pointcloud
— Functionget_pointcloud(las::LASDataset) -> TypedTables.FlexTable
Extract point cloud data as a Table from a LASDataset
las
LASDatasets.get_vlrs
— Functionget_vlrs(las::LASDataset) -> Vector{LasVariableLengthRecord}
Extract the set of Variable Length Records from a LASDataset
las
LASDatasets.get_evlrs
— Functionget_evlrs(
las::LASDataset
) -> Vector{LasVariableLengthRecord}
Extract the set of Extended Variable Length Records from a LASDataset
las
LASDatasets.get_user_defined_bytes
— Functionget_user_defined_bytes(las::LASDataset) -> Vector{UInt8}
Extract the set of user-defined bytes from a LASDataset
las
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_las
— Functionload_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 fromfields
: Name of the LAS point fields to extract as columns in the output data. If set tonothing
, ingest all available columns. DefaultDEFAULT_LAS_COLUMNS
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_pointcloud
— Functionload_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
LASDatasets.load_header
— Functionload_header(file_name::AbstractString) -> LasHeader
Ingest a LAS header from a file
LASDatasets.load_vlrs
— Functionload_vlrs(
file_name::AbstractString,
header::LasHeader
) -> Any
Ingest a set of variable length records from a LAS file
load_vlrs(file_name, header)
defined at /home/runner/work/LASDatasets.jl/LASDatasets.jl/src/read.jl:57
.
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_las
— Functionsave_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 intopointcloud
: Point cloud data in a tabular format
Keyword Arguments
vlrs
: Collection of Variable Length Records to write to the LAS file, defaultLasVariableLengthRecord[]
evlrs
: Collection of Extended Variable Length Records to write to the LAS file, defaultLasVariableLengthRecord[]
user_defined_bytes
: Any user-defined bytes to write in between the VLRs and point records, defaultUInt8[]
scale
: Scaling factor applied to points on writing, defaultLASDatasets.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
.
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!
— Functionadd_column!(
las::LASDataset,
column::Symbol,
values::AbstractArray{T, 1}
)
Add a column with name column
and set of values
to a las
dataset
LASDatasets.merge_column!
— Functionmerge_column!(
las::LASDataset,
column::Symbol,
values::AbstractVector
) -> Any
Merge a column with name column
and a set of values
into a las
dataset
LASDatasets.add_points!
— Functionadd_points!(
las::LASDataset,
points::AbstractVector{<:NamedTuple}
)
Add a collection of points
to a LASDataset
, las
. Updates header information to ensure dataset consistency
LASDatasets.remove_points!
— Functionremove_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
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!
— Functionadd_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
LASDatasets.remove_vlr!
— Functionremove_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
LASDatasets.set_superseded!
— Functionset_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
set_superseded!(
las::LASDataset,
vlr::LasVariableLengthRecord
) -> UInt16
Mark a VLR vlr
as superseded in a dataset las