use crate::data::PolyData;
#[derive(Debug, Clone)]
pub struct LodLevel {
pub data: PolyData,
pub max_distance: f64,
}
#[derive(Debug, Clone)]
pub struct LodSet {
levels: Vec<LodLevel>,
}
impl LodSet {
pub fn new(mut levels: Vec<LodLevel>) -> Self {
levels.sort_by(|a, b| a.max_distance.partial_cmp(&b.max_distance).unwrap());
Self { levels }
}
pub fn two_level(high: PolyData, low: PolyData, switch_distance: f64) -> Self {
Self::new(vec![
LodLevel { data: high, max_distance: switch_distance },
LodLevel { data: low, max_distance: f64::INFINITY },
])
}
pub fn select(&self, distance: f64) -> &PolyData {
for level in &self.levels {
if distance <= level.max_distance {
return &level.data;
}
}
&self.levels.last().unwrap().data
}
pub fn num_levels(&self) -> usize {
self.levels.len()
}
pub fn levels(&self) -> &[LodLevel] {
&self.levels
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_pd(n: usize) -> PolyData {
let mut pts = vec![];
for i in 0..n {
pts.push([i as f64, 0.0, 0.0]);
}
let mut pd = PolyData::new();
for p in pts {
pd.points.push(p);
}
pd
}
#[test]
fn two_level_lod() {
let high = make_pd(100);
let low = make_pd(10);
let lod = LodSet::two_level(high, low, 5.0);
assert_eq!(lod.num_levels(), 2);
assert_eq!(lod.select(3.0).points.len(), 100); assert_eq!(lod.select(10.0).points.len(), 10); }
#[test]
fn multi_level_lod() {
let lod = LodSet::new(vec![
LodLevel { data: make_pd(1000), max_distance: 2.0 },
LodLevel { data: make_pd(100), max_distance: 10.0 },
LodLevel { data: make_pd(10), max_distance: f64::INFINITY },
]);
assert_eq!(lod.select(1.0).points.len(), 1000);
assert_eq!(lod.select(5.0).points.len(), 100);
assert_eq!(lod.select(50.0).points.len(), 10);
}
#[test]
fn boundary_distance() {
let lod = LodSet::two_level(make_pd(100), make_pd(10), 5.0);
assert_eq!(lod.select(5.0).points.len(), 100); assert_eq!(lod.select(5.01).points.len(), 10);
}
}