new algorithm for waypoints detection
parent
f276e9e4f2
commit
f35967d502
|
|
@ -1,4 +1,5 @@
|
|||
use itertools::Itertools;
|
||||
use osmio::ObjId;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, BufWriter, Write};
|
||||
|
|
@ -549,7 +550,7 @@ fn save_svg<'a, P: AsRef<Path>, I: IntoIterator<Item = &'a InterestPoint>>(
|
|||
waypoints.iter().try_for_each(|p| {
|
||||
writeln!(
|
||||
&mut writer,
|
||||
"<circle cx='{}' cy='{}' fill='black' r='0.8%'/>",
|
||||
"<circle cx='{}' cy='{}' fill='black' r='0.5%'/>",
|
||||
p.x, p.y,
|
||||
)
|
||||
})?;
|
||||
|
|
@ -558,27 +559,40 @@ fn save_svg<'a, P: AsRef<Path>, I: IntoIterator<Item = &'a InterestPoint>>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn detect_waypoints(points: &[Point], osm_waypoints: &HashSet<Point>) -> HashSet<Point> {
|
||||
fn detect_waypoints(
|
||||
points: &[Point],
|
||||
osm_waypoints: &HashMap<Point, Vec<ObjId>>,
|
||||
) -> HashSet<Point> {
|
||||
points
|
||||
.first()
|
||||
.into_iter()
|
||||
.chain(points.iter().tuple_windows().filter_map(|(p1, p2, p3)| {
|
||||
if !osm_waypoints.contains(&p2) {
|
||||
return None;
|
||||
}
|
||||
let x1 = p2.x - p1.x;
|
||||
let y1 = p2.y - p1.y;
|
||||
let a1 = y1.atan2(x1);
|
||||
let x2 = p3.x - p2.x;
|
||||
let y2 = p3.y - p2.y;
|
||||
let a2 = y2.atan2(x2);
|
||||
let a = (a2 - a1).abs();
|
||||
if a <= std::f64::consts::PI / 3.0 || a >= std::f64::consts::PI * 5.0 / 3.0 {
|
||||
None
|
||||
} else {
|
||||
Some(p2)
|
||||
}
|
||||
}))
|
||||
.chain(
|
||||
points
|
||||
.iter()
|
||||
.filter_map(|p: &Point| -> Option<(&Point, &Vec<ObjId>)> {
|
||||
osm_waypoints.get(p).map(|l| (p, l))
|
||||
})
|
||||
.tuple_windows()
|
||||
.filter_map(|((p1, l1), (p2, _), (p3, l2))| {
|
||||
if l1.iter().all(|e| !l2.contains(e)) {
|
||||
let x1 = p2.x - p1.x;
|
||||
let y1 = p2.y - p1.y;
|
||||
let a1 = y1.atan2(x1);
|
||||
let x2 = p3.x - p2.x;
|
||||
let y2 = p3.y - p2.y;
|
||||
let a2 = y2.atan2(x2);
|
||||
let a = (a2 - a1).abs();
|
||||
if a <= std::f64::consts::PI / 4.0 || a >= std::f64::consts::PI * 7.0 / 4.0
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some(p2)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}),
|
||||
)
|
||||
.chain(points.last().into_iter())
|
||||
.copied()
|
||||
.collect::<HashSet<_>>()
|
||||
|
|
@ -640,19 +654,20 @@ fn position_interests_along_path(
|
|||
async fn main() {
|
||||
let input_file = std::env::args().nth(1).unwrap_or("m.gpx".to_string());
|
||||
let osm_file = std::env::args().nth(2);
|
||||
eprintln!("input is {}", input_file);
|
||||
let p = points(&input_file);
|
||||
|
||||
eprintln!("initialy we have {} points", p.len());
|
||||
let rp = simplify_path(&p, 0.00015);
|
||||
eprintln!("we now have {} points", rp.len());
|
||||
|
||||
let (mut interests, osm_waypoints) = if let Some(osm) = osm_file {
|
||||
parse_osm_data(osm)
|
||||
} else {
|
||||
(Vec::new(), HashSet::new())
|
||||
(Vec::new(), HashMap::new())
|
||||
};
|
||||
|
||||
eprintln!("input is {}", input_file);
|
||||
let p = points(&input_file);
|
||||
eprintln!("initialy we have {} points", p.len());
|
||||
|
||||
let rp = simplify_path(&p, 0.00015);
|
||||
eprintln!("we now have {} points", rp.len());
|
||||
|
||||
let waypoints = detect_waypoints(&rp, &osm_waypoints);
|
||||
eprintln!("we found {} waypoints", waypoints.len());
|
||||
|
||||
|
|
|
|||
|
|
@ -150,9 +150,9 @@ async fn get_openstreetmap_data(points: &[(f64, f64)]) -> HashSet<InterestPoint>
|
|||
interest_points
|
||||
}
|
||||
|
||||
pub fn parse_osm_data<P: AsRef<Path>>(path: P) -> (Vec<InterestPoint>, HashSet<Point>) {
|
||||
pub fn parse_osm_data<P: AsRef<Path>>(path: P) -> (Vec<InterestPoint>, HashMap<Point, Vec<ObjId>>) {
|
||||
let reader = osmio::read_pbf(path).ok();
|
||||
let mut crossroads: HashMap<ObjId, usize> = HashMap::new();
|
||||
let mut crossroads: HashMap<ObjId, Vec<ObjId>> = HashMap::new();
|
||||
let mut coordinates: HashMap<ObjId, Point> = HashMap::new();
|
||||
let interests = reader
|
||||
.map(|mut reader| {
|
||||
|
|
@ -175,7 +175,7 @@ pub fn parse_osm_data<P: AsRef<Path>>(path: P) -> (Vec<InterestPoint>, HashSet<P
|
|||
osmio::obj_types::ArcOSMObj::Way(w) => {
|
||||
if !w.is_area() {
|
||||
for node in w.nodes() {
|
||||
*crossroads.entry(*node).or_default() += 1;
|
||||
crossroads.entry(*node).or_default().push(w.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -188,9 +188,9 @@ pub fn parse_osm_data<P: AsRef<Path>>(path: P) -> (Vec<InterestPoint>, HashSet<P
|
|||
(
|
||||
interests,
|
||||
crossroads
|
||||
.iter()
|
||||
.filter(|&(_, c)| *c >= 3)
|
||||
.filter_map(|(id, _)| coordinates.get(&id).copied())
|
||||
.into_iter()
|
||||
.filter(|(_, r)| r.len() >= 2)
|
||||
.filter_map(|(id, l)| coordinates.get(&id).copied().map(|c| (c, l)))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue