ovtile/open/
grid_layer.rs1use alloc::{string::String, vec::Vec};
2
3use crate::{delta_decode_array, delta_encode_array, open::Extent};
4
5use libm::round;
6use pbf::{ProtoRead, ProtoWrite, Protobuf};
7
8#[derive(Default, Debug, PartialEq)]
12pub struct GridData {
13 pub name: String,
15 pub data: Vec<f64>,
17 pub extent: Extent,
19 pub size: f64,
21 pub min: f64,
23 pub max: f64,
25}
26impl GridData {
27 pub fn new(
29 name: String,
30 extent: Extent,
31 size: f64,
32 min: f64,
33 max: f64,
34 data: Vec<f64>,
35 ) -> Self {
36 GridData { name, data, extent, size, min, max }
37 }
38}
39impl ProtoRead for GridData {
40 fn read(&mut self, tag: u64, pb: &mut Protobuf) {
41 match tag {
42 0 => self.extent = pb.read_varint(),
43 1 => self.size = pb.read_varint(),
44 2 => self.min = pb.read_varint(),
45 3 => self.max = pb.read_varint(),
46 4 => {
47 self.data = delta_decode_array(&pb.read_packed())
48 .into_iter()
49 .map(|v| unmap_value(v as f64, self.min, self.max, self.extent.into()))
50 .collect()
51 }
52 5 => self.name = pb.read_string(),
53 #[tarpaulin::skip]
54 _ => panic!("unknown tag: {}", tag),
55 }
56 }
57}
58impl ProtoWrite for GridData {
59 fn write(&self, pb: &mut Protobuf) {
60 let max = self.data.iter().fold(f64::MIN, |a, b| f64::max(a, *b));
61 let min = self.data.iter().fold(f64::MAX, |a, b| f64::min(a, *b));
62 let re_mapped: Vec<u32> =
63 self.data.iter().map(|v| remap_value(*v, min, max, self.extent.into())).collect();
64 let d_coded = delta_encode_array(&re_mapped);
65
66 pb.write_varint_field(0, self.extent);
67 pb.write_varint_field(1, self.size);
68 pb.write_varint_field(2, min);
69 pb.write_varint_field(3, max);
70 pb.write_packed_varint(4, &d_coded);
71 pb.write_string_field(5, &self.name);
72 }
73}
74
75fn remap_value(value: f64, min: f64, max: f64, extent: f64) -> u32 {
77 round(((value - min) * extent) / (max - min)) as u32
78}
79
80fn unmap_value(value: f64, min: f64, max: f64, extent: f64) -> f64 {
82 (value * (max - min)) / extent + min
83}
84
85pub fn convert_terrarium_elevation_data(r: u8, g: u8, b: u8) -> f64 {
87 r as f64 * 256. + g as f64 + b as f64 / 256. - 32768.
88}
89
90pub fn convert_mapbox_elevation_data(r: u8, g: u8, b: u8) -> f64 {
92 -10000. + (r as f64 * 256. * 256. + g as f64 * 256. + b as f64) * 0.1
93}