1use crate::{
2 build_sq_dists, clip_line, BBox3D, ClipLineResultWithBBox, Face, Feature, Geometry, LonLat,
3 S2Feature, S2Point, STPoint, VectorFeature, VectorGeometry, VectorGeometryType,
4 VectorLineString, VectorLineStringGeometry, VectorMultiLineStringGeometry,
5 VectorMultiPointGeometry, VectorMultiPolygonGeometry, VectorPoint, VectorPointGeometry,
6 VectorPolygon, VectorPolygonGeometry,
7};
8
9use alloc::collections::BTreeSet;
10use alloc::vec;
11use alloc::vec::Vec;
12
13impl<M: Clone> Feature<M> {
16 pub fn to_vector(data: &Feature<M>, build_bbox: Option<bool>) -> VectorFeature<M> {
18 let build_bbox = build_bbox.unwrap_or(false);
19 let Feature { id, properties, metadata, geometry, .. } = data;
20 let vector_geo = convert_geometry(geometry, build_bbox);
21 VectorFeature::new_wm(*id, properties.clone(), vector_geo, metadata.clone())
22 }
23}
24
25impl<M: Clone> VectorFeature<M> {
26 pub fn to_unit_scale(&mut self, tolerance: Option<f64>, maxzoom: Option<u8>) {
28 let mut bbox: Option<BBox3D> = None;
29 match &mut self.geometry {
30 VectorGeometry::Point(geo) => {
31 geo.coordinates.project(&mut bbox);
32 geo.vec_bbox = bbox;
33 }
34 VectorGeometry::LineString(geo) | VectorGeometry::MultiPoint(geo) => {
35 geo.coordinates.iter_mut().for_each(|p| p.project(&mut bbox));
36 geo.vec_bbox = bbox;
37 }
38 VectorGeometry::Polygon(geo) | VectorGeometry::MultiLineString(geo) => {
39 geo.coordinates
40 .iter_mut()
41 .for_each(|p| p.iter_mut().for_each(|p| p.project(&mut bbox)));
42 geo.vec_bbox = bbox;
43 }
44 VectorGeometry::MultiPolygon(geo) => {
45 geo.coordinates.iter_mut().for_each(|p| {
46 p.iter_mut().for_each(|p| p.iter_mut().for_each(|p| p.project(&mut bbox)))
47 });
48 geo.vec_bbox = bbox;
49 }
50 }
51
52 if let Some(tolerance) = tolerance {
53 build_sq_dists(&mut self.geometry, tolerance, maxzoom);
54 }
55 }
56
57 pub fn to_ll(&mut self) {
59 match &mut self.geometry {
60 VectorGeometry::Point(geo) => {
61 geo.coordinates.unproject();
62 }
63 VectorGeometry::LineString(geo) | VectorGeometry::MultiPoint(geo) => {
64 geo.coordinates.iter_mut().for_each(|p| p.unproject());
65 }
66 VectorGeometry::Polygon(geo) | VectorGeometry::MultiLineString(geo) => {
67 geo.coordinates.iter_mut().for_each(|p| p.iter_mut().for_each(|p| p.unproject()));
68 }
69 VectorGeometry::MultiPolygon(geo) => {
70 geo.coordinates.iter_mut().for_each(|p| {
71 p.iter_mut().for_each(|p| p.iter_mut().for_each(|p| p.unproject()))
72 });
73 }
74 }
75 }
76
77 pub fn to_s2(&self, tolerance: Option<f64>, maxzoom: Option<u8>) -> Vec<S2Feature<M>> {
79 let VectorFeature { _type, id, properties, metadata, geometry, .. } = self;
80 let mut res: Vec<S2Feature<M>> = vec![];
81
82 if _type == "S2Feature" {
83 res.push(self.clone());
84 } else {
85 let vector_geo = convert_geometry_wm_to_s2(geometry, tolerance, maxzoom);
86 for ConvertedGeometry { geometry, face } in vector_geo {
87 res.push(S2Feature::<M>::new_s2(
88 *id,
89 face,
90 properties.clone(),
91 geometry,
92 metadata.clone(),
93 ));
94 }
95 }
96
97 res
98 }
99}
100
101fn convert_geometry(geometry: &Geometry, _build_bbox: bool) -> VectorGeometry {
103 match geometry {
105 Geometry::Point(geo) => {
106 let mut coordinates: VectorPoint = (&geo.coordinates).into();
107 coordinates.m = geo.m_values.clone();
108 VectorGeometry::Point(VectorPointGeometry {
109 _type: VectorGeometryType::Point,
110 is_3d: false,
111 coordinates,
112 bbox: geo.bbox.as_ref().map(|bbox| bbox.into()),
113 offset: None,
114 vec_bbox: None,
115 indices: None,
116 tesselation: None,
117 })
118 }
119 Geometry::Point3D(geo) => {
120 let mut coordinates: VectorPoint = (&geo.coordinates).into();
121 coordinates.m = geo.m_values.clone();
122 VectorGeometry::Point(VectorPointGeometry {
123 _type: VectorGeometryType::Point,
124 is_3d: true,
125 coordinates,
126 bbox: geo.bbox,
127 offset: None,
128 vec_bbox: None,
129 indices: None,
130 tesselation: None,
131 })
132 }
133 Geometry::MultiPoint(geo) => VectorGeometry::MultiPoint(VectorMultiPointGeometry {
134 _type: VectorGeometryType::MultiPoint,
135 is_3d: false,
136 coordinates: geo
137 .coordinates
138 .iter()
139 .enumerate()
140 .map(|(i, p)| {
141 let mut vp = VectorPoint::from(p);
142 if let Some(m) = &geo.m_values {
143 vp.m = Some(m[i].clone());
144 }
145 vp
146 })
147 .collect(),
148 bbox: geo.bbox.as_ref().map(|bbox| bbox.into()),
149 ..Default::default()
150 }),
151 Geometry::MultiPoint3D(geo) => VectorGeometry::MultiPoint(VectorMultiPointGeometry {
152 _type: VectorGeometryType::MultiPoint,
153 is_3d: true,
154 coordinates: geo
155 .coordinates
156 .iter()
157 .enumerate()
158 .map(|(i, p)| {
159 let mut vp = VectorPoint::from(p);
160 if let Some(m) = &geo.m_values {
161 vp.m = Some(m[i].clone());
162 }
163 vp
164 })
165 .collect(),
166 bbox: geo.bbox,
167 ..Default::default()
168 }),
169 Geometry::LineString(geo) => VectorGeometry::LineString(VectorLineStringGeometry {
170 _type: VectorGeometryType::LineString,
171 is_3d: false,
172 coordinates: geo
173 .coordinates
174 .iter()
175 .enumerate()
176 .map(|(i, p)| {
177 let mut vp = VectorPoint::from(p);
178 if let Some(m) = &geo.m_values {
179 vp.m = Some(m[i].clone());
180 }
181 vp
182 })
183 .collect(),
184 bbox: geo.bbox.as_ref().map(|bbox| bbox.into()),
185 ..Default::default()
186 }),
187 Geometry::LineString3D(geo) => VectorGeometry::LineString(VectorLineStringGeometry {
188 _type: VectorGeometryType::LineString,
189 is_3d: true,
190 coordinates: geo
191 .coordinates
192 .iter()
193 .enumerate()
194 .map(|(i, p)| {
195 let mut vp = VectorPoint::from(p);
196 if let Some(m) = &geo.m_values {
197 vp.m = Some(m[i].clone());
198 }
199 vp
200 })
201 .collect(),
202 bbox: geo.bbox,
203 ..Default::default()
204 }),
205 Geometry::MultiLineString(geo) => {
206 VectorGeometry::MultiLineString(VectorMultiLineStringGeometry {
207 _type: VectorGeometryType::MultiLineString,
208 is_3d: false,
209 coordinates: geo
210 .coordinates
211 .iter()
212 .enumerate()
213 .map(|(i, line)| {
214 line.iter()
215 .enumerate()
216 .map(|(j, p)| {
217 let mut vp = VectorPoint::from(p);
218 if let Some(m) = &geo.m_values {
219 vp.m = Some(m[i][j].clone());
220 }
221 vp
222 })
223 .collect()
224 })
225 .collect(),
226 bbox: geo.bbox.as_ref().map(|bbox| bbox.into()),
227 ..Default::default()
228 })
229 }
230 Geometry::MultiLineString3D(geo) => {
231 VectorGeometry::MultiLineString(VectorMultiLineStringGeometry {
232 _type: VectorGeometryType::MultiLineString,
233 is_3d: true,
234 coordinates: geo
235 .coordinates
236 .iter()
237 .enumerate()
238 .map(|(i, line)| {
239 line.iter()
240 .enumerate()
241 .map(|(j, p)| {
242 let mut vp = VectorPoint::from(p);
243 if let Some(m) = &geo.m_values {
244 vp.m = Some(m[i][j].clone());
245 }
246 vp
247 })
248 .collect()
249 })
250 .collect(),
251 bbox: geo.bbox,
252 ..Default::default()
253 })
254 }
255 Geometry::Polygon(geo) => VectorGeometry::Polygon(VectorPolygonGeometry {
256 _type: VectorGeometryType::Polygon,
257 is_3d: false,
258 coordinates: geo
259 .coordinates
260 .iter()
261 .enumerate()
262 .map(|(i, line)| {
263 line.iter()
264 .enumerate()
265 .map(|(j, p)| {
266 let mut vp = VectorPoint::from(p);
267 if let Some(m) = &geo.m_values {
268 vp.m = Some(m[i][j].clone());
269 }
270 vp
271 })
272 .collect()
273 })
274 .collect(),
275 bbox: geo.bbox.as_ref().map(|bbox| bbox.into()),
276 ..Default::default()
277 }),
278 Geometry::Polygon3D(geo) => VectorGeometry::Polygon(VectorPolygonGeometry {
279 _type: VectorGeometryType::Polygon,
280 is_3d: true,
281 coordinates: geo
282 .coordinates
283 .iter()
284 .enumerate()
285 .map(|(i, line)| {
286 line.iter()
287 .enumerate()
288 .map(|(j, p)| {
289 let mut vp = VectorPoint::from(p);
290 if let Some(m) = &geo.m_values {
291 vp.m = Some(m[i][j].clone());
292 }
293 vp
294 })
295 .collect()
296 })
297 .collect(),
298 bbox: geo.bbox,
299 ..Default::default()
300 }),
301 Geometry::MultiPolygon(geo) => VectorGeometry::MultiPolygon(VectorMultiPolygonGeometry {
302 _type: VectorGeometryType::MultiPolygon,
303 is_3d: false,
304 coordinates: geo
305 .coordinates
306 .iter()
307 .enumerate()
308 .map(|(i, polygon)| {
309 polygon
310 .iter()
311 .enumerate()
312 .map(|(j, line)| {
313 line.iter()
314 .enumerate()
315 .map(|(k, p)| {
316 let mut vp = VectorPoint::from(p);
317 if let Some(m) = &geo.m_values {
318 vp.m = Some(m[i][j][k].clone());
319 }
320 vp
321 })
322 .collect()
323 })
324 .collect()
325 })
326 .collect(),
327 bbox: geo.bbox.as_ref().map(|bbox| bbox.into()),
328 ..Default::default()
329 }),
330 Geometry::MultiPolygon3D(geo) => VectorGeometry::MultiPolygon(VectorMultiPolygonGeometry {
331 _type: VectorGeometryType::MultiPolygon,
332 is_3d: true,
333 coordinates: geo
334 .coordinates
335 .iter()
336 .enumerate()
337 .map(|(i, polygon)| {
338 polygon
339 .iter()
340 .enumerate()
341 .map(|(j, line)| {
342 line.iter()
343 .enumerate()
344 .map(|(k, p)| {
345 let mut vp = VectorPoint::from(p);
346 if let Some(m) = &geo.m_values {
347 vp.m = Some(m[i][j][k].clone());
348 }
349 vp
350 })
351 .collect()
352 })
353 .collect()
354 })
355 .collect(),
356 bbox: geo.bbox,
357 ..Default::default()
358 }),
359 }
360}
361
362pub struct ConvertedGeometry {
364 pub geometry: VectorGeometry,
365 pub face: Face,
366}
367pub type ConvertedGeometryList = Vec<ConvertedGeometry>;
368
369fn convert_geometry_wm_to_s2(
371 geometry: &VectorGeometry,
372 tolerance: Option<f64>,
373 maxzoom: Option<u8>,
374) -> ConvertedGeometryList {
375 let mut res: ConvertedGeometryList = vec![];
376
377 match geometry {
378 VectorGeometry::Point(geo) => {
379 res.extend(convert_geometry_point(geo));
380 }
381 VectorGeometry::MultiPoint(geo) => {
382 res.extend(convert_geometry_multipoint(geo));
383 }
384 VectorGeometry::LineString(geo) => {
385 res.extend(convert_geometry_linestring(geo));
386 }
387 VectorGeometry::MultiLineString(geo) => {
388 res.extend(convert_geometry_multilinestring(geo));
389 }
390 VectorGeometry::Polygon(geo) => {
391 res.extend(convert_geometry_polygon(geo));
392 }
393 VectorGeometry::MultiPolygon(geo) => {
394 res.extend(convert_geometry_multipolygon(geo));
395 }
396 }
397
398 if let Some(tolerance) = tolerance {
399 for c_geo in &mut res {
400 build_sq_dists(&mut c_geo.geometry, tolerance, maxzoom);
401 }
402 }
403
404 res
405}
406
407fn convert_geometry_point(geometry: &VectorPointGeometry) -> ConvertedGeometryList {
413 let VectorPointGeometry { _type, is_3d, coordinates, bbox, .. } = geometry;
414 let mut new_point = coordinates.clone();
415 let ll: S2Point = (&LonLat::new(new_point.x, new_point.y)).into();
416 let (face, s, t) = ll.to_face_st();
417 new_point.x = s;
418 new_point.y = t;
419 let vec_bbox = Some(BBox3D::from_point(&new_point));
420 vec![ConvertedGeometry {
421 face: face.into(),
422 geometry: VectorGeometry::Point(VectorPointGeometry {
423 _type: VectorGeometryType::Point,
424 coordinates: new_point,
425 is_3d: *is_3d,
426 bbox: *bbox,
427 vec_bbox,
428 offset: None,
429 indices: None,
430 tesselation: None,
431 }),
432 }]
433}
434
435fn convert_geometry_multipoint(geometry: &VectorMultiPointGeometry) -> ConvertedGeometryList {
440 let VectorMultiPointGeometry { is_3d, coordinates, bbox, .. } = geometry;
441 coordinates
442 .iter()
443 .flat_map(|coordinates| {
444 convert_geometry_point(&VectorPointGeometry {
445 _type: VectorGeometryType::Point,
446 is_3d: *is_3d,
447 coordinates: coordinates.clone(),
448 bbox: *bbox,
449 offset: None,
450 vec_bbox: None,
451 indices: None,
452 tesselation: None,
453 })
454 })
455 .collect()
456}
457
458fn convert_geometry_linestring(geometry: &VectorLineStringGeometry) -> ConvertedGeometryList {
460 let VectorLineStringGeometry { _type, is_3d, coordinates, bbox, .. } = geometry;
461
462 convert_line_string(coordinates, false)
463 .into_iter()
464 .map(|cline| {
465 let ConvertedLineString { face, line, offset, vec_bbox } = cline;
466 ConvertedGeometry {
467 face,
468 geometry: VectorGeometry::LineString(VectorLineStringGeometry {
469 _type: VectorGeometryType::LineString,
470 is_3d: *is_3d,
471 coordinates: line.to_vec(),
472 bbox: *bbox,
473 offset: Some(offset),
474 vec_bbox: Some(vec_bbox),
475 ..Default::default()
476 }),
477 }
478 })
479 .collect()
480}
481
482fn convert_geometry_multilinestring(
484 geometry: &VectorMultiLineStringGeometry,
485) -> ConvertedGeometryList {
486 let VectorMultiLineStringGeometry { is_3d, coordinates, bbox, .. } = geometry;
487
488 coordinates
489 .iter()
490 .flat_map(|line| convert_line_string(line, false))
491 .map(|ConvertedLineString { face, line, offset, vec_bbox }| ConvertedGeometry {
492 face,
493 geometry: VectorGeometry::LineString(VectorLineStringGeometry {
494 _type: VectorGeometryType::LineString,
495 is_3d: *is_3d,
496 coordinates: line,
497 bbox: *bbox,
498 offset: Some(offset),
499 vec_bbox: Some(vec_bbox),
500 ..Default::default()
501 }),
502 })
503 .collect()
504}
505
506fn convert_geometry_polygon(geometry: &VectorPolygonGeometry) -> ConvertedGeometryList {
508 let VectorPolygonGeometry { _type, is_3d, coordinates, bbox, .. } = geometry;
509 let mut res: ConvertedGeometryList = vec![];
510
511 let mut outer_ring = convert_line_string(&coordinates[0], true);
513 let mut inner_rings = coordinates[1..].iter().flat_map(|line| convert_line_string(line, true));
514
515 for ConvertedLineString { face, line, offset, vec_bbox: poly_bbox } in &mut outer_ring {
517 let mut polygon: VectorPolygon = vec![line.to_vec()];
518 let mut polygon_offsets = vec![*offset];
519 let mut poly_bbox = *poly_bbox;
520 for ConvertedLineString {
521 face: inner_face,
522 line: inner_line,
523 offset: inner_offset,
524 vec_bbox,
525 } in &mut inner_rings
526 {
527 if inner_face == *face {
528 polygon.push(inner_line);
529 polygon_offsets.push(inner_offset);
530 poly_bbox = poly_bbox.merge(&vec_bbox);
531 }
532 }
533
534 res.push(ConvertedGeometry {
535 face: *face,
536 geometry: VectorGeometry::Polygon(VectorPolygonGeometry {
537 _type: VectorGeometryType::Polygon,
538 is_3d: *is_3d,
539 coordinates: polygon,
540 bbox: *bbox,
541 offset: Some(polygon_offsets),
542 vec_bbox: Some(poly_bbox),
543 ..Default::default()
544 }),
545 });
546 }
547
548 res
549}
550
551fn convert_geometry_multipolygon(geometry: &VectorMultiPolygonGeometry) -> ConvertedGeometryList {
553 let VectorMultiPolygonGeometry { is_3d, coordinates, bbox, offset, .. } = geometry;
554 coordinates
555 .iter()
556 .enumerate()
557 .flat_map(|(i, polygon)| {
558 let offset: Option<Vec<f64>> = offset.as_ref().map(|offset| offset[i].clone());
559 convert_geometry_polygon(&VectorPolygonGeometry {
560 _type: VectorGeometryType::Polygon,
561 is_3d: *is_3d,
562 coordinates: polygon.to_vec(),
563 bbox: *bbox,
564 offset,
565 ..Default::default()
566 })
567 })
568 .collect()
569}
570
571pub struct ConvertedLineString {
573 face: Face,
574 line: VectorLineString,
575 offset: f64,
576 vec_bbox: BBox3D,
577}
578
579fn convert_line_string(line: &VectorLineString, is_polygon: bool) -> Vec<ConvertedLineString> {
581 let mut res: Vec<ConvertedLineString> = vec![];
582 let mut new_geometry: Vec<STPoint> = vec![];
584 for VectorPoint { x: lon, y: lat, z, m, .. } in line {
585 let ll: S2Point = (&LonLat::new(*lon, *lat)).into();
586 let (face, s, t) = ll.to_face_st();
587 new_geometry.push(STPoint { face: face.into(), s, t, z: *z, m: m.clone() });
588 }
589 let mut faces = BTreeSet::<Face>::new();
591 new_geometry.iter().for_each(|stpoint| {
592 faces.insert(stpoint.face);
593 });
594 for face in faces {
596 let mut line: VectorLineString = vec![];
597 for st_point in &new_geometry {
598 line.push(st_point_to_face(face, st_point));
599 }
600 let clipped_lines = clip_line(&line, BBox3D::default(), is_polygon, None, None);
601 for ClipLineResultWithBBox { line, offset, vec_bbox } in clipped_lines {
602 res.push(ConvertedLineString { face, line, offset, vec_bbox });
603 }
604 }
605
606 res
607}
608
609fn st_point_to_face(target_face: Face, stp: &STPoint) -> VectorPoint {
611 let cur_face = stp.face;
612 if target_face == cur_face {
613 return VectorPoint { x: stp.s, y: stp.t, z: stp.z, m: stp.m.clone(), t: None };
614 }
615
616 let (rot, x, y) = &FACE_RULE_SET[target_face as usize][cur_face as usize];
617 let (new_s, new_t) = rotate(*rot, stp.s, stp.t);
618
619 VectorPoint { x: new_s + *x as f64, y: new_t + *y as f64, z: stp.z, m: stp.m.clone(), t: None }
620}
621
622fn rotate(rot: Rotation, s: f64, t: f64) -> (f64, f64) {
629 match rot {
630 Rotation::_0 => (s, t),
631 Rotation::_90 => (t, 1. - s),
632 Rotation::_Neg90 => (1. - t, s),
633 }
634}
635
636#[derive(Debug, PartialEq, Copy, Clone)]
637pub enum Rotation {
638 _0,
639 _90,
640 _Neg90,
641}
642
643pub const FACE_RULE_SET: [[(Rotation, i8, i8); 6]; 6] = [
649 [
651 (Rotation::_0, 0, 0), (Rotation::_0, 1, 0), (Rotation::_90, 0, 1), (Rotation::_Neg90, 2, 0), (Rotation::_Neg90, -1, 0), (Rotation::_0, 0, -1), ],
658 [
660 (Rotation::_0, -1, 0), (Rotation::_0, 0, 0), (Rotation::_0, 0, 1), (Rotation::_Neg90, 1, 0), (Rotation::_Neg90, 2, 0), (Rotation::_90, 0, -1), ],
667 [
669 (Rotation::_Neg90, -1, 0), (Rotation::_0, 0, -1), (Rotation::_0, 0, 0), (Rotation::_0, 1, 0), (Rotation::_90, 0, 1), (Rotation::_Neg90, 2, 0), ],
676 [
678 (Rotation::_Neg90, 2, 0), (Rotation::_90, 0, -1), (Rotation::_0, -1, 0), (Rotation::_0, 0, 0), (Rotation::_0, 0, 1), (Rotation::_Neg90, 1, 0), ],
685 [
687 (Rotation::_90, 0, 1), (Rotation::_Neg90, 2, 0), (Rotation::_Neg90, -1, 0), (Rotation::_0, 0, -1), (Rotation::_0, 0, 0), (Rotation::_0, 1, 0), ],
694 [
696 (Rotation::_0, 0, 1), (Rotation::_Neg90, 1, 0), (Rotation::_Neg90, 2, 0), (Rotation::_90, 0, -1), (Rotation::_0, -1, 0), (Rotation::_0, 0, 0), ],
703];