Browse Source

search: Find OSM ways in a second pass

search::par_search_blocking: Remember node ids for matching ways and
return the positions of these nodes in a second pass over the file.
Johannes Hofmann 7 years ago
parent
commit
e2f7171031
1 changed files with 53 additions and 5 deletions
  1. 53
    5
      src/search.rs

+ 53
- 5
src/search.rs View File

2
 use osmpbf::{Blob, BlobDecode, BlobReader, PrimitiveBlock};
2
 use osmpbf::{Blob, BlobDecode, BlobReader, PrimitiveBlock};
3
 use regex::Regex;
3
 use regex::Regex;
4
 use scoped_threadpool::Pool;
4
 use scoped_threadpool::Pool;
5
+use std::collections::hash_set::HashSet;
5
 use std::path::{Path, PathBuf};
6
 use std::path::{Path, PathBuf};
6
 use std::sync::mpsc::sync_channel;
7
 use std::sync::mpsc::sync_channel;
7
 use std::thread;
8
 use std::thread;
60
         .map_err(|e| format!("{}", e))?;
61
         .map_err(|e| format!("{}", e))?;
61
     let re = &re;
62
     let re = &re;
62
 
63
 
63
-    let search = move |block: &PrimitiveBlock, _: &()| {
64
+    let first_pass = move |block: &PrimitiveBlock, _: &()| {
64
         let mut matches = vec![];
65
         let mut matches = vec![];
66
+        let mut way_node_ids = vec![];
65
 
67
 
66
         for node in block.groups().flat_map(|g| g.nodes()) {
68
         for node in block.groups().flat_map(|g| g.nodes()) {
67
             for (_key, val) in node.tags() {
69
             for (_key, val) in node.tags() {
83
             }
85
             }
84
         }
86
         }
85
 
87
 
88
+        for way in block.groups().flat_map(|g| g.ways()) {
89
+            for (_key, val) in way.tags() {
90
+                if re.is_match(val) && !way.refs_slice().is_empty() {
91
+                    //TODO take middle node, not first one
92
+                    way_node_ids.push(way.refs_slice()[0]);
93
+                    break;
94
+                }
95
+            }
96
+        }
97
+
98
+        (matches, way_node_ids)
99
+    };
100
+
101
+    let mut way_node_ids: HashSet<i64> = HashSet::new();
102
+
103
+    par_iter_blobs(
104
+        &pbf_path,
105
+        || {},
106
+        first_pass,
107
+        |(matches, node_ids)| {
108
+            way_node_ids.extend(&node_ids);
109
+            found_func(matches)
110
+        },
111
+    )?;
112
+
113
+    let way_node_ids = &way_node_ids;
114
+
115
+    let second_pass = move |block: &PrimitiveBlock, _: &()| {
116
+        let mut matches = vec![];
117
+
118
+        for node in block.groups().flat_map(|g| g.nodes()) {
119
+            if way_node_ids.contains(&node.id()) {
120
+                let pos = LatLon::new(node.lat(), node.lon());
121
+                matches.push(pos);
122
+                break;
123
+            }
124
+        }
125
+
126
+        for node in block.groups().flat_map(|g| g.dense_nodes()) {
127
+            if way_node_ids.contains(&node.id) {
128
+                let pos = LatLon::new(node.lat(), node.lon());
129
+                matches.push(pos);
130
+                break;
131
+            }
132
+        }
133
+
86
         matches
134
         matches
87
     };
135
     };
88
 
136
 
89
     par_iter_blobs(
137
     par_iter_blobs(
90
-        pbf_path,
138
+        &pbf_path,
91
         || {},
139
         || {},
92
-        search,
140
+        second_pass,
93
         found_func,
141
         found_func,
94
     )
142
     )
95
 }
143
 }
98
     pbf_path: P,
146
     pbf_path: P,
99
     init_func: IF,
147
     init_func: IF,
100
     compute_func: CF,
148
     compute_func: CF,
101
-    result_func: RF,
149
+    mut result_func: RF,
102
 ) -> Result<(), String>
150
 ) -> Result<(), String>
103
 where P: AsRef<Path>,
151
 where P: AsRef<Path>,
104
       IF: Fn() -> D,
152
       IF: Fn() -> D,
105
       CF: Fn(&PrimitiveBlock, &D) -> R + Send + Sync,
153
       CF: Fn(&PrimitiveBlock, &D) -> R + Send + Sync,
106
-      RF: Fn(R) -> ControlFlow + Send + 'static,
154
+      RF: FnMut(R) -> ControlFlow,
107
       R: Send,
155
       R: Send,
108
       D: Send,
156
       D: Send,
109
 {
157
 {