Skip to content

Commit 34cd961

Browse files
committed
fill in vector_layer field in TileJSON, use geojson_to_tile for tiling
GeoJSON
1 parent ea69dc4 commit 34cd961

File tree

1 file changed

+85
-14
lines changed

1 file changed

+85
-14
lines changed

martin/src/geojson/mod.rs

Lines changed: 85 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1+
use std::collections::BTreeMap;
12
use std::fmt::{Debug, Formatter};
23
use std::path::PathBuf;
34
use std::sync::Arc;
45

56
use async_trait::async_trait;
6-
use geojson_vt_rs::{GeoJSONVT, Options};
77
use geozero::mvt::Message as _;
88
use martin_tile_utils::{Format, TileCoord, TileInfo};
99
use std::fs::File;
1010
use tilejson::TileJSON;
1111
use tilejson::tilejson;
12-
use tokio::sync::RwLock;
1312

1413
use crate::file_config::FileError;
1514
use crate::file_config::FileResult;
@@ -22,10 +21,11 @@ mod mvt;
2221

2322
pub use config::GeoJsonConfig;
2423

24+
#[derive(Clone)]
2525
pub struct GeoJsonSource {
2626
id: String,
2727
path: PathBuf,
28-
inner: Arc<RwLock<GeoJSONVT>>,
28+
geojson: Arc<geojson::GeoJson>,
2929
tilejson: TileJSON,
3030
tile_info: TileInfo,
3131
}
@@ -49,19 +49,18 @@ impl GeoJsonSource {
4949
let geojson = geojson::GeoJson::from_reader(geojson_file)
5050
.map_err(|e| FileError::InvalidFilePath(path.clone()))?;
5151

52-
// TODO: see if options default is goood enough
53-
let inner = GeoJSONVT::from_geojson(&geojson, &Options::default());
54-
52+
// TODO: vector layers
5553
let tilejson = tilejson! {
5654
tiles: vec![],
55+
vector_layers: geojson_to_vector_layer(&id, &geojson),
5756
minzoom: 0,
5857
maxzoom: 18,
5958
};
6059

6160
return Ok(Self {
6261
id,
6362
path,
64-
inner: Arc::new(RwLock::new(inner)),
63+
geojson: Arc::new(geojson),
6564
tilejson,
6665
tile_info,
6766
});
@@ -83,8 +82,7 @@ impl Source for GeoJsonSource {
8382
}
8483

8584
fn clone_source(&self) -> TileInfoSource {
86-
// TODO: implement clone for GeoJsonSource (GeoJSONVT is not cloneable, which is a blocker)
87-
Box::new(Self::new(self.id.clone(), self.path.clone()).unwrap())
85+
Box::new(self.clone())
8886
}
8987

9088
fn benefits_from_concurrent_scraping(&self) -> bool {
@@ -97,11 +95,17 @@ impl Source for GeoJsonSource {
9795
xyz: TileCoord,
9896
_url_query: Option<&UrlQuery>,
9997
) -> MartinResult<TileData> {
100-
let tile;
101-
{
102-
let mut guard = self.inner.write().await;
103-
tile = guard.get_tile(xyz.z, xyz.x, xyz.y).clone();
104-
}
98+
// TODO: get from source (self)
99+
let options = geojson_vt_rs::TileOptions::default();
100+
let tile = geojson_vt_rs::geojson_to_tile(
101+
&self.geojson,
102+
xyz.z,
103+
xyz.x,
104+
xyz.y,
105+
&options,
106+
true,
107+
true,
108+
);
105109
let mut builder = LayerBuilder::new(self.id.clone(), 4096);
106110
for feature in &tile.features.features {
107111
builder.add_feature(feature);
@@ -112,3 +116,70 @@ impl Source for GeoJsonSource {
112116
Ok(mvt_tile.encode_to_vec())
113117
}
114118
}
119+
120+
// TODO: maybe break down fields subroutine into a function
121+
fn geojson_to_vector_layer(
122+
layer_name: &str,
123+
geojson: &geojson::GeoJson,
124+
) -> Vec<tilejson::VectorLayer> {
125+
let mut fields = BTreeMap::new();
126+
match geojson {
127+
geojson::GeoJson::Geometry(_geometry) => {
128+
vec![tilejson::VectorLayer::new(layer_name.to_string(), fields)]
129+
}
130+
geojson::GeoJson::Feature(feature) => {
131+
if let Some(properties) = feature.properties.as_ref() {
132+
properties.iter().for_each(|(key, value)| {
133+
// should be in sync with mvt::tilevalue_from_json
134+
let val_type = match value {
135+
serde_json::Value::String(_) => "string",
136+
serde_json::Value::Number(n) => {
137+
if n.is_f64() {
138+
"double"
139+
} else if n.is_i64() {
140+
"signed integer"
141+
} else if n.is_u64() {
142+
"unsigned integer"
143+
} else {
144+
// TODO: check
145+
unreachable!()
146+
}
147+
}
148+
serde_json::Value::Bool(_) => "boolean",
149+
_ => "string",
150+
};
151+
fields.insert(key.to_string(), val_type.to_string());
152+
});
153+
}
154+
vec![tilejson::VectorLayer::new(layer_name.to_string(), fields)]
155+
}
156+
geojson::GeoJson::FeatureCollection(feature_collection) => {
157+
for feature in &feature_collection.features {
158+
if let Some(properties) = feature.properties.as_ref() {
159+
properties.iter().for_each(|(key, value)| {
160+
// should be in sync with mvt::tilevalue_from_json
161+
let val_type = match value {
162+
serde_json::Value::String(_) => "string",
163+
serde_json::Value::Number(n) => {
164+
if n.is_f64() {
165+
"double"
166+
} else if n.is_i64() {
167+
"signed integer"
168+
} else if n.is_u64() {
169+
"unsigned integer"
170+
} else {
171+
// TODO: check
172+
unreachable!()
173+
}
174+
}
175+
serde_json::Value::Bool(_) => "boolean",
176+
_ => "string",
177+
};
178+
fields.insert(key.to_string(), val_type.to_string());
179+
});
180+
}
181+
}
182+
vec![tilejson::VectorLayer::new(layer_name.to_string(), fields)]
183+
}
184+
}
185+
}

0 commit comments

Comments
 (0)