diff --git a/apps/gipy/ChangeLog b/apps/gipy/ChangeLog index 0410d07e7..1a9e16c05 100644 --- a/apps/gipy/ChangeLog +++ b/apps/gipy/ChangeLog @@ -10,3 +10,8 @@ * Special display for points with steep turns * Buzz on points with steep turns and unlock * Losing gps is now displayed + +0.07: + * We now use orientation to detect current segment + when segments overlap going in both directions. + * File format is now versioned. diff --git a/apps/gipy/TODO b/apps/gipy/TODO index 96642608f..e229268b2 100644 --- a/apps/gipy/TODO +++ b/apps/gipy/TODO @@ -1,12 +1,11 @@ -- nearest_segment : use direction to disambiguate - gps direction is weak when speed is low -- add a version number to gpc files + - water points ---> we group them following path by groups of cst_size and record segments ids marking limits -- store several tracks - turn off gps when moving to next waypoint +- store several tracks - display average speed - dynamic map rescale - display scale (100m) diff --git a/apps/gipy/app.js b/apps/gipy/app.js index 85d8cb11c..233680df7 100644 --- a/apps/gipy/app.js +++ b/apps/gipy/app.js @@ -1,5 +1,7 @@ -let simulated = false; +let simulated = true; +let code_version = 7; +let code_key = 47490; class Status { constructor(path) { @@ -36,11 +38,11 @@ class Status { this.position = new_position; // detect segment we are on now - let next_segment = this.path.nearest_segment(this.position, Math.max(0, this.current_segment-1), Math.min(this.current_segment+2, path.len - 1)); + let next_segment = this.path.nearest_segment(this.position, Math.max(0, this.current_segment-1), Math.min(this.current_segment+2, path.len - 1), this.cos_direction, this.sin_direction); if (this.is_lost(next_segment)) { // it did not work, try anywhere - next_segment = this.path.nearest_segment(this.position, 0, path.len - 1); + next_segment = this.path.nearest_segment(this.position, 0, path.len - 1, this.cos_direction, this.sin_direction); } // now check if we strayed away from path or back to it let lost = this.is_lost(next_segment); @@ -147,7 +149,15 @@ class Status { class Path { constructor(filename) { let buffer = require("Storage").readArrayBuffer(filename); - this.points = Float64Array(buffer); + let header = Uint16Array(buffer, 0, 3); + let key = header[0]; + let version = header[1]; + let points_number = header[2]; + if ((key != code_key)||(version>code_version)) { + E.showMessage("Invalid gpc file"); + return; + } + this.points = Float64Array(buffer, 3*2, points_number*2); } // if start, end or steep direction change @@ -189,18 +199,32 @@ class Path { return new Point(lon, lat); } - // return index of segment which is nearest from point - nearest_segment(point, start, end) { - let min_index = 0; - let min_distance = Number.MAX_VALUE; + // return index of segment which is nearest from point. + // we need a direction because we need there is an ambiguity + // for overlapping segments which are taken once to go and once to come back. + // (in the other direction). + nearest_segment(point, start, end, cos_direction, sin_direction) { + // we are going to compute two min distances, one for each direction. + let indices = [0, 0]; + let mins = [Number.MAX_VALUE, Number.MAX_VALUE]; this.on_segments(function(p1, p2, i) { + // we use the dot product to figure out if oriented correctly let distance = point.fake_distance_to_segment(p1, p2); - if (distance <= min_distance) { - min_distance = distance; - min_index = i - 1; + let diff = p2.minus(p1); + let dot = cos_direction * diff.lon + sin_direction * diff.lat; + let orientation = + (dot < 0); // index 0 is good orientation + if (distance <= mins[orientation]) { + mins[orientation] = distance; + indices[orientation] = i - 1; } }, start, end); - return min_index; + // by default correct orientation (0) wins + // but if other one is really closer, return other one + if (mins[1] < mins[0] / 10.0) { + return indices[1]; + } else { + return indices[0]; + } } get len() { return this.points.length / 2; diff --git a/apps/gipy/gpconv/src/main.rs b/apps/gipy/gpconv/src/main.rs index 3b6f7e9f2..c003bfb72 100644 --- a/apps/gipy/gpconv/src/main.rs +++ b/apps/gipy/gpconv/src/main.rs @@ -10,6 +10,9 @@ use gpx::Gpx; mod osm; use osm::InterestPoint; +const KEY: u16 = 47490; +const VERSION: u16 = 7; + #[derive(Debug, PartialEq, Clone, Copy)] pub struct Point { x: f64, @@ -328,8 +331,9 @@ fn save_coordinates>(path: P, points: &[Point]) -> std::io::Resul let mut writer = BufWriter::new(File::create(path)?); eprintln!("saving {} points", points.len()); - // writer.write_all(&xmin.to_be_bytes())?; - // writer.write_all(&ymin.to_be_bytes())?; + writer.write_all(&KEY.to_le_bytes())?; + writer.write_all(&VERSION.to_le_bytes())?; + writer.write_all(&(points.len() as u16).to_le_bytes())?; points .iter() .flat_map(|p| [p.x, p.y]) @@ -502,7 +506,6 @@ fn detect_waypoints(points: &[Point]) -> HashSet { if a <= std::f64::consts::PI / 3.0 || a >= std::f64::consts::PI * 5.0 / 3.0 { None } else { - eprintln!("we have {}", (a2 - a1).abs()); Some(p2) } }))