Skip to content

Commit d806d44

Browse files
authored
[feat] Add TileSchema support for expressions. (galileo-map#304)
* add: interpolation_base params in interpolation/step exprs * add: Zlevel and Resolution variants to internal struct *Expression * * refactor: converted *Expressions to fail when not possible to find suitable zlevel for resolution * add: example for resolution/z-level * add: tests for interpolation of z_levels and remove resolution_z
1 parent f572900 commit d806d44

5 files changed

Lines changed: 1359 additions & 782 deletions

File tree

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
//! This example show cases the two possible operating basis on interpolation
2+
//! With Z-levels and Resolution
3+
4+
use std::sync::Arc;
5+
6+
use egui::FontDefinitions;
7+
use galileo::layer::data_provider::remove_parameters_modifier;
8+
use galileo::layer::vector_tile_layer::style::{StyleRule, VectorTileStyle};
9+
use galileo::layer::vector_tile_layer::VectorTileLayerBuilder;
10+
use galileo::layer::VectorTileLayer;
11+
use galileo::render::text::text_service::TextService;
12+
use galileo::render::text::RustybuzzRasterizer;
13+
use galileo::tile_schema::{TileIndex, TileSchema, TileSchemaBuilder};
14+
use galileo::MapBuilder;
15+
use galileo_egui::{EguiMap, EguiMapState};
16+
use parking_lot::RwLock;
17+
18+
#[cfg(not(target_arch = "wasm32"))]
19+
fn main() {
20+
run()
21+
}
22+
23+
struct App {
24+
map: EguiMapState,
25+
layer: Arc<RwLock<VectorTileLayer>>,
26+
}
27+
28+
impl eframe::App for App {
29+
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
30+
egui::CentralPanel::default().show(ctx, |ui| {
31+
EguiMap::new(&mut self.map).show_ui(ui);
32+
});
33+
34+
egui::Window::new("Buttons")
35+
.title_bar(false)
36+
.show(ctx, |ui| {
37+
ui.horizontal(|ui| {
38+
if ui.button("Resolution").clicked() {
39+
self.set_style(with_overlay_rule(resolution_based_interpolation()));
40+
}
41+
if ui.button("ZLevel").clicked() {
42+
self.set_style(with_overlay_rule(zlevel_based_interpolation()));
43+
}
44+
});
45+
});
46+
}
47+
}
48+
49+
fn with_overlay_rule(overlay: StyleRule) -> VectorTileStyle {
50+
let mut base: VectorTileStyle =
51+
serde_json::from_str(include_str!("data/vt_style.json")).expect("invalid style json");
52+
base.rules.insert(0, overlay);
53+
base
54+
}
55+
56+
impl App {
57+
fn new(egui_map_state: EguiMapState, layer: Arc<RwLock<VectorTileLayer>>) -> Self {
58+
let fonts = FontDefinitions::default();
59+
let provider = RustybuzzRasterizer::default();
60+
61+
let text_service = TextService::initialize(provider);
62+
for font in fonts.font_data.values() {
63+
text_service.load_font(Arc::new(font.font.to_vec()));
64+
}
65+
66+
Self {
67+
map: egui_map_state,
68+
layer,
69+
}
70+
}
71+
72+
fn set_style(&mut self, style: VectorTileStyle) {
73+
let mut layer = self.layer.write();
74+
if style != *layer.style() {
75+
layer.update_style(style);
76+
self.map.request_redraw();
77+
}
78+
}
79+
}
80+
81+
pub(crate) fn run() {
82+
let Some(api_key) = std::option_env!("VT_API_KEY") else {
83+
panic!("Set the MapTiler API key into VT_API_KEY library when building this example");
84+
};
85+
86+
let style =
87+
serde_json::from_str(include_str!("data/vt_style.json")).expect("invalid style json");
88+
let layer = VectorTileLayerBuilder::new_rest(move |&index: &TileIndex| {
89+
format!(
90+
"https://api.maptiler.com/tiles/v3-openmaptiles/{z}/{x}/{y}.pbf?key={api_key}",
91+
z = index.z,
92+
x = index.x,
93+
y = index.y
94+
)
95+
})
96+
.with_style(style)
97+
.with_tile_schema(tile_schema())
98+
.with_file_cache_modifier_checked(".tile_cache", Box::new(remove_parameters_modifier))
99+
.with_attribution(
100+
"© MapTiler© OpenStreetMap contributors".to_string(),
101+
"https://www.maptiler.com/copyright/".to_string(),
102+
)
103+
.build()
104+
.expect("failed to create layer");
105+
106+
let layer = Arc::new(RwLock::new(layer));
107+
108+
let map = MapBuilder::default().with_layer(layer.clone()).build();
109+
galileo_egui::InitBuilder::new(map)
110+
.with_app_builder(|egui_map_state, _| Box::new(App::new(egui_map_state, layer)))
111+
.init()
112+
.expect("failed to initialize");
113+
}
114+
115+
fn resolution_based_interpolation() -> StyleRule {
116+
serde_json::from_str(
117+
r##"{
118+
"symbol": {
119+
"polygon": {
120+
"fill_color": {
121+
"interpolate": {
122+
"cubic":{
123+
"control_points": [0.25, 0.0, 0.75, 1.0],
124+
"step_values": [
125+
{"resolution": 9783.939620501465, "step_value": "#81C4EC"},
126+
{"resolution": 611.4962262813416, "step_value": "#29546dff"},
127+
{"resolution": 2.3886571339114906, "step_value": "#3d835cff"}
128+
]
129+
}
130+
}
131+
}
132+
}
133+
}
134+
}"##,
135+
)
136+
.expect("invalid style json")
137+
}
138+
139+
fn zlevel_based_interpolation() -> StyleRule {
140+
serde_json::from_str(
141+
r##"{
142+
"symbol": {
143+
"polygon": {
144+
"fill_color": {
145+
"interpolate": {
146+
"cubic":{
147+
"control_points": [0.25, 0.0, 0.75, 1.0],
148+
"step_values": [
149+
{"resolution": 9783.939620501465, "step_value": "#81C4EC"},
150+
{"resolution": 611.4962262813416, "step_value": "#29546dff"},
151+
{"resolution": 2.3886571339114906, "step_value": "#3d835cff"}
152+
]
153+
}
154+
},
155+
"operation_base":"z_level"
156+
}
157+
}
158+
}
159+
}"##,
160+
)
161+
.expect("invalid style json")
162+
}
163+
164+
fn tile_schema() -> TileSchema {
165+
TileSchemaBuilder::web_mercator(2..16)
166+
.rect_tile_size(1024)
167+
.build()
168+
.expect("invalid tile schema")
169+
}

0 commit comments

Comments
 (0)