mirror of
https://github.com/a-b-street/abstreet.git
synced 2025-01-01 19:04:50 +03:00
54 lines
1.5 KiB
Rust
54 lines
1.5 KiB
Rust
|
use aabb_quadtree::QuadTree;
|
||
|
use geo;
|
||
|
use geo::prelude::EuclideanDistance;
|
||
|
use geom::{Bounds, PolyLine};
|
||
|
use ordered_float::NotNaN;
|
||
|
use std::collections::HashMap;
|
||
|
|
||
|
// TODO Refactor and generalize all of this...
|
||
|
|
||
|
pub struct FindClosest<K> {
|
||
|
// TODO maybe any type of geo:: thing
|
||
|
geometries: HashMap<K, geo::LineString<f64>>,
|
||
|
quadtree: QuadTree<K>,
|
||
|
}
|
||
|
|
||
|
impl<K> FindClosest<K>
|
||
|
where
|
||
|
K: Clone + std::cmp::Eq + std::hash::Hash + std::fmt::Debug,
|
||
|
{
|
||
|
pub fn new(bounds: &Bounds) -> FindClosest<K> {
|
||
|
FindClosest {
|
||
|
geometries: HashMap::new(),
|
||
|
quadtree: QuadTree::default(bounds.as_bbox()),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn add(&mut self, key: K, pts: &PolyLine) {
|
||
|
self.geometries.insert(key.clone(), pts_to_line_string(pts));
|
||
|
self.quadtree
|
||
|
.insert_with_box(key, pts.get_bounds().as_bbox());
|
||
|
}
|
||
|
|
||
|
pub fn match_pts(&self, pts: &PolyLine) -> Option<K> {
|
||
|
let query_geom = pts_to_line_string(pts);
|
||
|
let query_bbox = pts.get_bounds().as_bbox();
|
||
|
|
||
|
self.quadtree
|
||
|
.query(query_bbox)
|
||
|
.into_iter()
|
||
|
.min_by_key(|(key, _, _)| {
|
||
|
NotNaN::new(query_geom.euclidean_distance(&self.geometries[key])).unwrap()
|
||
|
}).map(|(key, _, _)| key.clone())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn pts_to_line_string(pts: &PolyLine) -> geo::LineString<f64> {
|
||
|
let pts: Vec<geo::Point<f64>> = pts
|
||
|
.points()
|
||
|
.iter()
|
||
|
.map(|pt| geo::Point::new(pt.x(), pt.y()))
|
||
|
.collect();
|
||
|
pts.into()
|
||
|
}
|