1
+ use std:: collections:: BTreeMap ;
1
2
use std:: fmt:: { Debug , Formatter } ;
2
3
use std:: path:: PathBuf ;
3
4
use std:: sync:: Arc ;
4
5
5
6
use async_trait:: async_trait;
6
- use geojson_vt_rs:: { GeoJSONVT , Options } ;
7
7
use geozero:: mvt:: Message as _;
8
8
use martin_tile_utils:: { Format , TileCoord , TileInfo } ;
9
9
use std:: fs:: File ;
10
10
use tilejson:: TileJSON ;
11
11
use tilejson:: tilejson;
12
- use tokio:: sync:: RwLock ;
13
12
14
13
use crate :: file_config:: FileError ;
15
14
use crate :: file_config:: FileResult ;
@@ -22,10 +21,11 @@ mod mvt;
22
21
23
22
pub use config:: GeoJsonConfig ;
24
23
24
+ #[ derive( Clone ) ]
25
25
pub struct GeoJsonSource {
26
26
id : String ,
27
27
path : PathBuf ,
28
- inner : Arc < RwLock < GeoJSONVT > > ,
28
+ geojson : Arc < geojson :: GeoJson > ,
29
29
tilejson : TileJSON ,
30
30
tile_info : TileInfo ,
31
31
}
@@ -49,19 +49,18 @@ impl GeoJsonSource {
49
49
let geojson = geojson:: GeoJson :: from_reader ( geojson_file)
50
50
. map_err ( |e| FileError :: InvalidFilePath ( path. clone ( ) ) ) ?;
51
51
52
- // TODO: see if options default is goood enough
53
- let inner = GeoJSONVT :: from_geojson ( & geojson, & Options :: default ( ) ) ;
54
-
52
+ // TODO: vector layers
55
53
let tilejson = tilejson ! {
56
54
tiles: vec![ ] ,
55
+ vector_layers: geojson_to_vector_layer( & id, & geojson) ,
57
56
minzoom: 0 ,
58
57
maxzoom: 18 ,
59
58
} ;
60
59
61
60
return Ok ( Self {
62
61
id,
63
62
path,
64
- inner : Arc :: new ( RwLock :: new ( inner ) ) ,
63
+ geojson : Arc :: new ( geojson ) ,
65
64
tilejson,
66
65
tile_info,
67
66
} ) ;
@@ -83,8 +82,7 @@ impl Source for GeoJsonSource {
83
82
}
84
83
85
84
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 ( ) )
88
86
}
89
87
90
88
fn benefits_from_concurrent_scraping ( & self ) -> bool {
@@ -97,11 +95,17 @@ impl Source for GeoJsonSource {
97
95
xyz : TileCoord ,
98
96
_url_query : Option < & UrlQuery > ,
99
97
) -> 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
+ ) ;
105
109
let mut builder = LayerBuilder :: new ( self . id . clone ( ) , 4096 ) ;
106
110
for feature in & tile. features . features {
107
111
builder. add_feature ( feature) ;
@@ -112,3 +116,70 @@ impl Source for GeoJsonSource {
112
116
Ok ( mvt_tile. encode_to_vec ( ) )
113
117
}
114
118
}
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