Skip to content

Commit

Permalink
fix: start of first evlr
Browse files Browse the repository at this point in the history
  • Loading branch information
gadomski committed Aug 15, 2024
1 parent ee921b9 commit 13729f1
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 16 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Reorganize reading, including removing the lifetime specifier on `Reader` ([#89](https://github.com/gadomski/las-rs/pull/89))
- Conslidate errors to a single enum ([#87](https://github.com/gadomski/las-rs/pull/87))

### Fixed

- Start of first EVLR ([#91](https://github.com/gadomski/las-rs/pull/91))

## Deprecated

- `Read` trait ([#88](https://github.com/gadomski/las-rs/pull/88))
Expand Down
2 changes: 2 additions & 0 deletions src/header/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ impl Builder {
if self.version.supports::<Evlrs>() || evlr.has_large_data() {
evlrs.push(evlr);
} else {
log::warn!("moving Evlr to Vlr because version does not support Evlrs: user_id={}, record_id={}, description={}", evlr.user_id, evlr.record_id, evlr.description);
vlrs.push(evlr);
}
}
Expand Down Expand Up @@ -237,6 +238,7 @@ impl Builder {
padding: self.padding,
point_format: self.point_format,
point_padding: self.point_padding,
start_of_first_evlr: None,
system_identifier: self.system_identifier,
transforms: self.transforms,
version: self.version,
Expand Down
16 changes: 13 additions & 3 deletions src/header/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ pub struct Header {
padding: Vec<u8>,
point_format: Format,
point_padding: Vec<u8>,
start_of_first_evlr: Option<u64>,
system_identifier: String,
transforms: Vector<Transform>,
version: Version,
Expand Down Expand Up @@ -524,6 +525,10 @@ impl Header {
Ok(())
}

pub(crate) fn set_start_of_first_evlr(&mut self, start_of_first_evlr: u64) {
self.start_of_first_evlr = Some(start_of_first_evlr);
}

fn global_encoding(&self) -> u16 {
let mut bits = self.gps_time_type.into();
if self.has_synthetic_return_numbers {
Expand Down Expand Up @@ -631,9 +636,13 @@ impl Header {
} else if n > u32::MAX as usize {
Err(Error::TooManyEvlrs(n))
} else {
let start_of_first_evlr = self.point_data_len()
+ self.point_padding.len() as u64
+ u64::from(self.offset_to_point_data()?);
let start_of_first_evlr = if let Some(start_of_fist_evlr) = self.start_of_first_evlr {
start_of_fist_evlr
} else {
self.point_data_len()
+ self.point_padding.len() as u64
+ u64::from(self.offset_to_point_data()?)
};
Ok(Some(raw::header::Evlr {
start_of_first_evlr,
number_of_evlrs: n as u32,
Expand Down Expand Up @@ -681,6 +690,7 @@ impl Default for Header {
padding: Vec::new(),
point_format: Default::default(),
point_padding: Vec::new(),
start_of_first_evlr: None,
system_identifier: "las-rs".to_string(),
transforms: Default::default(),
version: Default::default(),
Expand Down
4 changes: 4 additions & 0 deletions src/writer/las.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ impl<W: Write + Seek + Send> WritePoint<W> for PointWriter<W> {
&self.header
}

fn header_mut(&mut self) -> &mut Header {
&mut self.header
}

fn done(&mut self) -> Result<()> {
Ok(())
}
Expand Down
38 changes: 38 additions & 0 deletions src/writer/laz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,46 @@ impl<W: Write + Seek + Send> WritePoint<W> for PointWriter<'_, W> {
&self.header
}

fn header_mut(&mut self) -> &mut Header {
&mut self.header
}

fn done(&mut self) -> Result<()> {
self.compressor.done()?;
Ok(())
}
}

#[cfg(test)]
mod tests {
use crate::{Builder, Point, Reader, Vlr, Writer};
use std::io::Cursor;

#[test]
fn evlr() {
let mut vlr = Vlr::default();
vlr.user_id = "@gadomski".to_string();
vlr.record_id = 42;
vlr.description = "A great vlr".to_string();
vlr.data = b"some data".to_vec();
let mut builder = Builder::default();
builder.version.minor = 4;
builder.point_format.is_compressed = true;
builder.evlrs.push(vlr);
let header = builder.into_header().unwrap();
let cursor = Cursor::new(Vec::new());
let mut writer = Writer::new(cursor, header).unwrap();
for i in 0..5 {
let mut point = Point::default();
point.return_number = i;
writer.write_point(point).unwrap();
}
let cursor = writer.into_inner().unwrap();
let reader = Reader::new(cursor).unwrap();
let evlr = &reader.header().evlrs()[0];
assert_eq!(evlr.user_id, "@gadomski");
assert_eq!(evlr.record_id, 42);
assert_eq!(evlr.description, "A great vlr");
assert_eq!(evlr.data, b"some data");
}
}
33 changes: 20 additions & 13 deletions src/writer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ trait WritePoint<W: std::io::Write>: Send {
fn into_inner(self: Box<Self>) -> W;
fn get_mut(&mut self) -> &mut W;
fn header(&self) -> &Header;
fn header_mut(&mut self) -> &mut Header;
fn done(&mut self) -> Result<()>;
}

Expand All @@ -67,6 +68,9 @@ impl<W: std::io::Write> WritePoint<W> for ClosedPointWriter {
fn header(&self) -> &Header {
unreachable!()
}
fn header_mut(&mut self) -> &mut Header {
unreachable!()
}
fn done(&mut self) -> Result<()> {
unreachable!()
}
Expand Down Expand Up @@ -188,6 +192,11 @@ impl<W: 'static + std::io::Write + Seek + Send> Writer<W> {

let point_padding = self.header().point_padding().clone();
self.point_writer.get_mut().write_all(&point_padding)?;

let start_of_first_evlr = self.point_writer.get_mut().stream_position()?;
self.point_writer
.header_mut()
.set_start_of_first_evlr(start_of_first_evlr);
let raw_evlrs: Vec<Result<crate::raw::Vlr>> = {
self.point_writer
.header()
Expand Down Expand Up @@ -258,20 +267,7 @@ impl<W: 'static + std::io::Write + Seek + Send> Writer<W> {
pub fn write(&mut self, point: Point) -> Result<()> {
self.write_point(point)
}
}

#[allow(deprecated)]
impl<W: 'static + std::io::Write + Seek + Debug + Send> Write for Writer<W> {
fn header(&self) -> &Header {
self.header()
}

fn write(&mut self, point: Point) -> Result<()> {
self.write(point)
}
}

impl<W: 'static + std::io::Write + Seek + Debug + Send> Writer<W> {
/// Closes this writer and returns its inner `Write`, seeked to the beginning of the las data.
///
/// # Examples
Expand Down Expand Up @@ -300,6 +296,17 @@ impl<W: 'static + std::io::Write + Seek + Debug + Send> Writer<W> {
}
}

#[allow(deprecated)]
impl<W: 'static + std::io::Write + Seek + Debug + Send> Write for Writer<W> {
fn header(&self) -> &Header {
self.header()
}

fn write(&mut self, point: Point) -> Result<()> {
self.write(point)
}
}

impl Writer<BufWriter<File>> {
/// Creates a new writer for a path.
///
Expand Down

0 comments on commit 13729f1

Please sign in to comment.