use crate::*;
use super::types::*;
use std::{
convert::{TryFrom, TryInto},
io::{BufRead, Read, Seek, SeekFrom},
};
use super::super::from_bytes::*;
pub fn load_las<IP, P, R>(read: &mut R, ip: &mut IP) -> LasResult<()>
where
IP: IsPushable<P>,
P: IsBuildable3D,
R: BufRead + Seek,
{
let header_raw = load_header(read)?;
let header = Header::try_from(header_raw)?;
ip.reserve(header.n_point_records as usize);
read.seek(SeekFrom::Start(header.offset_point_data as u64))?;
let mut buffer = vec![0u8; header.point_record_length as usize];
for _ in 0..header.n_point_records {
read.read_exact(&mut buffer)?;
let pd = PointData::from_bytes(buffer[0..12].try_into()?);
let x = header.offset_x + (pd.x as f64 * header.scale_factor_x);
let y = header.offset_y + (pd.y as f64 * header.scale_factor_y);
let z = header.offset_z + (pd.z as f64 * header.scale_factor_z);
ip.push(P::new(x, y, z))
}
Ok(())
}
fn load_header<R>(read: &mut R) -> LasResult<HeaderRaw>
where
R: Read,
{
let mut buffer = [0u8; 375];
read.read_exact(&mut buffer)?;
Ok(HeaderRaw {
file_signature: array_from_bytes_le!(u8, 4, &buffer[0..4])?, file_source_id: u16::from_le_bytes(buffer[4..6].try_into()?), global_encoding: u16::from_le_bytes(buffer[6..8].try_into()?), guid1: u32::from_le_bytes(buffer[8..12].try_into()?), guid2: u16::from_le_bytes(buffer[12..14].try_into()?), guid3: u16::from_le_bytes(buffer[14..16].try_into()?), guid4: buffer[16..24].try_into()?, version_major: u8::from_le_bytes(buffer[24..25].try_into()?), version_minor: u8::from_le_bytes(buffer[25..26].try_into()?), system_identifier: array_from_bytes_le!(u8, 32, &buffer[26..58])?, generating_software: array_from_bytes_le!(u8, 32, &buffer[58..90])?, file_creation_day: u16::from_le_bytes(buffer[90..92].try_into()?), file_creation_year: u16::from_le_bytes(buffer[92..94].try_into()?), header_size: u16::from_le_bytes(buffer[94..96].try_into()?), offset_point_data: u32::from_le_bytes(buffer[96..100].try_into()?), n_variable_length_records: u32::from_le_bytes(buffer[100..104].try_into()?), point_record_format: u8::from_le_bytes(buffer[104..105].try_into()?), point_record_length: u16::from_le_bytes(buffer[105..107].try_into()?), legacy_n_point_records: u32::from_le_bytes(buffer[107..111].try_into()?), legacy_n_point_return: array_from_bytes_le!(u32, 5, &buffer[111..131])?, scale_factor_x: f64::from_le_bytes(buffer[131..139].try_into()?), scale_factor_y: f64::from_le_bytes(buffer[139..147].try_into()?), scale_factor_z: f64::from_le_bytes(buffer[147..155].try_into()?), offset_x: f64::from_le_bytes(buffer[155..163].try_into()?), offset_y: f64::from_le_bytes(buffer[163..171].try_into()?), offset_z: f64::from_le_bytes(buffer[171..179].try_into()?), max_x: f64::from_le_bytes(buffer[179..187].try_into()?), min_x: f64::from_le_bytes(buffer[187..195].try_into()?), max_y: f64::from_le_bytes(buffer[195..203].try_into()?), min_y: f64::from_le_bytes(buffer[203..211].try_into()?), max_z: f64::from_le_bytes(buffer[211..219].try_into()?), min_z: f64::from_le_bytes(buffer[219..227].try_into()?), start_wavefront_data: u64::from_le_bytes(buffer[227..235].try_into()?), start_extended_variable_length: u64::from_le_bytes(buffer[235..243].try_into()?), n_extended_variable_length: u32::from_le_bytes(buffer[243..247].try_into()?), n_point_records: u64::from_le_bytes(buffer[247..255].try_into()?), n_points_return: array_from_bytes_le!(u64, 15, &buffer[255..375])?, })
}