• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Open-S2 / open-vector-tile / #21

10 Sep 2024 04:56AM UTC coverage: 98.024% (-0.6%) from 98.575%
#21

push

Mr Martian
support conversion from s2json-spec; 3D-Terrain storage added

127 of 179 new or added lines in 19 files covered. (70.95%)

1 existing line in 1 file now uncovered.

8929 of 9109 relevant lines covered (98.02%)

61.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.62
/rust/vector_tile.rs
1
use pbf::{ProtoRead, Protobuf};
2

3
use alloc::collections::BTreeMap;
4
use alloc::rc::Rc;
5
use alloc::string::String;
6
use alloc::vec::Vec;
7

8
use core::cell::RefCell;
9

10
use crate::{
11
    base::BaseVectorTile,
12
    mapbox::MapboxVectorLayer,
13
    open::{
14
        write_layer, ColumnCacheReader, ColumnCacheWriter, ElevationData, FeatureType,
15
        OpenVectorLayer, Properties,
16
    },
17
    VectorGeometry, VectorLines3DWithOffset, VectorLinesWithOffset, VectorPoints, VectorPoints3D,
18
    BBOX,
19
};
20

21
/// Methods that all vector features should have
22
pub trait VectorFeatureMethods {
23
    /// the id of the feature
24
    fn id(&self) -> Option<u64>;
25
    /// the version of the vector tile
26
    fn version(&self) -> u16;
27
    /// the properties
28
    fn properties(&self) -> Properties;
29
    /// the extent
30
    fn extent(&self) -> usize;
31
    /// the feature type
32
    fn get_type(&self) -> FeatureType;
33
    /// the bounding box
34
    fn bbox(&self) -> Option<BBOX>;
35
    /// whether the feature has m values
36
    fn has_m_values(&self) -> bool;
37
    /// regardless of the type, we return a flattend point array
38
    fn load_points(&mut self) -> VectorPoints;
39
    /// regardless of the type, we return a flattend point3D array
40
    fn load_points_3d(&mut self) -> VectorPoints3D;
41
    /// an array of lines. The offsets will be set to 0
42
    fn load_lines(&mut self) -> VectorLinesWithOffset;
43
    /// an array of 3D lines. The offsets will be set to 0
44
    fn load_lines_3d(&mut self) -> VectorLines3DWithOffset;
45
    /// (flattened geometry & tesslation if applicable, indices)
46
    fn load_geometry_flat(&mut self) -> (Vec<f64>, Vec<u32>);
47
    /// load the geometry
48
    fn load_geometry(&mut self) -> VectorGeometry;
49
    /// load the indices
50
    fn read_indices(&mut self) -> Vec<u32>;
51
    /// Add tesselation data to the geometry
52
    fn add_tesselation(&mut self, geometry: &mut Vec<f64>, multiplier: f64);
53
    /// Add 3D tesselation data to the geometry
54
    fn add_tesselation_3d(&mut self, geometry: &mut Vec<f64>, multiplier: f64);
55
}
56

57
/// Methods that all vector layers should have
58
pub trait VectorLayerMethods {
59
    /// the version of the vector tile layer.
60
    fn version(&self) -> u16;
61
    /// the name of the layer
62
    fn name(&self) -> String;
63
    /// the extent of the vector tile (only **512**, **1_024**, **2_048**, **4_096**, and **8_192**
64
    /// are supported for the open spec)
65
    fn extent(&self) -> usize;
66
    /// grab a feature from the layer
67
    fn feature(&mut self, i: usize) -> Option<&mut dyn VectorFeatureMethods>;
68
    /// length (layer count)
69
    fn len(&self) -> usize;
70
    /// empty (layer count is 0)
71
    fn is_empty(&self) -> bool;
72
}
73

74
/// Layer container supporting both mapbox and open vector layers
75
#[derive(Debug)]
76
pub enum VectorLayer {
77
    /// Mapbox vector layer
78
    Mapbox(MapboxVectorLayer),
79
    /// Open vector layer
80
    Open(OpenVectorLayer),
81
}
82
impl VectorLayerMethods for VectorLayer {
83
    fn version(&self) -> u16 {
24✔
84
        match self {
24✔
85
            VectorLayer::Mapbox(layer) => layer.version(),
6✔
86
            VectorLayer::Open(layer) => layer.version(),
18✔
87
        }
88
    }
24✔
89

90
    fn name(&self) -> String {
24✔
91
        match self {
24✔
92
            VectorLayer::Mapbox(layer) => layer.name(),
6✔
93
            VectorLayer::Open(layer) => layer.name(),
18✔
94
        }
95
    }
24✔
96

97
    fn extent(&self) -> usize {
24✔
98
        match self {
24✔
99
            VectorLayer::Mapbox(layer) => layer.extent(),
6✔
100
            VectorLayer::Open(layer) => layer.extent(),
18✔
101
        }
102
    }
24✔
103

104
    fn feature(&mut self, i: usize) -> Option<&mut dyn VectorFeatureMethods> {
45✔
105
        match self {
45✔
106
            VectorLayer::Mapbox(layer) => layer.feature(i),
9✔
107
            VectorLayer::Open(layer) => layer.feature(i),
36✔
108
        }
109
    }
45✔
110

111
    fn len(&self) -> usize {
27✔
112
        match self {
27✔
113
            VectorLayer::Mapbox(layer) => layer.len(),
9✔
114
            VectorLayer::Open(layer) => layer.len(),
18✔
115
        }
116
    }
27✔
117

118
    fn is_empty(&self) -> bool {
6✔
119
        match self {
6✔
120
            VectorLayer::Mapbox(layer) => layer.is_empty(),
3✔
121
            VectorLayer::Open(layer) => layer.is_empty(),
3✔
122
        }
123
    }
6✔
124
}
125

