1use std::{
26 convert::{TryFrom, TryInto},
27 fmt,
28 io::Error as ioError,
29};
30
31use super::super::from_bytes::*;
32
33#[derive(Debug)]
36pub struct Header {
37 pub offset_point_data: u32,
38 pub point_record_length: u16,
39 pub n_point_records: u64,
40 pub scale_factor_x: f64,
41 pub scale_factor_y: f64,
42 pub scale_factor_z: f64,
43 pub offset_x: f64,
44 pub offset_y: f64,
45 pub offset_z: f64,
46}
47
48impl TryFrom<HeaderRaw> for Header {
49 type Error = LasError;
50
51 fn try_from(x: HeaderRaw) -> LasResult<Header> {
52 if x.version_major > 1 || x.version_minor > 4 {
53 return Err(LasError::UnsupportedVersion);
54 }
55
56 let n_point_records = if x.legacy_n_point_records == 0 {
58 x.n_point_records
59 } else {
60 x.legacy_n_point_records as u64
61 };
62
63 if x.point_record_format > 10 {
64 return Err(LasError::UnknownPointFormat);
65 }
66
67 Ok(Header {
68 offset_point_data: x.offset_point_data,
69 point_record_length: x.point_record_length,
70 n_point_records,
71 scale_factor_x: x.scale_factor_x,
72 scale_factor_y: x.scale_factor_y,
73 scale_factor_z: x.scale_factor_z,
74 offset_x: x.offset_x,
75 offset_y: x.offset_y,
76 offset_z: x.offset_z,
77 })
78 }
79}
80
81#[derive(Debug)]
84pub struct HeaderRaw {
86 pub file_signature: [u8; 4], pub file_source_id: u16, pub global_encoding: u16, pub guid1: u32, pub guid2: u16, pub guid3: u16, pub guid4: [u8; 8], pub version_major: u8, pub version_minor: u8, pub system_identifier: [u8; 32], pub generating_software: [u8; 32], pub file_creation_day: u16, pub file_creation_year: u16, pub header_size: u16, pub offset_point_data: u32, pub n_variable_length_records: u32, pub point_record_format: u8, pub point_record_length: u16, pub legacy_n_point_records: u32, pub legacy_n_point_return: [u32; 5], pub scale_factor_x: f64, pub scale_factor_y: f64, pub scale_factor_z: f64, pub offset_x: f64, pub offset_y: f64, pub offset_z: f64, pub max_x: f64, pub min_x: f64, pub max_y: f64, pub min_y: f64, pub max_z: f64, pub min_z: f64, pub start_wavefront_data: u64, pub start_extended_variable_length: u64, pub n_extended_variable_length: u32, pub n_point_records: u64, pub n_points_return: [u64; 15], }
125
126#[derive(Debug, Default, Clone)]
129pub struct PointData {
130 pub x: i32, pub y: i32, pub z: i32, }
134
135impl PointData {
136 pub fn from_bytes(buffer: [u8; 12]) -> Self {
137 Self {
139 x: i32::from_le_bytes(buffer[0..4].try_into().unwrap()),
140 y: i32::from_le_bytes(buffer[4..8].try_into().unwrap()),
141 z: i32::from_le_bytes(buffer[8..12].try_into().unwrap()),
142 }
143 }
144}
145
146pub enum LasError {
150 AccessFile,
151 BinaryData,
152 UnknownPointFormat,
153 UnsupportedVersion,
154}
155
156impl fmt::Debug for LasError {
157 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
158 match self {
159 Self::AccessFile => write!(f, "Unable to access file"),
160 Self::BinaryData => write!(f, "Unable to parse binary data"),
161 Self::UnknownPointFormat => write!(f, "Unknown point format"),
162 Self::UnsupportedVersion => write!(f, "Unsupported version"),
163 }
164 }
165}
166
167impl fmt::Display for LasError {
168 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
169 write!(f, "{:?}", self)
170 }
171}
172
173pub type LasResult<T> = std::result::Result<T, LasError>;
175
176impl From<ioError> for LasError {
177 fn from(_error: ioError) -> Self {
178 LasError::AccessFile
179 }
180}
181
182impl From<std::array::TryFromSliceError> for LasError {
183 fn from(_error: std::array::TryFromSliceError) -> Self {
184 LasError::BinaryData
185 }
186}
187
188impl From<FromBytesError> for LasError {
189 fn from(_error: FromBytesError) -> Self {
190 LasError::BinaryData
191 }
192}