use approx::assert_abs_diff_eq;
use std::f32::consts::PI;
use lensfun::mod_coord::geometry::{
equisolid_erect, erect_equisolid, erect_fisheye, erect_orthographic, erect_panoramic,
erect_rect, erect_stereographic, erect_thoby, fisheye_erect, fisheye_panoramic, fisheye_rect,
orthographic_erect, panoramic_erect, panoramic_fisheye, panoramic_rect, rect_erect,
rect_fisheye, rect_panoramic, stereographic_erect, thoby_erect,
};
const EPS: f32 = 1.0e-5;
const ROUND_TRIP_EPS: f32 = 1.0e-4;
#[test]
fn fisheye_rect_at_origin() {
let (x, y) = fisheye_rect(0.0, 0.0);
assert_eq!((x, y), (0.0, 0.0));
}
#[test]
fn rect_fisheye_at_origin() {
let (x, y) = rect_fisheye(0.0, 0.0);
assert_eq!((x, y), (0.0, 0.0));
}
#[test]
fn panoramic_rect_at_origin() {
let (x, y) = panoramic_rect(0.0, 0.0);
assert_abs_diff_eq!(x, 0.0, epsilon = EPS);
assert_abs_diff_eq!(y, 0.0, epsilon = EPS);
}
#[test]
fn rect_panoramic_at_origin() {
let (x, y) = rect_panoramic(0.0, 0.0);
assert_abs_diff_eq!(x, 0.0, epsilon = EPS);
assert_abs_diff_eq!(y, 0.0, epsilon = EPS);
}
#[test]
fn fisheye_panoramic_at_origin() {
let (x, y) = fisheye_panoramic(0.0, 0.0);
assert_abs_diff_eq!(x, 0.0, epsilon = EPS);
assert_abs_diff_eq!(y, 0.0, epsilon = EPS);
}
#[test]
fn panoramic_fisheye_at_origin() {
let (x, y) = panoramic_fisheye(0.0, 0.0);
assert_abs_diff_eq!(x, 0.0, epsilon = EPS);
assert_abs_diff_eq!(y, 0.0, epsilon = EPS);
}
#[test]
fn rect_erect_at_origin() {
let (x, y) = rect_erect(0.0, 0.0);
assert_abs_diff_eq!(x, 0.0, epsilon = EPS);
assert_abs_diff_eq!(y, 0.0, epsilon = EPS);
}
#[test]
fn fisheye_erect_at_origin() {
let (x, y) = fisheye_erect(0.0, 0.0);
assert_abs_diff_eq!(x, 0.0, epsilon = EPS);
assert_abs_diff_eq!(y, 0.0, epsilon = EPS);
}
#[test]
fn erect_panoramic_at_origin() {
let (x, y) = erect_panoramic(0.0, 0.0);
assert_abs_diff_eq!(x, 0.0, epsilon = EPS);
assert_abs_diff_eq!(y, 0.0, epsilon = EPS);
}
#[test]
fn panoramic_erect_at_origin() {
let (x, y) = panoramic_erect(0.0, 0.0);
assert_abs_diff_eq!(x, 0.0, epsilon = EPS);
assert_abs_diff_eq!(y, 0.0, epsilon = EPS);
}
#[test]
fn orthographic_erect_at_origin() {
let (x, y) = orthographic_erect(0.0, 0.0);
assert_abs_diff_eq!(x, 0.0, epsilon = EPS);
assert_abs_diff_eq!(y, 0.0, epsilon = EPS);
}
#[test]
fn equisolid_erect_at_origin() {
let (x, y) = equisolid_erect(0.0, 0.0);
assert_abs_diff_eq!(x, 0.0, epsilon = EPS);
assert_abs_diff_eq!(y, 0.0, epsilon = EPS);
}
#[test]
fn thoby_erect_at_origin() {
let (x, y) = thoby_erect(0.0, 0.0);
assert_abs_diff_eq!(x, 0.0, epsilon = EPS);
assert_abs_diff_eq!(y, 0.0, epsilon = EPS);
}
#[test]
fn erect_stereographic_at_origin() {
let (x, y) = erect_stereographic(0.0, 0.0);
assert_abs_diff_eq!(x, 0.0, epsilon = EPS);
assert_abs_diff_eq!(y, 0.0, epsilon = EPS);
}
#[test]
fn stereographic_erect_at_origin_returns_sentinel() {
let (x, y) = stereographic_erect(0.0, 0.0);
assert_eq!(x, 0.0);
assert_eq!(y, 1.6e16_f32);
}
#[test]
fn erect_equisolid_at_origin() {
let (x, y) = erect_equisolid(0.0, 0.0);
assert_abs_diff_eq!(x, 0.0, epsilon = EPS);
assert_abs_diff_eq!(y, 0.0, epsilon = EPS);
}
#[test]
fn fisheye_rect_returns_sentinel_outside_pi_half() {
let (x, _) = fisheye_rect(PI / 2.0 + 0.1, 0.0);
assert!(x > 1.0e16);
}
#[test]
fn rect_erect_known_point() {
let (x, y) = rect_erect(1.0, 0.0);
assert_abs_diff_eq!(x, PI / 4.0, epsilon = EPS);
assert_abs_diff_eq!(y, 0.0, epsilon = EPS);
}
#[test]
fn erect_panoramic_known_point() {
let (x, y) = erect_panoramic(0.5, PI / 4.0);
assert_abs_diff_eq!(x, 0.5, epsilon = EPS);
assert_abs_diff_eq!(y, 1.0, epsilon = EPS);
}
#[test]
fn panoramic_erect_known_point() {
let (x, y) = panoramic_erect(0.5, 1.0);
assert_abs_diff_eq!(x, 0.5, epsilon = EPS);
assert_abs_diff_eq!(y, PI / 4.0, epsilon = EPS);
}
fn assert_round_trip((rx, ry): (f32, f32), (ex, ey): (f32, f32), tag: &str) {
assert_abs_diff_eq!(rx, ex, epsilon = ROUND_TRIP_EPS);
assert_abs_diff_eq!(ry, ey, epsilon = ROUND_TRIP_EPS);
let _ = tag;
}
#[test]
fn round_trip_rect_fisheye() {
for &(x, y) in &[(0.1_f32, 0.1_f32), (0.3, -0.2), (-0.4, 0.5), (0.6, 0.0)] {
let fwd = fisheye_rect(x, y);
let back = rect_fisheye(fwd.0, fwd.1);
assert_round_trip(back, (x, y), "rect↔fisheye");
}
}
#[test]
fn round_trip_panoramic_rect() {
for &(x, y) in &[(0.1_f32, 0.1_f32), (0.3, -0.2), (-0.4, 0.5)] {
let fwd = panoramic_rect(x, y);
let back = rect_panoramic(fwd.0, fwd.1);
assert_round_trip(back, (x, y), "panoramic↔rect");
}
}
#[test]
fn round_trip_erect_panoramic() {
for &(x, y) in &[(0.1_f32, 0.1_f32), (0.3, -0.2), (-0.4, 0.5)] {
let fwd = erect_panoramic(x, y);
let back = panoramic_erect(fwd.0, fwd.1);
assert_round_trip(back, (x, y), "erect↔panoramic");
}
}
#[test]
fn round_trip_rect_erect() {
for &(x, y) in &[(0.1_f32, 0.1_f32), (0.3, -0.2), (-0.4, 0.5), (0.6, 0.7)] {
let fwd = rect_erect(x, y);
let back = erect_rect(fwd.0, fwd.1);
assert_round_trip(back, (x, y), "rect↔erect");
}
}
#[test]
fn round_trip_fisheye_erect() {
for &(x, y) in &[(0.1_f32, 0.1_f32), (0.3, -0.2), (-0.4, 0.5)] {
let fwd = fisheye_erect(x, y);
let back = erect_fisheye(fwd.0, fwd.1);
assert_round_trip(back, (x, y), "fisheye↔erect");
}
}
#[test]
fn round_trip_stereographic_erect() {
for &(x, y) in &[(0.1_f32, 0.1_f32), (0.3, -0.2), (-0.4, 0.5)] {
let fwd = stereographic_erect(x, y);
let back = erect_stereographic(fwd.0, fwd.1);
assert_round_trip(back, (x, y), "stereographic↔erect");
}
}
#[test]
fn round_trip_equisolid_erect() {
for &(x, y) in &[(0.1_f32, 0.1_f32), (0.3, -0.2), (-0.4, 0.5)] {
let fwd = equisolid_erect(x, y);
let back = erect_equisolid(fwd.0, fwd.1);
assert_round_trip(back, (x, y), "equisolid↔erect");
}
}
#[test]
fn round_trip_thoby_erect() {
for &(x, y) in &[(0.1_f32, 0.1_f32), (0.3, -0.2), (-0.4, 0.5)] {
let fwd = thoby_erect(x, y);
let back = erect_thoby(fwd.0, fwd.1);
assert_round_trip(back, (x, y), "thoby↔erect");
}
}
#[test]
fn round_trip_orthographic_erect() {
for &(x, y) in &[(0.1_f32, 0.1_f32), (0.3, -0.2), (-0.4, 0.5)] {
let fwd = orthographic_erect(x, y);
let back = erect_orthographic(fwd.0, fwd.1);
assert_round_trip(back, (x, y), "orthographic↔erect");
}
}
#[test]
fn upstream_apply_geometry_distortion_smoke() {
use std::path::Path;
use lensfun::Database;
use lensfun::modifier::Modifier;
let data_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("data/db");
let db = Database::load_dir(&data_dir).expect("bundled DB loads");
let lenses = db.find_lenses(None, "pEntax 50-200 ED");
let lens = lenses[0];
let (img_w, img_h) = (300_u32, 300_u32);
let mut modifier = Modifier::new(lens, 80.89, 1.534, img_w, img_h, false);
assert!(
modifier.enable_distortion_correction(lens),
"distortion should enable"
);
let mut buf = vec![0.0_f32; (img_w as usize) * 2];
for y in 0..img_h {
assert!(modifier.apply_geometry_distortion(0.0, y as f32, img_w as usize, 1, &mut buf));
}
}