open_vector_tile/
vector_tile.rs

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