|
@@ -1,4 +1,3 @@
|
|
|
-#![feature(extern_prelude)]
|
|
|
extern crate chrono;
|
|
|
extern crate quick_xml;
|
|
|
|
|
@@ -11,8 +10,8 @@ use quick_xml::Writer;
|
|
|
use std::fs::File;
|
|
|
use std::io::prelude::*;
|
|
|
use std::io::Cursor;
|
|
|
-use std::time::Duration as stdDuration;
|
|
|
use std::path::Path;
|
|
|
+use std::time::Duration as stdDuration;
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
@@ -34,7 +33,6 @@ impl Point {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
#[derive(Default, Debug)]
|
|
|
pub struct Track {
|
|
|
pub name: String,
|
|
@@ -56,48 +54,74 @@ impl Track {
|
|
|
sum
|
|
|
}
|
|
|
|
|
|
- fn to_xml(&self) {
|
|
|
+ pub fn to_xml(&self) {
|
|
|
let mut writer = Writer::new_with_indent(Cursor::new(Vec::new()), 32, 4); //32 is space character
|
|
|
|
|
|
let mut gpx_elem = BytesStart::owned(b"gpx".to_vec(), "gpx".len());
|
|
|
- gpx_elem.push_attribute(("creator", "Pothole"));
|
|
|
- assert!(writer.write_event(Event::Start(gpx_elem)).is_ok());
|
|
|
+ gpx_elem.push_attribute(("creator", "rust gps module"));
|
|
|
+ writer.write_event(Event::Start(gpx_elem)).unwrap();
|
|
|
|
|
|
let trk_elem = BytesStart::owned(b"trk".to_vec(), "trk".len());
|
|
|
+
|
|
|
+ let name_elem = BytesStart::owned(b"name".to_vec(), "name".len());
|
|
|
+ writer.write_event(Event::Start(name_elem)).unwrap();
|
|
|
+ writer.write(self.name.as_bytes()).unwrap();
|
|
|
+ writer.write_event(Event::End(BytesEnd::borrowed(b"name"))).unwrap();
|
|
|
+
|
|
|
assert!(writer.write_event(Event::Start(trk_elem)).is_ok());
|
|
|
|
|
|
let mut prev_point = &self.points[0];
|
|
|
|
|
|
let trkseg_elem = BytesStart::owned(b"trkseg".to_vec(), "trkseg".len());
|
|
|
- assert!(writer.write_event(Event::Start(trkseg_elem)).is_ok());
|
|
|
+
|
|
|
+ assert!(writer.write_event(Event::Start(trkseg_elem.clone())).is_ok());
|
|
|
|
|
|
+ let mut ptnum = 0;
|
|
|
for pt in &self.points {
|
|
|
//segment detection
|
|
|
let d = dist(prev_point, pt);
|
|
|
prev_point = pt;
|
|
|
-
|
|
|
+ // if there is a gap to the last point, consider this a new segment
|
|
|
if d > 0.5 {
|
|
|
assert!(
|
|
|
writer
|
|
|
.write_event(Event::End(BytesEnd::borrowed(b"trkseg")))
|
|
|
.is_ok()
|
|
|
);
|
|
|
- let trkseg_elem = BytesStart::owned(b"trkseg".to_vec(), "trkseg".len());
|
|
|
- assert!(writer.write_event(Event::Start(trkseg_elem)).is_ok());
|
|
|
- } else {
|
|
|
-
|
|
|
+ // let trkseg_elem = BytesStart::owned(b"trkseg".to_vec(), "trkseg".len());
|
|
|
+ assert!(writer.write_event(Event::Start(trkseg_elem.clone())).is_ok());
|
|
|
}
|
|
|
|
|
|
+
|
|
|
let mut pt_elem = BytesStart::owned(b"trkpt".to_vec(), "trkpt".len());
|
|
|
pt_elem.push_attribute(("lat", pt.lat.to_string().as_str()));
|
|
|
pt_elem.push_attribute(("lon", pt.long.to_string().as_str()));
|
|
|
- pt_elem.push_attribute(("ele", pt.ele.to_string().as_str()));
|
|
|
assert!(writer.write_event(Event::Start(pt_elem)).is_ok());
|
|
|
+
|
|
|
+ let ele_elem = BytesStart::owned(b"ele".to_vec(), "ele".len());
|
|
|
+ writer.write_event(Event::Start(ele_elem)).unwrap();
|
|
|
+ writer.write(pt.ele.to_string().as_bytes()).unwrap();
|
|
|
+ writer.write_event(Event::End(BytesEnd::borrowed(b"ele"))).unwrap();
|
|
|
+
|
|
|
+ let time_timem = BytesStart::owned(b"time".to_vec(), "time".len());
|
|
|
+ writer.write_event(Event::Start(time_timem)).unwrap();
|
|
|
+ writer.write(pt.time.format("%FT%H:%M:%S%.3fZ").to_string().as_bytes()).unwrap();
|
|
|
+ writer.write_event(Event::End(BytesEnd::borrowed(b"time"))).unwrap();
|
|
|
+
|
|
|
+
|
|
|
assert!(
|
|
|
writer
|
|
|
.write_event(Event::End(BytesEnd::borrowed(b"trkpt")))
|
|
|
.is_ok()
|
|
|
);
|
|
|
+ if ptnum >= self.points.len()-1 {
|
|
|
+ assert!(
|
|
|
+ writer
|
|
|
+ .write_event(Event::End(BytesEnd::borrowed(b"trkseg")))
|
|
|
+ .is_ok()
|
|
|
+ );
|
|
|
+ }
|
|
|
+ ptnum+=1;
|
|
|
}
|
|
|
|
|
|
assert!(
|
|
@@ -114,7 +138,6 @@ impl Track {
|
|
|
let result = writer.into_inner().into_inner();
|
|
|
// println!("{:?}", str::from_utf8( &result).unwrap());
|
|
|
|
|
|
-
|
|
|
let mut name: String = self.name.clone();
|
|
|
name.push_str(".gpx");
|
|
|
write_bytes(result, name);
|
|
@@ -143,7 +166,37 @@ impl Track {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- pub fn parse(&mut self) {
|
|
|
+
|
|
|
+ pub fn get_maxspeed(&mut self) -> f64 {
|
|
|
+ // how far to average the track together
|
|
|
+ let sample_distance = 0.1;
|
|
|
+ let mut maxspeed: f64 = 0.0;
|
|
|
+
|
|
|
+ let mut fifo_track = Track {
|
|
|
+ ..Default::default()
|
|
|
+ };
|
|
|
+
|
|
|
+ let mut analyzed_track = Track {
|
|
|
+ name: "analyzed".to_string(),
|
|
|
+ ..Default::default()
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ for pt in &self.points {
|
|
|
+ fifo_track.points.push(pt.clone());
|
|
|
+ analyzed_track.points.push(pt.clone());
|
|
|
+ fifo_track.truncate_by_length(sample_distance);
|
|
|
+ let speed = fifo_track.speed();
|
|
|
+ if speed > maxspeed {
|
|
|
+ maxspeed = speed
|
|
|
+ }
|
|
|
+ }
|
|
|
+ maxspeed
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ pub fn get_bad_points(&mut self) -> Track {
|
|
|
// how far to average the track together
|
|
|
let sample_distance = 0.1;
|
|
|
// This is where a track is considered bad = min_speed_factor * your average over sample_distance
|
|
@@ -161,12 +214,11 @@ impl Track {
|
|
|
};
|
|
|
|
|
|
let mut bad_track = Track {
|
|
|
- name: "bad".to_string(),
|
|
|
+ name: format!("{}_{}", self.name, "bad"),
|
|
|
..Default::default()
|
|
|
};
|
|
|
|
|
|
for pt in &self.points {
|
|
|
- // i = i + 1; if i > 30 {break};
|
|
|
fifo_track.points.push(pt.clone());
|
|
|
analyzed_track.points.push(pt.clone());
|
|
|
fifo_track.truncate_by_length(sample_distance);
|
|
@@ -176,24 +228,20 @@ impl Track {
|
|
|
// println!("Track seems bad @ Km {:.1} {:.2} Km/h", analyzed_track.len(), speed);
|
|
|
}
|
|
|
}
|
|
|
- bad_track.to_xml();
|
|
|
+ bad_track
|
|
|
}
|
|
|
|
|
|
pub fn from_xml(&mut self, filename: String) {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
// Records for the pull parser
|
|
|
let mut current_point = Point::new();
|
|
|
let mut current_data = "".to_string();
|
|
|
|
|
|
- println!("XML parse start.");
|
|
|
+ // println!("XML parse start.");
|
|
|
|
|
|
let mut reader = Reader::from_file(filename).unwrap();
|
|
|
reader.trim_text(true);
|
|
|
let mut buf = Vec::new();
|
|
|
|
|
|
- // The `Reader` does not implement `Iterator` because it outputs borrowed data (`Cow`s)
|
|
|
loop {
|
|
|
match reader.read_event(&mut buf) {
|
|
|
Ok(Event::Start(ref e)) => {
|
|
@@ -247,20 +295,18 @@ impl Track {
|
|
|
}
|
|
|
Ok(Event::Eof) => break, // exits the loop when reaching end of file
|
|
|
Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e),
|
|
|
- _ => (), // There are several other `Event`s we do not consider here
|
|
|
+ _ => (),
|
|
|
}
|
|
|
|
|
|
// if we don't keep a borrow elsewhere, we can clear the buffer to keep memory usage low
|
|
|
buf.clear();
|
|
|
}
|
|
|
-
|
|
|
- println!("XML parse end.");
|
|
|
+ // println!("XML parse end.");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
fn dist(p1: &Point, p2: &Point) -> f64 {
|
|
|
- let r = 6371.0;
|
|
|
+ let r = 6371.0; //earth rad in km
|
|
|
let d_lat = (p1.lat - p2.lat).to_radians();
|
|
|
let d_long = (p1.long - p2.long).to_radians();
|
|
|
let a = (d_lat / 2.0).sin() * (d_lat / 2.0).sin()
|
|
@@ -276,20 +322,18 @@ fn write_bytes(bytes_to_write: Vec<u8>, filename: String) {
|
|
|
let path = Path::new(filename.as_str());
|
|
|
let display = path.display();
|
|
|
|
|
|
- // Open a file in write-only mode, returns `io::Result<File>`
|
|
|
let mut file = match File::create(&path) {
|
|
|
Err(_why) => panic!("couldn't create {}", display),
|
|
|
Ok(file) => file,
|
|
|
};
|
|
|
|
|
|
- // Write the `LOREM_IPSUM` string to `file`, returns `io::Result<()>`
|
|
|
match file.write_all("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".as_bytes()) {
|
|
|
Err(_why) => panic!("couldn't write to {}", display),
|
|
|
- Ok(_) => (println!("Wrote header -> {}", display)),
|
|
|
+ Ok(_) => (),
|
|
|
}
|
|
|
|
|
|
match file.write_all(&bytes_to_write) {
|
|
|
Err(_why) => panic!("couldn't write to {}", display),
|
|
|
- Ok(_) => println!("Wrote data -> {}", display),
|
|
|
+ Ok(_) => println!("Wrote xml: {}", display),
|
|
|
}
|
|
|
-}
|
|
|
+}
|