Skip to content

Writing support, error handling and simplifications #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Apr 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
3613896
Update dependencies, use las::Bounds and only keep copc-reader
yvind Nov 30, 2024
e59a612
update dependencies
yvind Dec 1, 2024
324f157
Simplifying, using more of las crate instead of copc-rs
yvind Dec 2, 2024
434e54e
copc reader simplified
yvind Dec 2, 2024
8dc0151
Update README.md
yvind Dec 2, 2024
9e5f95c
Update README.md
yvind Dec 2, 2024
f36ac40
make open pub again
yvind Dec 2, 2024
915ac5d
understanding the decompressor
yvind Dec 2, 2024
c542fd6
pre-writer branching
yvind Dec 3, 2024
72286e4
first implementation of writer
yvind Dec 9, 2024
5ad9ad9
Merge pull request #1 from oyhj1801/writer
yvind Dec 9, 2024
f76f173
qgis cant read the written files still
yvind Dec 11, 2024
d4b0a92
works, but the sub layers are not representative for the entire cloud
yvind Dec 12, 2024
b67ed09
pre rewrite
yvind Jan 13, 2025
a4ef54b
to do: merge small leaves for greedy and implement stochastic strat
yvind Jan 13, 2025
ffa6bc2
visability changes, still needed to revise writing strategie. How to …
yvind Jan 22, 2025
8267082
random adding funciton added, does not yet respect min node size
yvind Jan 24, 2025
8fa08c2
bug fix
yvind Jan 24, 2025
04bcc9a
converts geotiff crs to wkt crs, but still bad no distribution when w…
yvind Jan 24, 2025
8f23e69
wrong stochastics
yvind Jan 25, 2025
5b75323
Update README.md
yvind Feb 3, 2025
f8281c5
wkt crs vlr forwarding correction
yvind Feb 4, 2025
7b40306
Merge branch 'main' of https://github.com/oyhj1801/copc-rs
yvind Feb 4, 2025
01bb7d8
readme and default node max size update
yvind Apr 2, 2025
8d51f8c
readme update on writing WIP
yvind Apr 2, 2025
97639d4
read me changes and added my name to the MIT license
yvind Apr 29, 2025
cc359b9
Update examples
pka Apr 30, 2025
a7ed1df
Add minimal reader example
pka Apr 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 13 additions & 16 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,29 +1,26 @@
[workspace]
members = [".", "viewer"]
default-members = ["."]

[package]
name = "copc-rs"
version = "0.3.0"
authors = ["Pirmin Kalberer <[email protected]>"]
version = "0.5.0"
authors = ["Pirmin Kalberer <[email protected]>", "Øyvind Hjermstad @oyhj1801"]
edition = "2021"

description = "Cloud Optimized Point Cloud (COPC) reader."
description = "Cloud Optimized Point Cloud (COPC) reader and writer."
homepage = "https://github.com/pka/copc-rs"
repository = "https://github.com/pka/copc-rs"
readme = "README.md"
license = "MIT/Apache-2.0"
keywords = ["lidar", "pointcloud", "copc", "las", "geo"]
categories = ["science::geo", "rendering::data-formats"]
exclude = [
"tests/data",
]
keywords = ["lidar", "pointcloud", "copc", "las", "laz", "geo"]

[dependencies]
byteorder = "1.4.3"
las = "0.8.1"
laz = "0.8.2"
fastrand = "2.3.0"
las-crs = { git = "https://github.com/oyhj1801/las-crs" }
las = {version = "0.9.2", features = ["laz"]}
laz = "0.9.2"
log = "0.4.25"
thiserror = "2.0.6"
crs-definitions = "0.3.0"

