use crate::data::{AnyDataArray, DataArray, PolyData};
pub fn circumradius(input: &PolyData) -> PolyData {
let mut radii = Vec::new();
let mut ratios = Vec::new();
for cell in input.polys.iter() {
if cell.len()<3 { radii.push(0.0); ratios.push(0.0); continue; }
let v0=input.points.get(cell[0] as usize);
let v1=input.points.get(cell[1] as usize);
let v2=input.points.get(cell[2] as usize);
let a=dist(v0,v1); let b=dist(v1,v2); let c=dist(v2,v0);
let s=(a+b+c)*0.5;
let area=(s*(s-a)*(s-b)*(s-c)).max(0.0).sqrt();
let cr = if area>1e-15{a*b*c/(4.0*area)}else{0.0};
let ir = if s>1e-15{area/s}else{0.0};
let ratio = if ir>1e-15{cr/ir}else{0.0};
radii.push(cr);
ratios.push(ratio);
}
let mut pd=input.clone();
pd.cell_data_mut().add_array(AnyDataArray::F64(DataArray::from_vec("Circumradius", radii, 1)));
pd.cell_data_mut().add_array(AnyDataArray::F64(DataArray::from_vec("CircumInRatio", ratios, 1)));
pd
}
fn dist(a:[f64;3],b:[f64;3])->f64{((a[0]-b[0]).powi(2)+(a[1]-b[1]).powi(2)+(a[2]-b[2]).powi(2)).sqrt()}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn equilateral_circumradius() {
let h=(3.0f64).sqrt()/2.0;
let mut pd = PolyData::new();
pd.points.push([0.0,0.0,0.0]); pd.points.push([1.0,0.0,0.0]); pd.points.push([0.5,h,0.0]);
pd.polys.push_cell(&[0,1,2]);
let result=circumradius(&pd);
let arr=result.cell_data().get_array("Circumradius").unwrap();
let mut buf=[0.0f64];
arr.tuple_as_f64(0,&mut buf);
assert!((buf[0]-1.0/3.0f64.sqrt()).abs()<0.01);
}
#[test]
fn ratio_equilateral() {
let h=(3.0f64).sqrt()/2.0;
let mut pd = PolyData::new();
pd.points.push([0.0,0.0,0.0]); pd.points.push([1.0,0.0,0.0]); pd.points.push([0.5,h,0.0]);
pd.polys.push_cell(&[0,1,2]);
let result=circumradius(&pd);
let arr=result.cell_data().get_array("CircumInRatio").unwrap();
let mut buf=[0.0f64];
arr.tuple_as_f64(0,&mut buf);
assert!((buf[0]-2.0).abs()<0.01); }
#[test]
fn empty_input() {
let pd = PolyData::new();
let result=circumradius(&pd);
assert_eq!(result.polys.num_cells(), 0);
}
}