Browse Source

Search PBF files and display matches as markers

Use the parameters -s and --pbf for this.
Johannes Hofmann 7 years ago
parent
commit
0f30790da8
3 changed files with 82 additions and 5 deletions
  1. 11
    0
      src/args.rs
  2. 23
    0
      src/config.rs
  3. 48
    5
      src/main.rs

+ 11
- 0
src/args.rs View File

19
             .value_name("FILE")
19
             .value_name("FILE")
20
             .help("Set a custom tile sources file")
20
             .help("Set a custom tile sources file")
21
             .takes_value(true))
21
             .takes_value(true))
22
+        .arg(Arg::with_name("pbf")
23
+            .long("pbf")
24
+            .value_name("FILE")
25
+            .help("Set a *.osm.pbf file")
26
+            .takes_value(true))
27
+        .arg(Arg::with_name("search")
28
+            .short("s")
29
+            .long("search")
30
+            .value_name("PATTERN")
31
+            .help("Search for places which match the given pattern")
32
+            .takes_value(true))
22
         .arg(Arg::with_name("fps")
33
         .arg(Arg::with_name("fps")
23
             .long("fps")
34
             .long("fps")
24
             .value_name("FPS")
35
             .value_name("FPS")

+ 23
- 0
src/config.rs View File

19
 pub struct Config {
19
 pub struct Config {
20
     tile_cache_dir: PathBuf,
20
     tile_cache_dir: PathBuf,
21
     sources: Vec<(String, TileSource)>,
21
     sources: Vec<(String, TileSource)>,
22
+    pbf_path: Option<PathBuf>,
23
+    search_pattern: Option<String>,
22
     fps: f64,
24
     fps: f64,
23
     use_network: bool,
25
     use_network: bool,
24
     async: bool,
26
     async: bool,
40
             config.add_tile_sources_from_default_or_create()?;
42
             config.add_tile_sources_from_default_or_create()?;
41
         };
43
         };
42
 
44
 
45
+        if let Some(os_path) = matches.value_of_os("pbf") {
46
+            let path = PathBuf::from(os_path);
47
+            if path.is_file() {
48
+                config.pbf_path = Some(path);
49
+            } else {
50
+                return Err(format!("PBF file does not exist: {:?}", os_path));
51
+            }
52
+        }
53
+
43
         config.merge_arg_matches(matches);
54
         config.merge_arg_matches(matches);
44
 
55
 
45
         Ok(config)
56
         Ok(config)
46
     }
57
     }
47
 
58
 
48
     fn merge_arg_matches<'a>(&mut self, matches: &clap::ArgMatches<'a>) {
59
     fn merge_arg_matches<'a>(&mut self, matches: &clap::ArgMatches<'a>) {
60
+        self.search_pattern = matches.value_of("search").map(|s| s.to_string());
61
+
49
         if let Some(Ok(fps)) = matches.value_of("fps").map(|s| s.parse()) {
62
         if let Some(Ok(fps)) = matches.value_of("fps").map(|s| s.parse()) {
50
             self.fps = fps;
63
             self.fps = fps;
51
         }
64
         }
188
                     Config {
201
                     Config {
189
                         tile_cache_dir,
202
                         tile_cache_dir,
190
                         sources: vec![],
203
                         sources: vec![],
204
+                        pbf_path: None,
205
+                        search_pattern: None,
191
                         fps,
206
                         fps,
192
                         use_network,
207
                         use_network,
193
                         async,
208
                         async,
304
         &self.sources
319
         &self.sources
305
     }
320
     }
306
 
321
 
322
+    pub fn pbf_path(&self) -> Option<&Path> {
323
+        self.pbf_path.as_ref().map(|p| p.as_path())
324
+    }
325
+
326
+    pub fn search_pattern(&self) -> Option<&str> {
327
+        self.search_pattern.as_ref().map(|s| s.as_str())
328
+    }
329
+
307
     pub fn fps(&self) -> f64 {
330
     pub fn fps(&self) -> f64 {
308
         self.fps
331
         self.fps
309
     }
332
     }

+ 48
- 5
src/main.rs View File

10
 extern crate linked_hash_map;
10
 extern crate linked_hash_map;
11
 #[macro_use]
11
 #[macro_use]
12
 extern crate log;
12
 extern crate log;
13
+extern crate osmpbf;
13
 extern crate regex;
14
 extern crate regex;
14
 extern crate reqwest;
15
 extern crate reqwest;
15
 extern crate toml;
16
 extern crate toml;
35
 use coord::ScreenCoord;
36
 use coord::ScreenCoord;
36
 use glutin::{ControlFlow, ElementState, Event, GlContext, MouseButton, MouseScrollDelta, VirtualKeyCode, WindowEvent};
37
 use glutin::{ControlFlow, ElementState, Event, GlContext, MouseButton, MouseScrollDelta, VirtualKeyCode, WindowEvent};
37
 use map_view_gl::MapViewGl;
38
 use map_view_gl::MapViewGl;
39
+use regex::Regex;
38
 use std::error::Error;
40
 use std::error::Error;
41
+use std::path::PathBuf;
42
+use std::sync::mpsc;
43
+use std::thread;
39
 use std::time::{Duration, Instant};
44
 use std::time::{Duration, Instant};
40
 use tile_source::TileSource;
45
 use tile_source::TileSource;
41
 
46
 
66
     mouse_pressed: bool,
71
     mouse_pressed: bool,
67
 }
