1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
7#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
8pub struct Location {
9 pub x: f64,
11 pub y: f64,
13 #[serde(default, skip_serializing_if = "Option::is_none")]
15 pub kind: Option<CoordsKind>,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
20#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
21#[serde(rename_all = "snake_case")]
22#[non_exhaustive]
23pub enum CoordsKind {
24 Source,
25 Synthetic,
26 Manual,
27 Derived,
28}
29
30#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
32#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
33pub struct GeoMeta {
34 #[serde(flatten)]
36 pub space: CoordinateSpace,
37 #[serde(default, skip_serializing_if = "Option::is_none")]
39 pub kind: Option<CoordsKind>,
40}
41
42#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
44#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
45#[serde(tag = "space", rename_all = "snake_case")]
46#[non_exhaustive]
47pub enum CoordinateSpace {
48 Geographic {
50 #[serde(default, skip_serializing_if = "Option::is_none")]
51 crs: Option<String>,
52 },
53 Projected {
55 #[serde(default, skip_serializing_if = "Option::is_none")]
56 crs: Option<String>,
57 },
58 Diagram {
60 #[serde(default, skip_serializing_if = "Option::is_none")]
61 canvas: Option<Canvas>,
62 },
63 Unknown,
65}
66
67#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
69#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
70pub struct Canvas {
71 #[serde(default, skip_serializing_if = "Option::is_none")]
72 pub width: Option<f64>,
73 #[serde(default, skip_serializing_if = "Option::is_none")]
74 pub height: Option<f64>,
75 #[serde(default, skip_serializing_if = "Option::is_none")]
76 pub units: Option<String>,
77}