dcso3/
coord.rs

1/*
2Copyright 2024 Eric Stokes.
3
4This file is part of dcso3.
5
6dcso3 is free software: you can redistribute it and/or modify it under
7the terms of the MIT License.
8
9dcso3 is distributed in the hope that it will be useful, but WITHOUT
10ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11FITNESS FOR A PARTICULAR PURPOSE.
12*/
13
14use super::{as_tbl, String};
15use crate::{lua_err, wrapped_table, LuaEnv, LuaVec3};
16use anyhow::Result;
17use mlua::{prelude::*, Value};
18use serde_derive::{Deserialize, Serialize};
19use std::ops::Deref;
20
21#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
22pub struct LLPos {
23    pub latitude: f64,
24    pub longitude: f64,
25    pub altitude: f64,
26}
27
28#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
29pub struct MGRSPos {
30    pub utm_zone: String,
31    pub mgrs_digraph: String,
32    pub easting: f64,
33    pub northing: f64,
34}
35
36impl<'lua> FromLua<'lua> for MGRSPos {
37    fn from_lua(value: Value<'lua>, _lua: &'lua Lua) -> LuaResult<Self> {
38        let tbl = as_tbl("MGRSPos", None, value).map_err(lua_err)?;
39        Ok(MGRSPos {
40            utm_zone: tbl.raw_get("UTMZone")?,
41            mgrs_digraph: tbl.raw_get("MGRSDigraph")?,
42            easting: tbl.raw_get("Easting")?,
43            northing: tbl.raw_get("Northing")?,
44        })
45    }
46}
47
48impl<'lua> IntoLua<'lua> for MGRSPos {
49    fn into_lua(self, lua: &'lua Lua) -> LuaResult<Value<'lua>> {
50        let tbl = lua.create_table()?;
51        tbl.raw_set("UTMZone", self.utm_zone)?;
52        tbl.raw_set("MGRSDigraph", self.mgrs_digraph)?;
53        tbl.raw_set("Easting", self.easting)?;
54        tbl.raw_set("Northing", self.northing)?;
55        Ok(Value::Table(tbl))
56    }
57}
58
59wrapped_table!(Coord, None);
60
61impl<'lua> Coord<'lua> {
62    pub fn singleton<L: LuaEnv<'lua>>(lua: L) -> Result<Self> {
63        Ok(lua.inner().globals().raw_get("coord")?)
64    }
65
66    pub fn ll_to_lo(&self, pos: LLPos) -> Result<LuaVec3> {
67        Ok(self
68            .t
69            .call_function("LLtoLO", (pos.latitude, pos.longitude, pos.altitude))?)
70    }
71
72    pub fn lo_to_ll(&self, pos: LuaVec3) -> Result<LLPos> {
73        let (latitude, longitude, altitude) = self.t.call_function("LOtoLL", pos)?;
74        Ok(LLPos {
75            latitude,
76            longitude,
77            altitude,
78        })
79    }
80
81    pub fn ll_to_mgrs(&self, latitude: f64, longitude: f64) -> Result<MGRSPos> {
82        Ok(self.t.call_function("LLtoMGRS", (latitude, longitude))?)
83    }
84
85    pub fn mgrs_to_ll(&self, mgrs: MGRSPos) -> Result<LLPos> {
86        let (latitude, longitude, altitude) = self.t.call_function("MGRStoLL", mgrs)?;
87        Ok(LLPos {
88            latitude,
89            longitude,
90            altitude,
91        })
92    }
93}