72
 }
68
 
73
 
69
-fn handle_event(event: &Event, map: &mut MapViewGl, input_state: &mut InputState, sources: &mut TileSources) -> Action {
74
+fn handle_event(
75
+    event: &Event,
76
+    map: &mut MapViewGl,
77
+    input_state: &mut InputState,
78
+    sources: &mut TileSources,
79
+    marker_rx: &mpsc::Receiver<(f64, f64)>,
80
+) -> Action {
70
     match *event {
81
     match *event {
71
-        Event::Awakened => Action::Redraw,
82
+        Event::Awakened => {
83
+            for (lat, lon) in marker_rx.try_iter() {
84
+                map.add_marker(coord::MapCoord::from_latlon(lat, lon));
85
+            }
86
+            Action::Redraw
87
+        },
72
         Event::WindowEvent{ref event, ..} => match *event {
88
         Event::WindowEvent{ref event, ..} => match *event {
73
             WindowEvent::CloseRequested => Action::Close,
89
             WindowEvent::CloseRequested => Action::Close,
74
             WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Left, .. } => {
90
             WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Left, .. } => {
227
         mouse_pressed: false,
243
         mouse_pressed: false,
228
     };
244
     };
229
 
245
 
246
+    let (marker_tx, marker_rx) = mpsc::channel();
247
+    if let (Some(path), Some(pattern)) = (config.pbf_path(), config.search_pattern()) {
248
+        let pathbuf = PathBuf::from(path);
249
+        let re = Regex::new(pattern).unwrap();
250
+        let proxy = events_loop.create_proxy();
251
+
252
+        thread::spawn(move|| {
253
+            let reader = osmpbf::ElementReader::from_path(&pathbuf).unwrap();
254
+
255
+            // Increment the counter by one for each way.
256
+            reader.for_each(|element| {
257
+                match element {
258
+                    osmpbf::Element::Node(_) => {},
259
+                    osmpbf::Element::DenseNode(dnode) => {
260
+                        for (_key, val) in dnode.tags() {
261
+                            if re.is_match(val) {
262
+                                marker_tx.send((dnode.lat(), dnode.lon())).unwrap();
263
+                                proxy.wakeup().unwrap();
264
+                            }
265
+                        }
266
+                    },
267
+                    _ => {},
268
+                }
269
+            }).unwrap();
270
+        });
271
+    }
272
+
230
     let duration_per_frame = Duration::from_millis((1000.0 / config.fps() - 0.5).max(0.0).floor() as u64);
273
     let duration_per_frame = Duration::from_millis((1000.0 / config.fps() - 0.5).max(0.0).floor() as u64);
231
     info!("milliseconds per frame: {}", dur_to_sec(duration_per_frame) * 1000.0);
274
     info!("milliseconds per frame: {}", dur_to_sec(duration_per_frame) * 1000.0);
232
 
275
 
240
         let mut action = Action::Nothing;
283
         let mut action = Action::Nothing;
241
 
284
 
242
         events_loop.run_forever(|event| {
285
         events_loop.run_forever(|event| {
243
-            let a = handle_event(&event, &mut map, &mut input_state, &mut sources);
286
+            let a = handle_event(&event, &mut map, &mut input_state, &mut sources, &marker_rx);
244
             action.combine_with(a);
287
             action.combine_with(a);
245
             ControlFlow::Break
288
             ControlFlow::Break
246
         });
289
         });
250
         }
293
         }
251
 
294
 
252
         events_loop.poll_events(|event| {
295
         events_loop.poll_events(|event| {
253
-            let a = handle_event(&event, &mut map, &mut input_state, &mut sources);
296
+            let a = handle_event(&event, &mut map, &mut input_state, &mut sources, &marker_rx);
254
             action.combine_with(a);
297
             action.combine_with(a);
255
             if action == Action::Close {
298
             if action == Action::Close {
256
                 return;
299
                 return;
268
                     std::thread::sleep(dur);
311
                     std::thread::sleep(dur);
269
 
312
 
270
                     events_loop.poll_events(|event| {
313
                     events_loop.poll_events(|event| {
271
-                        let a = handle_event(&event, &mut map, &mut input_state, &mut sources);
314
+                        let a = handle_event(&event, &mut map, &mut input_state, &mut sources, &marker_rx);
272
                         action.combine_with(a);
315
                         action.combine_with(a);
273
                         if action == Action::Close {
316
                         if action == Action::Close {
274
                             return;
317
                             return;