osm_lump_ways/nodeid_position.rs
1/// Storing the position of nodes based on their node id
2use super::*;
3use ordered_float::OrderedFloat;
4use osmio::{Lat, Lon};
5use std::collections::BTreeMap;
6
7#[allow(dead_code)]
8/// Store the position of a node based on it's id
9pub trait NodeIdPosition: std::fmt::Debug + std::marker::Send + std::marker::Sync {
10 fn new() -> Self
11 where
12 Self: Sized;
13
14 /// Set this position
15 fn insert(&mut self, node_id: i64, pos: (f64, f64));
16
17 /// Set this position (f64 explict)
18 fn insert_f64(&mut self, node_id: i64, pos: (f64, f64)) {
19 self.insert(node_id, pos);
20 }
21 /// Set this position if already have explicit inner format
22 fn insert_i32(&mut self, node_id: i64, pos: (i32, i32)) {
23 let pos: (f64, f64) = (
24 Lat::from_inner(pos.0).degrees(),
25 Lon::from_inner(pos.1).degrees(),
26 );
27 self.insert_f64(node_id, pos);
28 }
29
30 fn contains_key(&self, node_id: &i64) -> bool {
31 self.get(node_id).is_ok()
32 }
33 /// Return the location for this node id
34 fn get(&self, node_id: &i64) -> Result<(f64, f64)>;
35
36 fn get_arr(&self, node_id: &i64) -> Result<[f64; 2]> {
37 let res = self.get(node_id)?;
38 Ok([res.0, res.1])
39 }
40
41 fn get_ord(&self, node_id: &i64) -> Result<(OrderedFloat<f64>, OrderedFloat<f64>)> {
42 let res = self.get(node_id)?;
43 Ok((OrderedFloat(res.0), OrderedFloat(res.1)))
44 }
45
46 fn get_many_unwrap(&self, nids: &[i64], output: &mut [(f64, f64)]) {
47 for (nid, output) in nids.iter().zip(output.iter_mut()) {
48 *output = self.get(nid).unwrap();
49 }
50 }
51
52 fn get_many(&self, nids: &[i64], output: &mut [Result<(f64, f64)>]) {
53 for i in 0..nids.len() {
54 output[i] = self.get(&nids[i]);
55 }
56 }
57
58 /// Number of nodes inside
59 fn len(&self) -> usize;
60 fn is_empty(&self) -> bool {
61 self.len() == 0
62 }
63
64 fn detailed_size(&self) -> String;
65
66 fn shrink_to_fit(&mut self) {}
67
68 fn finished_inserting(&mut self) {}
69}
70
71/// A default good value
72pub fn default() -> impl NodeIdPosition {
73 //NodeIdPositionMap::new()
74 NodeIdPositionBucket::with_bucket(3)
75}
76
77/// A simple map
78// IME BTreeMap is smaller than HashMap. Positions are stored as i32
79#[derive(Debug, GetSize)]
80pub struct NodeIdPositionMap {
81 inner: BTreeMap<i64, (i32, i32)>,
82}
83
84impl NodeIdPosition for NodeIdPositionMap {
85 fn new() -> Self {
86 NodeIdPositionMap {
87 inner: BTreeMap::new(),
88 }
89 }
90
91 fn insert_i32(&mut self, node_id: i64, pos: (i32, i32)) {
92 self.inner.insert(node_id, pos);
93 }
94
95 fn insert(&mut self, node_id: i64, pos: (f64, f64)) {
96 let pos = (
97 Lat::try_from(pos.0).unwrap().inner(),
98 Lon::try_from(pos.1).unwrap().inner(),
99 );
100 self.insert_i32(node_id, pos);
101 }
102
103 fn contains_key(&self, node_id: &i64) -> bool {
104 self.inner.contains_key(node_id)
105 }
106
107 fn get(&self, node_id: &i64) -> Result<(f64, f64)> {
108 self.inner
109 .get(node_id)
110 .map(|(lat, lng)| {
111 (
112 Lat::from_inner(*lat).degrees(),
113 Lon::from_inner(*lng).degrees(),
114 )
115 })
116 .ok_or_else(|| anyhow::anyhow!("Couldn't get node position for nid {}", node_id))
117 }
118
119 fn len(&self) -> usize {
120 self.inner.len()
121 }
122
123 fn detailed_size(&self) -> String {
124 let mut output = String::new();
125 output.push_str(&format!(
126 "Size of nodeid_pos (NodeIdPositionMap): {} = {} bytes.\nnum_nodes: {} = {}.\nbytes/node = {:>.2}\n",
127 self.get_size(),
128 self.get_size().to_formatted_string(&Locale::en),
129 self.len(),
130 self.len().to_formatted_string(&Locale::en),
131 self.get_size() as f64 / self.len() as f64,
132 ));
133 output
134 }
135}
136
137/// A memory effecient node location store
138/// nodes with the same id are often very close together. This will bucket nodes based on id, and
139/// store several relative offsets (in a compressed form)
140#[derive(Debug, GetSize)]
141pub struct NodeIdPositionBucket {
142 /// left shift node ids by this much. Max 6
143 bucket_shift: i64,
144 num_nodes: usize,
145
146 /// All the data is here. Key is the bucket id
147 inner: BTreeMap<i32, Vec<u8>>,
148
149 /// A local cache of decoded values to make lookup & inserts faster
150 #[allow(clippy::type_complexity)]
151 cache: Option<(i32, Vec<Option<(i32, i32)>>)>,
152}
153
154impl NodeIdPositionBucket {
155 /// Create a new object with this shift
156 fn with_bucket(bucket_shift: i64) -> Self {
157 NodeIdPositionBucket {
158 bucket_shift,
159 num_nodes: 0,
160 inner: BTreeMap::new(),
161 cache: None,
162 }
163 }
164
165 /// a simple getter
166 fn bucket_shift(&self) -> i64 {
167 self.bucket_shift
168 }
169
170 /// Return the bucket id, and the local offset within that bucket for this nodeid
171 fn nodeid_bucket_local(&self, nid: i64) -> (i32, usize) {
172 let bucket: i32 = (nid >> self.bucket_shift())
173 .try_into()
174 .expect("Node id >> by bucket size is too large to fit in i32. This tool uses optimizations which assume that it will fit");
175
176 let local_index = (nid % (2_i64.pow(self.bucket_shift() as u32))) as usize;
177 (bucket, local_index)
178 }
179
180 /// Write the contents of the cache to the inner
181 fn write_out_cache(&mut self) {
182 let bucket_shift = self.bucket_shift();
183 if let Some(cache) = &mut self.cache {
184 let inner_entry = self
185 .inner
186 .entry(cache.0)
187 .or_insert_with(|| Vec::with_capacity(8 + 2 * cache.1.len()));
188 bucket_bytes_write(bucket_shift, &cache.1, inner_entry);
189 }
190 }
191
192 /// Set the cache to be the value for this node id
193 fn warm_cache(&mut self, nid: i64) {
194 let (bucket_id, _local_index) = self.nodeid_bucket_local(nid);
195 let bucket_shift = self.bucket_shift();
196
197 // Do we have a cache that isn't for this node id? If so, write that out
198 if let Some(cache) = &mut self.cache
199 && cache.0 != bucket_id
200 {
201 self.write_out_cache();
202 }
203
204 // Have to duplicate it for lifetime reasons
205 if let Some(cache) = &mut self.cache {
206 if cache.0 != bucket_id {
207 // now take from the real store to the cache.
208 let bytes: &[u8] = self.inner.entry(bucket_id).or_insert_with(|| vec![0]);
209 cache.0 = bucket_id;
210 cache.1.truncate(0);
211 cache.1.reserve(2_usize.pow(bucket_shift as u32));
212 cache.1.extend(bucket_bytes_read(bucket_shift, bytes));
213 }
214 } else {
215 // no cache, so store it
216 // Read from the inner data
217 let bytes: &[u8] = self.inner.entry(bucket_id).or_insert_with(|| vec![0]);
218 let latlngs = bucket_bytes_read(self.bucket_shift, bytes).collect::<Vec<_>>();
219 self.cache = Some((bucket_id, latlngs));
220 }
221 }
222}
223
224impl NodeIdPosition for NodeIdPositionBucket {
225 fn new() -> Self {
226 Self::with_bucket(6)
227 }
228
229 fn insert(&mut self, nid: i64, pos: (f64, f64)) {
230 trace!("nodeid_pos.insert({}, ({}, {}))", nid, pos.0, pos.1);
231 let pos: (i32, i32) = (
232 Lat::try_from(pos.0).unwrap().inner(),
233 Lon::try_from(pos.1).unwrap().inner(),
234 );
235 self.insert_i32(nid, pos);
236 }
237
238 fn insert_i32(&mut self, nid: i64, pos: (i32, i32)) {
239 self.warm_cache(nid);
240 let (_bucket_id, local_index) = self.nodeid_bucket_local(nid);
241
242 let latlngs = &mut self.cache.as_mut().unwrap().1;
243
244 if latlngs[local_index].is_none() {
245 trace!("inc self.num_nodes");
246 self.num_nodes += 1;
247 } else {
248 trace!("latlngs[{}] {:?}", local_index, latlngs[local_index]);
249 }
250 latlngs[local_index] = Some(pos);
251 }
252
253 fn get(&self, nid: &i64) -> Result<(f64, f64)> {
254 let (bucket_id, local_index) = self.nodeid_bucket_local(*nid);
255 if let Some((cache_bucket_id, cache_latlngs)) = &self.cache
256 && *cache_bucket_id == bucket_id
257 {
258 return cache_latlngs[local_index]
259 .map(|(lat_i32, lng_i32)| {
260 (
261 Lat::from_inner(lat_i32).degrees(),
262 Lon::from_inner(lng_i32).degrees(),
263 )
264 })
265 .ok_or_else(|| anyhow::anyhow!("Couldn't get node position for nid {nid}"));
266 }
267
268 self.inner
269 .get(&bucket_id)
270 .and_then(|bytes| {
271 bucket_bytes_read(self.bucket_shift, bytes)
272 .nth(local_index)
273 .unwrap()
274 })
275 .map(|(lat_i32, lng_i32)| {
276 (
277 Lat::from_inner(lat_i32).degrees(),
278 Lon::from_inner(lng_i32).degrees(),
279 )
280 })
281 .ok_or_else(|| anyhow::anyhow!("Couldn't get node position for nid {nid}"))
282 }
283
284 fn get_many_unwrap(&self, nids: &[i64], output: &mut [(f64, f64)]) {
285 assert_eq!(nids.len(), output.len());
286 if nids.is_empty() {
287 return;
288 }
289 let mut buckets = HashMap::new();
290 let mut bucket_id;
291 let mut new_bucket_id;
292 let mut bucket_latlngs_i32s;
293 let mut local_index;
294 let mut new_local_index;
295 (bucket_id, local_index) = self.nodeid_bucket_local(nids[0]);
296
297 bucket_latlngs_i32s = buckets.entry(bucket_id).or_insert_with(|| {
298 let new_bucket_value = self.inner.get(&bucket_id).unwrap();
299 bucket_bytes_read(self.bucket_shift, new_bucket_value).collect::<Vec<_>>()
300 });
301 assert!(
302 bucket_latlngs_i32s[local_index].is_some(),
303 "Node {} does not have a position",
304 nids[0]
305 );
306 output[0] = bucket_latlngs_i32s[local_index]
307 .map(|(lat_i32, lng_i32)| {
308 (
309 Lat::from_inner(lat_i32).degrees(),
310 Lon::from_inner(lng_i32).degrees(),
311 )
312 })
313 .unwrap();
314
315 for (nid, output_el) in nids[1..].iter().zip(output[1..].iter_mut()) {
316 (new_bucket_id, new_local_index) = self.nodeid_bucket_local(*nid);
317 if new_bucket_id != bucket_id {
318 bucket_latlngs_i32s = buckets.entry(new_bucket_id).or_insert_with(|| {
319 let new_bucket_value = self.inner.get(&new_bucket_id).unwrap();
320 bucket_bytes_read(self.bucket_shift, new_bucket_value).collect::<Vec<_>>()
321 });
322 bucket_id = new_bucket_id;
323 }
324 local_index = new_local_index;
325
326 assert!(
327 bucket_latlngs_i32s[local_index].is_some(),
328 "Node {nid} does not have a position"
329 );
330
331 *output_el = bucket_latlngs_i32s[local_index]
332 .map(|(lat_i32, lng_i32)| {
333 (
334 Lat::from_inner(lat_i32).degrees(),
335 Lon::from_inner(lng_i32).degrees(),
336 )
337 })
338 .unwrap_or_else(|| panic!("unable to get position for nid {nid}"));
339 }
340 }
341
342 fn len(&self) -> usize {
343 self.num_nodes
344 }
345
346 fn detailed_size(&self) -> String {
347 let mut output = String::new();
348 output.push_str(&format!(
349 "Size of nodeid_pos (NodeIdPositionBucket): {} = {} bytes.\nnum_nodes: {} = {}.\nbytes/node = {:>.2}\ninner bucket_len {} = {}\nbucket_shift = {}",
350 self.get_size(),
351 self.get_size().to_formatted_string(&Locale::en),
352 self.len(),
353 self.len().to_formatted_string(&Locale::en),
354 self.get_size() as f64 / self.len() as f64,
355 self.inner.len(),
356 self.inner.len().to_formatted_string(&Locale::en),
357 self.bucket_shift(),
358 ));
359 output
360 }
361
362 fn finished_inserting(&mut self) {
363 self.write_out_cache();
364 }
365}
366
367// First i64 has the i-th bit set if there is a node at position i
368// then there are all lat's delta encoded & varint encoded. then all the lng's
369// TODO this could return an iterator
370fn bucket_bytes_read(
371 bucket_size: i64,
372 bytes: &[u8],
373) -> impl Iterator<Item = Option<(i32, i32)>> + '_ {
374 assert!(bucket_size <= 6); // only support i64
375 let (mask, bytes) = vartyint::read_i64(bytes).expect("");
376
377 (0..2_i32.pow(bucket_size as u32)).scan(
378 (0i32, 0i32, bytes),
379 move |(curr_0, curr_1, bytes), i| {
380 if (mask >> i) & 1 == 1 {
381 let (n, new_bytes) = vartyint::read_i32(bytes).unwrap();
382 *bytes = new_bytes;
383 let p0 = *curr_0 + n;
384
385 let (n, new_bytes) = vartyint::read_i32(bytes).unwrap();
386 *bytes = new_bytes;
387 let p1 = *curr_1 + n;
388 *curr_0 = p0;
389 *curr_1 = p1;
390 Some(Some((p0, p1)))
391 } else {
392 Some(None)
393 }
394 },
395 )
396}
397
398/// Store the node positions
399/// Data format:
400/// varint i64 bitmask. if bit i is set (i.e. `1`) then that node has a position set, `0` =
401/// nid not in the bucket
402/// Then 2N more varint32's. 2 int for each node, the latitude & longitudes
403/// All lats are stored as the offset from the last lat. (lng are the same).
404fn bucket_bytes_write(bucket_size: i64, pos: &[Option<(i32, i32)>], output: &mut Vec<u8>) {
405 assert_eq!(pos.len(), 2_i32.pow(bucket_size as u32) as usize);
406 assert!(bucket_size <= 6); // only support i64
407 output.truncate(0);
408 output.reserve(8 + 2 * pos.len());
409
410 // Node id mask
411 let mut mask = 0i64;
412 for (i, p) in pos.iter().enumerate() {
413 if p.is_some() {
414 mask |= 1 << i;
415 }
416 }
417 vartyint::write_i64(mask, output);
418
419 // the locations
420 let mut curr_0 = 0;
421 let mut curr_1 = 0;
422 for p in pos.iter().filter_map(|x| *x) {
423 vartyint::write_i32(p.0 - curr_0, output);
424 vartyint::write_i32(p.1 - curr_1, output);
425 curr_0 = p.0;
426 curr_1 = p.1;
427 }
428}
429
430#[cfg(test)]
431mod test {
432 use super::*;
433
434 macro_rules! test_round_trip {
435 ( $name:ident, $bucket_shift: expr_2021, $input:expr_2021 ) => {
436 #[test]
437 fn $name() {
438 let input = $input;
439 let bucket_shift: i64 = $bucket_shift;
440 let mut output = vec![];
441 bucket_bytes_write(bucket_shift, &input, &mut output);
442 let result = bucket_bytes_read(bucket_shift, &output).collect::<Vec<_>>();
443
444 assert_eq!(
445 result, input,
446 "Ouput was {:?} but expected {:?}",
447 result, input,
448 );
449 }
450 };
451 }
452
453 test_round_trip!(empty, 2, vec![None; 4]);
454 test_round_trip!(test1, 2, vec![Some((1, 1)), None, None, None]);
455 test_round_trip!(test2, 2, vec![Some((1, 1)), Some((1, 1)), None, None]);
456 test_round_trip!(test3, 2, vec![Some((2, 2)), None, None, None]);
457 test_round_trip!(test4, 2, vec![Some((2, 2)), Some((100, 100)), None, None]);
458 test_round_trip!(
459 test5,
460 2,
461 vec![
462 Some((2, 2)),
463 Some((100, 100)),
464 Some((100, 100)),
465 Some((2, 2))
466 ]
467 );
468 test_round_trip!(test6, 2, vec![None, None, None, Some((1, 1))]);
469
470 //fn init() {
471 // let _ = env_logger::builder().is_test(true).try_init();
472 //}
473 //#[test]
474 //fn real_life() {
475 // init();
476 // let mut nodeid_pos = NodeIdPositionBucket::with_bucket(5);
477 // assert_eq!(nodeid_pos.len(), 0);
478
479 // nodeid_pos.insert(1494342551, (14.2637113, 36.0239228));
480 // assert_eq!(nodeid_pos.get(&1494342551), Some((14.2637113, 36.0239228)));
481 // assert_eq!(nodeid_pos.len(), 1);
482 // nodeid_pos.insert(1494342553, (14.2663291, 36.0216147));
483 // assert_eq!(nodeid_pos.get(&1494342553), Some((14.2663291, 36.0216147)));
484 // assert_eq!(nodeid_pos.len(), 2);
485 // nodeid_pos.insert(1494342577, (14.2647091, 36.0225345));
486 // assert_eq!(nodeid_pos.get(&1494342577), Some((14.2647091, 36.0225345)));
487 // assert_eq!(nodeid_pos.len(), 3);
488 // nodeid_pos.insert(1494342562, (14.2627028, 36.0234716));
489 // assert_eq!(nodeid_pos.get(&1494342562), Some((14.2627028, 36.0234716)));
490 // assert_eq!(nodeid_pos.len(), 4);
491 // nodeid_pos.insert(1494342554, (14.265385, 36.0215626));
492 // assert_eq!(nodeid_pos.get(&1494342554), Some((14.265385, 36.0215626)));
493 // assert_eq!(nodeid_pos.len(), 5);
494 // nodeid_pos.insert(1494342589, (14.2580679, 36.0263698));
495 // assert_eq!(nodeid_pos.get(&1494342589), Some((14.2580679, 36.0263698)));
496 // assert_eq!(nodeid_pos.len(), 6);
497 // nodeid_pos.insert(1494342590, (14.2643657, 36.0229076));
498 // assert_eq!(nodeid_pos.get(&1494342590), Some((14.2643657, 36.0229076)));
499 // assert_eq!(nodeid_pos.len(), 7);
500 // nodeid_pos.insert(1494342591, (14.2647842, 36.0228035));
501 // assert_eq!(nodeid_pos.get(&1494342591), Some((14.2647842, 36.0228035)));
502 // assert_eq!(nodeid_pos.len(), 8);
503 // nodeid_pos.insert(1494342598, (14.2646447, 36.0222047));
504 // assert_eq!(nodeid_pos.get(&1494342598), Some((14.2646447, 36.0222047)));
505 // assert_eq!(nodeid_pos.len(), 9);
506 // nodeid_pos.insert(1494342550, (14.2670694, 36.0217622));
507 // assert_eq!(nodeid_pos.get(&1494342550), Some((14.2670694, 36.0217622)));
508 // assert_eq!(nodeid_pos.len(), 10);
509 // nodeid_pos.insert(1494342579, (14.2648593, 36.0226733));
510 // assert_eq!(nodeid_pos.get(&1494342579), Some((14.2648593, 36.0226733)));
511 // assert_eq!(nodeid_pos.len(), 11);
512 // nodeid_pos.insert(1494342567, (14.2602673, 36.0260487));
513 // assert_eq!(nodeid_pos.get(&1494342567), Some((14.2602673, 36.0260487)));
514 // assert_eq!(nodeid_pos.len(), 12);
515 // nodeid_pos.insert(1494342569, (14.2677131, 36.0217709));
516 // assert_eq!(nodeid_pos.get(&1494342569), Some((14.2677131, 36.0217709)));
517 // assert_eq!(nodeid_pos.len(), 13);
518 // nodeid_pos.insert(1494342582, (14.263958, 36.0238534));
519 // assert_eq!(nodeid_pos.get(&1494342582), Some((14.263958, 36.0238534)));
520 // assert_eq!(nodeid_pos.len(), 14);
521 // nodeid_pos.insert(1494342568, (14.2647198, 36.0219357));
522 // assert_eq!(nodeid_pos.get(&1494342568), Some((14.2647198, 36.0219357)));
523 // assert_eq!(nodeid_pos.len(), 15);
524 // nodeid_pos.insert(1494342557, (14.2693198, 36.020732));
525 // assert_eq!(nodeid_pos.get(&1494342557), Some((14.2693198, 36.020732)));
526 // assert_eq!(nodeid_pos.len(), 16);
527 // nodeid_pos.insert(1494342599, (14.2626062, 36.0252331));
528 // assert_eq!(nodeid_pos.get(&1494342599), Some((14.2626062, 36.0252331)));
529 // assert_eq!(nodeid_pos.len(), 17);
530 // nodeid_pos.insert(1494342602, (14.2533043, 36.0282613));
531 // assert_eq!(nodeid_pos.get(&1494342602), Some((14.2533043, 36.0282613)));
532 // assert_eq!(nodeid_pos.len(), 18);
533 // nodeid_pos.insert(1494342600, (14.2689469, 36.0209031));
534 // assert_eq!(nodeid_pos.get(&1494342600), Some((14.2689469, 36.0209031)));
535 // assert_eq!(nodeid_pos.len(), 19);
536 // nodeid_pos.insert(1494342611, (14.258894, 36.0261268));
537 // assert_eq!(nodeid_pos.get(&1494342611), Some((14.258894, 36.0261268)));
538 // assert_eq!(nodeid_pos.len(), 20);
539 // nodeid_pos.insert(1494342618, (14.2593876, 36.0258405));
540 // assert_eq!(nodeid_pos.get(&1494342618), Some((14.2593876, 36.0258405)));
541 // assert_eq!(nodeid_pos.len(), 21);
542 // nodeid_pos.insert(1494342625, (14.2557076, 36.0266387));
543 // assert_eq!(nodeid_pos.get(&1494342625), Some((14.2557076, 36.0266387)));
544 // assert_eq!(nodeid_pos.len(), 22);
545 // nodeid_pos.insert(1494342646, (14.2640331, 36.0231679));
546 // assert_eq!(nodeid_pos.get(&1494342646), Some((14.2640331, 36.0231679)));
547 // assert_eq!(nodeid_pos.len(), 23);
548 // nodeid_pos.insert(1494342647, (14.2682496, 36.0215886));
549 // assert_eq!(nodeid_pos.get(&1494342647), Some((14.2682496, 36.0215886)));
550 // assert_eq!(nodeid_pos.len(), 24);
551 // nodeid_pos.insert(1494342648, (14.2686251, 36.0211982));
552 // assert_eq!(nodeid_pos.get(&1494342648), Some((14.2686251, 36.0211982)));
553 // assert_eq!(nodeid_pos.len(), 25);
554 // nodeid_pos.insert(1494342650, (14.2679921, 36.0217448));
555 // assert_eq!(nodeid_pos.get(&1494342650), Some((14.2679921, 36.0217448)));
556 // assert_eq!(nodeid_pos.len(), 26);
557 // nodeid_pos.insert(1494342658, (14.2571345, 36.0264131));
558 // assert_eq!(nodeid_pos.get(&1494342658), Some((14.2571345, 36.0264131)));
559 // assert_eq!(nodeid_pos.len(), 27);
560 // nodeid_pos.insert(1494342612, (14.2627457, 36.024027));
561 // assert_eq!(nodeid_pos.get(&1494342612), Some((14.2627457, 36.024027)));
562 // assert_eq!(nodeid_pos.len(), 28);
563 // nodeid_pos.insert(1494342664, (14.2622629, 36.0255194));
564 // assert_eq!(nodeid_pos.get(&1494342664), Some((14.2622629, 36.0255194)));
565 // assert_eq!(nodeid_pos.len(), 29);
566 // nodeid_pos.insert(1494342665, (14.2549458, 36.0268904));
567 // assert_eq!(nodeid_pos.get(&1494342665), Some((14.2549458, 36.0268904)));
568 // assert_eq!(nodeid_pos.len(), 30);
569 // nodeid_pos.insert(1494342644, (14.2629603, 36.0231506));
570 // assert_eq!(nodeid_pos.get(&1494342644), Some((14.2629603, 36.0231506)));
571 // assert_eq!(nodeid_pos.len(), 31);
572 // nodeid_pos.insert(1494342607, (14.2608574, 36.0261008));
573 // assert_eq!(nodeid_pos.get(&1494342607), Some((14.2608574, 36.0261008)));
574 // assert_eq!(nodeid_pos.len(), 32);
575 // nodeid_pos.insert(1494342615, (14.2544416, 36.0271073));
576 // assert_eq!(nodeid_pos.get(&1494342615), Some((14.2544416, 36.0271073)));
577 // assert_eq!(nodeid_pos.len(), 33);
578 // nodeid_pos.insert(1494342620, (14.2640117, 36.0234109));
579 // assert_eq!(nodeid_pos.get(&1494342620), Some((14.2640117, 36.0234109)));
580 // assert_eq!(nodeid_pos.len(), 34);
581 // nodeid_pos.insert(1494342662, (14.2633679, 36.0231506));
582 // assert_eq!(nodeid_pos.get(&1494342662), Some((14.2633679, 36.0231506)));
583 // assert_eq!(nodeid_pos.len(), 35);
584 // nodeid_pos.insert(1494342604, (14.263604, 36.0234976));
585 // assert_eq!(nodeid_pos.get(&1494342604), Some((14.263604, 36.0234976)));
586 // assert_eq!(nodeid_pos.len(), 36);
587 // nodeid_pos.insert(1494342614, (14.253948, 36.0274804));
588 // assert_eq!(nodeid_pos.get(&1494342614), Some((14.253948, 36.0274804)));
589 // assert_eq!(nodeid_pos.len(), 37);
590 // nodeid_pos.insert(1494342675, (14.2628744, 36.0248773));
591 // assert_eq!(nodeid_pos.get(&1494342675), Some((14.2628744, 36.0248773)));
592 // assert_eq!(nodeid_pos.len(), 38);
593 // nodeid_pos.insert(3933446907, (14.2571911, 36.026411));
594 // assert_eq!(nodeid_pos.get(&3933446907), Some((14.2571911, 36.026411)));
595 // assert_eq!(nodeid_pos.len(), 39);
596 // nodeid_pos.insert(4008848336, (14.2623883, 36.0254219));
597 // assert_eq!(nodeid_pos.get(&4008848336), Some((14.2623883, 36.0254219)));
598 // assert_eq!(nodeid_pos.len(), 40);
599 //}
600}