@@ -307,6 +307,52 @@ export abstract class Dataset<T extends Tile> {
307
307
}
308
308
}
309
309
310
+ /**
311
+ * Invoke a function on all tiles in the dataset that have been downloaded.
312
+ * The general architecture here is taken from the
313
+ * d3 quadtree functions. That's why, for example, it doesn't
314
+ * recurse.
315
+
316
+ * @param callback The function to invoke on each tile.
317
+ * @param after Whether to execute the visit in bottom-up order. Default false.
318
+ * @param filter
319
+ */
320
+
321
+ async visit_full (
322
+ callback : ( tile : T ) => Promise < void > ,
323
+ after = false ,
324
+ starting_tile : T | null = null ,
325
+ filter : ( t : T ) => boolean = ( x ) => true ,
326
+ updateFunction : ( tile : T , completed , total ) => Promise < void >
327
+ ) {
328
+
329
+ // Visit all children with a callback function.
330
+ // In general recursing quadtrees isn't that fast, but
331
+ // we rarely have more than ten tiles deep and the
332
+ // code is much cleaner this way than an async queue.
333
+
334
+ let seen = 0 ;
335
+ const start = starting_tile || this . root_tile ;
336
+ await start . download ( ) ;
337
+ const total = JSON . parse ( start . record_batch . schema . metadata . get ( "total_points" ) )
338
+
339
+ async function resolve ( tile : T ) {
340
+ await tile . download ( ) ;
341
+ if ( after ) {
342
+ await Promise . all ( tile . children . map ( resolve ) )
343
+ await callback ( tile ) ;
344
+ seen += tile . record_batch . numRows
345
+ void updateFunction ( tile , seen , total )
346
+ } else {
347
+ await callback ( tile ) ;
348
+ seen += tile . record_batch . numRows
349
+ void updateFunction ( tile , seen , total )
350
+ await Promise . all ( tile . children . map ( resolve ) )
351
+ }
352
+ }
353
+ await resolve ( start ) ;
354
+ }
355
+
310
356
async schema ( ) {
311
357
await this . ready ;
312
358
if ( this . _schema ) {
0 commit comments