#![allow(dead_code)]
#[derive(Debug, Clone, PartialEq)]
pub struct GeoTransform {
pub x_origin: f64,
pub pixel_width: f64,
pub row_rotation: f64,
pub y_origin: f64,
pub col_rotation: f64,
pub pixel_height: f64,
}
impl GeoTransform {
pub fn new(
x_origin: f64,
pixel_width: f64,
row_rotation: f64,
y_origin: f64,
col_rotation: f64,
pixel_height: f64,
) -> Self {
Self {
x_origin,
pixel_width,
row_rotation,
y_origin,
col_rotation,
pixel_height,
}
}
pub fn north_up(x_origin: f64, pixel_width: f64, y_origin: f64, pixel_height: f64) -> Self {
Self::new(x_origin, pixel_width, 0.0, y_origin, 0.0, pixel_height)
}
pub fn pixel_to_geo(&self, col: f64, row: f64) -> (f64, f64) {
let x = self.x_origin + col * self.pixel_width + row * self.row_rotation;
let y = self.y_origin + col * self.col_rotation + row * self.pixel_height;
(x, y)
}
pub fn geo_to_pixel(&self, x: f64, y: f64) -> Option<(f64, f64)> {
let det = self.pixel_width * self.pixel_height - self.row_rotation * self.col_rotation;
if det.abs() < f64::EPSILON {
return None;
}
let dx = x - self.x_origin;
let dy = y - self.y_origin;
let col = (self.pixel_height * dx - self.row_rotation * dy) / det;
let row = (self.pixel_width * dy - self.col_rotation * dx) / det;
Some((col, row))
}
pub fn to_pixel_scale(&self) -> [f64; 3] {
[self.pixel_width, -self.pixel_height, 0.0]
}
pub fn to_tiepoint(&self) -> [f64; 6] {
[0.0, 0.0, 0.0, self.x_origin, self.y_origin, 0.0]
}
pub fn from_scale_tiepoint(scale: &[f64], tiepoint: &[f64]) -> Option<Self> {
if scale.len() < 2 || tiepoint.len() < 6 {
return None;
}
let (px, py) = (tiepoint[0], tiepoint[1]);
let (gx, gy) = (tiepoint[3], tiepoint[4]);
let sx = scale[0];
let sy = scale[1]; Some(Self::new(
gx - px * sx,
sx,
0.0,
gy + py * sy,
0.0,
-sy,
))
}
}
impl Default for GeoTransform {
fn default() -> Self {
Self::new(0.0, 1.0, 0.0, 0.0, 0.0, -1.0)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct BoundingBox {
pub min_x: f64,
pub min_y: f64,
pub max_x: f64,
pub max_y: f64,
}
impl BoundingBox {
pub fn new(min_x: f64, min_y: f64, max_x: f64, max_y: f64) -> Self {
Self { min_x, min_y, max_x, max_y }
}
pub fn width(&self) -> f64 {
self.max_x - self.min_x
}
pub fn height(&self) -> f64 {
self.max_y - self.min_y
}
pub fn center(&self) -> (f64, f64) {
((self.min_x + self.max_x) / 2.0, (self.min_y + self.max_y) / 2.0)
}
}