A simple map viewer

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. use ::std::ffi::CStr;
  2. use buffer::{Buffer, DrawMode};
  3. use cgmath::{Matrix3, Point2, Transform, vec2, vec3};
  4. use context::Context;
  5. use coord::{MapCoord, ScreenRect};
  6. use image;
  7. use map_view::MapView;
  8. use mercator_view::MercatorView;
  9. use program::Program;
  10. use texture::Texture;
  11. use vertex_attrib::VertexAttribParams;
  12. #[derive(Debug)]
  13. pub struct MarkerLayer {
  14. buffer: Buffer,
  15. program: Program,
  16. texture: Texture,
  17. positions: Vec<MapCoord>,
  18. }
  19. impl MarkerLayer {
  20. pub fn new(cx: &mut Context) -> MarkerLayer {
  21. let buffer = Buffer::new(cx, &[], 0);
  22. cx.bind_buffer(buffer.id());
  23. check_gl_errors!(cx);
  24. let mut program = Program::new(
  25. cx,
  26. include_bytes!("../shader/marker.vert"),
  27. include_bytes!("../shader/marker.frag"),
  28. ).unwrap();
  29. check_gl_errors!(cx);
  30. //TODO Create textures for higher DPI factors / use mipmaps
  31. let texture = {
  32. let img = image::load_from_memory(
  33. include_bytes!("../img/marker.png"),
  34. ).unwrap();
  35. Texture::new(cx, &img).unwrap()
  36. };
  37. program.add_texture(cx, &texture, CStr::from_bytes_with_nul(b"tex\0").unwrap());
  38. program.add_attribute(
  39. cx,
  40. CStr::from_bytes_with_nul(b"position\0").unwrap(),
  41. &VertexAttribParams::new(2, 4, 0)
  42. );
  43. program.add_attribute(
  44. cx,
  45. CStr::from_bytes_with_nul(b"tex_coord\0").unwrap(),
  46. &VertexAttribParams::new(2, 4, 2)
  47. );
  48. MarkerLayer {
  49. buffer,
  50. program,
  51. texture,
  52. positions: vec![],
  53. }
  54. }
  55. pub fn is_empty(&self) -> bool {
  56. self.positions.is_empty()
  57. }
  58. pub fn add_marker(&mut self, map_coord: MapCoord) {
  59. self.positions.push(map_coord);
  60. }
  61. // Has to be called once before one or multiple calls to `draw`.
  62. pub fn prepare_draw(&mut self, cx: &mut Context) {
  63. cx.set_active_texture_unit(self.texture.unit());
  64. self.program.enable_vertex_attribs(cx);
  65. self.program.set_vertex_attribs(cx, &self.buffer);
  66. }
  67. pub fn draw_mercator(
  68. &mut self,
  69. cx: &mut Context,
  70. map_view: &MapView,
  71. dpi_factor: f64,
  72. snap_to_pixel: bool
  73. ) {
  74. let mut vertex_data: Vec<f32> = vec![];
  75. let marker_size = vec2::<f64>(40.0, 50.0) * dpi_factor;
  76. let marker_offset = vec2::<f64>(-20.0, -50.0) * dpi_factor;
  77. let scale_x = 2.0 / map_view.width as f32;
  78. let scale_y = -2.0 / map_view.height as f32;
  79. let tex_mat: Matrix3<f32> = Matrix3::from_cols(
  80. vec3(marker_size.x as f32, 0.0, 0.0),
  81. vec3(0.0, marker_size.y as f32, 0.0),
  82. vec3(marker_offset.x as f32, marker_offset.y as f32, 1.0),
  83. );
  84. let screen_mat: Matrix3<f32> = Matrix3::from_cols(
  85. vec3(scale_x, 0.0, 0.0),
  86. vec3(0.0, scale_y, 0.0),
  87. vec3(-1.0, 1.0, 1.0),
  88. );
  89. let t1 = Point2::new(0.0f32, 0.0);
  90. let t2 = Point2::new(1.0f32, 0.0);
  91. let t3 = Point2::new(1.0f32, 1.0);
  92. let t4 = Point2::new(0.0f32, 1.0);
  93. let visible_rect = ScreenRect {
  94. x: -(marker_offset.x + marker_size.x),
  95. y: -(marker_offset.y + marker_size.y),
  96. width: map_view.width + marker_size.x,
  97. height: map_view.height + marker_size.y,
  98. };
  99. for map_pos in &self.positions {
  100. let screen_pos = {
  101. let mut sp = MercatorView::map_to_screen_coord(map_view, *map_pos);
  102. if snap_to_pixel {
  103. let topleft = MercatorView::map_to_screen_coord(map_view, MapCoord::new(0.0, 0.0));
  104. let mut snapped = topleft;
  105. snapped.snap_to_pixel();
  106. sp.x += snapped.x - topleft.x;
  107. sp.y += snapped.y - topleft.y;
  108. }
  109. sp
  110. };
  111. if !screen_pos.is_inside(&visible_rect) {
  112. continue;
  113. }
  114. let trans_mat: Matrix3<f32> = Matrix3::from_cols(
  115. vec3(0.0, 0.0, 0.0),
  116. vec3(0.0, 0.0, 0.0),
  117. vec3(screen_pos.x as f32, screen_pos.y as f32, 0.0),
  118. );
  119. let mat: Matrix3<f32> = screen_mat * (tex_mat + trans_mat);
  120. let p1: Point2<f32> = mat.transform_point(t1);
  121. let p2: Point2<f32> = mat.transform_point(t2);
  122. let p3: Point2<f32> = mat.transform_point(t3);
  123. let p4: Point2<f32> = mat.transform_point(t4);
  124. vertex_data.extend::<&[f32; 2]>(p1.as_ref());
  125. vertex_data.extend::<&[f32; 2]>(t1.as_ref());
  126. vertex_data.extend::<&[f32; 2]>(p2.as_ref());
  127. vertex_data.extend::<&[f32; 2]>(t2.as_ref());
  128. vertex_data.extend::<&[f32; 2]>(p3.as_ref());
  129. vertex_data.extend::<&[f32; 2]>(t3.as_ref());
  130. vertex_data.extend::<&[f32; 2]>(p1.as_ref());
  131. vertex_data.extend::<&[f32; 2]>(t1.as_ref());
  132. vertex_data.extend::<&[f32; 2]>(p3.as_ref());
  133. vertex_data.extend::<&[f32; 2]>(t3.as_ref());
  134. vertex_data.extend::<&[f32; 2]>(p4.as_ref());
  135. vertex_data.extend::<&[f32; 2]>(t4.as_ref());
  136. }
  137. self.buffer.set_data(cx, &vertex_data, vertex_data.len() / 4);
  138. self.buffer.draw(cx, &self.program, DrawMode::Triangles);
  139. }
  140. }