1use crate::*;
26
27use super::types::*;
28
29use std::{
30 convert::{TryFrom, TryInto},
31 io::{BufRead, Read, Seek, SeekFrom},
32};
33
34use super::super::from_bytes::*;
35
36pub fn load_las<IP, P, R>(read: &mut R, ip: &mut IP) -> LasResult<()>
40where
41 IP: IsPushable<P>,
42 P: IsBuildable3D,
43 R: BufRead + Seek,
44{
45 let header_raw = load_header(read)?;
46 let header = Header::try_from(header_raw)?;
47
48 ip.reserve(header.n_point_records as usize);
49
50 read.seek(SeekFrom::Start(header.offset_point_data as u64))?;
51
52 let mut buffer = vec![0u8; header.point_record_length as usize];
53
54 for _ in 0..header.n_point_records {
55 read.read_exact(&mut buffer)?;
56
57 let pd = PointData::from_bytes(buffer[0..12].try_into()?);
58
59 let x = header.offset_x + (pd.x as f64 * header.scale_factor_x);
60 let y = header.offset_y + (pd.y as f64 * header.scale_factor_y);
61 let z = header.offset_z + (pd.z as f64 * header.scale_factor_z);
62
63 ip.push(P::new(x, y, z))
64 }
65
66 Ok(())
67}
68
69fn load_header<R>(read: &mut R) -> LasResult<HeaderRaw>
72where
73 R: Read,
74{
75 let mut buffer = [0u8; 375];
76 read.read_exact(&mut buffer)?;
77
78 Ok(HeaderRaw {
79 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])?, })
117}