11use chrono:: prelude:: * ;
2- use geo:: prelude:: * ;
32use rayon:: prelude:: * ;
43use structopt:: StructOpt ;
54
@@ -26,7 +25,14 @@ struct GpxResult {
2625 time : Option < String > ,
2726}
2827
29- fn analyze ( path : & std:: path:: PathBuf , lon : f64 , lat : f64 , distance : f64 ) -> Vec < GpxResult > {
28+ fn analyze (
29+ path : & std:: path:: PathBuf ,
30+ lon : f64 ,
31+ lat : f64 ,
32+ deg_lon_to_dist : f64 ,
33+ deg_lat_to_dist : f64 ,
34+ distance : f64 ,
35+ ) -> Vec < GpxResult > {
3036 let mut reader = quick_xml:: Reader :: from_file ( & path) . unwrap ( ) ;
3137 reader. trim_text ( true ) ;
3238 let mut buf = Vec :: new ( ) ;
@@ -43,7 +49,7 @@ fn analyze(path: &std::path::PathBuf, lon: f64, lat: f64, distance: f64) -> Vec<
4349 match reader. read_event ( & mut buf) {
4450 Ok ( quick_xml:: events:: Event :: Start ( ref e) ) => {
4551 if e. name ( ) . eq ( b"trkpt" ) {
46- let pt = geo_types :: Point :: new (
52+ let ( found_lon , found_lat ) = (
4753 match e. attributes ( ) . find ( |e| match e {
4854 Ok ( attr) => attr. key == b"lon" ,
4955 Err ( _) => false ,
@@ -126,12 +132,30 @@ fn analyze(path: &std::path::PathBuf, lon: f64, lat: f64, distance: f64) -> Vec<
126132 } ,
127133 ) ;
128134
129- let dist = match last_point {
130- Some ( last_point) => {
131- let line = geo_types:: Line :: new ( last_point, pt) ;
132- geo_types:: Point :: new ( lon, lat) . euclidean_distance ( & line)
135+ let d_lon = found_lon - lon;
136+ let d_lat = found_lat - lat;
137+ let x = ( d_lon) * deg_lon_to_dist;
138+ let y = ( d_lat) * deg_lat_to_dist;
139+
140+ let dist = if let Some ( ( last_x, last_y) ) = last_point {
141+ let d_x = x - last_x;
142+ let d_y: f64 = y - last_y;
143+
144+ let a = d_y. atan2 ( d_x) * -1.0 ;
145+
146+ let dist = ( -x * a. sin ( ) + y * a. cos ( ) ) . abs ( ) ;
147+
148+ let last_t_x = last_x * a. cos ( ) + last_y * a. sin ( ) ;
149+
150+ let t_x = x * a. cos ( ) + y * a. sin ( ) ;
151+
152+ if ( last_t_x >= 0.0 && t_x <= 0.0 ) || ( last_t_x <= 0.0 && t_x >= 0.0 ) {
153+ dist
154+ } else {
155+ ( x * x + y * y) . sqrt ( )
133156 }
134- None => geo_types:: Point :: new ( lon, lat) . haversine_distance ( & pt) ,
157+ } else {
158+ ( x * x + y * y) . sqrt ( )
135159 } ;
136160
137161 if ( nearest. is_none ( ) || nearest. as_ref ( ) . unwrap ( ) . distance > dist)
@@ -161,7 +185,7 @@ fn analyze(path: &std::path::PathBuf, lon: f64, lat: f64, distance: f64) -> Vec<
161185 } ) ;
162186 searching_time_for = new_results. len ( ) - 1 ;
163187 }
164- last_point = Some ( pt ) ;
188+ last_point = Some ( ( x , y ) ) ;
165189 } else if e. name ( ) . eq ( b"time" ) {
166190 in_time = true ;
167191 }
@@ -334,6 +358,14 @@ fn main() {
334358 panic ! ( "You must specify either --longitude and --latitude or --coordinates" ) ;
335359 } ;
336360
361+ let deg_lon_to_dist: f64 = 6_356_752.314_245 * 2.0 * std:: f64:: consts:: PI / 360.0
362+ * ( latitude * std:: f64:: consts:: PI / 180.0 ) . cos ( ) ;
363+
364+ let deg_lat_to_dist: f64 = 6_378_137.0 * 2.0 * std:: f64:: consts:: PI / 360.0
365+ * ( longitude * std:: f64:: consts:: PI / 180.0 ) . cos ( ) ;
366+
367+ println ! ( "{}, {}" , deg_lat_to_dist, deg_lon_to_dist) ;
368+
337369 println ! ( "{}, {}" , latitude, longitude) ;
338370 println ! (
339371 "{} {}° {:.6} {} {}° {:.6}" ,
@@ -371,7 +403,16 @@ fn main() {
371403 let distance = opt. distance ;
372404 let analysis_results = analyze_db
373405 . par_iter ( )
374- . map ( |gpx_file| analyze ( gpx_file, longitude, latitude, distance) )
406+ . map ( |gpx_file| {
407+ analyze (
408+ gpx_file,
409+ longitude,
410+ latitude,
411+ deg_lon_to_dist,
412+ deg_lat_to_dist,
413+ distance,
414+ )
415+ } )
375416 . collect :: < Vec < _ > > ( ) ;
376417 let mut results = Vec :: with_capacity (
377418 analysis_results
@@ -421,8 +462,6 @@ fn main() {
421462 std:: mem:: drop ( filtered_results) ;
422463 print_result ( results. first ( ) . unwrap ( ) ) ;
423464 } else {
424- println ! (
425- "Did not find any points."
426- ) ;
465+ println ! ( "Did not find any points." ) ;
427466 }
428467}
0 commit comments