// Copyright (c) Oleksandr Omelchuk 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>, } 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, ways: HashMap, strings: HashMap, } 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::(); 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::::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 ¤t_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(); }