trying some fixes for the various pb
parent
d3fcc943e6
commit
f276e9e4f2
|
|
@ -30,3 +30,5 @@
|
|||
* Waypoints information is embedded in file and extracted from comments on
|
||||
points.
|
||||
* Bugfix in map display (last segment was missing + wrong colors).
|
||||
* Waypoint detections using OSM + sharp angles
|
||||
* New algorith for direction detection
|
||||
|
|
|
|||
|
|
@ -1,19 +1,22 @@
|
|||
|
||||
* bugs
|
||||
|
||||
- waypoints seem wrong
|
||||
- direction is still shitty on gps
|
||||
- we are always lost
|
||||
- meters seem to be a bit too long
|
||||
|
||||
- direction is still shitty on gps ?
|
||||
- we are always lost (done ?)
|
||||
- waypoints seem wrong ?
|
||||
|
||||
* additional features
|
||||
|
||||
- display direction to nearest point
|
||||
- turn off gps when moving to next waypoint
|
||||
- display distance to next water/toilet
|
||||
- display distance to next waypoint
|
||||
- display average speed
|
||||
- dynamic map rescale
|
||||
- display scale (100m)
|
||||
- get waypoints from osm
|
||||
|
||||
- compress path ?
|
||||
|
||||
|
|
|
|||
|
|
@ -541,16 +541,11 @@ function start(fn) {
|
|||
}
|
||||
}
|
||||
if (old_points.length == 4) {
|
||||
// let's just take average angle of 3 previous segments
|
||||
let angles_sum = 0;
|
||||
for (let i = 0; i < 3; i++) {
|
||||
let p1 = old_points[i];
|
||||
let p2 = old_points[i + 1];
|
||||
let diff = p2.minus(p1);
|
||||
let angle = Math.atan2(diff.lat, diff.lon);
|
||||
angles_sum += angle;
|
||||
}
|
||||
status.update_position(position, angles_sum / 3.0);
|
||||
// let's just take angle of segment between oldest and newest point
|
||||
let oldest = old_points[0];
|
||||
let diff = position.minus(oldest);
|
||||
let angle = Math.atan2(diff.lat, diff.lon);
|
||||
status.update_position(position, angle);
|
||||
} else {
|
||||
status.update_position(position, direction);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,17 +13,26 @@ use osm::{parse_osm_data, InterestPoint};
|
|||
const KEY: u16 = 47490;
|
||||
const FILE_VERSION: u16 = 3;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Point {
|
||||
x: f64,
|
||||
y: f64,
|
||||
}
|
||||
|
||||
impl PartialEq for Point {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
(self.x - other.x).abs() < 0.0005 && (self.y - other.y).abs() < 0.0005
|
||||
}
|
||||
}
|
||||
impl Eq for Point {}
|
||||
impl std::hash::Hash for Point {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
unsafe { std::mem::transmute::<f64, u64>(self.x) }.hash(state);
|
||||
unsafe { std::mem::transmute::<f64, u64>(self.y) }.hash(state);
|
||||
let x = format!("{:.4}", self.x);
|
||||
let y = format!("{:.4}", self.y);
|
||||
x.hash(state);
|
||||
y.hash(state);
|
||||
// unsafe { std::mem::transmute::<f64, u64>(self.x) }.hash(state);
|
||||
// unsafe { std::mem::transmute::<f64, u64>(self.y) }.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +67,7 @@ impl Point {
|
|||
}
|
||||
}
|
||||
|
||||
fn points(filename: &str) -> Vec<Vec<Point>> {
|
||||
fn points(filename: &str) -> Vec<Point> {
|
||||
let file = File::open(filename).unwrap();
|
||||
let reader = BufReader::new(file);
|
||||
|
||||
|
|
@ -66,38 +75,15 @@ fn points(filename: &str) -> Vec<Vec<Point>> {
|
|||
let mut gpx: Gpx = read(reader).unwrap();
|
||||
eprintln!("we have {} tracks", gpx.tracks.len());
|
||||
|
||||
let mut points = Vec::new();
|
||||
|
||||
let mut iter = gpx
|
||||
.tracks
|
||||
gpx.tracks
|
||||
.pop()
|
||||
.unwrap()
|
||||
.segments
|
||||
.into_iter()
|
||||
.flat_map(|segment| segment.points.into_iter())
|
||||
.map(|p| {
|
||||
let geop = p.point();
|
||||
(
|
||||
Point {
|
||||
x: geop.x(),
|
||||
y: geop.y(),
|
||||
},
|
||||
p.comment.is_some(),
|
||||
)
|
||||
})
|
||||
.dedup();
|
||||
let mut current_segment = iter.next().map(|(p, _)| p).into_iter().collect::<Vec<_>>();
|
||||
for (p, is_waypoint) in iter {
|
||||
if is_waypoint {
|
||||
points.push(current_segment);
|
||||
current_segment = Vec::new();
|
||||
}
|
||||
current_segment.push(p);
|
||||
}
|
||||
let last_point = current_segment.pop();
|
||||
points.push(current_segment);
|
||||
points.extend(last_point.map(|p| vec![p]));
|
||||
points
|
||||
.flat_map(|segment| segment.linestring())
|
||||
.map(|c| c.x_y())
|
||||
.map(|(x, y)| Point { x, y })
|
||||
.collect()
|
||||
}
|
||||
|
||||
// // NOTE: this angles idea could maybe be use to get dp from n^3 to n^2
|
||||
|
|
@ -553,7 +539,7 @@ fn save_svg<'a, P: AsRef<Path>, I: IntoIterator<Item = &'a InterestPoint>>(
|
|||
for point in interest_points {
|
||||
writeln!(
|
||||
&mut writer,
|
||||
"<circle cx='{}' cy='{}' fill='{}' r='1%'/>",
|
||||
"<circle cx='{}' cy='{}' fill='{}' r='0.8%'/>",
|
||||
point.point.x,
|
||||
point.point.y,
|
||||
point.color(),
|
||||
|
|
@ -563,7 +549,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='1%'/>",
|
||||
"<circle cx='{}' cy='{}' fill='black' r='0.8%'/>",
|
||||
p.x, p.y,
|
||||
)
|
||||
})?;
|
||||
|
|
@ -572,11 +558,14 @@ fn save_svg<'a, P: AsRef<Path>, I: IntoIterator<Item = &'a InterestPoint>>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn detect_waypoints(points: &[Point]) -> HashSet<Point> {
|
||||
fn detect_waypoints(points: &[Point], osm_waypoints: &HashSet<Point>) -> 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);
|
||||
|
|
@ -652,35 +641,21 @@ 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 mut segmented_points = points(&input_file);
|
||||
let p = segmented_points
|
||||
.iter()
|
||||
.flatten()
|
||||
.copied()
|
||||
.collect::<Vec<_>>();
|
||||
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());
|
||||
|
||||
eprintln!("we have {} waypoints", segmented_points.len());
|
||||
|
||||
let mut waypoints = HashSet::new();
|
||||
let mut rp = Vec::new();
|
||||
for (i1, i2) in (0..segmented_points.len()).tuple_windows() {
|
||||
if let [s1, s2] = &mut segmented_points[i1..=i2] {
|
||||
s1.extend(s2.first().copied());
|
||||
waypoints.insert(s1.first().copied().unwrap());
|
||||
let mut simplified = simplify_path(&s1, 0.00015);
|
||||
rp.append(&mut simplified);
|
||||
rp.pop();
|
||||
}
|
||||
}
|
||||
rp.extend(segmented_points.last().and_then(|l| l.last()).copied());
|
||||
|
||||
let mut interests = if let Some(osm) = osm_file {
|
||||
let (mut interests, osm_waypoints) = if let Some(osm) = osm_file {
|
||||
parse_osm_data(osm)
|
||||
} else {
|
||||
Vec::new()
|
||||
(Vec::new(), HashSet::new())
|
||||
};
|
||||
|
||||
let waypoints = detect_waypoints(&rp, &osm_waypoints);
|
||||
eprintln!("we found {} waypoints", waypoints.len());
|
||||
|
||||
// let mut interests = parse_osm_data("isere.osm.pbf");
|
||||
let buckets = position_interests_along_path(&mut interests, &rp, 0.001, 5, 3);
|
||||
// let i = get_openstreetmap_data(&rp).await;
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ use openstreetmap_api::{
|
|||
types::{BoundingBox, Credentials},
|
||||
Openstreetmap,
|
||||
};
|
||||
use osmio::prelude::*;
|
||||
use osmio::OSMObjBase;
|
||||
use osmio::{prelude::*, ObjId};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::path::Path;
|
||||
|
||||
|
|
@ -150,9 +150,11 @@ async fn get_openstreetmap_data(points: &[(f64, f64)]) -> HashSet<InterestPoint>
|
|||
interest_points
|
||||
}
|
||||
|
||||
pub fn parse_osm_data<P: AsRef<Path>>(path: P) -> Vec<InterestPoint> {
|
||||
pub fn parse_osm_data<P: AsRef<Path>>(path: P) -> (Vec<InterestPoint>, HashSet<Point>) {
|
||||
let reader = osmio::read_pbf(path).ok();
|
||||
reader
|
||||
let mut crossroads: HashMap<ObjId, usize> = HashMap::new();
|
||||
let mut coordinates: HashMap<ObjId, Point> = HashMap::new();
|
||||
let interests = reader
|
||||
.map(|mut reader| {
|
||||
let mut interests = Vec::new();
|
||||
for obj in reader.objects() {
|
||||
|
|
@ -167,13 +169,28 @@ pub fn parse_osm_data<P: AsRef<Path>>(path: P) -> Vec<InterestPoint> {
|
|||
}) {
|
||||
interests.push(p);
|
||||
}
|
||||
coordinates.insert(n.id(), Point { x: lon, y: lat });
|
||||
});
|
||||
}
|
||||
osmio::obj_types::ArcOSMObj::Way(_) => {}
|
||||
osmio::obj_types::ArcOSMObj::Way(w) => {
|
||||
if !w.is_area() {
|
||||
for node in w.nodes() {
|
||||
*crossroads.entry(*node).or_default() += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
osmio::obj_types::ArcOSMObj::Relation(_) => {}
|
||||
}
|
||||
}
|
||||
interests
|
||||
})
|
||||
.unwrap_or_default()
|
||||
.unwrap_or_default();
|
||||
(
|
||||
interests,
|
||||
crossroads
|
||||
.iter()
|
||||
.filter(|&(_, c)| *c >= 3)
|
||||
.filter_map(|(id, _)| coordinates.get(&id).copied())
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue