use crate::GpsPoint;
use crate::geo_utils::{bounds_overlap, compute_bounds};
use rstar::{AABB, PointDistance, RTree, RTreeObject};
#[derive(Debug, Clone, Copy)]
pub struct IndexedPoint {
pub idx: usize,
pub lat: f64,
pub lng: f64,
}
impl RTreeObject for IndexedPoint {
type Envelope = AABB<[f64; 2]>;
fn envelope(&self) -> Self::Envelope {
AABB::from_point([self.lat, self.lng])
}
}
impl PointDistance for IndexedPoint {
fn distance_2(&self, point: &[f64; 2]) -> f64 {
let dlat = self.lat - point[0];
let dlng = self.lng - point[1];
dlat * dlat + dlng * dlng
}
}
pub fn build_rtree(points: &[GpsPoint]) -> RTree<IndexedPoint> {
let indexed: Vec<IndexedPoint> = points
.iter()
.enumerate()
.map(|(i, p)| IndexedPoint {
idx: i,
lat: p.latitude,
lng: p.longitude,
})
.collect();
RTree::bulk_load(indexed)
}
pub fn bounds_overlap_tracks(track_a: &[GpsPoint], track_b: &[GpsPoint], buffer: f64) -> bool {
if track_a.is_empty() || track_b.is_empty() {
return false;
}
let bounds_a = compute_bounds(track_a);
let bounds_b = compute_bounds(track_b);
let ref_lat = (bounds_a.min_lat + bounds_a.max_lat) / 2.0;
bounds_overlap(&bounds_a, &bounds_b, buffer, ref_lat)
}