1use crate::Error;
2use crate::Error::{InvalidFileExtension, NoFileExtension};
3use crate::e57::FILE_EXTENSION_E57_FORMAT;
4use crate::e57::read_impl::import_point_cloud_from_e57_file;
5use chrono::Utc;
6use ecoord::{ChannelId, FrameId};
7use epoint_core::PointCloud;
8use std::fmt::Debug;
9use std::fs::File;
10use std::io::{Read, Seek};
11use std::path::Path;
12
13#[derive(Debug, Clone)]
16pub struct E57Reader<R: Read + Seek> {
17 reader: R,
18 acquisition_start_timestamps: Option<Vec<chrono::DateTime<Utc>>>,
19 channel_id: ChannelId,
20 world_frame_id: FrameId,
21 scanner_frame_id: FrameId,
22}
23
24impl<R: Read + Seek> E57Reader<R> {
25 pub fn new(reader: R) -> Self {
26 Self {
27 reader,
28 acquisition_start_timestamps: None,
29 channel_id: "default".into(),
30 world_frame_id: "world".into(),
31 scanner_frame_id: "scanner".into(),
32 }
33 }
34
35 pub fn with_acquisition_start_timestamps(
36 mut self,
37 acquisition_start_timestamps: Vec<chrono::DateTime<Utc>>,
38 ) -> Self {
39 self.acquisition_start_timestamps = Some(acquisition_start_timestamps);
40 self
41 }
42
43 pub fn finish(self) -> Result<PointCloud, Error> {
44 let point_cloud = import_point_cloud_from_e57_file(
45 self.reader,
46 self.acquisition_start_timestamps,
47 self.channel_id,
48 self.world_frame_id,
49 self.scanner_frame_id,
50 )?;
51
52 Ok(point_cloud)
53 }
54}
55
56impl E57Reader<File> {
57 pub fn from_path(path: impl AsRef<Path>) -> Result<Self, Error> {
58 let extension = path.as_ref().extension().ok_or(NoFileExtension())?;
59 if extension != FILE_EXTENSION_E57_FORMAT {
60 return Err(InvalidFileExtension(
61 extension.to_str().unwrap_or_default().to_string(),
62 ));
63 }
64
65 let file = File::open(path)?;
66 Ok(Self::new(file))
67 }
68}