use std::{
convert::{TryFrom, TryInto},
fmt,
io::Error as ioError,
};
use super::super::from_bytes::*;
#[derive(Debug)]
pub struct Header {
pub offset_point_data: u32,
pub point_record_length: u16,
pub n_point_records: u64,
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,
}
impl TryFrom<HeaderRaw> for Header {
type Error = LasError;
fn try_from(x: HeaderRaw) -> LasResult<Header> {
if x.version_major > 1 || x.version_minor > 4 {
return Err(LasError::UnsupportedVersion);
}
let n_point_records = if x.legacy_n_point_records == 0 {
x.n_point_records
} else {
x.legacy_n_point_records as u64
};
if x.point_record_format > 10 {
return Err(LasError::UnknownPointFormat);
}
Ok(Header {
offset_point_data: x.offset_point_data,
point_record_length: x.point_record_length,
n_point_records,
scale_factor_x: x.scale_factor_x,
scale_factor_y: x.scale_factor_y,
scale_factor_z: x.scale_factor_z,
offset_x: x.offset_x,
offset_y: x.offset_y,
offset_z: x.offset_z,
})
}
}
#[derive(Debug)]
pub struct HeaderRaw {
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], }
#[derive(Debug, Default, Clone)]
pub struct PointData {
pub x: i32, pub y: i32, pub z: i32, }
impl PointData {
pub fn from_bytes(buffer: [u8; 12]) -> Self {
Self {
x: i32::from_le_bytes(buffer[0..4].try_into().unwrap()),
y: i32::from_le_bytes(buffer[4..8].try_into().unwrap()),
z: i32::from_le_bytes(buffer[8..12].try_into().unwrap()),
}
}
}
pub enum LasError {
AccessFile,
BinaryData,
UnknownPointFormat,
UnsupportedVersion,
}
impl fmt::Debug for LasError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::AccessFile => write!(f, "Unable to access file"),
Self::BinaryData => write!(f, "Unable to parse binary data"),
Self::UnknownPointFormat => write!(f, "Unknown point format"),
Self::UnsupportedVersion => write!(f, "Unsupported version"),
}
}
}
impl fmt::Display for LasError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
}
}
pub type LasResult<T> = std::result::Result<T, LasError>;
impl From<ioError> for LasError {
fn from(_error: ioError) -> Self {
LasError::AccessFile
}
}
impl From<std::array::TryFromSliceError> for LasError {
fn from(_error: std::array::TryFromSliceError) -> Self {
LasError::BinaryData
}
}
impl From<FromBytesError> for LasError {
fn from(_error: FromBytesError) -> Self {
LasError::BinaryData
}
}