From 1c906532511083fded0d7ec5dc82a445a645d157 Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Sat, 22 Feb 2025 21:13:08 +0100 Subject: [PATCH 1/2] position module --- walkers/src/center.rs | 5 ++- walkers/src/lib.rs | 4 ++- walkers/src/map.rs | 49 ++------------------------ walkers/src/mercator.rs | 36 ++++--------------- walkers/src/position.rs | 78 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 79 deletions(-) create mode 100644 walkers/src/position.rs diff --git a/walkers/src/center.rs b/walkers/src/center.rs index 440888d4..79f1f36c 100644 --- a/walkers/src/center.rs +++ b/walkers/src/center.rs @@ -1,6 +1,9 @@ use egui::{Response, Vec2}; -use crate::{map::AdjustedPosition, mercator::Pixels, Position}; +use crate::{ + position::{AdjustedPosition, Pixels}, + Position, +}; /// Position at the map's center. Initially, the map follows `my_position` argument which typically /// is meant to be fed by a GPS sensor or other geo-localization method. If user drags the map, diff --git a/walkers/src/lib.rs b/walkers/src/lib.rs index aaee5eba..904748d4 100644 --- a/walkers/src/lib.rs +++ b/walkers/src/lib.rs @@ -7,12 +7,14 @@ pub mod extras; mod io; mod map; mod mercator; +mod position; pub mod sources; mod tiles; mod zoom; pub use download::{HeaderValue, HttpOptions}; pub use map::{Map, MapMemory, Plugin, Projector}; -pub use mercator::{lat_lon, lon_lat, screen_to_position, Position, TileId}; +pub use mercator::{screen_to_position, TileId}; +pub use position::{lat_lon, lon_lat, Position}; pub use tiles::{HttpTiles, Texture, TextureWithUv, Tiles}; pub use zoom::InvalidZoom; diff --git a/walkers/src/map.rs b/walkers/src/map.rs index 4ecc7fcd..2509ee9a 100644 --- a/walkers/src/map.rs +++ b/walkers/src/map.rs @@ -4,7 +4,8 @@ use egui::{Mesh, PointerButton, Rect, Response, Sense, Ui, UiBuilder, Vec2, Widg use crate::{ center::Center, - mercator::{project, screen_to_position, tile_id, Pixels, PixelsExt, TileId}, + mercator::{project, tile_id, TileId}, + position::{AdjustedPosition, Pixels, PixelsExt}, tiles, zoom::{InvalidZoom, Zoom}, Position, Tiles, @@ -336,52 +337,6 @@ impl Widget for Map<'_, '_, '_> { } } -/// [`Position`] alone is not able to represent detached (e.g. after map gets dragged) position -/// due to insufficient accuracy. -#[derive(Debug, Clone, PartialEq)] -pub struct AdjustedPosition { - /// Base geographical position. - pub position: Position, - - /// Offset in pixels. - pub offset: Pixels, -} - -impl AdjustedPosition { - pub(crate) fn new(position: Position, offset: Pixels) -> Self { - Self { position, offset } - } - - /// Calculate the real position, i.e. including the offset. - pub(crate) fn position(&self, zoom: f64) -> Position { - screen_to_position(project(self.position, zoom) - self.offset, zoom) - } - - /// Recalculate `position` so that `offset` is zero. - pub(crate) fn zero_offset(self, zoom: f64) -> Self { - Self { - position: screen_to_position(project(self.position, zoom) - self.offset, zoom), - offset: Default::default(), - } - } - - pub(crate) fn shift(self, offset: Vec2) -> Self { - Self { - position: self.position, - offset: self.offset + Pixels::new(offset.x as f64, offset.y as f64), - } - } -} - -impl From for AdjustedPosition { - fn from(position: Position) -> Self { - Self { - position, - offset: Default::default(), - } - } -} - /// State of the map widget which must persist between frames. #[derive(Debug, Default, Clone)] pub struct MapMemory { diff --git a/walkers/src/mercator.rs b/walkers/src/mercator.rs index 3497e712..66610be3 100644 --- a/walkers/src/mercator.rs +++ b/walkers/src/mercator.rs @@ -3,26 +3,17 @@ //! //! +use crate::{ + lon_lat, + position::{Pixels, Position}, +}; +use std::f64::consts::PI; + // zoom level tile coverage number of tiles tile size(*) in degrees // 0 1 tile 1 tile 360° x 170.1022° // 1 2 × 2 tiles 4 tiles 180° x 85.0511° // 2 4 × 4 tiles 16 tiles 90° x [variable] -/// Geographical position with latitude and longitude. -pub type Position = geo_types::Point; - -/// Construct `Position` from latitude and longitude. -pub fn lat_lon(lat: f64, lon: f64) -> Position { - Position::new(lon, lat) -} - -/// Construct `Position` from longitude and latitude. Note that it is common standard to write -/// coordinates starting with the latitude instead (e.g. `51.104465719934176, 17.075169894118684` is -/// the [Wrocław's zoo](https://zoo.wroclaw.pl/en/)). -pub fn lon_lat(lon: f64, lat: f64) -> Position { - Position::new(lon, lat) -} - /// Zoom specifies how many pixels are in the whole map. For example, zoom 0 means that the whole /// map is just one 256x256 tile, zoom 1 means that it is 2x2 tiles, and so on. pub(crate) fn total_pixels(zoom: f64) -> f64 { @@ -36,21 +27,6 @@ pub fn total_tiles(zoom: u8) -> u32 { /// Size of a single tile in pixels. Walkers uses 256px tiles as most of the tile sources do. const TILE_SIZE: u32 = 256; -/// Location projected on the screen or an abstract bitmap. -pub type Pixels = geo_types::Point; - -use std::f64::consts::PI; - -pub trait PixelsExt { - fn to_vec2(&self) -> egui::Vec2; -} - -impl PixelsExt for Pixels { - fn to_vec2(&self) -> egui::Vec2 { - egui::Vec2::new(self.x() as f32, self.y() as f32) - } -} - /// Project the position into the Mercator projection and normalize it to 0-1 range. fn mercator_normalized(position: Position) -> (f64, f64) { // Project into Mercator (cylindrical map projection). diff --git a/walkers/src/position.rs b/walkers/src/position.rs new file mode 100644 index 00000000..51fd943e --- /dev/null +++ b/walkers/src/position.rs @@ -0,0 +1,78 @@ +//! Types and functions for working with positions. + +use crate::{mercator::project, screen_to_position}; +use egui::Vec2; + +/// Geographical position with latitude and longitude. +pub type Position = geo_types::Point; + +/// Construct `Position` from latitude and longitude. +pub fn lat_lon(lat: f64, lon: f64) -> Position { + Position::new(lon, lat) +} + +/// Construct `Position` from longitude and latitude. Note that it is common standard to write +/// coordinates starting with the latitude instead (e.g. `51.104465719934176, 17.075169894118684` is +/// the [Wrocław's zoo](https://zoo.wroclaw.pl/en/)). +pub fn lon_lat(lon: f64, lat: f64) -> Position { + Position::new(lon, lat) +} + +/// [`Position`] alone is not able to represent detached (e.g. after map gets dragged) position +/// due to insufficient accuracy. +#[derive(Debug, Clone, PartialEq)] +pub struct AdjustedPosition { + /// Base geographical position. + pub position: Position, + + /// Offset in pixels. + pub offset: Pixels, +} + +impl AdjustedPosition { + pub(crate) fn new(position: Position, offset: Pixels) -> Self { + Self { position, offset } + } + + /// Calculate the real position, i.e. including the offset. + pub(crate) fn position(&self, zoom: f64) -> Position { + screen_to_position(project(self.position, zoom) - self.offset, zoom) + } + + /// Recalculate `position` so that `offset` is zero. + pub(crate) fn zero_offset(self, zoom: f64) -> Self { + Self { + position: screen_to_position(project(self.position, zoom) - self.offset, zoom), + offset: Default::default(), + } + } + + pub(crate) fn shift(self, offset: Vec2) -> Self { + Self { + position: self.position, + offset: self.offset + Pixels::new(offset.x as f64, offset.y as f64), + } + } +} + +impl From for AdjustedPosition { + fn from(position: Position) -> Self { + Self { + position, + offset: Default::default(), + } + } +} + +/// Location projected on the screen or an abstract bitmap. +pub type Pixels = geo_types::Point; + +pub trait PixelsExt { + fn to_vec2(&self) -> egui::Vec2; +} + +impl PixelsExt for Pixels { + fn to_vec2(&self) -> egui::Vec2 { + egui::Vec2::new(self.x() as f32, self.y() as f32) + } +} From 9067f733ef41e941cf7dd7d48bfd43b2a5c52691 Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Sat, 22 Feb 2025 21:26:00 +0100 Subject: [PATCH 2/2] fix ut --- walkers/src/mercator.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/walkers/src/mercator.rs b/walkers/src/mercator.rs index 66610be3..e1f47a85 100644 --- a/walkers/src/mercator.rs +++ b/walkers/src/mercator.rs @@ -136,6 +136,7 @@ pub fn screen_to_position(pixels: Pixels, zoom: f64) -> Position { #[cfg(test)] mod tests { use super::*; + use crate::lat_lon; #[test] fn projecting_position_and_tile() {