Przeglądaj źródła

Rename Tile -> TileCoord

Johannes Hofmann 8 lat temu
rodzic
commit
2912a7b684
8 zmienionych plików z 124 dodań i 121 usunięć
  1. 0
    1
      src/config.rs
  2. 72
    4
      src/coord.rs
  3. 6
    7
      src/map_view.rs
  4. 4
    65
      src/tile.rs
  5. 6
    6
      src/tile_cache.rs
  6. 4
    5
      src/tile_cache_gl.rs
  7. 23
    23
      src/tile_loader.rs
  8. 9
    10
      src/tile_source.rs

+ 0
- 1
src/config.rs Wyświetl plik

@@ -1,4 +1,3 @@
1
-use serde_derive;
2 1
 use std::collections::BTreeMap;
3 2
 use std::fs::File;
4 3
 use std::io::Read;

+ 72
- 4
src/coord.rs Wyświetl plik

@@ -29,7 +29,7 @@ impl MapCoord {
29 29
     }
30 30
 
31 31
     //TODO differ between normalized and not normalized tiles
32
-    pub fn on_tile_at_zoom(&self, zoom: u32) -> Tile {
32
+    pub fn on_tile_at_zoom(&self, zoom: u32) -> TileCoord {
33 33
         let zoom_factor = f64::powi(2.0, zoom as i32);
34 34
         let ix = (self.x * zoom_factor).floor() as i32;
35 35
         let iy = (self.y * zoom_factor).floor() as i32;
@@ -37,10 +37,10 @@ impl MapCoord {
37 37
         let x = ix;
38 38
         let y = iy;
39 39
 
40
-        Tile {
40
+        TileCoord {
41 41
             zoom: zoom,
42
-            tile_x: x,
43
-            tile_y: y,
42
+            x: x,
43
+            y: y,
44 44
         }
45 45
     }
46 46
 
@@ -102,3 +102,71 @@ pub struct ScreenRect {
102 102
     pub width: f64,
103 103
     pub height: f64,
104 104
 }
105
+
106
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
107
+pub struct TileCoord {
108
+    pub zoom: u32,
109
+    pub x: i32,
110
+    pub y: i32,
111
+}
112
+
113
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
114
+pub struct SubTileCoord {
115
+    pub size: u32,
116
+    pub x: u32,
117
+    pub y: u32,
118
+}
119
+
120
+impl TileCoord {
121
+    pub fn new(zoom: u32, x: i32, y: i32) -> TileCoord {
122
+        TileCoord {
123
+            zoom: zoom,
124
+            x: Self::normalize_coord(x, zoom),
125
+            y: y,
126
+        }
127
+    }
128
+
129
+    pub fn is_on_planet(&self) -> bool {
130
+        let num_tiles = Self::get_zoom_level_tiles(self.zoom);
131
+        self.y >= 0 && self.y < num_tiles &&
132
+        self.x >= 0 && self.x < num_tiles
133
+    }
134
+
135
+    pub fn map_coord(&self) -> MapCoord {
136
+        let inv_zoom_factor = f64::powi(2.0, -(self.zoom as i32));
137
+        MapCoord::new(f64::from(self.x) * inv_zoom_factor, f64::from(self.y) * inv_zoom_factor)
138
+    }
139
+
140
+    pub fn parent(&self, distance: u32) -> Option<(TileCoord, SubTileCoord)> {
141
+        if distance > self.zoom {
142
+            None
143
+        } else {
144
+            let scale = u32::pow(2, distance);
145
+
146
+            Some((
147
+                TileCoord {
148
+                    zoom: self.zoom - distance,
149
+                    x: self.x / scale as i32,
150
+                    y: self.y / scale as i32,
151
+                },
152
+                SubTileCoord {
153
+                    size: scale,
154
+                    x: (Self::normalize_coord(self.x, self.zoom) as u32) % scale,
155
+                    y: (Self::normalize_coord(self.y, self.zoom) as u32) % scale,
156
+                },
157
+            ))
158
+        }
159
+    }
160
+
161
+    #[inline]
162
+    fn normalize_coord(coord: i32, zoom: u32) -> i32 {
163
+        let max = Self::get_zoom_level_tiles(zoom);
164
+        ((coord % max) + max) % max
165
+    }
166
+
167
+    #[inline]
168
+    pub fn get_zoom_level_tiles(zoom: u32) -> i32 {
169
+        //TODO throw error when zoom too big
170
+        i32::pow(2, zoom)
171
+    }
172
+}

+ 6
- 7
src/map_view.rs Wyświetl plik

@@ -1,5 +1,4 @@
1
-use coord::{MapCoord, ScreenCoord, ScreenRect};
2
-use tile::Tile;
1
+use coord::{MapCoord, ScreenCoord, ScreenRect, TileCoord};
3 2
 
4 3
 
5 4
 #[derive(Clone, Debug)]
@@ -13,7 +12,7 @@ pub struct MapView {
13 12
 
14 13
 #[derive(Clone, Debug)]
15 14
 pub struct VisibleTile {
16
-    pub tile: Tile,
15
+    pub tile: TileCoord,
17 16
     pub rect: ScreenRect,
18 17
 }
19 18
 
@@ -49,7 +48,7 @@ impl MapView {
49 48
         }
50 49
     }
51 50
 
52
-    pub fn tile_screen_position(&self, tile: &Tile) -> ScreenCoord {
51
+    pub fn tile_screen_position(&self, tile: &TileCoord) -> ScreenCoord {
53 52
         self.map_to_screen_coord(tile.map_coord())
54 53
     }
55 54
 
@@ -63,8 +62,8 @@ impl MapView {
63 62
             top_left_tile_screen_coord.snap_to_pixel();
64 63
         }
65 64
 
66
-        let start_tile_x = top_left_tile.tile_x;
67
-        let start_tile_y = top_left_tile.tile_y;
65
+        let start_tile_x = top_left_tile.x;
66
+        let start_tile_y = top_left_tile.y;
68 67
         let num_tiles_x = ((self.width - top_left_tile_screen_coord.x) / tile_screen_size).ceil().max(0.0) as i32;
69 68
         let num_tiles_y = ((self.height - top_left_tile_screen_coord.y) / tile_screen_size).ceil().max(0.0) as i32;
70 69
 
@@ -72,7 +71,7 @@ impl MapView {
72 71
 
73 72
         for y in 0..num_tiles_y {
74 73
             for x in 0..num_tiles_x {
75
-                let t = Tile::new(uzoom, start_tile_x + x, start_tile_y + y);
74
+                let t = TileCoord::new(uzoom, start_tile_x + x, start_tile_y + y);
76 75
                 if t.is_on_planet() {
77 76
                     visible_tiles.push(
78 77
                         VisibleTile {

+ 4
- 65
src/tile.rs Wyświetl plik

@@ -1,70 +1,9 @@
1
-use coord::MapCoord;
1
+use coord::TileCoord;
2
+use tile_source::TileSourceId;
2 3
 
3 4
 
4 5
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
5 6
 pub struct Tile {
6
-    pub zoom: u32,
7
-    pub tile_x: i32,
8
-    pub tile_y: i32,
9
-}
10
-
11
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
12
-pub struct SubTileCoord {
13
-    pub size: u32,
14
-    pub x: u32,
15
-    pub y: u32,
16
-}
17
-
18
-impl Tile {
19
-    pub fn new(zoom: u32, tile_x: i32, tile_y: i32) -> Tile {
20
-        Tile {
21
-            zoom: zoom,
22
-            tile_x: Self::normalize_coord(tile_x, zoom),
23
-            tile_y: tile_y,
24
-        }
25
-    }
26
-
27
-    pub fn is_on_planet(&self) -> bool {
28
-        let num_tiles = Self::get_zoom_level_tiles(self.zoom);
29
-        self.tile_y >= 0 && self.tile_y < num_tiles &&
30
-        self.tile_x >= 0 && self.tile_x < num_tiles
31
-    }
32
-
33
-    pub fn map_coord(&self) -> MapCoord {
34
-        let inv_zoom_factor = f64::powi(2.0, -(self.zoom as i32));
35
-        MapCoord::new(f64::from(self.tile_x) * inv_zoom_factor, f64::from(self.tile_y) * inv_zoom_factor)
36
-    }
37
-
38
-    pub fn parent(&self, distance: u32) -> Option<(Tile, SubTileCoord)> {
39
-        if distance > self.zoom {
40
-            None
41
-        } else {
42
-            let scale = u32::pow(2, distance);
43
-
44
-            Some((
45
-                Tile {
46
-                    zoom: self.zoom - distance,
47
-                    tile_x: self.tile_x / scale as i32,
48
-                    tile_y: self.tile_y / scale as i32,
49
-                },
50
-                SubTileCoord {
51
-                    size: scale,
52
-                    x: (Self::normalize_coord(self.tile_x, self.zoom) as u32) % scale,
53
-                    y: (Self::normalize_coord(self.tile_y, self.zoom) as u32) % scale,
54
-                },
55
-            ))
56
-        }
57
-    }
58
-
59
-    #[inline]
60
-    fn normalize_coord(coord: i32, zoom: u32) -> i32 {
61
-        let max = Self::get_zoom_level_tiles(zoom);
62
-        ((coord % max) + max) % max
63
-    }
64
-
65
-    #[inline]
66
-    pub fn get_zoom_level_tiles(zoom: u32) -> i32 {
67
-        //TODO throw error when zoom too big
68
-        i32::pow(2, zoom)
69
-    }
7
+    pub coord: TileCoord,
8
+    pub source_id: TileSourceId,
70 9
 }

+ 6
- 6
src/tile_cache.rs Wyświetl plik

@@ -1,19 +1,19 @@
1 1
 use image;
2 2
 use linked_hash_map::{Entry, LinkedHashMap};
3
-use tile::Tile;
3
+use coord::TileCoord;
4 4
 use tile_loader::TileLoader;
5 5
 use tile_source::TileSource;
6 6
 
7 7
 
8 8
 pub struct TileCache {
9 9
     loader: TileLoader,
10
-    map: LinkedHashMap<Tile, image::DynamicImage>,
10
+    map: LinkedHashMap<TileCoord, image::DynamicImage>,
11 11
     max_tiles: usize,
12 12
 }
13 13
 
14 14
 impl TileCache {
15 15
     pub fn new<F>(new_tile_func: F) -> Self
16
-        where F: Fn(Tile) + Sync + Send + 'static,
16
+        where F: Fn(TileCoord) + Sync + Send + 'static,
17 17
     {
18 18
         TileCache {
19 19
             loader: TileLoader::new(move |tile| {
@@ -26,7 +26,7 @@ impl TileCache {
26 26
 
27 27
     pub fn get_sync(
28 28
         &mut self,
29
-        tile: Tile,
29
+        tile: TileCoord,
30 30
         source: &TileSource,
31 31
         write_to_file: bool,
32 32
         ) -> Option<&image::DynamicImage>
@@ -51,7 +51,7 @@ impl TileCache {
51 51
 
52 52
     pub fn get_async(
53 53
         &mut self,
54
-        tile: Tile,
54
+        tile: TileCoord,
55 55
         source: &TileSource,
56 56
         write_to_file: bool,
57 57
         ) -> Option<&image::DynamicImage>
@@ -79,7 +79,7 @@ impl TileCache {
79 79
     }
80 80
 
81 81
     // Return a tile from the cache but do not use TileLoader.
82
-    pub fn lookup(&mut self, tile: Tile, source: &TileSource) -> Option<&image::DynamicImage> {
82
+    pub fn lookup(&mut self, tile: TileCoord, source: &TileSource) -> Option<&image::DynamicImage> {
83 83
         //TODO Return the value from get_refresh with borrowck agreeing that this is OK.
84 84
         self.map.get_refresh(&tile);
85 85
 

+ 4
- 5
src/tile_cache_gl.rs Wyświetl plik

@@ -1,10 +1,9 @@
1
-use coord::ScreenRect;
1
+use coord::{ScreenRect, SubTileCoord, TileCoord};
2 2
 use linked_hash_map::LinkedHashMap;
3 3
 use map_view::VisibleTile;
4 4
 use std::collections::HashMap;
5 5
 use std::collections::hash_map::Entry;
6 6
 use texture::Texture;
7
-use tile::{Tile, SubTileCoord};
8 7
 use tile_cache::TileCache;
9 8
 use tile_source::TileSource;
10 9
 
@@ -38,8 +37,8 @@ pub struct TexturedVisibleTile {
38 37
 pub struct TileCacheGl<'a> {
39 38
     texture: Texture<'a>,
40 39
     tile_size: u32,
41
-    slots_lru: LinkedHashMap<CacheSlot, Option<Tile>>, // LRU cache of slots
42
-    tile_to_slot: HashMap<Tile, CacheSlot>,
40
+    slots_lru: LinkedHashMap<CacheSlot, Option<TileCoord>>, // LRU cache of slots
41
+    tile_to_slot: HashMap<TileCoord, CacheSlot>,
43 42
 }
44 43
 
45 44
 impl<'a> TileCacheGl<'a> {
@@ -70,7 +69,7 @@ impl<'a> TileCacheGl<'a> {
70 69
         CacheSlot { x: 0, y: 0 }
71 70
     }
72 71
 
73
-    pub fn store(&mut self, tile: Tile, source: &TileSource, cache: &mut TileCache, load: bool) -> Option<CacheSlot> {
72
+    pub fn store(&mut self, tile: TileCoord, source: &TileSource, cache: &mut TileCache, load: bool) -> Option<CacheSlot> {
74 73
         let mut remove_tile = None;
75 74
 
76 75
         let slot = match self.tile_to_slot.entry(tile) {

+ 23
- 23
src/tile_loader.rs Wyświetl plik

@@ -1,3 +1,4 @@
1
+use coord::TileCoord;
1 2
 use image::DynamicImage;
2 3
 use image;
3 4
 use reqwest::Client;
@@ -7,8 +8,7 @@ use std::io::Write;
7 8
 use std::path::{Path, PathBuf};
8 9
 use std::sync::mpsc;
9 10
 use std::thread;
10
-use tile::Tile;
11
-use tile_source::TileSource;
11
+use tile_source::{TileSource, TileSourceId};
12 12
 
13 13
 
14 14
 //TODO remember failed loading attempts
@@ -17,15 +17,14 @@ use tile_source::TileSource;
17 17
 pub struct TileLoader {
18 18
     client: Option<Client>,
19 19
     join_handle: thread::JoinHandle<()>,
20
-    request_tx: mpsc::Sender<(Tile, String, PathBuf, bool)>,
21
-    result_rx: mpsc::Receiver<(Tile, Option<DynamicImage>)>,
22
-    //TODO store source together with tile in pending
23
-    pending: HashSet<Tile>,
20
+    request_tx: mpsc::Sender<(TileCoord, TileSourceId, String, PathBuf, bool)>,
21
+    result_rx: mpsc::Receiver<(TileCoord, TileSourceId, Option<DynamicImage>)>,
22
+    pending: HashSet<(TileCoord, TileSourceId)>,
24 23
 }
25 24
 
26 25
 impl TileLoader {
27 26
     pub fn new<F>(notice_func: F) -> Self
28
-        where F: Fn(Tile) + Sync + Send + 'static,
27
+        where F: Fn(TileCoord) + Sync + Send + 'static,
29 28
     {
30 29
         let (request_tx, request_rx) = mpsc::channel();
31 30
         let (result_tx, result_rx) = mpsc::channel();
@@ -40,18 +39,18 @@ impl TileLoader {
40 39
     }
41 40
 
42 41
     fn work<F>(
43
-        request_rx: mpsc::Receiver<(Tile, String, PathBuf, bool)>,
44
-        result_tx: mpsc::Sender<(Tile, Option<DynamicImage>)>,
42
+        request_rx: mpsc::Receiver<(TileCoord, TileSourceId, String, PathBuf, bool)>,
43
+        result_tx: mpsc::Sender<(TileCoord, TileSourceId, Option<DynamicImage>)>,
45 44
         notice_func: F,
46 45
     )
47
-        where F: Fn(Tile) + Sync + Send + 'static,
46
+        where F: Fn(TileCoord) + Sync + Send + 'static,
48 47
     {
49 48
         let mut client_opt = None;
50
-        while let Ok((tile, url, path, write_to_file)) = request_rx.recv() {
49
+        while let Ok((tile, source_id, url, path, write_to_file)) = request_rx.recv() {
51 50
             println!("work {:?}", tile);
52 51
             match image::open(&path) {
53 52
                 Ok(img) => {
54
-                    result_tx.send((tile, Some(img))).unwrap();
53
+                    result_tx.send((tile, source_id, Some(img))).unwrap();
55 54
                     notice_func(tile);
56 55
                     continue;
57 56
                 },
@@ -67,7 +66,7 @@ impl TileLoader {
67 66
                             let mut buf: Vec<u8> = vec![];
68 67
                             response.copy_to(&mut buf).unwrap();
69 68
                             if let Ok(img) = image::load_from_memory(&buf) {
70
-                                result_tx.send((tile, Some(img))).unwrap();
69
+                                result_tx.send((tile, source_id, Some(img))).unwrap();
71 70
                                 notice_func(tile);
72 71
 
73 72
                                 if write_to_file {
@@ -81,19 +80,20 @@ impl TileLoader {
81 80
                     }
82 81
                 },
83 82
             }
84
-            result_tx.send((tile, None)).unwrap();
83
+            result_tx.send((tile, source_id, None)).unwrap();
85 84
         }
86 85
     }
87 86
 
88
-    pub fn async_request(&mut self, tile: Tile, source: &TileSource, write_to_file: bool) {
87
+    pub fn async_request(&mut self, tile: TileCoord, source: &TileSource, write_to_file: bool) {
89 88
         if tile.zoom > source.max_tile_zoom() {
90 89
             return;
91 90
         }
92 91
 
93
-        if !self.pending.contains(&tile) {
94
-            self.pending.insert(tile);
92
+        if !self.pending.contains(&(tile, source.id())) {
93
+            self.pending.insert((tile, source.id()));
95 94
             self.request_tx.send((
96 95
                 tile,
96
+                source.id(),
97 97
                 source.remote_tile_url(tile),
98 98
                 source.local_tile_path(tile),
99 99
                 write_to_file
@@ -101,21 +101,21 @@ impl TileLoader {
101 101
         }
102 102
     }
103 103
 
104
-    pub fn async_result(&mut self) -> Option<(Tile, DynamicImage)> {
104
+    pub fn async_result(&mut self) -> Option<(TileCoord, DynamicImage)> {
105 105
         match self.result_rx.try_recv() {
106 106
             Err(_) => None,
107
-            Ok((tile, None)) => {
108
-                self.pending.remove(&tile);
107
+            Ok((tile, source_id, None)) => {
108
+                self.pending.remove(&(tile, source_id));
109 109
                 None
110 110
             },
111
-            Ok((tile, Some(img))) => {
112
-                self.pending.remove(&tile);
111
+            Ok((tile, source_id, Some(img))) => {
112
+                self.pending.remove(&(tile, source_id));
113 113
                 Some((tile, img))
114 114
             },
115 115
         }
116 116
     }
117 117
 
118
-    pub fn get_sync(&mut self, tile: Tile, source: &TileSource, write_to_file: bool) -> Option<DynamicImage> {
118
+    pub fn get_sync(&mut self, tile: TileCoord, source: &TileSource, write_to_file: bool) -> Option<DynamicImage> {
119 119
         match image::open(source.local_tile_path(tile)) {
120 120
             Ok(img) => {
121 121
                 Some(img)

+ 9
- 10
src/tile_source.rs Wyświetl plik

@@ -1,4 +1,4 @@
1
-use tile::Tile;
1
+use coord::TileCoord;
2 2
 use std::path::{Path, PathBuf};
3 3
 
4 4
 
@@ -10,7 +10,7 @@ pub struct TileSource {
10 10
     max_zoom: u32,
11 11
 }
12 12
 
13
-#[derive(Copy, Clone, Debug)]
13
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
14 14
 pub struct TileSourceId {
15 15
     id: u32,
16 16
 }
@@ -36,17 +36,16 @@ impl TileSource {
36 36
         }
37 37
     }
38 38
 
39
-    pub fn local_tile_path(&self, tile: Tile) -> PathBuf {
40
-
39
+    pub fn local_tile_path(&self, tile: TileCoord) -> PathBuf {
41 40
         let mut path = PathBuf::from(&self.directory);
42 41
         path.push(tile.zoom.to_string());
43
-        path.push(tile.tile_x.to_string());
44
-        path.push(tile.tile_y.to_string() + ".png");
42
+        path.push(tile.x.to_string());
43
+        path.push(tile.y.to_string() + ".png");
45 44
 
46 45
         path
47 46
     }
48 47
 
49
-    pub fn remote_tile_url(&self, tile: Tile) -> String {
48
+    pub fn remote_tile_url(&self, tile: TileCoord) -> String {
50 49
         Self::fill_template(&self.url_template, tile)
51 50
     }
52 51
 
@@ -54,9 +53,9 @@ impl TileSource {
54 53
         self.max_zoom
55 54
     }
56 55
 
57
-    fn fill_template(template: &str, tile: Tile) -> String {
58
-        let x_str = tile.tile_x.to_string();
59
-        let y_str = tile.tile_y.to_string();
56
+    fn fill_template(template: &str, tile: TileCoord) -> String {
57
+        let x_str = tile.x.to_string();
58
+        let y_str = tile.y.to_string();
60 59
         let z_str = tile.zoom.to_string();
61 60
 
62 61
         //let len = (template.len() + x_str.len() + y_str.len() + z_str.len()).saturating_sub(9);