pbf-reader 0.1.9

Fast openstreetmap PBF file format reader. Reads Nodes, Ways, Relations. It uses mpsc::channell and multiple threads to do job as fast as possible.
// Copyright (c) Oleksandr Omelchuk <kaznashcho()gmail.com>

extern crate pbf_reader;
extern crate piston_window;

use pbf_reader::*;

use piston_window::*;
use std::sync::mpsc;
use std::sync::Arc;
use std::thread;
use std::collections::HashMap;
use std::env;

type FloatType = CoordType;

#[derive(Debug)]
struct VisibleMapData {
    width: FloatType,
    height: FloatType,
    viewport: [FloatType; 4],
    visual_ways: Vec<Vec<[FloatType; 4]>>,
}

impl VisibleMapData {
    fn empty(&self) -> bool {
        return self.visual_ways.len() == 0;
    }

    fn wh_max(&self) -> FloatType {
        return (self.width as FloatType).max(self.height as FloatType);
    }
}

#[derive(Debug)]
struct MapData {
    nodes: HashMap<IDType, Node>,
    ways: HashMap<IDType, Way>,
    strings: HashMap<IDType, Strings>,
}

fn main() {
    if env::args().len() < 2 {
        println!(
            "No pbf file found. \nTry running: \ncargo run --release --example paint \
             ./src/sample.pbf"
        );
        return;
    }
    let fname = env::args().last().unwrap();

    let (mut node_tx, node_rx) = mpsc::channel::<PBFData>();
    let h = thread::spawn(move || {
        //        return read_pbf(&("./src/sample.pbf".to_string()), 10, &mut node_tx);
        return read_pbf(&fname, 9, &mut node_tx);
    });

    let mut max = Coord { lat: 0.0, lon: 0.0 };
    let mut min = Coord { lat: 0.0, lon: 0.0 };
    let mut count = 0;
    let mut map_data = MapData {
        nodes: HashMap::with_capacity(900),
        ways: HashMap::with_capacity(90),
        strings: HashMap::with_capacity(5),
    };
    let mut info = Vec::<PbfInfo>::new();

    loop {
        match node_rx.recv().unwrap() {
            PBFData::NodesSet(set) => {
                for (id, node) in set {
                    count = count + 1;

                    if max.lat < node.coord.lat || count == 1 {
                        max.lat = node.coord.lat
                    }
                    if max.lon < node.coord.lon || count == 1 {
                        max.lon = node.coord.lon
                    }
                    if min.lat > node.coord.lat || count == 1 {
                        min.lat = node.coord.lat
                    }
                    if min.lon > node.coord.lon || count == 1 {
                        min.lon = node.coord.lon
                    }
                    // println!("node {:?}", node);
                    match map_data.nodes.insert(id, node) {
                        Some(onode) => {
                            println!("W node id {} exists!!!! {:?} ", id, onode);
                        }
                        None => {}
                    }
                }
            }
            PBFData::WaysSet(set) => {
                for (id, way) in set {
                    // println!("got way {:?}", way );
                    match map_data.ways.insert(id, way) {
                        Some(oway) => {
                            println!("W node id {} exists!!!! {:?} ", id, oway);
                        }
                        None => {}
                    }
                }
            }
            PBFData::RelationsSet(_) => {}
            PBFData::Strings(id, strings) => match map_data.strings.insert(id, strings) {
                Some(ostrings) => {
                    println!("Error: strings id {} exists!!!! {:?} ", id, ostrings);
                }
                None => {
                    println!("got strings {}", id);
                }
            },
            PBFData::PbfInfo(inf) => {
                // println!("BBox '{:?}'", inf);
                info.push(inf);
            }

            PBFData::ParseEnd => {
                break;
            }
        }
    }
    // assert_eq!(count, 290);
    let r = h.join().unwrap();
    println!("DONE!!!! {:?}", r);
    let shared_map_data = Arc::new(map_data);

    let (width, height) = (900, 900);

    let mut window: PistonWindow = WindowSettings::new("piston: sample map", (width, height))
        .exit_on_esc(true)
        //.opengl(OpenGL::V3_2)
        .build()
        .unwrap();
    window.set_max_fps(25);

    let mut vp = [min.lat, min.lon, max.lat - min.lat, max.lon - min.lon]; // x,y, w,h
                                                                           // keep proportions
    if vp[2] > vp[3] {
        vp[2] = vp[3];
    } else {
        vp[3] = vp[2];
    }
    let mut current_visuals = Arc::new(VisibleMapData {
        width: width as FloatType,
        height: height as FloatType,
        viewport: vp,
        visual_ways: Vec::new(),
    });

    println!("viewport is {:?}", vp);

    //////////////////////////////////////////////
    let mut needs_update = true;
    let mut updating = false;
    let (tx_out, rx_out) = mpsc::sync_channel(10);
    let (tx_in, rx_in) = mpsc::sync_channel(10);

    let h;

    {
        let tx_out = tx_out.clone();
        h = thread::spawn(move || {
            let tx_out = tx_out.clone();
            loop {
                println!("loop");
                //                        let tx_out = tx_out.clone();

                match rx_in.recv() {
                    Ok(shared_visuals) => {
                        let mut visuals: VisibleMapData = Arc::try_unwrap(shared_visuals).unwrap();
                        println!("calculating new visuals");
                        let min_sz_pixels = 95.0;
                        let accepted_lsize =
                            (min_sz_pixels * visuals.viewport[2]) / visuals.wh_max();
                        // let mut errs = 0;
                        for (_, w) in &shared_map_data.ways {
                            let mut x0 = 0.0;
                            let mut y0 = 0.0;
                            let mut polys = Vec::with_capacity(w.nodes.len());
                            let mut total_length = 0.0;
                            for node_id in &w.nodes {
                                match shared_map_data.nodes.get(&node_id) {
                                    Some(node) => {
                                        //                                println!("way node {:?}", node)
                                        let x = node.coord.lat - visuals.viewport[0];
                                        let y = node.coord.lon - visuals.viewport[1];
                                        // println!("xy {} \t\t {}", x, y);
                                        if x0 > 0.0 && y0 > 0.0 {
                                            // TODO
                                            total_length = total_length
                                                + ((x0 - x) * (x0 - x) + (y0 - y) * (y0 - y))
                                                    .sqrt();
                                            polys.push([x0, y0, x, y]);
                                        }
                                        x0 = x;
                                        y0 = y;
                                    }
                                    None => {
                                        // errs = errs + 1;
                                        //  println!("error {} : no nodes for this id {}",errs, &node_id);
                                    }
                                }
                            }

                            if polys.len() > 0 && total_length > accepted_lsize {
                                // println!("total_length {:?} > accepted_lsize {}", total_length, accepted_lsize);
                                visuals.visual_ways.push(polys);
                            }
                        }
                        println!("push to draw visual_ways {}", visuals.visual_ways.len());
                        &tx_out.send(Arc::new(visuals)).unwrap();
                        thread::park();
                    }
                    Err(_) => {
                        println!("park");
                        thread::park();
                    }
                }
            }
        });
    }

    ////////////////////////////////////////////////////
    while let Some(e) = window.next() {
        // println!("Event {:?}", e);

        //        if let Event::Idle(_) = e {
        match rx_out.try_recv() {
            Ok(vd) => {
                println!("got visuals in main {}", vd.visual_ways.len());
                current_visuals = vd;
                updating = false;
            }
            Err(_) => {
                // println!("error receiving!!! {:?}", e);
            }
        }
        if needs_update {
            println!("request new visuals");
            needs_update = false;
            updating = true;
            tx_in
                .send(Arc::new(VisibleMapData {
                    width: window.draw_size().width as FloatType,
                    height: window.draw_size().height as FloatType,
                    viewport: vp,
                    visual_ways: Vec::new(),
                }))
                .unwrap();
            h.thread().unpark();
        }
        //      }

            let draw_size = window.draw_size();
            window.draw_2d(&e, |context, g2d, _device| {
                if !updating
                    && ((current_visuals.width - (draw_size.width as FloatType)).abs() > 0.1
                        || (current_visuals.height - (draw_size.height as FloatType)).abs() > 0.1)
                {
                    println!("set needs new visuals");
                    needs_update = true;
                }

                clear([1.0; 4], g2d);

                let red = [0.7, 0.20, 0.10, 1.0];
                let line = Line::new(red, 0.50);
                line.width(1.0);
                let ds = DrawState::new_alpha();

                if !current_visuals.empty() {
                    //println!("draw visual_ways {}",                         current_visuals.visual_ways.len());
                    for poly in &current_visuals.visual_ways {
                        for l in poly {
                            let wh_min = (draw_size.width as FloatType).max(draw_size.height as FloatType);
                            let ln = [
                                (l[0] * wh_min / vp[2]) as f64,
                                (l[1] * wh_min / vp[3]) as f64,
                                (l[2] * wh_min / vp[2]) as f64,
                                (l[3] * wh_min / vp[3]) as f64,
                            ];
                            line.draw(ln, &ds, context.transform, g2d);
                        }
                    }
                }
            });
        // if let Some(button) = e.press_args() {
        //     if button == Button::Mouse(MouseButton::Left) {
        //         draw = true;
        //         last_pos = e.mouse_cursor_args()
        //     }
        // };
        // if let Some(button) = e.release_args() {
        //     if button == Button::Mouse(MouseButton::Left) {
        //         draw = false;
        //         last_pos = None
        //     }
        // };
        // if draw {
        //     if let Some(pos) = e.mouse_cursor_args() {
        //         let (x, y) = (pos[0] as f32, pos[1] as f32);

        //         if let Some(p) = last_pos {
        //             let (last_x, last_y) = (p[0] as f32, p[1] as f32);

        //             // for i in 0..distance {
        //             //     let diff_x = x - last_x;
        //             //     let diff_y = y - last_y;
        //             //     let delta = i as f32 / distance as f32;
        //             //     let new_x = (last_x + (diff_x * delta)) as u32;
        //             //     let new_y = (last_y + (diff_y * delta)) as u32;
        //             //     if new_x < width && new_y < height {
        //             //         //canvas.put_pixel(new_x, new_y, im::Rgba([0, 0, 0, 255]));
        //             //     };
        //             // };
        //         };

        //         last_pos = Some(pos)
        //     };

        // }
    }
    // h.join().unwrap();
}