Skip to main content

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}