open_vector_tile/base/
s2json_impl.rs

1use super::{
2    BaseVectorFeature, BaseVectorLines3DFeature, BaseVectorLinesFeature, BaseVectorPoints3DFeature,
3    BaseVectorPointsFeature, BaseVectorPolys3DFeature, BaseVectorPolysFeature, tess_to_points,
4    tess_to_points_3d,
5};
6use crate::{
7    Extent, Point, Point3D, VectorLine3DWithOffset, VectorLineWithOffset, VectorLines3DWithOffset,
8    VectorLinesWithOffset,
9};
10use alloc::{vec, vec::Vec};
11use libm::round;
12use s2json::{
13    MValueCompatible, Properties, VectorFeature, VectorLineString, VectorMultiLineString,
14    VectorMultiPolygon, VectorPoint,
15};
16
17// This is a convenience function to convert an S2JSON VectorFeature to a BaseVectorFeature
18
19/// Converts a VectorFeature to a BaseVectorFeature given a target extent
20pub fn s2json_to_base<M: Clone, P: MValueCompatible, D: MValueCompatible>(
21    vf: &VectorFeature<M, P, D>,
22    extent: Extent,
23) -> BaseVectorFeature {
24    let id = vf.id;
25    let extent: f64 = extent.into();
26    let properties: Properties = vf.properties.clone().into();
27
28    match &vf.geometry {
29        s2json::VectorGeometry::Point(p) => {
30            if !p.is_3d {
31                BaseVectorFeature::BaseVectorPointsFeature(BaseVectorPointsFeature::new(
32                    id,
33                    vec![vp_to_point(&p.coordinates, extent)],
34                    properties,
35                    p.bbox.map(|b| b.into()),
36                ))
37            } else {
38                BaseVectorFeature::BaseVectorPoints3DFeature(BaseVectorPoints3DFeature::new(
39                    id,
40                    vec![vp_to_point3d(&p.coordinates, extent)],
41                    properties,
42                    p.bbox,
43                ))
44            }
45        }
46        s2json::VectorGeometry::MultiPoint(mp) => {
47            if !mp.is_3d {
48                BaseVectorFeature::BaseVectorPointsFeature(BaseVectorPointsFeature::new(
49                    id,
50                    mp.coordinates.iter().map(|p| vp_to_point(p, extent)).collect(),
51                    properties,
52                    mp.bbox.map(|b| b.into()),
53                ))
54            } else {
55                BaseVectorFeature::BaseVectorPoints3DFeature(BaseVectorPoints3DFeature::new(
56                    id,
57                    mp.coordinates.iter().map(|p| vp_to_point3d(p, extent)).collect(),
58                    properties,
59                    mp.bbox,
60                ))
61            }
62        }
63        s2json::VectorGeometry::LineString(l) => {
64            if !l.is_3d {
65                BaseVectorFeature::BaseVectorLinesFeature(BaseVectorLinesFeature::new(
66                    id,
67                    vec![vl_to_ls_w_off(l.offset.unwrap_or_default(), &l.coordinates, extent)],
68                    properties,
69                    l.bbox.map(|b| b.into()),
70                ))
71            } else {
72                BaseVectorFeature::BaseVectorLines3DFeature(BaseVectorLines3DFeature::new(
73                    id,
74                    vec![vl_to_ls_w_off_3d(l.offset.unwrap_or_default(), &l.coordinates, extent)],
75                    properties,
76                    l.bbox,
77                ))
78            }
79        }
80        s2json::VectorGeometry::MultiLineString(ml) => {
81            if !ml.is_3d {
82                BaseVectorFeature::BaseVectorLinesFeature(BaseVectorLinesFeature::new(
83                    id,
84                    vml_to_ls_w_off(ml.offset.as_ref(), &ml.coordinates, extent),
85                    properties,
86                    ml.bbox.map(|b| b.into()),
87                ))
88            } else {
89                BaseVectorFeature::BaseVectorLines3DFeature(BaseVectorLines3DFeature::new(
90                    id,
91                    vml_to_ls_w_off_3d(ml.offset.as_ref(), &ml.coordinates, extent),
92                    properties,
93                    ml.bbox,
94                ))
95            }
96        }
97        s2json::VectorGeometry::Polygon(p) => {
98            if !p.is_3d {
99                BaseVectorFeature::BaseVectorPolysFeature(BaseVectorPolysFeature::new(
100                    id,
101                    vec![vml_to_ls_w_off(p.offset.as_ref(), &p.coordinates, extent)],
102                    properties,
103                    p.bbox.map(|b| b.into()),
104                    p.indices.clone().unwrap_or_default(),
105                    p.tessellation.clone().map(tess_to_points).unwrap_or_default(),
106                ))
107            } else {
108                BaseVectorFeature::BaseVectorPolys3DFeature(BaseVectorPolys3DFeature::new(
109                    id,
110                    vec![vml_to_ls_w_off_3d(p.offset.as_ref(), &p.coordinates, extent)],
111                    properties,
112                    p.bbox,
113                    p.indices.clone().unwrap_or_default(),
114                    p.tessellation.clone().map(tess_to_points_3d).unwrap_or_default(),
115                ))
116            }
117        }
118        s2json::VectorGeometry::MultiPolygon(mp) => {
119            if !mp.is_3d {
120                BaseVectorFeature::BaseVectorPolysFeature(BaseVectorPolysFeature::new(
121                    id,
122                    vmp_to_ls_w_off(mp.offset.as_ref(), &mp.coordinates, extent),
123                    properties,
124                    mp.bbox.map(|b| b.into()),
125                    mp.indices.clone().unwrap_or_default(),
126                    mp.tessellation.clone().map(tess_to_points).unwrap_or_default(),
127                ))
128            } else {
129                BaseVectorFeature::BaseVectorPolys3DFeature(BaseVectorPolys3DFeature::new(
130                    id,
131                    vmp_to_ls_w_off_3d(mp.offset.as_ref(), &mp.coordinates, extent),
132                    properties,
133                    mp.bbox,
134                    mp.indices.clone().unwrap_or_default(),
135                    mp.tessellation.clone().map(tess_to_points_3d).unwrap_or_default(),
136                ))
137            }
138        }
139    }
140}
141
142/// Vector MultiPolygon to Vec<VectorLinesWithOffset>
143fn vmp_to_ls_w_off<D: MValueCompatible>(
144    offsets: Option<&Vec<Vec<f64>>>,
145    mp: &VectorMultiPolygon<D>,
146    extent: f64,
147) -> Vec<VectorLinesWithOffset> {
148    mp.iter()
149        .enumerate()
150        .map(|(i, l)| vml_to_ls_w_off(offsets.and_then(|o| o.get(i)), l, extent))
151        .collect()
152}
153
154/// Vector MultiLineString to VectorLinesWithOffset
155fn vml_to_ls_w_off<D: MValueCompatible>(
156    offsets: Option<&Vec<f64>>,
157    vl: &VectorMultiLineString<D>,
158    extent: f64,
159) -> VectorLinesWithOffset {
160    vl.iter()
161        .enumerate()
162        .map(|(i, l)| {
163            vl_to_ls_w_off(offsets.and_then(|o| o.get(i).copied()).unwrap_or_default(), l, extent)
164        })
165        .collect()
166}
167
168/// Vector LineString to VectorLineWithOffset
169fn vl_to_ls_w_off<D: MValueCompatible>(
170    offset: f64,
171    vl: &VectorLineString<D>,
172    extent: f64,
173) -> VectorLineWithOffset {
174    VectorLineWithOffset::new(offset, vl.iter().map(|p| vp_to_point(p, extent)).collect())
175}
176
177/// Vector MultiPolygon to Vec<VectorLines3DWithOffset>
178fn vmp_to_ls_w_off_3d<D: MValueCompatible>(
179    offsets: Option<&Vec<Vec<f64>>>,
180    mp: &VectorMultiPolygon<D>,
181    extent: f64,
182) -> Vec<VectorLines3DWithOffset> {
183    mp.iter()
184        .enumerate()
185        .map(|(i, l)| vml_to_ls_w_off_3d(offsets.and_then(|o| o.get(i)), l, extent))
186        .collect()
187}
188
189/// Vector MultiLineString to VectorLines3DWithOffset
190fn vml_to_ls_w_off_3d<D: MValueCompatible>(
191    offsets: Option<&Vec<f64>>,
192    vl: &VectorMultiLineString<D>,
193    extent: f64,
194) -> VectorLines3DWithOffset {
195    vl.iter()
196        .enumerate()
197        .map(|(i, l)| {
198            vl_to_ls_w_off_3d(
199                offsets.and_then(|o| o.get(i).copied()).unwrap_or_default(),
200                l,
201                extent,
202            )
203        })
204        .collect()
205}
206
207/// Vector LineString to VectorLine3DWithOffset
208fn vl_to_ls_w_off_3d<D: MValueCompatible>(
209    offset: f64,
210    vl: &VectorLineString<D>,
211    extent: f64,
212) -> VectorLine3DWithOffset {
213    VectorLine3DWithOffset::new(offset, vl.iter().map(|p| vp_to_point3d(p, extent)).collect())
214}
215
216fn vp_to_point<D: MValueCompatible>(vp: &VectorPoint<D>, extent: f64) -> Point {
217    Point {
218        x: round(vp.x * extent) as i32,
219        y: round(vp.y * extent) as i32,
220        m: vp.m.clone().map(|m| m.into()),
221    }
222}
223
224fn vp_to_point3d<D: MValueCompatible>(vp: &VectorPoint<D>, extent: f64) -> Point3D {
225    Point3D {
226        x: round(vp.x * extent) as i32,
227        y: round(vp.y * extent) as i32,
228        z: round(vp.z.unwrap_or_default() * extent) as i32,
229        m: vp.m.clone().map(|m| m.into()),
230    }
231}