wxbox/crates/client/src/map/tiles.rs

137 lines
No EOL
4.2 KiB
Rust

use std::cell::RefCell;
use crate::map::sources::baselayers::*;
use crate::map::sources::datalayers::*;
use crate::map::sources::{ActiveLayer, LayerSource, Tile};
use eframe::emath::{pos2, Rect};
use futures::channel::mpsc::TrySendError;
use image::{ColorType, DynamicImage};
use lru::LruCache;
use poll_promise::Promise;
use serde::{Deserialize, Serialize};
use std::cmp::PartialEq;
use std::collections::HashMap;
use std::fmt::{Debug, Formatter};
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use tracing::{debug, error, trace};
use walkers::sources::{Attribution, TileSource};
use walkers::{HttpTiles, Texture, TextureWithUv, TileId, Tiles};
// type aliases to make the tile map less hellish
pub type ZoomLevel = usize;
pub type XCoord = usize;
pub type YCoord = usize;
pub type SourceId = u64;
#[derive(Default, Serialize, Deserialize, Debug)]
#[serde(default)]
pub struct LayerManager {
#[serde(skip)]
pub ctx: Option<egui::Context>,
pub registered_sources: HashMap<SourceId, LayerSource>,
pub active_layers: Vec<ActiveLayer>,
#[serde(skip)]
pub individual_sources: HashMap<SourceId, WHttpTiles>,
}
pub struct WHttpTiles(pub Rc<RefCell<HttpTiles>>);
impl Debug for WHttpTiles {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "<WHttpTiles>")
}
}
impl LayerManager {
pub fn register_layer(&mut self, layer: &LayerSource) {
self.registered_sources
.insert(layer.source_id, layer.clone());
}
pub fn unregister_layer(&mut self, layer_id: &SourceId) {
self.registered_sources.remove(layer_id);
self.active_layers.retain(|u| u.source_id != *layer_id);
}
pub fn register_builtin_layers(&mut self) {
let layers = [
// -- Base layers --
&*BASELAYER_OSM, // OpenStreetMap
// -- NOAA MRMS - Merged Composite Reflectivity - QCd
&*NOAA_MRMS_MERGED_CREF_QC_CONUS, // Continental United States
&*NOAA_MRMS_MERGED_CREF_QC_HAWAII, // Hawaii
&*NOAA_MRMS_MERGED_CREF_QC_ALASKA, // Alaska FSS
&*NOAA_MRMS_MERGED_CREF_QC_CARIB, // Caribbean
&*NOAA_MRMS_MERGED_CREF_QC_GUAM, // Guam
// -- NOAA MRMS - Merged RhoHV (Differential Reflectivity) @ 3km
&*NOAA_MRMS_MERGED_RHOHV_3KM_CONUS,
];
for layer in layers {
self.register_layer(layer);
}
}
pub fn remove_unregistered_layers(&mut self) {
// remove any
self.active_layers
.retain(|u| self.registered_sources.contains_key(&u.source_id));
}
}
impl TileSource for LayerSource {
fn tile_url(&self, tile_id: TileId) -> String {
self.tile_url
.replace("{z}", &tile_id.zoom.to_string())
.replace("{x}", &tile_id.x.to_string())
.replace("{y}", &tile_id.y.to_string())
}
fn attribution(&self) -> Attribution {
Attribution {
text: self.source.clone().leak(),
url: self.source_link.clone().leak(),
logo_light: None,
logo_dark: None,
}
}
fn tile_size(&self) -> u32 {
self.tile_size
}
fn max_zoom(&self) -> u8 {
self.max_zoom
}
}
impl Tiles for LayerManager {
fn at(&mut self, tile_id: TileId) -> Vec<TextureWithUv> {
let mut layers = vec![];
for layer in self.active_layers.iter().rev().filter(|u| u.visible) {
let layer = self.individual_sources.entry(layer.source_id)
.or_insert_with(|| {
WHttpTiles(Rc::new(RefCell::new(HttpTiles::new(
self.registered_sources
.get(&layer.source_id)
.unwrap()
.clone(),
self.ctx.as_ref().unwrap().clone(),
))))
});
let tiles_here = layer.0.borrow_mut().at(tile_id);
layers.extend(tiles_here);
}
layers
}
fn attribution(&self) -> Attribution {
Attribution {
text: "our sources",
url: "https://weather.ax/credits",
logo_light: None,
logo_dark: None,
}
}
fn tile_size(&self) -> u32 {
256
}
}