gistools/writers/to_tiles/
types.rs

1use crate::{
2    data_structures::{ClusterOptions, GridOptions, HasLayer, TileStoreOptions},
3    parsers::RGBA,
4    readers::ReaderType,
5    writers::OnFeature,
6};
7use alloc::{collections::BTreeMap, string::String, vec, vec::Vec};
8use open_vector_tile::Extent;
9use s2_tilejson::{Attributions, DrawType, Encoding, LayerMetaData, SourceType};
10use s2json::{MValue, MValueCompatible, Projection, Properties, Shape, VectorFeature};
11use serde::{Deserialize, Serialize};
12
13/// This is how all vector features metadata will be stored
14#[derive(Debug, Clone, Default, Serialize, Deserialize)]
15pub struct ToTileMetadata {
16    /// Name of the layer
17    pub layer_name: String,
18}
19impl ToTileMetadata {
20    /// Create a new ToTileMetadata
21    pub fn new(layer_name: String) -> ToTileMetadata {
22        ToTileMetadata { layer_name }
23    }
24}
25impl HasLayer for ToTileMetadata {
26    fn get_layer(&self) -> Option<String> {
27        Some(self.layer_name.clone())
28    }
29}
30
31/// A Vector feature that uses the Open S2 spec to manage props and values
32pub type MVectorFeature = VectorFeature<ToTileMetadata, Properties, MValue>;
33
34/// This is a generic handler for any layer type
35#[derive(Debug)]
36pub struct LayerHandler<M: Clone + HasLayer, P: MValueCompatible, D: MValueCompatible> {
37    /// Name of the layer
38    pub layer_name: String,
39    /// Manipulate the feature before storing it
40    pub on_feature: OnFeature<M, P, D>,
41}
42
43/// No matter the type of layer you want to build, these are default properties to include
44#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
45pub struct BaseLayer {
46    /// Explain what the layer is
47    pub description: Option<String>,
48    /// Name of the source
49    pub source_name: String,
50    /// Name of the layer
51    pub layer_name: String,
52}
53
54/// Guide to building Raster layer data
55#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
56pub struct RasterLayerGuide {
57    /// describes how the image will be stored
58    pub output_type: String,
59    /// Raster clustering guide
60    pub raster_guide: GridOptions<RGBA>,
61    /// Common layer properties across all layer types
62    #[serde(flatten)]
63    pub base: BaseLayer,
64}
65impl From<&RasterLayerGuide> for LayerMetaData {
66    #[cfg_attr(feature = "nightly", coverage(off))] // not implemented don't punish
67    fn from(lg: &RasterLayerGuide) -> Self {
68        LayerMetaData {
69            description: lg.base.description.clone(),
70            minzoom: lg.raster_guide.minzoom.unwrap_or(0),
71            maxzoom: lg.raster_guide.maxzoom.unwrap_or(16),
72            draw_types: vec![DrawType::Raster],
73            ..Default::default()
74        }
75    }
76}
77
78/// Guide to building Grid layer data
79#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
80pub struct GridLayerGuide {
81    /// Grid clustering guide
82    pub grid_guide: GridOptions<f64>,
83    /// Extent at which the layer is storing its data
84    pub extent: Extent,
85    /// Common layer properties across all layer types
86    #[serde(flatten)]
87    pub base: BaseLayer,
88}
89impl From<&GridLayerGuide> for LayerMetaData {
90    #[cfg_attr(feature = "nightly", coverage(off))] // not implemented don't punish
91    fn from(lg: &GridLayerGuide) -> Self {
92        LayerMetaData {
93            description: lg.base.description.clone(),
94            minzoom: lg.grid_guide.minzoom.unwrap_or(0),
95            maxzoom: lg.grid_guide.maxzoom.unwrap_or(16),
96            draw_types: vec![DrawType::Grid],
97            ..Default::default()
98        }
99    }
100}
101
102/// Guide to building Cluster layer data
103#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
104pub struct ClusterLayerGuide {
105    /// If options are provided, the assumption is the point data is clustered
106    pub cluster_guide: ClusterOptions,
107    /// Extent at which the layer is storing its data
108    pub extent: Extent,
109    /// Common layer properties across all layer types
110    #[serde(flatten)]
111    pub base: BaseLayer,
112}
113impl From<&ClusterLayerGuide> for LayerMetaData {
114    fn from(lg: &ClusterLayerGuide) -> Self {
115        LayerMetaData {
116            description: lg.base.description.clone(),
117            minzoom: lg.cluster_guide.minzoom.unwrap_or(0),
118            maxzoom: lg.cluster_guide.maxzoom.unwrap_or(16),
119            draw_types: vec![DrawType::Points],
120            ..Default::default()
121        }
122    }
123}
124
125/// Guide to building Vector layer data
126#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
127pub struct VectorLayerGuide {
128    /// Guide on how to splice the data into vector tiles
129    pub vector_guide: TileStoreOptions,
130    /// Extent at which the layer is storing its data
131    pub extent: Extent,
132    /// Shape guide for the vector layer. If not provided it will be built for you
133    pub shape: Option<Shape>,
134    /// M-Value Shape guide for the vector layer
135    pub m_shape: Option<Shape>,
136    /// Draw Types (points, lines, polygons, 3D points, 3D lines, 3D polygons).
137    /// This is a filter mechanic. The source data may have multiple feature/draw types,
138    /// but if the layer you"re building only wants to use the points, you can filter that here
139    pub draw_types: Vec<DrawType>,
140    /// Common layer properties across all layer types
141    #[serde(flatten)]
142    pub base: BaseLayer,
143}
144impl From<&VectorLayerGuide> for LayerMetaData {
145    fn from(lg: &VectorLayerGuide) -> Self {
146        LayerMetaData {
147            description: lg.base.description.clone(),
148            minzoom: lg.vector_guide.minzoom.unwrap_or(0),
149            maxzoom: lg.vector_guide.maxzoom.unwrap_or(16),
150            draw_types: vec![DrawType::Points],
151            shape: lg.shape.clone().unwrap_or_default(),
152            m_shape: lg.m_shape.clone(),
153        }
154    }
155}
156
157/// List of user defined guides to build layers
158#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
159#[serde(untagged)]
160pub enum LayerGuide {
161    /// Raster guide
162    Raster(RasterLayerGuide),
163    /// Grid guide
164    Grid(GridLayerGuide),
165    /// Cluster guide
166    Cluster(ClusterLayerGuide),
167    /// Vector guide
168    Vector(VectorLayerGuide),
169}
170impl LayerGuide {
171    /// Get the minzoom and maxzoom of the active layer guide
172    pub fn zooms(&self) -> (u8, u8) {
173        match self {
174            LayerGuide::Raster(r) => {
175                (r.raster_guide.minzoom.unwrap_or(0), r.raster_guide.maxzoom.unwrap_or(16))
176            }
177            LayerGuide::Grid(g) => {
178                (g.grid_guide.minzoom.unwrap_or(0), g.grid_guide.maxzoom.unwrap_or(16))
179            }
180            LayerGuide::Cluster(c) => {
181                (c.cluster_guide.minzoom.unwrap_or(0), c.cluster_guide.maxzoom.unwrap_or(16))
182            }
183            LayerGuide::Vector(v) => {
184                (v.vector_guide.minzoom.unwrap_or(0), v.vector_guide.maxzoom.unwrap_or(16))
185            }
186        }
187    }
188
189    /// Check the source name matches the layer"s source
190    pub fn has_source(&self, source_name: &str) -> bool {
191        match self {
192            LayerGuide::Raster(r) => r.base.source_name == source_name,
193            LayerGuide::Grid(g) => g.base.source_name == source_name,
194            LayerGuide::Cluster(c) => c.base.source_name == source_name,
195            LayerGuide::Vector(v) => v.base.source_name == source_name,
196        }
197    }
198
199    /// Get the layer name of the active layer guide
200    pub fn layer_name(&self) -> &str {
201        match self {
202            LayerGuide::Raster(r) => &r.base.layer_name,
203            LayerGuide::Grid(g) => &g.base.layer_name,
204            LayerGuide::Cluster(c) => &c.base.layer_name,
205            LayerGuide::Vector(v) => &v.base.layer_name,
206        }
207    }
208
209    /// Grab the vector guide
210    pub fn to_vector(&self) -> Option<VectorLayerGuide> {
211        match self {
212            LayerGuide::Vector(v) => Some(v.clone()),
213            _ => None,
214        }
215    }
216}
217impl Default for LayerGuide {
218    fn default() -> Self {
219        LayerGuide::Vector(VectorLayerGuide::default())
220    }
221}
222impl From<&LayerGuide> for LayerMetaData {
223    fn from(layer_guide: &LayerGuide) -> Self {
224        match layer_guide {
225            LayerGuide::Raster(r) => r.into(),
226            LayerGuide::Grid(g) => g.into(),
227            LayerGuide::Cluster(c) => c.into(),
228            LayerGuide::Vector(v) => v.into(),
229        }
230    }
231}
232
233/// The vector format if applicable helps define how the vector data is stored.
234/// - The more modern vector format is the "open-s2" which supports things like m-values
235///   and 3D geometries.
236/// - The new vector format is the "open-s2" which only supports 2D & 3D geometries, supports M-Values,
237///   properties and M-Values can have nested properties and/or arrays, and is decently fast to parse.
238/// - The basic vector format is the "flat-open-s2" which only supports 2D geometries and works on
239///   older map engines like Mapbox-gl-js, is faster to parse and often lighter in size.
240/// - The older vector format is the "mapbox" which is the legacy format used by Mapbox and slow to parse.
241/// - The `raster` format is used speciially for raster ONLY data. Ensures the data is stored as a raster
242///
243/// Defaults to `"open-s2"`
244#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
245#[serde(rename_all = "kebab-case")]
246pub enum FormatOutput {
247    /// Legacy Mapbox format
248    Mapbox,
249    /// Flat Open S2. Modified Legacy Mapbox format for better compression of polygons
250    FlatOpenS2,
251    /// Open Vector Tile format
252    #[default]
253    OpenS2,
254    /// Raster data
255    Raster,
256}
257impl From<&str> for FormatOutput {
258    fn from(value: &str) -> Self {
259        match value {
260            "mapbox" => FormatOutput::Mapbox,
261            "flat-open-s2" => FormatOutput::FlatOpenS2,
262            "open-s2" => FormatOutput::OpenS2,
263            "raster" => FormatOutput::Raster,
264            _ => FormatOutput::OpenS2,
265        }
266    }
267}
268impl From<&FormatOutput> for SourceType {
269    fn from(value: &FormatOutput) -> Self {
270        match value {
271            FormatOutput::Mapbox | FormatOutput::FlatOpenS2 | FormatOutput::OpenS2 => {
272                SourceType::Vector
273            }
274            FormatOutput::Raster => SourceType::Raster,
275        }
276    }
277}
278
279/// The source input
280#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
281pub struct Source {
282    /// The name of the source
283    pub source_name: String,
284    /// The type of source data. E.g. "csv", "json", "pmtiles", "shapefile", etc.
285    #[serde(rename = "inputType")]
286    pub input_type: ReaderType,
287}
288
289/// The source input
290#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
291pub enum WhichTileWriting {
292    /// Use local memory
293    #[default]
294    Local,
295    /// Filesystem
296    File,
297    /// Memory Mapped
298    MMap,
299}
300
301/// A user defined guide on building the vector tiles
302#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
303#[serde(default)]
304pub struct JSONBuildGuide {
305    /// The name of the data
306    pub name: String,
307    /// The description of the data
308    pub description: String,
309    /// User defined versioning for their data
310    pub version: String,
311    /// Specify the image type. e.g. "pbf", "png", "jpg", "webp", etc.
312    /// [Default: "pbf"]
313    pub extension: String,
314    /// What kind of output format should be used. Used for describing either S2 or WM
315    /// projections. [Default: "fzxy"]
316    pub projection: Projection,
317    /// The encoding format. Can be either "gz", "br", "zstd" or "none". [Default: "none"]
318    pub encoding: Encoding,
319    /// The attribution of the data. Store as `{ "presentation name": "href" }`.
320    pub attribution: Attributions,
321    /// The vector format if applicable helps define how the vector data is stored.
322    /// - The more modern vector format is the "open-s2" which supports things like m-values
323    ///   and 3D geometries.
324    /// - The new vector format is the "open-s2" which only supports 2D & 3D geometries, supports M-Values,
325    ///   properties and M-Values can have nested properties and/or arrays, and is decently fast to parse.
326    /// - The basic vector format is the "flat-open-s2" which only supports 2D geometries and works on
327    ///   older map engines like Mapbox-gl-js, is faster to parse and often lighter in size.
328    /// - The older vector format is the "mapbox" which is the legacy format used by Mapbox and slow to parse.
329    /// - The `raster` format is used speciially for raster ONLY data. Ensures the data is stored as a raster
330    ///
331    /// Defaults to `"open-s2"`
332    pub format: FormatOutput,
333    /// The vector sources that the tile is built from and how the layers are to be stored.
334    /// Created using `{ [source_name: string]: Source }`
335    /// See: [`crate::parsers::FeatureReader`]
336    #[serde(rename = "vectorSources")]
337    pub vector_sources: Vec<Source>,
338    /// The raster sources that will be conjoined into a single rgba pixel index for tile extraction
339    #[serde(rename = "rasterSources")]
340    pub raster_sources: Vec<Source>,
341    /// The grid sources that will be conjoined into a single grid index for tile extraction
342    #[serde(rename = "gridSources")]
343    pub grid_sources: Vec<Source>,
344    /// Should the indices be built for polygon data for faster rendering (file cost increases). [Default: true]
345    #[serde(rename = "buildIndices")]
346    pub build_indices: bool,
347    /// The guides on how to build the various data
348    /// See: {@link LayerGuide}
349    #[serde(default, rename = "layerGuides")]
350    pub layer_guides: Vec<LayerGuide>,
351    /// Set the number of threads to use. [Default: 1]
352    pub threads: usize,
353    /// tileWriter
354    #[serde(default, rename = "tileWriter")]
355    pub tile_writer: WhichTileWriting,
356}
357impl Default for JSONBuildGuide {
358    fn default() -> Self {
359        JSONBuildGuide {
360            name: "auto generated".into(),
361            description: "generated via OpenS2 gis-tools".into(),
362            version: "1.0.0".into(),
363            extension: "pbf".into(),
364            projection: Projection::S2,
365            encoding: Encoding::None,
366            attribution: BTreeMap::default(),
367            format: FormatOutput::default(),
368            vector_sources: vec![],
369            raster_sources: vec![],
370            grid_sources: vec![],
371            build_indices: true,
372            layer_guides: vec![],
373            tile_writer: WhichTileWriting::Local,
374            threads: 1,
375        }
376    }
377}
378
379/// A user defined guide on building the vector tiles
380#[derive(Debug, Clone)]
381pub struct BuildGuide {
382    /// The name of the data
383    pub name: String,
384    /// The description of the data
385    pub description: String,
386    /// User defined versioning for their data
387    pub version: String,
388    /// Specify the image type. e.g. "pbf", "png", "jpg", "webp", etc.
389    /// [Default: `"pbf"`]
390    pub extension: String,
391    /// What kind of output format should be used. Used for describing either S2 or WM
392    /// projections. [Default: `"fzxy"`]
393    pub projection: Projection,
394    /// The encoding format. Can be either "gz", "br", "zstd" or "none". [Default: `"none"`]
395    pub encoding: Encoding,
396    /// The attribution of the data. Store as `{ "presentation name": "href" }`.
397    pub attributions: Attributions,
398    /// The vector format if applicable helps define how the vector data is stored.
399    /// - The more modern vector format is the "open-s2" which supports things like m-values
400    ///   and 3D geometries.
401    /// - The new vector format is the "open-s2" which only supports 2D & 3D geometries, supports M-Values,
402    ///   properties and M-Values can have nested properties and/or arrays, and is decently fast to parse.
403    /// - The basic vector format is the "flat-open-s2" which only supports 2D geometries and works on
404    ///   older map engines like Mapbox-gl-js, is faster to parse and often lighter in size.
405    /// - The older vector format is the "mapbox" which is the legacy format used by Mapbox and slow to parse.
406    /// - The `raster` format is used speciially for raster ONLY data. Ensures the data is stored as a raster
407    ///
408    /// [Default: `"open-s2"`]
409    pub format: FormatOutput,
410    /// Should the indices be built for polygon data for faster rendering (file cost increases). [Default: `true`]
411    pub build_indices: bool,
412    /// The guides on how to build the various data
413    pub layer_guides: Vec<LayerGuide>,
414    /// Set the number of threads to use. [Default: `1`]
415    pub threads: usize,
416}
417impl Default for BuildGuide {
418    fn default() -> Self {
419        BuildGuide {
420            name: "auto generated".into(),
421            description: "generated via OpenS2 gis-tools".into(),
422            version: "1.0.0".into(),
423            extension: "pbf".into(),
424            projection: Projection::S2,
425            encoding: Encoding::None,
426            attributions: BTreeMap::default(),
427            format: FormatOutput::default(),
428            build_indices: true,
429            layer_guides: vec![],
430            threads: 1,
431        }
432    }
433}