use derive_getters::Getters;
use serde::{Deserialize, Serialize};
use tracing::instrument;
#[derive(
Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Getters, derive_builder::Builder,
)]
#[builder(setter(into, strip_option))]
#[serde(rename_all = "camelCase")]
pub struct SpatialReference {
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default)]
wkid: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default)]
latest_wkid: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(default)]
wkt: Option<String>,
}
impl SpatialReference {
pub fn builder() -> SpatialReferenceBuilder {
SpatialReferenceBuilder::default()
}
pub const fn wgs84() -> Self {
Self {
wkid: Some(4326),
latest_wkid: Some(4326),
wkt: None,
}
}
pub const fn web_mercator() -> Self {
Self {
wkid: Some(3857),
latest_wkid: Some(3857),
wkt: None,
}
}
#[instrument(skip(self), fields(wkid = ?self.wkid))]
pub fn is_geographic(&self) -> bool {
let result = matches!(self.wkid, Some(4326) | Some(4269) | Some(4267));
tracing::debug!(is_geographic = result, "Checked coordinate system type");
result
}
#[instrument(skip(self), fields(wkid = ?self.wkid))]
pub fn is_projected(&self) -> bool {
let result = self.wkid.is_some() && !self.is_geographic();
tracing::debug!(is_projected = result, "Checked coordinate system type");
result
}
}
#[cfg(test)]
mod tests {
use super::*;
fn init_tracing() {
let _ = tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("debug")),
)
.with_test_writer()
.try_init();
}
#[test]
fn test_wgs84() {
init_tracing();
let sr = SpatialReference::wgs84();
assert_eq!(*sr.wkid(), Some(4326));
assert_eq!(*sr.latest_wkid(), Some(4326));
assert!(sr.is_geographic());
assert!(!sr.is_projected());
}
#[test]
fn test_web_mercator() {
init_tracing();
let sr = SpatialReference::web_mercator();
assert_eq!(*sr.wkid(), Some(3857));
assert_eq!(*sr.latest_wkid(), Some(3857));
assert!(!sr.is_geographic());
assert!(sr.is_projected());
}
#[test]
fn test_builder() -> anyhow::Result<()> {
init_tracing();
let sr = SpatialReferenceBuilder::default()
.wkid(2263u32)
.latest_wkid(2263u32)
.build()?;
assert_eq!(*sr.wkid(), Some(2263u32));
assert!(sr.is_projected());
Ok(())
}
}