A simple map viewer

map_view_gl.rs 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. use atmos_layer::AtmosLayer;
  2. use context::Context;
  3. use coord::{MapCoord, ScreenCoord};
  4. use map_view::{MapView, MIN_ZOOM_LEVEL, MAX_ZOOM_LEVEL};
  5. use marker_layer::MarkerLayer;
  6. use mercator_tile_layer::MercatorTileLayer;
  7. use mercator_view::MercatorView;
  8. use ortho_tile_layer::OrthoTileLayer;
  9. use orthografic_view::OrthograficView;
  10. use projection::Projection;
  11. use session::Session;
  12. use texture::{Texture, TextureFormat};
  13. use tile_atlas::TileAtlas;
  14. use tile_cache::TileCache;
  15. use tile_source::TileSource;
  16. #[derive(Debug)]
  17. pub struct MapViewGl {
  18. map_view: MapView,
  19. /// Size in physical pixels
  20. viewport_size: (u32, u32),
  21. dpi_factor: f64,
  22. tile_cache: TileCache,
  23. tile_atlas: TileAtlas,
  24. mercator_tile_layer: MercatorTileLayer,
  25. marker_layer: MarkerLayer,
  26. ortho_tile_layer: OrthoTileLayer,
  27. atmos_layer: AtmosLayer,
  28. projection: Projection,
  29. show_atmos: bool,
  30. last_draw_type: DrawType,
  31. }
  32. #[derive(Debug, Eq, PartialEq)]
  33. enum DrawType {
  34. Null,
  35. Tiles,
  36. Markers,
  37. OrthoTiles,
  38. Atmos,
  39. }
  40. impl MapViewGl {
  41. pub fn new<F>(
  42. cx: &mut Context,
  43. initial_size: (u32, u32),
  44. dpi_factor: f64,
  45. update_func: F,
  46. use_network: bool,
  47. use_async: bool,
  48. ) -> MapViewGl
  49. where F: Fn() + Sync + Send + 'static,
  50. {
  51. let tile_size = 256;
  52. let map_view = MercatorView::initial_map_view(
  53. f64::from(initial_size.0),
  54. f64::from(initial_size.1),
  55. tile_size,
  56. );
  57. let atlas_size = {
  58. let default_size = 2048;
  59. let max_size = cx.max_texture_size() as u32;
  60. if default_size <= max_size {
  61. default_size
  62. } else {
  63. if tile_size * 3 > max_size {
  64. error!("maximal tile size ({}) is too small", max_size);
  65. }
  66. max_size
  67. }
  68. };
  69. let atlas_tex = Texture::empty(cx, atlas_size, atlas_size, TextureFormat::Rgb8);
  70. check_gl_errors!(cx);
  71. let tile_atlas = TileAtlas::new(cx, atlas_tex, tile_size, use_async);
  72. let mercator_tile_layer = MercatorTileLayer::new(cx, &tile_atlas);
  73. let ortho_tile_layer = OrthoTileLayer::new(cx, &tile_atlas);
  74. let atmos_layer = AtmosLayer::new(cx);
  75. MapViewGl {
  76. map_view,
  77. viewport_size: initial_size,
  78. dpi_factor,
  79. tile_cache: TileCache::new(move |_tile| update_func(), use_network),
  80. tile_atlas,
  81. mercator_tile_layer,
  82. marker_layer: MarkerLayer::new(cx),
  83. ortho_tile_layer,
  84. atmos_layer,
  85. projection: Projection::Mercator,
  86. show_atmos: false,
  87. last_draw_type: DrawType::Null,
  88. }
  89. }
  90. pub fn set_viewport_size(&mut self, cx: &mut Context, width: u32, height: u32) {
  91. self.viewport_size = (width, height);
  92. self.map_view.set_size(f64::from(width), f64::from(height));
  93. cx.set_viewport(0, 0, width, height);
  94. }
  95. pub fn set_dpi_factor(&mut self, dpi_factor: f64) {
  96. self.dpi_factor = dpi_factor;
  97. }
  98. pub fn add_marker(&mut self, map_coord: MapCoord) {
  99. self.marker_layer.add_marker(map_coord);
  100. }
  101. pub fn map_covers_viewport(&self) -> bool {
  102. match self.projection {
  103. Projection::Mercator => MercatorView::covers_viewport(&self.map_view),
  104. Projection::Orthografic => OrthograficView::covers_viewport(&self.map_view),
  105. }
  106. }
  107. pub fn increase_atlas_size(&mut self, cx: &mut Context) -> Result<(), ()> {
  108. self.tile_atlas.double_texture_size(cx)
  109. }
  110. pub fn toggle_projection(&mut self) {
  111. self.projection = match self.projection {
  112. Projection::Mercator => Projection::Orthografic,
  113. Projection::Orthografic => Projection::Mercator,
  114. };
  115. }
  116. pub fn toggle_atmosphere(&mut self) {
  117. self.show_atmos = !self.show_atmos;
  118. }
  119. fn draw_mercator_tiles(&mut self, cx: &mut Context, source: &TileSource, snap_to_pixel: bool)
  120. -> Result<usize, usize>
  121. {
  122. if self.last_draw_type != DrawType::Tiles {
  123. self.last_draw_type = DrawType::Tiles;
  124. self.mercator_tile_layer.prepare_draw(cx, &self.tile_atlas);
  125. }
  126. self.mercator_tile_layer.draw(
  127. cx,
  128. &self.map_view,
  129. source,
  130. &mut self.tile_cache,
  131. &mut self.tile_atlas,
  132. snap_to_pixel
  133. )
  134. }
  135. fn draw_mercator_marker(&mut self, cx: &mut Context, snap_to_pixel: bool) {
  136. if self.last_draw_type != DrawType::Markers {
  137. self.last_draw_type = DrawType::Markers;
  138. self.marker_layer.prepare_draw(cx);
  139. }
  140. self.marker_layer.draw_mercator(
  141. cx,
  142. &self.map_view,
  143. self.dpi_factor,
  144. snap_to_pixel,
  145. );
  146. }
  147. fn draw_ortho_marker(&mut self, cx: &mut Context) {
  148. if self.last_draw_type != DrawType::Markers {
  149. self.last_draw_type = DrawType::Markers;
  150. self.marker_layer.prepare_draw(cx);
  151. }
  152. self.marker_layer.draw_ortho(
  153. cx,
  154. &self.map_view,
  155. self.dpi_factor,
  156. );
  157. }
  158. fn draw_ortho_tiles(&mut self, cx: &mut Context, source: &TileSource) -> Result<usize, usize> {
  159. if self.last_draw_type != DrawType::OrthoTiles {
  160. self.last_draw_type = DrawType::OrthoTiles;
  161. self.ortho_tile_layer.prepare_draw(cx, &self.tile_atlas);
  162. }
  163. self.ortho_tile_layer.draw(
  164. cx,
  165. &self.map_view,
  166. source,
  167. &mut self.tile_cache,
  168. &mut self.tile_atlas,
  169. )
  170. }
  171. fn draw_atmos(&mut self, cx: &mut Context) {
  172. if self.last_draw_type != DrawType::Atmos {
  173. self.last_draw_type = DrawType::Atmos;
  174. self.atmos_layer.prepare_draw(cx);
  175. }
  176. self.atmos_layer.draw(
  177. cx,
  178. &self.map_view,
  179. )
  180. }
  181. /// Returns `Err` when tile cache is too small for this view.
  182. /// Returns the number of OpenGL draw calls, which can be decreased to `1` by increasing the
  183. /// size of the tile atlas.
  184. pub fn draw(&mut self, cx: &mut Context, source: &TileSource) -> Result<usize, usize> {
  185. // only snap to pixel grid if zoom has integral value
  186. let snap_to_pixel = (self.map_view.zoom - (self.map_view.zoom + 0.5).floor()).abs() < 1e-10;
  187. match self.projection {
  188. Projection::Mercator => {
  189. let ret = self.draw_mercator_tiles(cx, source, snap_to_pixel);
  190. if !self.marker_layer.is_empty() {
  191. self.draw_mercator_marker(cx, snap_to_pixel);
  192. }
  193. ret
  194. },
  195. Projection::Orthografic => {
  196. let ret = self.draw_ortho_tiles(cx, source);
  197. if !self.marker_layer.is_empty() {
  198. self.draw_ortho_marker(cx);
  199. }
  200. if self.show_atmos {
  201. self.draw_atmos(cx);
  202. }
  203. ret
  204. },
  205. }
  206. }
  207. pub fn zoom(&mut self, zoom_delta: f64) {
  208. self.map_view.zoom(zoom_delta);
  209. }
  210. pub fn step_zoom(&mut self, steps: i32, step_size: f64) {
  211. self.map_view.step_zoom(steps, step_size);
  212. }
  213. pub fn zoom_at(&mut self, pos: ScreenCoord, zoom_delta: f64) {
  214. match self.projection {
  215. Projection::Mercator => {
  216. if self.map_view.zoom + zoom_delta < MIN_ZOOM_LEVEL {
  217. MercatorView::set_zoom_at(&mut self.map_view, pos, MIN_ZOOM_LEVEL);
  218. } else if self.map_view.zoom + zoom_delta > MAX_ZOOM_LEVEL {
  219. MercatorView::set_zoom_at(&mut self.map_view, pos, MAX_ZOOM_LEVEL);
  220. } else {
  221. MercatorView::zoom_at(&mut self.map_view, pos, zoom_delta);
  222. }
  223. self.map_view.center.normalize_xy();
  224. },
  225. Projection::Orthografic => {
  226. if self.map_view.zoom + zoom_delta < MIN_ZOOM_LEVEL {
  227. OrthograficView::set_zoom_at(&mut self.map_view, pos, MIN_ZOOM_LEVEL);
  228. } else if self.map_view.zoom + zoom_delta > MAX_ZOOM_LEVEL {
  229. OrthograficView::set_zoom_at(&mut self.map_view, pos, MAX_ZOOM_LEVEL);
  230. } else {
  231. OrthograficView::zoom_at(&mut self.map_view, pos, zoom_delta);
  232. }
  233. },
  234. }
  235. }
  236. pub fn change_tile_zoom_offset(&mut self, delta_offset: f64) {
  237. let offset = self.map_view.tile_zoom_offset;
  238. self.map_view.set_tile_zoom_offset(offset + delta_offset);
  239. }
  240. //TODO Make sure to use physical pixel deltas
  241. pub fn move_pixel(&mut self, delta_x: f64, delta_y: f64) {
  242. //TODO implement for OrthograficView
  243. MercatorView::move_pixel(&mut self.map_view, delta_x, delta_y);
  244. self.map_view.center.normalize_xy();
  245. }
  246. pub fn restore_session(&mut self, session: &Session) {
  247. self.map_view.center = session.view_center;
  248. self.map_view.center.normalize_xy();
  249. self.map_view.zoom = session.zoom
  250. .max(MIN_ZOOM_LEVEL)
  251. .min(MAX_ZOOM_LEVEL);
  252. self.projection = session.projection;
  253. }
  254. pub fn to_session(&self) -> Session {
  255. Session {
  256. view_center: self.map_view.center,
  257. zoom: self.map_view.zoom,
  258. tile_source: None,
  259. projection: self.projection,
  260. }
  261. }
  262. }