use crate::{Dimension, Extent};
pub fn vcrop(
target: &Extent,
parent_dim: &Dimension,
parent_extent: &Extent,
) -> (Extent, Dimension) {
let x_res = (parent_extent[1] - parent_extent[0]) / parent_dim[0] as f64;
let y_res = (parent_extent[3] - parent_extent[2]) / parent_dim[1] as f64;
let col_min = ((target[0] - parent_extent[0]) / x_res).floor() as i64;
let col_max = ((target[1] - parent_extent[0]) / x_res).ceil() as i64;
let row_min = ((target[2] - parent_extent[2]) / y_res).floor() as i64;
let row_max = ((target[3] - parent_extent[2]) / y_res).ceil() as i64;
let col_min = col_min.max(0) as usize;
let col_max = (col_max as usize).min(parent_dim[0]);
let row_min = row_min.max(0) as usize;
let row_max = (row_max as usize).min(parent_dim[1]);
let aligned_extent = [
parent_extent[0] + col_min as f64 * x_res,
parent_extent[0] + col_max as f64 * x_res,
parent_extent[2] + row_min as f64 * y_res,
parent_extent[2] + row_max as f64 * y_res,
];
let aligned_dim = [col_max - col_min, row_max - row_min];
(aligned_extent, aligned_dim)
}
pub fn crop_offset(
sub_extent: &Extent,
parent_dim: &Dimension,
parent_extent: &Extent,
) -> (usize, usize) {
let x_res = (parent_extent[1] - parent_extent[0]) / parent_dim[0] as f64;
let y_res = (parent_extent[3] - parent_extent[2]) / parent_dim[1] as f64;
let col_off = ((sub_extent[0] - parent_extent[0]) / x_res).round() as usize;
let row_off = ((parent_extent[3] - sub_extent[3]) / y_res).round() as usize;
(col_off, row_off)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn vcrop_exact_alignment() {
let parent_dim = [10, 10];
let parent_extent = [0.0, 10.0, 0.0, 10.0];
let target = [2.0, 5.0, 3.0, 7.0];
let (ext, dim) = vcrop(&target, &parent_dim, &parent_extent);
assert!((ext[0] - 2.0).abs() < 1e-10);
assert!((ext[1] - 5.0).abs() < 1e-10);
assert!((ext[2] - 3.0).abs() < 1e-10);
assert!((ext[3] - 7.0).abs() < 1e-10);
assert_eq!(dim, [3, 4]);
}
#[test]
fn vcrop_snaps_outward() {
let parent_dim = [10, 10];
let parent_extent = [0.0, 10.0, 0.0, 10.0];
let target = [2.3, 4.7, 3.1, 6.9];
let (ext, dim) = vcrop(&target, &parent_dim, &parent_extent);
assert!((ext[0] - 2.0).abs() < 1e-10);
assert!((ext[1] - 5.0).abs() < 1e-10);
assert!((ext[2] - 3.0).abs() < 1e-10);
assert!((ext[3] - 7.0).abs() < 1e-10);
assert_eq!(dim, [3, 4]);
}
#[test]
fn vcrop_clamped_to_parent() {
let parent_dim = [10, 10];
let parent_extent = [0.0, 10.0, 0.0, 10.0];
let target = [-5.0, 15.0, -5.0, 15.0];
let (ext, dim) = vcrop(&target, &parent_dim, &parent_extent);
assert!((ext[0] - 0.0).abs() < 1e-10);
assert!((ext[1] - 10.0).abs() < 1e-10);
assert!((ext[2] - 0.0).abs() < 1e-10);
assert!((ext[3] - 10.0).abs() < 1e-10);
assert_eq!(dim, [10, 10]);
}
#[test]
fn crop_offset_basic() {
let parent_dim = [360, 180];
let parent_extent = [-180.0, 180.0, -90.0, 90.0];
let sub_extent = [10.0, 21.0, -6.0, 9.0];
let (col_off, row_off) = crop_offset(&sub_extent, &parent_dim, &parent_extent);
assert_eq!(col_off, 190);
assert_eq!(row_off, 81);
}
}