treeadvisor/server/src/tile_style.rs

101 lines
4.0 KiB
Rust

use std::collections::HashMap;
pub enum Selector {
MinZoom(i32),
MaxZoom(i32),
HasTag(&'static str),
TagEquals(&'static str, &'static str),
And(&'static [Selector]),
Or(&'static [Selector]),
}
impl Selector {
fn matches(&self, zoom: &i32, tags: &HashMap<String, String>) -> bool {
match self {
Selector::MinZoom(min_zoom) =>
zoom >= min_zoom,
Selector::MaxZoom(max_zoom) =>
zoom <= max_zoom,
Selector::HasTag(name) =>
tags.contains_key(*name),
Selector::TagEquals(name, value) =>
tags.get(*name).map(|s| s.as_str()) == Some(*value),
Selector::And(selectors) =>
selectors.iter().all(|selector| selector.matches(zoom, tags)),
Selector::Or(selectors) =>
selectors.iter().any(|selector| selector.matches(zoom, tags)),
}
}
}
type Color = (f64, f64, f64, f64);
pub struct Style {
pub z_index: i32,
pub stroke: Option<(f64, Color)>,
pub fill: Option<Color>,
}
impl Style {
const DEFAULT: Style = Style {
z_index: 0,
stroke: None,
fill: None,
};
}
const STYLES: &[(Selector, Style)] = &[
(Selector::HasTag("tunnel"),
Style { z_index: -10, ..Style::DEFAULT }),
(Selector::TagEquals("landuse", "forest"),
Style { z_index: -8, fill: Some((0.2, 0.7, 0.2, 0.8)), ..Style::DEFAULT }),
(Selector::TagEquals("leisure", "park"),
Style { z_index: -8, fill: Some((0.3, 0.7, 0.3, 0.8)), ..Style::DEFAULT }),
(Selector::TagEquals("landuse", "meadow"),
Style { z_index: -6, fill: Some((0.2, 0.8, 0.2, 0.8)), ..Style::DEFAULT }),
(Selector::TagEquals("landuse", "grass"),
Style { z_index: -5, fill: Some((0.3, 0.9, 0.3, 0.8)), ..Style::DEFAULT }),
(Selector::TagEquals("landuse", "industrial"),
Style { z_index: -9, fill: Some((0.3, 0.3, 0.2, 0.8)), ..Style::DEFAULT }),
(Selector::TagEquals("landuse", "construction"),
Style { z_index: -9, fill: Some((0.5, 0.5, 0.3, 0.8)), ..Style::DEFAULT }),
(Selector::TagEquals("highway", "motorway"),
Style { z_index: 10, stroke: Some((50., (1., 1., 1., 1.))), ..Style::DEFAULT }),
(Selector::TagEquals("highway", "trunk"),
Style { z_index: 9, stroke: Some((35., (1., 1., 1., 1.))), ..Style::DEFAULT }),
(Selector::TagEquals("highway", "primary"),
Style { z_index: 8, stroke: Some((25., (1., 1., 1., 1.))), ..Style::DEFAULT }),
(Selector::And(&[Selector::TagEquals("highway", "secondary"), Selector::MinZoom(12)]),
Style { z_index: 7, stroke: Some((20., (1., 1., 1., 1.))), ..Style::DEFAULT }),
(Selector::And(&[Selector::TagEquals("highway", "tertiary"), Selector::MinZoom(14)]),
Style { z_index: 6, stroke: Some((15., (1., 1., 1., 1.))), ..Style::DEFAULT }),
(Selector::And(&[Selector::TagEquals("highway", "residential"), Selector::MinZoom(16)]),
Style { z_index: 5, stroke: Some((10., (1., 1., 1., 1.))), ..Style::DEFAULT }),
(Selector::And(&[Selector::TagEquals("highway", "living_street"), Selector::MinZoom(16)]),
Style { z_index: 4, stroke: Some((8., (1., 1., 1., 1.))), ..Style::DEFAULT }),
(Selector::And(&[Selector::HasTag("highway"), Selector::MinZoom(18)]),
Style { z_index: 3, stroke: Some((6., (1., 1., 1., 1.))), ..Style::DEFAULT }),
(Selector::And(&[Selector::HasTag("railway"), Selector::MinZoom(10)]),
Style { z_index: 20, stroke: Some((3., (0., 0., 0., 1.))), ..Style::DEFAULT }),
(Selector::Or(&[Selector::HasTag("waterway"), Selector::TagEquals("natural", "water")]),
Style { z_index: -2, fill: Some((0.5, 0.5, 0.7, 1.)), ..Style::DEFAULT }),
(Selector::And(&[Selector::HasTag("building"), Selector::MinZoom(16)]),
Style { z_index: 30, fill: Some((0.7, 0.7, 0.7, 1.)), stroke: Some((1., (0., 0., 0., 1.))), ..Style::DEFAULT }),
];
pub fn find(zoom: &i32, tags: &HashMap<String, String>) -> Option<&'static Style> {
for (selector, style) in STYLES {
if selector.matches(zoom, tags) {
return Some(&style);
}
}
None
}