#lidar #pointcloud #las #gis #asprs

las

Read and write point clouds stored in the ASPRS las file format

26 releases

new 0.8.1 Mar 14, 2023
0.8.0 Nov 30, 2022
0.7.8 Nov 28, 2022
0.7.7 Jul 15, 2022
0.2.0 Jun 25, 2015

#130 in Data structures

Download history 225/week @ 2022-11-28 179/week @ 2022-12-05 188/week @ 2022-12-12 156/week @ 2022-12-19 97/week @ 2022-12-26 136/week @ 2023-01-02 214/week @ 2023-01-09 181/week @ 2023-01-16 218/week @ 2023-01-23 290/week @ 2023-01-30 159/week @ 2023-02-06 244/week @ 2023-02-13 235/week @ 2023-02-20 269/week @ 2023-02-27 273/week @ 2023-03-06 217/week @ 2023-03-13

1,016 downloads per month
Used in 6 crates

MIT license

205KB
3.5K SLoC

las-rs

GitHub Workflow Status Crates.io docs.rs Crates.io Contributor Covenant

Read and write ASPRS las files natively with rust.

[dependencies]
las = "0.8"

To include laz support:

[dependencies]
las = { version = "0.8", features = ["laz"] }

lib.rs:

Read and write ASPRS LAS point cloud data.

Reading

Create a Reader from a Path:

use las::Reader;
let reader = Reader::from_path("tests/data/autzen.las").unwrap();

Or anything that implements Read:

use std::io::BufReader;
use std::fs::File;
use las::Reader;
let read = BufReader::new(File::open("tests/data/autzen.las").unwrap());
let reader = Reader::new(read).unwrap();

Prefer BufRead

Your performance will be better if your Read is actually a BufRead. Reader::from_path takes care of this for you, but Reader::new doesn't.

Read points

Read points one-by-one with Reader::read:

use las::{Read, Reader};
let mut reader = Reader::from_path("tests/data/autzen.las").unwrap();
let point = reader.read().unwrap().unwrap();

Or iterate over all points with Reader::points:

use las::{Read, Reader};
let mut reader = Reader::from_path("tests/data/autzen.las").unwrap();
for wrapped_point in reader.points() {
    let point = wrapped_point.unwrap();
    println!("Point coordinates: ({}, {}, {})", point.x, point.y, point.z);
    if let Some(color) = point.color {
        println!("Point color: red={}, green={}, blue={}",
            color.red,
            color.green,
            color.blue,
        );
    }
}

Writing

Create a Writer from a Write and a Header:

use std::io::Cursor;
use las::{Writer, Header};
let write = Cursor::new(Vec::new());
let header = Header::default();
let writer = Writer::new(write, header).unwrap();

You can also write out to a path (automatically buffered with BufWriter):

use las::Writer;
let writer = Writer::from_path("/dev/null", Default::default());

Use a Builder to customize the las data:

use std::io::Cursor;
use las::{Writer, Builder};
use las::point::Format;

let mut builder = Builder::from((1, 4));
builder.point_format = Format::new(2).unwrap();
let header = builder.into_header().unwrap();

let write = Cursor::new(Vec::new());
let writer = Writer::new(write, header).unwrap();

If compiled with laz you can compress the data written

use std::io::Cursor;
use las::{Writer, Builder};
use las::point::Format;

let mut builder = Builder::from((1, 4));
builder.point_format = Format::new(2).unwrap();
// asking to compress data
builder.point_format.is_compressed = true;
let header = builder.into_header().unwrap();

let write = Cursor::new(Vec::new());
let is_compiled_with_laz = cfg!(feature = "laz");


let result =  Writer::new(write, header);
if is_compiled_with_laz {
    assert_eq!(result.is_ok(), true);
} else {
   assert_eq!(result.is_err(), true);
}

The from_path will use the extension of the output file to determine wether the data should be compressed or not 'laz' => compressed 'las' => not compressed

Prefer BufWrite

Just like the Reader, your performance will improve greatly if you use a BufWrite instead of just a Write.

Write points

Write points one at a time:

use std::io::Cursor;
use las::{Write, Writer, Point};
let mut writer = Writer::default();
let point = Point { x: 1., y: 2., z: 3., ..Default::default() };
writer.write(point).unwrap();

Dependencies

~1.8–2.6MB
~52K SLoC