瀏覽代碼

Search PBF files and display matches as markers

Use the parameters -s and --pbf for this.
Johannes Hofmann 7 年之前
父節點
當前提交
0f30790da8
共有 3 個文件被更改,包括 82 次插入5 次删除
  1. 11
    0
      src/args.rs
  2. 23
    0
      src/config.rs
  3. 48
    5
      src/main.rs

+ 11
- 0
src/args.rs 查看文件

@@ -19,6 +19,17 @@ pub fn parse<'a>() -> clap::ArgMatches<'a> {
19 19
             .value_name("FILE")
20 20
             .help("Set a custom tile sources file")
21 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 33
         .arg(Arg::with_name("fps")
23 34
             .long("fps")
24 35
             .value_name("FPS")

+ 23
- 0
src/config.rs 查看文件

@@ -19,6 +19,8 @@ lazy_static! {
19 19
 pub struct Config {
20 20
     tile_cache_dir: PathBuf,
21 21
     sources: Vec<(String, TileSource)>,
22
+    pbf_path: Option<PathBuf>,
23
+    search_pattern: Option<String>,
22 24
     fps: f64,
23 25
     use_network: bool,
24 26
     async: bool,
@@ -40,12 +42,23 @@ impl Config {
40 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 54
         config.merge_arg_matches(matches);
44 55
 
45 56
         Ok(config)
46 57
     }
47 58
 
48 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 62
         if let Some(Ok(fps)) = matches.value_of("fps").map(|s| s.parse()) {
50 63
             self.fps = fps;
51 64
         }
@@ -188,6 +201,8 @@ impl Config {
188 201
                     Config {
189 202
                         tile_cache_dir,
190 203
                         sources: vec![],
204
+                        pbf_path: None,
205
+                        search_pattern: None,
191 206
                         fps,
192 207
                         use_network,
193 208
                         async,
@@ -304,6 +319,14 @@ impl Config {
304 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 330
     pub fn fps(&self) -> f64 {
308 331
         self.fps
309 332
     }

+ 48
- 5
src/main.rs 查看文件

@@ -10,6 +10,7 @@ extern crate lazy_static;
10 10
 extern crate linked_hash_map;
11 11
 #[macro_use]
12 12
 extern crate log;
13
+extern crate osmpbf;
13 14
 extern crate regex;
14 15
 extern crate reqwest;
15 16
 extern crate toml;
@@ -35,7 +36,11 @@ pub mod vertex_attrib;
35 36
 use coord::ScreenCoord;
36 37
 use glutin::{ControlFlow, ElementState, Event, GlContext, MouseButton, MouseScrollDelta, VirtualKeyCode, WindowEvent};
37 38
 use map_view_gl::MapViewGl;
39
+use regex::Regex;
38 40
 use std::error::Error;
41
+use std::path::PathBuf;
42
+use std::sync::mpsc;
43
+use std::thread;
39 44
 use std::time::{Duration, Instant};
40 45
 use tile_source::TileSource;
41 46
 
@@ -66,9 +71,20 @@ struct InputState {
66 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 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 88
         Event::WindowEvent{ref event, ..} => match *event {
73 89
             WindowEvent::CloseRequested => Action::Close,
74 90
             WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Left, .. } => {
@@ -227,6 +243,33 @@ fn run() -> Result<(), Box<Error>> {
227 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 273
     let duration_per_frame = Duration::from_millis((1000.0 / config.fps() - 0.5).max(0.0).floor() as u64);
231 274
     info!("milliseconds per frame: {}", dur_to_sec(duration_per_frame) * 1000.0);
232 275
 
@@ -240,7 +283,7 @@ fn run() -> Result<(), Box<Error>> {
240 283
         let mut action = Action::Nothing;
241 284
 
242 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 287
             action.combine_with(a);
245 288
             ControlFlow::Break
246 289
         });
@@ -250,7 +293,7 @@ fn run() -> Result<(), Box<Error>> {
250 293
         }
251 294
 
252 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 297
             action.combine_with(a);
255 298
             if action == Action::Close {
256 299
                 return;
@@ -268,7 +311,7 @@ fn run() -> Result<(), Box<Error>> {
268 311
                     std::thread::sleep(dur);
269 312
 
270 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 315
                         action.combine_with(a);
273 316
                         if action == Action::Close {
274 317
                             return;