@@ -212,14 +212,17 @@ impl<W: Write + Seek> PmTilesStreamWriter<W> {
212
212
/// Add tile to writer.
213
213
///
214
214
/// Tiles are deduplicated and written to output.
215
- /// `tile_id` should be increasing.
215
+ /// `tile_id` should be increasing for best read performance .
216
216
pub fn add_tile ( & mut self , tile_id : u64 , data : & [ u8 ] ) -> PmtResult < ( ) > {
217
217
if data. is_empty ( ) {
218
218
// Ignore empty tiles, since the spec does not allow storing them
219
219
return Ok ( ( ) ) ;
220
220
}
221
221
222
222
let is_first = self . entries . is_empty ( ) ;
223
+ if is_first && tile_id > 0 {
224
+ self . header . clustered = false ;
225
+ }
223
226
let mut first_entry = DirEntry {
224
227
tile_id : 0 ,
225
228
offset : 0 ,
@@ -241,6 +244,9 @@ impl<W: Write + Seek> PmTilesStreamWriter<W> {
241
244
data. write_compressed_to_counted ( & mut self . out , self . header . tile_compression ) ?;
242
245
let length = into_u32 ( len) ?;
243
246
self . n_tile_contents += 1 ;
247
+ if tile_id != last_entry. tile_id + u64:: from ( last_entry. run_length ) {
248
+ self . header . clustered = false ;
249
+ }
244
250
245
251
self . entries . push ( DirEntry {
246
252
tile_id,
@@ -259,6 +265,11 @@ impl<W: Write + Seek> PmTilesStreamWriter<W> {
259
265
/// Leaf directories are written to output.
260
266
/// The root directory is returned.
261
267
fn build_directories ( & mut self ) -> PmtResult < Directory > {
268
+ if !self . header . clustered {
269
+ // Spec does only say that leaf directories *should* be in ascending order,
270
+ // but sorted directories are better for readers anyway.
271
+ self . entries . sort_by_key ( |entry| entry. tile_id ) ;
272
+ }
262
273
let ( root_dir, num_leaves) = self . optimize_directories ( MAX_INITIAL_BYTES - HEADER_SIZE ) ?;
263
274
if num_leaves > 0 {
264
275
// Write leaf directories
@@ -466,4 +477,16 @@ mod tests {
466
477
assert_eq ! ( num_leaves, 5 ) ;
467
478
assert_eq ! ( root_dir. entries( ) . len( ) , num_leaves) ;
468
479
}
480
+
481
+ #[ test]
482
+ fn unclustered ( ) {
483
+ let fname = get_temp_file_path ( "pmtiles" ) . unwrap ( ) ;
484
+ let file = File :: create ( fname) . unwrap ( ) ;
485
+ let mut writer = PmTilesWriter :: new ( TileType :: Png ) . create ( file) . unwrap ( ) ;
486
+ writer. add_tile ( 0 , & [ 0 , 1 , 2 , 3 ] ) . unwrap ( ) ;
487
+ assert ! ( writer. header. clustered) ;
488
+ writer. add_tile ( 2 , & [ 0 , 1 , 2 , 3 ] ) . unwrap ( ) ;
489
+ assert ! ( !writer. header. clustered) ;
490
+ writer. finish ( ) . unwrap ( ) ;
491
+ }
469
492
}
0 commit comments