1use crate::las::write_impl::write_las_format;
2use crate::{Error, FILE_EXTENSION_LAS_FORMAT, FILE_EXTENSION_LAZ_FORMAT};
3use epoint_core::PointCloud;
4
5use crate::Error::{InvalidFileExtension, NoFileExtension};
6use ecoord::FrameId;
7use std::fmt::Debug;
8use std::fs::File;
9use std::io::{BufWriter, Seek, Write};
10use std::path::Path;
11
12#[derive(Debug, Clone)]
15pub struct LasWriter<W: 'static + std::io::Write + Seek + Debug + Send> {
16 writer: W,
17 frame_id: Option<FrameId>,
18}
19
20impl<W: Write + Seek + Debug + Send> LasWriter<W> {
21 pub fn new(writer: W) -> Self {
22 Self {
23 writer,
24 frame_id: None,
25 }
26 }
27
28 pub fn with_frame_id(mut self, frame_id: FrameId) -> Self {
29 self.frame_id = Some(frame_id);
30 self
31 }
32
33 pub fn finish(self, point_cloud: &PointCloud) -> Result<(), Error> {
34 let mut exported_point_cloud = point_cloud.clone();
35 let resulting_point_cloud: PointCloud =
36 self.frame_id.map_or(point_cloud.to_owned(), |f: FrameId| {
37 exported_point_cloud
38 .resolve_to_frame(f)
39 .expect("Resolving should work");
40 exported_point_cloud
41 });
42
43 write_las_format(BufWriter::new(self.writer), &resulting_point_cloud)?;
44
45 Ok(())
46 }
47}
48
49impl LasWriter<File> {
50 pub fn from_path(path: impl AsRef<Path>) -> Result<Self, Error> {
51 let extension = path.as_ref().extension().ok_or(NoFileExtension())?;
52 if extension != FILE_EXTENSION_LAS_FORMAT && extension != FILE_EXTENSION_LAZ_FORMAT {
53 return Err(InvalidFileExtension(
54 extension.to_str().unwrap_or_default().to_string(),
55 ));
56 }
57
58 let file = File::create(path)?;
59 Ok(Self::new(file))
60 }
61}