open_vector_tile/
vector_tile.rs

1use crate::{
2    VectorFeature,
3    base::BaseVectorTile,
4    mapbox::MapboxVectorLayer,
5    open::{
6        ColumnCacheReader, ColumnCacheWriter, GridData, ImageData, OpenVectorLayer, write_layer,
7    },
8};
9use alloc::{collections::BTreeMap, rc::Rc, string::String, vec::Vec};
10use core::cell::RefCell;
11use pbf::{ProtoRead, Protobuf};
12
13/// Methods that all vector layers should have
14pub trait VectorLayerMethods {
15    /// the version of the vector tile layer.
16    fn version(&self) -> u16;
17    /// the name of the layer
18    fn name(&self) -> String;
19    /// the extent of the vector tile (only **512**, **1_024**, **2_048**, **4_096**, and **8_192**
20    /// are supported for the open spec)
21    fn extent(&self) -> usize;
22    /// grab a feature from the layer
23    fn feature(&mut self, i: usize) -> Option<VectorFeature<'_>>;
24    /// length (layer count)
25    fn len(&self) -> usize;
26    /// empty (layer count is 0)
27    fn is_empty(&self) -> bool;
28}
29
30/// Layer container supporting both mapbox and open vector layers
31#[derive(Debug)]
32pub enum VectorLayer {
33    /// Mapbox vector layer
34    Mapbox(MapboxVectorLayer),
35    /// Open vector layer
36    Open(OpenVectorLayer),
37}
38impl VectorLayerMethods for VectorLayer {
39    fn version(&self) -> u16 {
40        match self {
41            VectorLayer::Mapbox(layer) => layer.version(),
42            VectorLayer::Open(layer) => layer.version(),
43        }
44    }
45
46    fn name(&self) -> String {
47        match self {
48            VectorLayer::Mapbox(layer) => layer.name(),
49            VectorLayer::Open(layer) => layer.name(),
50        }
51    }
52
53    fn extent(&self) -> usize {
54        match self {
55            VectorLayer::Mapbox(layer) => layer.extent(),
56            VectorLayer::Open(layer) => layer.extent(),
57        }
58    }
59
60    fn feature(&mut self, i: usize) -> Option<VectorFeature<'_>> {
61        match self {
62            VectorLayer::Mapbox(layer) => layer.feature(i).map(Into::into),
63            VectorLayer::Open(layer) => layer.feature(i).map(Into::into),
64        }
65    }
66
67    fn len(&self) -> usize {
68        match self {
69            VectorLayer::Mapbox(layer) => layer.len(),
70            VectorLayer::Open(layer) => layer.len(),
71        }
72    }
73
74    fn is_empty(&self) -> bool {
75        match self {
76            VectorLayer::Mapbox(layer) => layer.is_empty(),
77            VectorLayer::Open(layer) => layer.is_empty(),
78        }
79    }
80}
81
82/// # Open Vector Tile
83///
84/// ## Description
85/// A Vector Tile may parse either Mapbox or OpenVector Tile Layers
86/// The input is an unsigned byte array that has encoded protobuffer messages.
87///
88/// Types of layers include:
89/// - Vector data - vector points, lines, and polygons with 3D coordinates, properties, and/or m-values
90/// - Image data - raster data that is RGB(A) encoded
91/// - Grid data: data that has a max-min range, works much like an image but has floating/double precision point values for each point on the grid
92///
93/// ## Usage
94/// ```rust,ignore
95/// use ovtile::{VectorTile, VectorLayerMethods};
96///
97/// let data: Vec<u8> = vec![];
98/// let mut tile = VectorTile::new(data, None);
99///
100/// // VECTOR API
101///
102/// let landuse = tile.layer("landuse").unwrap();
103///
104/// // grab the first feature
105/// let firstFeature = landuse.feature(0).unwrap();
106/// // grab the geometry
107/// let geometry = firstFeature.load_geometry();
108///
109/// // OR specifically ask for a geometry type
110/// let points = firstFeature.load_points();
111/// let lines = firstFeature.load_lines();
112///
113/// // If you want to take advantage of the pre-tessellated and indexed geometries
114/// // and you're loading the data for a renderer, you can grab the pre-tessellated geometry
115/// let (geometry_flat, indices) = firstFeature.load_geometry_flat();
116///
117/// // IMAGE API
118///
119/// let satellite = tile.images.get("satellite").unwrap();
120/// // grab the image data
121/// let data = &satellite.image;
122///
123/// // GRID API
124///
125/// let elevation = tile.grids.get("elevation").unwrap();
126/// // grab the grid data
127/// let data = &elevation.data;
128/// ```
129#[derive(Debug)]
130pub struct VectorTile {
131    /// the layers in the vector tile
132    pub layers: BTreeMap<String, VectorLayer>,
133    /// indexes to track the layers. Needed for the open spec because we need the cache before we can
134    /// parse layers and features
135    layer_indexes: Vec<usize>,
136    /// the protobuf for the vector tile
137    pbf: Rc<RefCell<Protobuf>>,
138    /// the column cache
139    columns: Option<Rc<RefCell<ColumnCacheReader>>>,
140    /// Gridded data
141    pub grids: BTreeMap<String, GridData>,
142    /// Image data
143    pub images: BTreeMap<String, ImageData>,
144}
145impl VectorTile {
146    /// Create a new vector tile
147    pub fn new(data: Vec<u8>, end: Option<usize>) -> Self {
148        let pbf = Rc::new(RefCell::new(data.into()));
149        let mut vt = VectorTile {
150            pbf: pbf.clone(),
151            columns: None,
152            layer_indexes: Vec::new(),
153            layers: BTreeMap::new(),
154            grids: BTreeMap::new(),
155            images: BTreeMap::new(),
156        };
157
158        pbf.borrow_mut().read_fields(&mut vt, end);
159
160        if !vt.layer_indexes.is_empty() {
161            vt.read_layers();
162        }
163
164        vt
165    }
166
167    /// Read the layers
168    pub fn read_layers(&mut self) -> Option<()> {
169        let layer_indexes = self.layer_indexes.clone();
170        let mut tmp_pbf = self.pbf.borrow_mut();
171        let cache = self.columns.as_ref()?.clone();
172
173        for pos in layer_indexes {
174            tmp_pbf.set_pos(pos);
175            let mut layer = OpenVectorLayer::new(cache.clone());
176            tmp_pbf.read_message(&mut layer);
177            self.layers.insert(layer.name.clone(), VectorLayer::Open(layer));
178        }
179
180        Some(())
181    }
182
183    /// Get a layer given the name
184    pub fn layer(&mut self, name: &str) -> Option<&mut VectorLayer> {
185        self.layers.get_mut(name)
186    }
187}
188impl ProtoRead for VectorTile {
189    fn read(&mut self, tag: u64, pb: &mut Protobuf) {
190        match tag {
191            1 | 3 => {
192                let mut layer = MapboxVectorLayer::new(self.pbf.clone(), tag == 1);
193                pb.read_message(&mut layer);
194                self.layers.insert(layer.name.clone(), VectorLayer::Mapbox(layer));
195            }
196            4 => {
197                // store the position of each layer for later retrieval.
198                // Columns must be prepped before reading the layer.
199                self.layer_indexes.push(pb.get_pos());
200            }
201            5 => {
202                let mut column_reader = ColumnCacheReader::new();
203                pb.read_message(&mut column_reader);
204                self.columns = Some(Rc::new(RefCell::new(column_reader)));
205            }
206            6 => {
207                let mut grid = GridData::default();
208                pb.read_message(&mut grid);
209                self.grids.insert(grid.name.clone(), grid);
210            }
211            7 => {
212                let mut image = ImageData::default();
213                pb.read_message(&mut image);
214                self.images.insert(image.name.clone(), image);
215            }
216            _ => panic!("unknown tag: {}", tag),
217        }
218    }
219}
220
221/// writer for converting a BaseVectorTile to encoded bytes of the Open Vector Tile format
222pub fn write_tile(
223    tile: Option<&mut BaseVectorTile>,
224    images: Option<Vec<&ImageData>>,
225    grids: Option<Vec<&GridData>>,
226) -> Vec<u8> {
227    let mut pbf = Protobuf::new();
228    let mut cache = ColumnCacheWriter::default();
229
230    // first write layers
231    if let Some(tile) = tile {
232        for layer in tile.layers.values_mut() {
233            pbf.write_bytes_field(4, &write_layer(layer, &mut cache));
234        }
235        // now we can write columns
236        pbf.write_message(5, &cache);
237    }
238    // if an gridded data exists, let's write it
239    if let Some(grids) = grids {
240        for grid in grids.iter() {
241            pbf.write_message(6, *grid);
242        }
243    }
244    // if an image exists, let's write it
245    if let Some(images) = images {
246        for image in images.iter() {
247            pbf.write_message(7, *image);
248        }
249    }
250
251    pbf.take()
252}