[dev-dependencies]
http-range-client = "0.7.0"
env_logger = "0.10.0"
env_logger = "0.11.8"
http-range-client = "0.9.0" # default-features = false, features = ["ureq-sync"]
2 changes: 1 addition & 1 deletion LICENSE-MIT
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2020 Pirmin Kalberer
Copyright (c) 2025 Pirmin Kalberer, Øyvind Hjermstad

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
Expand Down
72 changes: 66 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,86 @@
[![crates.io version](https://img.shields.io/crates/v/copc-rs.svg)](https://crates.io/crates/copc-rs)
[![docs.rs docs](https://docs.rs/copc-rs/badge.svg)](https://docs.rs/copc-rs)

copc-rs is a rust library for reading and writing Cloud Optimized Point Cloud ([COPC](https://copc.io/)) data.
It utilizes the las and laz crates heavily and tries to offer a similiar API to las.

copc-rs is a library for reading Cloud Optimized Point Cloud ([COPC](https://copc.io/)) data.
## Usage examples


## Usage example
### Reader

```rust
let laz_file = BufReader::new(File::open("autzen-classified.copc.laz")?);
let mut copc_reader = CopcReader::open(laz_file)?;
let mut copc_reader = CopcReader::from_path("autzen-classified.copc.laz")?;
for point in copc_reader.points(LodSelection::Level(0), BoundsSelection::All)?.take(5) {
println!("Point coordinates: ({}, {}, {})", point.x, point.y, point.z);
}
```

Full example with bounds selection:
```rust
use copc_rs::{Bounds, BoundsSelection, CopcReader, LodSelection, Vector};

fn main() {
let mut copc_reader = CopcReader::from_path("./lidar.copc.laz").unwrap();

let bounds = Bounds {
min: Vector {
x: 698_100.,
y: 6_508_100.,
z: 0.,
},
max: Vector {
x: 698_230.,
y: 6_508_189.,
z: 2_000.,
},
};

for point in copc_reader
.points(LodSelection::Resolution(1.), BoundsSelection::Within(bounds))
.unwrap()
{
// do something with the points
}
}
```

Run an example:
```
cargo run --example copc_http
```

### Writer [[*]](#writing-is-still-a-wip)

```rust
use copc_rs::CopcWriter;
use las::Reader;

fn main() {
let mut las_reader = Reader::from_path("./lidar.las").unwrap();

let header = las_reader.header().clone();
let num_points = header.number_of_points() as i32;
let points = las_reader.points().filter_map(las::Result::ok);

let mut copc_writer = CopcWriter::from_path("./lidar.copc.laz", header, -1, -1).unwrap();

copc_writer.write(points, num_points).unwrap();

println!("{:#?}", copc_writer.copc_info());
}
```

## Writing is still a WIP

Writing of the octree structure seem to work, so spatial queries in full resolution on copc-rs written files should be good.
BUT the octree levels does not yet contain a similar point distribution as the whole cloud so results from resolution queries on copc-rs written files are wrong.
This means the written files will look bad in viewers.


I will look into it when I find time, for now I only need full resolution spatial queries in my current project anyway.

-oyhj1801

## Credits

This library depends heavily on the work of Thomas Montaigu (@tmontaigu) and Pete Gadomski (@gadomski).
This library depends heavily on the work of Thomas Montaigu (@tmontaigu) and Pete Gadomski (@gadomski), the authors of the laz and las crates.
4 changes: 2 additions & 2 deletions examples/copc_http.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use copc_rs::{BoundsSelection, CopcReader, LodSelection};
use http_range_client::HttpReader;

fn main() -> laz::Result<()> {
fn main() -> copc_rs::Result<()> {
env_logger::init();
let mut http_reader =
HttpReader::new("https://s3.amazonaws.com/hobu-lidar/autzen-classified.copc.laz");
// http_reader.set_min_req_size(1_048_576); // 1MB - 3 requests, 3'145'728 B
// http_reader.set_min_req_size(524288); // 512KB - 4 requests, 2'097'152 B
http_reader.set_min_req_size(262144); // 256KB - 5 requests, 1'310'720 B

let mut copc_reader = CopcReader::open(http_reader)?;
let mut copc_reader = CopcReader::new(http_reader)?;

let mut max_z: f64 = 0.0;
for point in copc_reader.points(LodSelection::Level(0), BoundsSelection::All)? {
Expand Down
7 changes: 3 additions & 4 deletions examples/copc_to_xyz.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use copc_rs::{BoundsSelection, CopcReader, LodSelection};
use std::env;
use std::fs::File;
use std::io::{BufReader, BufWriter, Write};
use std::io::{BufWriter, Write};
use std::path::Path;

fn main() -> laz::Result<()> {
fn main() -> copc_rs::Result<()> {
let lazfn = env::args().nth(1).expect("COPC file required");

let laz_file = BufReader::new(File::open(&lazfn)?);
let mut copc_reader = CopcReader::open(laz_file)?;
let mut copc_reader = CopcReader::from_path(&lazfn)?;

let dest = Path::new(&lazfn).with_extension("xyz");
println!("Writing {:?}", &dest);
Expand Down
7 changes: 2 additions & 5 deletions examples/print_points.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
use copc_rs::{BoundsSelection, CopcReader, LodSelection};
use std::env;
use std::fs::File;
use std::io::BufReader;

fn main() -> laz::Result<()> {
fn main() -> copc_rs::Result<()> {
let lazfn = env::args().nth(1).expect("COPC file required");

let laz_file = BufReader::new(File::open(&lazfn)?);
let mut copc_reader = CopcReader::open(laz_file)?;
let mut copc_reader = CopcReader::from_path(&lazfn)?;
for (i, point) in copc_reader
.points(LodSelection::Level(0), BoundsSelection::All)?
.enumerate()
Expand Down
117 changes: 0 additions & 117 deletions src/bounds.rs

This file was deleted.

Loading