Skip to content

Commit 327d03d

Browse files
shri-achaMaximkaaa
andauthored
Property value interpolation of color and numbers (galileo-map#290)
Add support of values interpolation for vector tile style symbols. --------- Co-authored-by: Maxim <maxim@gritsenko.biz>
1 parent b169c4b commit 327d03d

File tree

8 files changed

+1094
-36
lines changed

8 files changed

+1094
-36
lines changed

galileo/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ raw-window-handle = { workspace = true, optional = true }
4747
regex = { workspace = true }
4848
rustybuzz = { workspace = true, optional = true }
4949
serde = { workspace = true, optional = true, features = ["std", "derive", "rc"] }
50+
serde_json = { workspace = true }
5051
strfmt = { workspace = true }
5152
thiserror = { workspace = true }
5253
web-time = { workspace = true, features = ["serde"] }

galileo/examples/vector_tiles.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! This exmpale shows how to create and work with vector tile layers.
1+
//! This example shows how to create and work with vector tile layers.
22
33
use std::sync::Arc;
44

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
//! This example shows how to create and work with vector
2+
//! tile layers with style strings containing interpolate and step like expressions
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("Linear Interpolation").clicked() {
39+
self.set_style(with_overlay_rule(linear_interpolation_style()));
40+
}
41+
if ui.button("Exponential Interpolation").clicked() {
42+
self.set_style(with_overlay_rule(exponential_interpolation_style()));
43+
}
44+
if ui.button("Stepped Interpolation").clicked() {
45+
self.set_style(with_overlay_rule(stepped_interpolation_style()));
46+
}
47+
});
48+
});
49+
}
50+
}
51+
52+
fn with_overlay_rule(overlay: StyleRule) -> VectorTileStyle {
53+
let mut base: VectorTileStyle =
54+
serde_json::from_str(include_str!("data/vt_style.json")).expect("invalid style json");
55+
base.rules.insert(0, overlay);
56+
base
57+
}
58+
59+
impl App {
60+
fn new(egui_map_state: EguiMapState, layer: Arc<RwLock<VectorTileLayer>>) -> Self {
61+
let fonts = FontDefinitions::default();
62+
let provider = RustybuzzRasterizer::default();
63+
64+
let text_service = TextService::initialize(provider);
65+
for font in fonts.font_data.values() {
66+
text_service.load_font(Arc::new(font.font.to_vec()));
67+
}
68+
69+
Self {
70+
map: egui_map_state,
71+
layer,
72+
}
73+
}
74+
75+
fn set_style(&mut self, style: VectorTileStyle) {
76+
let mut layer = self.layer.write();
77+
if style != *layer.style() {
78+
layer.update_style(style);
79+
self.map.request_redraw();
80+
}
81+
}
82+
}
83+
84+
pub(crate) fn run() {
85+
let Some(api_key) = std::option_env!("VT_API_KEY") else {
86+
panic!("Set the MapTiler API key into VT_API_KEY library when building this example");
87+
};
88+
89+
let style =
90+
serde_json::from_str(include_str!("data/vt_style.json")).expect("invalid style json");
91+
let layer = VectorTileLayerBuilder::new_rest(move |&index: &TileIndex| {
92+
format!(
93+
"https://api.maptiler.com/tiles/v3-openmaptiles/{z}/{x}/{y}.pbf?key={api_key}",
94+
z = index.z,
95+
x = index.x,
96+
y = index.y
97+
)
98+
})
99+
.with_style(style)
100+
.with_tile_schema(tile_schema())
101+
.with_file_cache_modifier_checked(".tile_cache", Box::new(remove_parameters_modifier))
102+
.with_attribution(
103+
"© MapTiler© OpenStreetMap contributors".to_string(),
104+
"https://www.maptiler.com/copyright/".to_string(),
105+
)
106+
.build()
107+
.expect("failed to create layer");
108+
109+
let layer = Arc::new(RwLock::new(layer));
110+
111+
let map = MapBuilder::default().with_layer(layer.clone()).build();
112+
galileo_egui::InitBuilder::new(map)
113+
.with_app_builder(|egui_map_state, _| Box::new(App::new(egui_map_state, layer)))
114+
.init()
115+
.expect("failed to initialize");
116+
}
117+
118+
fn stepped_interpolation_style() -> StyleRule {
119+
serde_json::from_str(
120+
r##"{
121+
"symbol": {
122+
"polygon": {
123+
"fill_color": {
124+
"default_value": "#3d835cff",
125+
"step_values": [
126+
{"resolution": 9783.939620501465, "step_value": "#81C4EC"},
127+
{"resolution": 611.4962262813416, "step_value": "#29546dff"},
128+
{"resolution": 38.21851414258385, "step_value": "#3d835cff"}
129+
]
130+
}
131+
}
132+
}
133+
}"##,
134+
)
135+
.expect("invalid style json")
136+
}
137+
138+
fn linear_interpolation_style() -> StyleRule {
139+
serde_json::from_str(
140+
r##"{
141+
"symbol": {
142+
"polygon": {
143+
"fill_color": {
144+
"interpolate": {
145+
"linear":{
146+
"default_value": "#3d835cff",
147+
"step_values": [
148+
{"resolution": 9783.939620501465, "step_value": "#81C4EC"},
149+
{"resolution": 611.4962262813416, "step_value": "#29546dff"},
150+
{"resolution": 2.3886571339114906, "step_value": "#3d835cff"}
151+
]
152+
}
153+
}
154+
}
155+
}
156+
}
157+
}"##,
158+
)
159+
.expect("invalid style json")
160+
}
161+
162+
fn exponential_interpolation_style() -> StyleRule {
163+
serde_json::from_str(
164+
r##"{
165+
"symbol": {
166+
"polygon": {
167+
"fill_color": {
168+
"interpolate": {
169+
"exponential":{
170+
"base": 2,
171+
"step_values": [
172+
{"resolution": 9783.939620501465, "step_value": "#81C4EC"},
173+
{"resolution": 611.4962262813416, "step_value": "#29546dff"},
174+
{"resolution": 2.3886571339114906, "step_value": "#3d835cff"}
175+
]
176+
}
177+
}
178+
}
179+
}
180+
}
181+
}"##,
182+
)
183+
.expect("invalid style json")
184+
}
185+
186+
fn tile_schema() -> TileSchema {
187+
TileSchemaBuilder::web_mercator(2..16)
188+
.rect_tile_size(1024)
189+
.build()
190+
.expect("invalid tile schema")
191+
}

galileo/src/layer/vector_tile_layer/builder.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,8 @@ impl VectorTileLayerBuilder {
462462
min_resolution: None,
463463
properties: Default::default(),
464464
symbol: VectorTileSymbol::Line(VectorTileLineSymbol {
465-
width: 1.0,
466-
stroke_color: Color::BLACK,
465+
width: 1.0.into(),
466+
stroke_color: Color::BLACK.into(),
467467
}),
468468
},
469469
StyleRule {
@@ -472,7 +472,7 @@ impl VectorTileLayerBuilder {
472472
min_resolution: None,
473473
properties: Default::default(),
474474
symbol: VectorTileSymbol::Polygon(VectorTilePolygonSymbol {
475-
fill_color: Color::GRAY,
475+
fill_color: Color::GRAY.into(),
476476
}),
477477
},
478478
],

0 commit comments

Comments
 (0)