use anyhow::anyhow;
use dvb::point::Point;
use proj::Proj;
use crate::server::args::DVBPointCoords;
fn dvb_coords_to_wgs84(coords: (i64, i64)) -> Result<(f64, f64), String> {
let (northing, easting) = coords;
let proj = Proj::new_known_crs("EPSG:31468", "EPSG:4326", None)
.map_err(|e| format!("Failed to create projection: {}", e))?;
let result = proj
.convert((easting as f64, northing as f64))
.map_err(|e| format!("Failed to transform coordinates: {}", e))?;
let (longitude, latitude) = result;
if !((-90.0..=90.0).contains(&latitude) && (-180.0..=180.0).contains(&longitude)) {
return Err(format!(
"Converted coordinates ({}, {}) are outside valid WGS84 ranges",
latitude, longitude
));
}
Ok((latitude, longitude))
}
#[derive(Debug)]
pub struct OsmCoords {
pub latitude: f64,
pub longitude: f64,
}
impl OsmCoords {
pub fn url(self) -> String {
let OsmCoords {
latitude,
longitude,
} = self;
format!("https://www.openstreetmap.org/?mlat={latitude}&mlon={longitude}&zoom=17")
}
}
impl TryFrom<DVBPointCoords> for OsmCoords {
type Error = anyhow::Error;
fn try_from(coords: DVBPointCoords) -> Result<Self, Self::Error> {
let (latitude, longitude) = dvb_coords_to_wgs84((coords.latitude, coords.longitude))
.map_err(|error| anyhow!("Failed to converting coordinates: {error}"))?;
Ok(OsmCoords {
latitude,
longitude,
})
}
}
impl TryFrom<Point> for OsmCoords {
type Error = anyhow::Error;
fn try_from(Point { coords, name, .. }: Point) -> anyhow::Result<Self> {
let (latitude, longitude) = dvb_coords_to_wgs84(coords)
.map_err(|error| anyhow!("{name}: Failed to converting coordinates: {error}"))?;
Ok(OsmCoords {
latitude,
longitude,
})
}
}
#[test]
fn test_dvb_coords_conversion() {
let coords = (5657516, 4621644);
let result = dvb_coords_to_wgs84(coords);
if let Err(e) = &result {
eprintln!("Conversion error: {}", e);
}
assert!(result.is_ok(), "Conversion should succeed: {:?}", result);
let (lat, lon) = result.unwrap();
println!("Converted coords: lat={:.6}, lon={:.6}", lat, lon);
assert!(
(50.0..=52.0).contains(&lat),
"Latitude should be in Dresden area"
);
assert!(
(13.0..=15.0).contains(&lon),
"Longitude should be in Dresden area"
);
assert!(
(51.03..=51.05).contains(&lat),
"Should be near Dresden Hbf latitude"
);
assert!(
(13.72..=13.74).contains(&lon),
"Should be near Dresden Hbf longitude"
);
}