gistools/readers/las/laz/
v1.rs

1use super::{
2    ItemReader,
3    arithmetic_decoder::{ArithmeticDecoder, ArithmeticModel},
4    integer_compressor::IntegerCompressor,
5};
6use crate::{
7    parsers::{RGBA, Reader},
8    readers::{LASPoint, WavePacket, util::U64I64F64},
9};
10use alloc::{rc::Rc, vec, vec::Vec};
11use core::cell::RefCell;
12
13const LASZIP_GPSTIME_MULTIMAX: u32 = 512;
14
15/// Parse LAZ Point 10.1
16#[derive(Debug, Clone)]
17pub struct LAZPoint10v1Reader<T: Reader> {
18    last_item: LASPoint,
19    dec: Rc<RefCell<ArithmeticDecoder<T>>>,
20    last_x_diff: [i32; 3],
21    last_y_diff: [i32; 3],
22    last_incr: i32,
23    ic_dx: IntegerCompressor<T>,
24    ic_dy: IntegerCompressor<T>,
25    ic_z: IntegerCompressor<T>,
26    ic_intensity: IntegerCompressor<T>,
27    ic_scan_angle_rank: IntegerCompressor<T>,
28    ic_point_source_id: IntegerCompressor<T>,
29    m_changed_values: ArithmeticModel,
30    m_bit_byte: [Option<ArithmeticModel>; 256],
31    m_classification: [Option<ArithmeticModel>; 256],
32    m_user_data: [Option<ArithmeticModel>; 256],
33}
34impl<T: Reader> LAZPoint10v1Reader<T> {
35    /// Create a new LAZPoint10v1Reader
36    pub fn new(dec: Rc<RefCell<ArithmeticDecoder<T>>>) -> Self {
37        Self {
38            dec: dec.clone(),
39            last_item: LASPoint::default(),
40            last_x_diff: [0, 0, 0],
41            last_y_diff: [0, 0, 0],
42            last_incr: 0,
43            ic_dx: IntegerCompressor::new(dec.clone(), Some(32), None, None, None),
44            ic_dy: IntegerCompressor::new(dec.clone(), Some(32), Some(20), None, None),
45            ic_z: IntegerCompressor::new(dec.clone(), Some(32), Some(20), None, None),
46            ic_intensity: IntegerCompressor::new(dec.clone(), Some(16), None, None, None),
47            ic_scan_angle_rank: IntegerCompressor::new(dec.clone(), Some(8), Some(2), None, None),
48            ic_point_source_id: IntegerCompressor::new(dec.clone(), Some(16), None, None, None),
49            m_changed_values: ArithmeticModel::new(64, false),
50            m_bit_byte: [const { None }; 256],
51            m_classification: [const { None }; 256],
52            m_user_data: [const { None }; 256],
53        }
54    }
55}
56impl<T: Reader> ItemReader for LAZPoint10v1Reader<T> {
57    fn init<R: Reader>(&mut self, item: &R, point: &mut LASPoint, _context: &mut u32) {
58        // init state
59        self.last_x_diff = [0, 0, 0];
60        self.last_y_diff = [0, 0, 0];
61        self.last_incr = 0;
62        // init models and integer compressors
63        self.ic_dx.init_decompressor();
64        self.ic_dy.init_decompressor();
65        self.ic_z.init_decompressor();
66        self.ic_intensity.init_decompressor();
67        self.ic_scan_angle_rank.init_decompressor();
68        self.ic_point_source_id.init_decompressor();
69        self.m_changed_values.init(None);
70        // init "last item" to current item
71        self.last_item.inject_point10(item, 0);
72        point.inject_point10(item, 0);
73    }
74
75    fn read(&mut self, item: &mut LASPoint, context: &mut u32) {
76        // find median difference for x and y from 3 preceding differences
77        let median_x;
78        if self.last_x_diff[0] < self.last_x_diff[1] {
79            if self.last_x_diff[1] < self.last_x_diff[2] {
80                median_x = self.last_x_diff[1];
81            } else if self.last_x_diff[0] < self.last_x_diff[2] {
82                median_x = self.last_x_diff[2];
83            } else {
84                median_x = self.last_x_diff[0];
85            }
86        } else if self.last_x_diff[0] < self.last_x_diff[2] {
87            median_x = self.last_x_diff[0];
88        } else if self.last_x_diff[1] < self.last_x_diff[2] {
89            median_x = self.last_x_diff[2];
90        } else {
91            median_x = self.last_x_diff[1];
92        }
93
94        let median_y;
95        if self.last_y_diff[0] < self.last_y_diff[1] {
96            if self.last_y_diff[1] < self.last_y_diff[2] {
97                median_y = self.last_y_diff[1];
98            } else if self.last_y_diff[0] < self.last_y_diff[2] {
99                median_y = self.last_y_diff[2];
100            } else {
101                median_y = self.last_y_diff[0];
102            }
103        } else if self.last_y_diff[0] < self.last_y_diff[2] {
104            median_y = self.last_y_diff[0];
105        } else if self.last_y_diff[1] < self.last_y_diff[2] {
106            median_y = self.last_y_diff[2];
107        } else {
108            median_y = self.last_y_diff[1];
109        }
110
111        // decompress x y z coordinates
112        let x_diff = self.ic_dx.decompress(median_x, *context);
113        self.last_item.x += x_diff;
114        // we use the number k of bits corrector bits to switch contexts
115        let mut k_bits = self.ic_dx.get_k();
116        let y_diff = self.ic_dy.decompress(median_y, if k_bits < 19 { k_bits } else { 19 });
117        self.last_item.y += y_diff;
118        k_bits = (k_bits + self.ic_dy.get_k()) / 2;
119        self.last_item.z =
120            self.ic_z.decompress(self.last_item.z, if k_bits < 19 { k_bits } else { 19 });
121
122        // decompress which other values have changed
123        let changed_values = self.dec.borrow_mut().decode_symbol(&mut self.m_changed_values);
124
125        if changed_values != 0 {
126            // decompress the intensity if it has changed
127            if (changed_values & 32) != 0 {
128                self.last_item.intensity =
129                    self.ic_intensity.decompress(self.last_item.intensity as i32, *context) as u16;
130            }
131
132            // decompress the edge_of_flight_line, scan_direction_flag, ... if it has changed
133            if (changed_values & 16) != 0 {
134                if self.m_bit_byte[self.last_item.flags as usize].is_none() {
135                    let mut model = ArithmeticModel::new(256, false);
136                    model.init(None);
137                    self.m_bit_byte[self.last_item.flags as usize] = Some(model);
138                }
139                self.last_item.set_flags(
140                    self.dec.borrow_mut().decode_symbol(
141                        self.m_bit_byte[self.last_item.flags as usize].as_mut().unwrap(),
142                    ) as u8,
143                    false,
144                );
145            }
146
147            // decompress the classification ... if it has changed
148            if (changed_values & 8) != 0 {
149                if self.m_classification[self.last_item.classification as usize].is_none() {
150                    let mut model = ArithmeticModel::new(256, false);
151                    model.init(None);
152                    self.m_classification[self.last_item.classification as usize] = Some(model);
153                }
154                self.last_item.set_flags2(self.dec.borrow_mut().decode_symbol(
155                    self.m_classification[self.last_item.classification as usize].as_mut().unwrap(),
156                ) as u8);
157            }
158
159            // decompress the scan_angle_rank ... if it has changed
160            if (changed_values & 4) != 0 {
161                self.last_item.scan_angle_rank = self.ic_scan_angle_rank.decompress(
162                    self.last_item.scan_angle_rank as i32,
163                    if k_bits < 3 { 1 } else { 0 },
164                ) as i8;
165            }
166
167            // decompress the user_data ... if it has changed
168            if (changed_values & 2) != 0 {
169                if self.m_user_data[self.last_item.user_data as usize].is_none() {
170                    let mut model = ArithmeticModel::new(256, false);
171                    model.init(None);
172                    self.m_user_data[self.last_item.user_data as usize] = Some(model);
173                }
174                self.last_item.user_data = self.dec.borrow_mut().decode_symbol(
175                    self.m_user_data[self.last_item.user_data as usize].as_mut().unwrap(),
176                ) as u8;
177            }
178
179            // decompress the point_source_ID ... if it has changed
180            if (changed_values & 1) != 0 {
181                self.last_item.point_source_id = self
182                    .ic_point_source_id
183                    .decompress(self.last_item.point_source_id as i32, *context)
184                    as u16;
185            }
186        }
187
188        // record the difference
189        self.last_x_diff[self.last_incr as usize] = x_diff;
190        self.last_y_diff[self.last_incr as usize] = y_diff;
191        self.last_incr += 1;
192        if self.last_incr > 2 {
193            self.last_incr = 0;
194        }
195
196        *item = self.last_item.clone();
197    }
198
199    fn chunk_sizes<R: Reader>(&mut self, _reader: &R) {}
200}
201
202/// Parse LAZ GPS Time 1.1v1
203#[derive(Debug, Clone)]
204pub struct LAZGpsTime11v1Reader<T: Reader> {
205    last_item: U64I64F64,
206    dec: Rc<RefCell<ArithmeticDecoder<T>>>,
207    m_gpstime_multi: ArithmeticModel,
208    m_gpstime0_diff: ArithmeticModel,
209    ic_gpstime: IntegerCompressor<T>,
210    last_item_diff: i64,
211    multi_extreme_counter: u8,
212}
213impl<T: Reader> LAZGpsTime11v1Reader<T> {
214    /// Create a new LAZPoint10v1Reader
215    pub fn new(dec: Rc<RefCell<ArithmeticDecoder<T>>>) -> Self {
216        Self {
217            dec: dec.clone(),
218            // create entropy models and integer compressors
219            m_gpstime_multi: ArithmeticModel::new(LASZIP_GPSTIME_MULTIMAX, false),
220            m_gpstime0_diff: ArithmeticModel::new(3, false),
221            ic_gpstime: IntegerCompressor::new(dec, Some(32), Some(6), None, None),
222            last_item_diff: 0,
223            multi_extreme_counter: 0,
224            last_item: U64I64F64::default(),
225        }
226    }
227}
228impl<T: Reader> ItemReader for LAZGpsTime11v1Reader<T> {
229    fn init<R: Reader>(&mut self, item: &R, point: &mut LASPoint, _context: &mut u32) {
230        // init state
231        self.last_item_diff = 0;
232        self.multi_extreme_counter = 0;
233        // init models and integer compressors
234        self.m_gpstime_multi.init(None);
235        self.m_gpstime0_diff.init(None);
236        self.ic_gpstime.init_decompressor();
237        // init last item
238        self.last_item.set_u64(item.uint64_le(Some(0)));
239        point.gps_time = Some(self.last_item.f64());
240    }
241
242    fn read(&mut self, item: &mut LASPoint, _context: &mut u32) {
243        let multi;
244        if self.last_item_diff == 0 {
245            // if the last integer difference was zero
246            multi = self.dec.borrow_mut().decode_symbol(&mut self.m_gpstime0_diff);
247            if multi == 1 {
248                // the difference can be represented with 32 bits
249                self.last_item_diff = self.ic_gpstime.decompress(0, 0) as i64;
250                self.last_item.set_i64(self.last_item_diff + self.last_item.i64());
251            } else if multi == 2 {
252                // the difference is huge
253                self.last_item.set_u64(self.dec.borrow_mut().read_int64());
254            }
255        } else {
256            multi = self.dec.borrow_mut().decode_symbol(&mut self.m_gpstime_multi);
257
258            if multi < LASZIP_GPSTIME_MULTIMAX - 2 {
259                let gpstime_diff; // I32
260                if multi == 1 {
261                    gpstime_diff = self.ic_gpstime.decompress(self.last_item_diff as i32, 1);
262                    self.last_item_diff = gpstime_diff as i64;
263                    self.multi_extreme_counter = 0;
264                } else if multi == 0 {
265                    gpstime_diff = self.ic_gpstime.decompress((self.last_item_diff / 4) as i32, 2);
266                    self.multi_extreme_counter += 1;
267                    if self.multi_extreme_counter > 3 {
268                        self.last_item_diff = gpstime_diff as i64;
269                        self.multi_extreme_counter = 0;
270                    }
271                } else if multi < 10 {
272                    gpstime_diff =
273                        self.ic_gpstime.decompress((multi as i64 * self.last_item_diff) as i32, 3);
274                } else if multi < 50 {
275                    gpstime_diff =
276                        self.ic_gpstime.decompress((multi as i64 * self.last_item_diff) as i32, 4);
277                } else {
278                    gpstime_diff =
279                        self.ic_gpstime.decompress((multi as i64 * self.last_item_diff) as i32, 5);
280                    if multi == LASZIP_GPSTIME_MULTIMAX - 3 {
281                        self.multi_extreme_counter += 1;
282                        if self.multi_extreme_counter > 3 {
283                            self.last_item_diff = gpstime_diff as i64;
284                            self.multi_extreme_counter = 0;
285                        }
286                    }
287                }
288                self.last_item.set_i64(gpstime_diff as i64 + self.last_item.i64());
289            } else if multi < LASZIP_GPSTIME_MULTIMAX - 1 {
290                self.last_item.set_u64(self.dec.borrow_mut().read_int64());
291            }
292        }
293
294        item.gps_time = Some(self.last_item.f64());
295    }
296
297    fn chunk_sizes<R: Reader>(&mut self, _reader: &R) {}
298}
299
300/// Parse LAZ RGB 1.2v1
301#[derive(Debug, Clone)]
302pub struct LAZrgb12v1Reader<T: Reader> {
303    /// The arithmetic decoder
304    last_item: [u16; 3],
305    dec: Rc<RefCell<ArithmeticDecoder<T>>>,
306    m_byte_used: ArithmeticModel,
307    ic_rgb: IntegerCompressor<T>,
308}
309impl<T: Reader> LAZrgb12v1Reader<T> {
310    /// Create a new LAZrgb12v1Reader
311    pub fn new(dec: Rc<RefCell<ArithmeticDecoder<T>>>) -> Self {
312        Self {
313            dec: dec.clone(),
314            // create models and integer compressors
315            m_byte_used: ArithmeticModel::new(64, false),
316            ic_rgb: IntegerCompressor::new(dec, Some(8), Some(6), None, None),
317            last_item: [0; 3],
318        }
319    }
320}
321impl<T: Reader> ItemReader for LAZrgb12v1Reader<T> {
322    fn init<R: Reader>(&mut self, item: &R, point: &mut LASPoint, _context: &mut u32) {
323        // init models and integer compressors
324        self.m_byte_used.init(None);
325        self.ic_rgb.init_decompressor();
326        let r = item.uint16_le(None);
327        let g = item.uint16_le(None);
328        let b = item.uint16_le(None);
329        self.last_item = [r, g, b];
330        point.rgba = Some(RGBA::from_u16s(r, g, b, u16::MAX));
331    }
332
333    fn read(&mut self, item: &mut LASPoint, _context: &mut u32) {
334        let mut curr_item: [u16; 3] = [0; 3];
335        let sym = self.dec.borrow_mut().decode_symbol(&mut self.m_byte_used);
336        if (sym & (1 << 0)) != 0 {
337            curr_item[0] = self.ic_rgb.decompress((self.last_item[0] & 255) as i32, 0) as u16;
338        } else {
339            curr_item[0] = self.last_item[0] & 0xff;
340        }
341        if (sym & (1 << 1)) != 0 {
342            curr_item[0] |=
343                (self.ic_rgb.decompress((self.last_item[0] >> 8) as i32, 1) as u16) << 8;
344        } else {
345            curr_item[0] |= self.last_item[0] & 0xff00;
346        }
347        if (sym & (1 << 2)) != 0 {
348            curr_item[1] = self.ic_rgb.decompress((self.last_item[1] & 255) as i32, 2) as u16;
349        } else {
350            curr_item[1] = self.last_item[1] & 0xff;
351        }
352        if (sym & (1 << 3)) != 0 {
353            curr_item[1] |=
354                (self.ic_rgb.decompress((self.last_item[1] >> 8) as i32, 3) as u16) << 8;
355        } else {
356            curr_item[1] |= self.last_item[1] & 0xff00;
357        }
358        if (sym & (1 << 4)) != 0 {
359            curr_item[2] = self.ic_rgb.decompress((self.last_item[2] & 255) as i32, 4) as u16;
360        } else {
361            curr_item[2] = self.last_item[2] & 0xff;
362        }
363        if (sym & (1 << 5)) != 0 {
364            curr_item[2] |=
365                (self.ic_rgb.decompress((self.last_item[2] >> 8) as i32, 5) as u16) << 8;
366        } else {
367            curr_item[2] |= self.last_item[2] & 0xff00;
368        }
369
370        self.last_item = curr_item;
371        item.rgba = Some(RGBA::from_u16s(curr_item[0], curr_item[1], curr_item[2], u16::MAX));
372    }
373
374    fn chunk_sizes<R: Reader>(&mut self, _reader: &R) {}
375}
376
377/// Parse LAZ wavepacket 1.3v1
378#[derive(Debug, Clone)]
379pub struct LAZwavepacket13v1Reader<T: Reader> {
380    dec: Rc<RefCell<ArithmeticDecoder<T>>>,
381    index: u32,
382    last_item: WavePacket,
383    m_packet_index: ArithmeticModel,
384    m_offset_diff: [ArithmeticModel; 4],
385    ic_offset_diff: IntegerCompressor<T>,
386    ic_packet_size: IntegerCompressor<T>,
387    ic_return_point: IntegerCompressor<T>,
388    ic_xyz: IntegerCompressor<T>,
389    last_diff32: i32,
390    sym_last_offset_diff: u32,
391}
392impl<T: Reader> LAZwavepacket13v1Reader<T> {
393    /// Create a new LAZwavepacket13v1Reader
394    pub fn new(dec: Rc<RefCell<ArithmeticDecoder<T>>>) -> Self {
395        Self {
396            index: 0,
397            dec: dec.clone(),
398            // create models and integer compressors
399            m_packet_index: ArithmeticModel::new(256, false),
400            m_offset_diff: [
401                ArithmeticModel::new(4, false),
402                ArithmeticModel::new(4, false),
403                ArithmeticModel::new(4, false),
404                ArithmeticModel::new(4, false),
405            ],
406            ic_offset_diff: IntegerCompressor::new(dec.clone(), Some(32), None, None, None),
407            ic_packet_size: IntegerCompressor::new(dec.clone(), Some(32), None, None, None),
408            ic_return_point: IntegerCompressor::new(dec.clone(), Some(32), None, None, None),
409            ic_xyz: IntegerCompressor::new(dec, Some(32), Some(3), None, None),
410            last_item: WavePacket::default(),
411            last_diff32: 0,
412            sym_last_offset_diff: 0,
413        }
414    }
415}
416impl<T: Reader> ItemReader for LAZwavepacket13v1Reader<T> {
417    fn init<R: Reader>(&mut self, item: &R, point: &mut LASPoint, _context: &mut u32) {
418        // init state
419        self.index = 0;
420        self.last_diff32 = 0;
421        self.sym_last_offset_diff = 0;
422
423        // init models and integer compressors
424        self.m_packet_index.init(None);
425        for m in self.m_offset_diff.iter_mut() {
426            m.init(None);
427        }
428        self.ic_offset_diff.init_decompressor();
429        self.ic_packet_size.init_decompressor();
430        self.ic_return_point.init_decompressor();
431        self.ic_xyz.init_decompressor();
432
433        self.last_item = WavePacket::from_reader(item, 0);
434        point.wave_packet = Some(self.last_item.clone());
435    }
436
437    fn read(&mut self, item: &mut LASPoint, _context: &mut u32) {
438        // let this_item_m = new LASWavePacket13(item);
439        let mut this_item_m = WavePacket::default();
440        self.index = self.dec.borrow_mut().decode_symbol(&mut self.m_packet_index);
441
442        self.sym_last_offset_diff = self
443            .dec
444            .borrow_mut()
445            .decode_symbol(&mut self.m_offset_diff[self.sym_last_offset_diff as usize]);
446
447        if self.sym_last_offset_diff == 0 {
448            this_item_m.offset = self.last_item.offset;
449        } else if self.sym_last_offset_diff == 1 {
450            this_item_m.offset = self.last_item.offset + self.last_item.length as u64;
451        } else if self.sym_last_offset_diff == 2 {
452            self.last_diff32 = self.ic_offset_diff.decompress(self.last_diff32, 0);
453            this_item_m.offset = (self.last_item.offset as i32 + self.last_diff32) as u64;
454        } else {
455            this_item_m.offset = self.dec.borrow_mut().read_int64();
456        }
457
458        this_item_m.length = self.ic_packet_size.decompress(self.last_item.length as i32, 0) as u32;
459        this_item_m.return_point =
460            self.ic_return_point.decompress(self.last_item.return_point as i32, 0) as f32;
461        this_item_m.x_t = self.ic_xyz.decompress(self.last_item.x_t as i32, 0) as f32;
462        this_item_m.y_t = self.ic_xyz.decompress(self.last_item.y_t as i32, 1) as f32;
463        this_item_m.z_t = self.ic_xyz.decompress(self.last_item.z_t as i32, 2) as f32;
464
465        // this_item_m.copyTo(self.last_item.data, 29);
466        item.wave_packet = Some(this_item_m.clone());
467        self.last_item = this_item_m;
468    }
469
470    fn chunk_sizes<R: Reader>(&mut self, _reader: &R) {}
471}
472
473/// Parse LAZ byte 1.0v1
474#[derive(Debug, Clone)]
475pub struct LAZbyte10v1Reader<T: Reader> {
476    size: u32,
477    last_item: Vec<u8>,
478    ic_byte: IntegerCompressor<T>,
479}
480impl<T: Reader> LAZbyte10v1Reader<T> {
481    /// Create a new LAZbyte10v1Reader
482    pub fn new(dec: Rc<RefCell<ArithmeticDecoder<T>>>, size: u32) -> Self {
483        Self {
484            size,
485            last_item: vec![0; size as usize],
486            ic_byte: IntegerCompressor::new(dec, Some(8), Some(size), None, None),
487        }
488    }
489}
490impl<T: Reader> ItemReader for LAZbyte10v1Reader<T> {
491    fn init<R: Reader>(&mut self, item: &R, _point: &mut LASPoint, _context: &mut u32) {
492        // init models and integer compressors
493        self.ic_byte.init_decompressor();
494        self.last_item = item.seek_slice(self.size as usize);
495    }
496
497    fn read(&mut self, _item: &mut LASPoint, _context: &mut u32) {
498        let mut this_item = vec![0; self.size as usize];
499        for (i, val) in self.last_item.iter().enumerate() {
500            this_item[i] = self.ic_byte.decompress(*val as i32, i as u32);
501        }
502        self.last_item = this_item.iter().map(|x| *x as u8).collect();
503    }
504
505    fn chunk_sizes<R: Reader>(&mut self, _reader: &R) {}
506}