126
/// The vector tile struct that covers both "open" and "mapbox" specifications
127
#[derive(Debug)]
128
pub struct VectorTile {
129
    /// the layers in the vector tile
130
    pub layers: BTreeMap<String, VectorLayer>,
131
    /// indexes to track the layers. Needed for the open spec because we need the cache before we can
132
    /// parse layers and features
133
    layer_indexes: Vec<usize>,
134
    /// the protobuf for the vector tile
135
    pbf: Rc<RefCell<Protobuf>>,
136
    /// the column cache
137
    columns: Option<Rc<RefCell<ColumnCacheReader>>>,
138
    /// Elevation data
139
    pub elevation: Option<ElevationData>,
140
}
141
impl VectorTile {
142
    /// Create a new vector tile
143
    pub fn new(data: Vec<u8>, end: Option<usize>) -> Self {
18✔
144
        let pbf = Rc::new(RefCell::new(data.into()));
18✔
145
        let mut vt = VectorTile {
18✔
146
            pbf: pbf.clone(),
18✔
147
            columns: None,
18✔
148
            layer_indexes: Vec::new(),
18✔
149
            layers: BTreeMap::new(),
18✔
150
            elevation: None,
18✔
151
        };
18✔
152

18✔
153
        pbf.borrow_mut().read_fields(&mut vt, end);
18✔
154

18✔
155
        if !vt.layer_indexes.is_empty() {
18✔
156
            vt.read_layers();
9✔
157
        }
9✔
158

159
        vt
18✔
160
    }
18✔
161

162
    /// Read the layers
163
    pub fn read_layers(&mut self) -> Option<()> {
9✔
164
        let layer_indexes = self.layer_indexes.clone();
9✔
165
        let mut tmp_pbf = self.pbf.borrow_mut();
9✔
166
        let cache = self.columns.as_ref()?.clone();
9✔
167

168
        for pos in layer_indexes {
30✔
169
            tmp_pbf.set_pos(pos);
21✔
170
            let mut layer = OpenVectorLayer::new(cache.clone());
21✔
171
            tmp_pbf.read_message(&mut layer);
21✔
172
            self.layers
21✔
173
                .insert(layer.name.clone(), VectorLayer::Open(layer));
21✔
174
        }
21✔
175

176
        Some(())
9✔
177
    }
9✔
178

179
    /// Get a layer given the name
180
    pub fn layer(&mut self, name: &str) -> Option<&mut VectorLayer> {
27✔
181
        self.layers.get_mut(name)
27✔
182
    }
27✔
183
}
184
impl ProtoRead for VectorTile {
185
    fn read(&mut self, tag: u64, pb: &mut Protobuf) {
39✔
186
        match tag {
39✔
187
            1 | 3 => {
9✔
188
                let mut layer = MapboxVectorLayer::new(self.pbf.clone(), tag == 1);
9✔
189
                pb.read_message(&mut layer);
9✔
190
                self.layers
9✔
191
                    .insert(layer.name.clone(), VectorLayer::Mapbox(layer));
9✔
192
            }
9✔
193
            4 => {
21✔
194
                // store the position of each layer for later retrieval.
21✔
195
                // Columns must be prepped before reading the layer.
21✔
196
                self.layer_indexes.push(pb.get_pos());
21✔
197
            }
21✔
198
            5 => {
9✔
199
                let mut column_reader = ColumnCacheReader::new();
9✔
200
                pb.read_message(&mut column_reader);
9✔
201
                self.columns = Some(Rc::new(RefCell::new(column_reader)));
9✔
202
            }
9✔
NEW
203
            6 => {
×
NEW
204
                let mut elevation = ElevationData::default();
×
NEW
205
                pb.read_message(&mut elevation);
×
NEW
206
                self.elevation = Some(elevation);
×
NEW
207
            }
×
UNCOV
208
            _ => panic!("unknown tag: {}", tag),
×
209
        }
210
    }
39✔
211
}
212

213
/// writer for converting a BaseVectorTile to encoded bytes of the Open Vector Tile format
214
pub fn write_tile(tile: &mut BaseVectorTile) -> Vec<u8> {
9✔
215
    let mut pbf = Protobuf::new();
9✔
216
    let mut cache = ColumnCacheWriter::default();
9✔
217

218
    // first write layers
219
    for layer in tile.layers.values_mut() {
21✔
220
        pbf.write_bytes_field(4, &write_layer(layer, &mut cache));
21✔
221
    }
21✔
222
    // now we can write columns
223
    pbf.write_message(5, &cache);
9✔
224

9✔
225
    pbf.take()
9✔
226
}
9✔
227

228
/// write elevation tile
NEW
229
pub fn write_elevation_tile(e_data: &mut ElevationData) -> Vec<u8> {
×
NEW
230
    let mut pbf = Protobuf::new();
×
NEW
231

×
NEW
232
    pbf.write_message(6, e_data);
×
NEW
233

×
NEW
234
    pbf.take()
×
NEW
235
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc