maps_engine_rust/
geojson.rs1#[derive(Debug, Clone, PartialEq)]
5pub struct Position(pub f64, pub f64);
6
7#[derive(Debug, Clone, PartialEq)]
9pub enum Geometry {
10 Point(Position),
11 LineString(Vec<Position>),
12 Polygon(Vec<Vec<Position>>),
13 MultiPoint(Vec<Position>),
14 MultiLineString(Vec<Vec<Position>>),
15 MultiPolygon(Vec<Vec<Vec<Position>>>),
16}
17
18impl Geometry {
19 pub fn bbox(&self) -> Option<(f64, f64, f64, f64)> {
21 let mut pts: Vec<&Position> = Vec::new();
22 fn collect<'a>(g: &'a Geometry, out: &mut Vec<&'a Position>) {
23 match g {
24 Geometry::Point(p) => out.push(p),
25 Geometry::LineString(v) | Geometry::MultiPoint(v) => out.extend(v),
26 Geometry::Polygon(v) | Geometry::MultiLineString(v) => {
27 for ring in v {
28 out.extend(ring)
29 }
30 }
31 Geometry::MultiPolygon(v) => {
32 for poly in v {
33 for ring in poly {
34 out.extend(ring)
35 }
36 }
37 }
38 }
39 }
40 collect(self, &mut pts);
41 if pts.is_empty() {
42 return None;
43 }
44 let mut w = f64::INFINITY;
45 let mut s = f64::INFINITY;
46 let mut e = f64::NEG_INFINITY;
47 let mut n = f64::NEG_INFINITY;
48 for p in pts {
49 w = w.min(p.0);
50 e = e.max(p.0);
51 s = s.min(p.1);
52 n = n.max(p.1);
53 }
54 Some((w, s, e, n))
55 }
56}
57
58#[derive(Debug, Clone)]
60pub struct Feature {
61 pub geometry: Geometry,
62 pub properties: Vec<(String, String)>,
63}
64
65impl Feature {
66 pub fn new(geometry: Geometry) -> Self {
67 Feature {
68 geometry,
69 properties: Vec::new(),
70 }
71 }
72
73 pub fn prop(mut self, k: impl Into<String>, v: impl Into<String>) -> Self {
74 self.properties.push((k.into(), v.into()));
75 self
76 }
77
78 pub fn get(&self, k: &str) -> Option<&str> {
79 self.properties
80 .iter()
81 .find(|(key, _)| key == k)
82 .map(|(_, v)| v.as_str())
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn bbox_of_polygon() {
92 let g = Geometry::Polygon(vec![vec![
93 Position(0.0, 0.0),
94 Position(2.0, 0.0),
95 Position(2.0, 3.0),
96 Position(0.0, 3.0),
97 ]]);
98 assert_eq!(g.bbox(), Some((0.0, 0.0, 2.0, 3.0)));
99 }
100
101 #[test]
102 fn feature_properties() {
103 let f = Feature::new(Geometry::Point(Position(105.85, 21.02))).prop("name", "Hà Nội");
104 assert_eq!(f.get("name"), Some("Hà Nội"));
105 assert_eq!(f.get("missing"), None);
106 }
107}