use super::Arc;
use geo::Simplify;
use geo_types::LineString;
#[must_use]
pub fn simplify_arcs(arcs: &[Arc], tolerance: f64) -> Vec<Arc> {
if tolerance <= 0.0 {
return arcs.to_vec();
}
arcs.iter().map(|arc| simplify_arc(arc, tolerance)).collect()
}
fn simplify_arc(arc: &Arc, tolerance: f64) -> Arc {
if arc.coords.len() < 3 {
return arc.clone();
}
let ls = LineString::from(arc.coords.clone());
let simplified = ls.simplify(tolerance);
Arc { coords: simplified.0 }
}
#[cfg(test)]
mod tests {
use super::*;
use geo_types::Coord;
fn arc(coords: Vec<[f64; 2]>) -> Arc {
Arc {
coords: coords.into_iter().map(|[x, y]| Coord { x, y }).collect(),
}
}
#[test]
fn preserves_endpoints() {
let a = arc(vec![[0.0, 0.0], [1.0, 0.001], [2.0, -0.001], [3.0, 0.0005], [4.0, 0.0]]);
let s = simplify_arc(&a, 0.5);
assert_eq!(s.coords.first(), a.coords.first());
assert_eq!(s.coords.last(), a.coords.last());
assert!(s.coords.len() < a.coords.len());
}
#[test]
fn cascading_matches_single_shot() {
let arcs = vec![arc(vec![
[0.0, 0.0],
[0.25, 0.7],
[0.5, -0.4],
[0.75, 0.9],
[1.0, -0.2],
[1.25, 0.6],
[1.5, -0.8],
[1.75, 0.3],
[2.0, 0.0],
])];
let single = simplify_arcs(&arcs, 0.6);
let cascaded = simplify_arcs(&simplify_arcs(&arcs, 0.2), 0.6);
assert_eq!(single, cascaded);
}
#[test]
fn tolerance_zero_is_noop() {
let a = arc(vec![[0.0, 0.0], [1.0, 0.5], [2.0, 0.0]]);
let s = simplify_arc(&a, 0.0);
assert_eq!(s.coords, a.coords);
}
#[test]
fn shared_arc_is_simplified_once() {
let mut graph = super::super::ArcGraph::default();
let _ = graph.insert(vec![
Coord { x: 0.0, y: 0.0 },
Coord { x: 1.0, y: 0.001 },
Coord { x: 2.0, y: -0.002 },
Coord { x: 3.0, y: 0.0 },
]);
let simplified = simplify_arcs(graph.arcs(), 0.5);
assert_eq!(simplified.len(), 1);
assert_eq!(simplified[0].coords.first(), Some(&Coord { x: 0.0, y: 0.0 }));
assert_eq!(simplified[0].coords.last(), Some(&Coord { x: 3.0, y: 0.0 }));
}
}