const NEWTON_EPS: f64 = 0.00001;
pub fn dist_poly3(x: f32, y: f32, k1: f32) -> (f32, f32) {
let poly2 = k1 * (x * x + y * y) + 1.0;
(x * poly2, y * poly2)
}
pub fn undist_poly3(x: f32, y: f32, k1: f32) -> (f32, f32) {
let inv_k1_ = 1.0_f32 / k1;
let rd = ((x * x + y * y) as f64).sqrt();
if rd == 0.0 {
return (x, y);
}
let rd_div_k1_: f32 = (rd * inv_k1_ as f64) as f32;
let mut ru = rd;
let mut step = 0;
loop {
let fru = ru * ru * ru + ru * inv_k1_ as f64 - rd_div_k1_ as f64;
if (-NEWTON_EPS..NEWTON_EPS).contains(&fru) {
break;
}
if step > 5 {
return (f32::NAN, f32::NAN);
}
ru -= fru / (3.0 * ru * ru + inv_k1_ as f64);
step += 1;
}
if ru < 0.0 {
return (f32::NAN, f32::NAN);
}
let scale = (ru / rd) as f32;
(x * scale, y * scale)
}
pub fn dist_poly5(x: f32, y: f32, k1: f32, k2: f32) -> (f32, f32) {
let ru2 = x * x + y * y;
let poly4 = 1.0 + k1 * ru2 + k2 * ru2 * ru2;
(x * poly4, y * poly4)
}
pub fn undist_poly5(x: f32, y: f32, k1: f32, k2: f32) -> (f32, f32) {
let rd = ((x * x + y * y) as f64).sqrt();
if rd == 0.0 {
return (x, y);
}
let mut ru = rd;
let mut step = 0;
let converged = loop {
let ru2 = ru * ru;
let fru = ru * (1.0 + k1 as f64 * ru2 + k2 as f64 * ru2 * ru2) - rd;
if (-NEWTON_EPS..NEWTON_EPS).contains(&fru) {
break true;
}
if step > 5 {
break false;
}
ru -= fru / (1.0 + 3.0 * k1 as f64 * ru2 + 5.0 * k2 as f64 * ru2 * ru2);
step += 1;
};
if !converged || ru < 0.0 {
return (x, y);
}
let scale = (ru / rd) as f32;
(x * scale, y * scale)
}
pub fn dist_ptlens(x: f32, y: f32, a: f32, b: f32, c: f32) -> (f32, f32) {
let ru2 = x * x + y * y;
let r = ru2.sqrt();
let poly3 = a * ru2 * r + b * ru2 + c * r + 1.0;
(x * poly3, y * poly3)
}
pub fn undist_ptlens(x: f32, y: f32, a: f32, b: f32, c: f32) -> (f32, f32) {
let rd = ((x * x + y * y) as f64).sqrt();
if rd == 0.0 {
return (x, y);
}
let a_ = a as f64;
let b_ = b as f64;
let c_ = c as f64;
let mut ru = rd;
let mut step = 0;
let converged = loop {
let fru = ru * (a_ * ru * ru * ru + b_ * ru * ru + c_ * ru + 1.0) - rd;
if (-NEWTON_EPS..NEWTON_EPS).contains(&fru) {
break true;
}
if step > 5 {
break false;
}
ru -= fru / (4.0 * a_ * ru * ru * ru + 3.0 * b_ * ru * ru + 2.0 * c_ * ru + 1.0);
step += 1;
};
if !converged || ru < 0.0 {
return (x, y);
}
let scale = (ru / rd) as f32;
(x * scale, y * scale)
}