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
17pub 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
142fn 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
154fn 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
168fn 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
177fn 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
189fn 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
207fn 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}