@@ -307,6 +307,52 @@ export abstract class Dataset<T extends Tile> {
307307 }
308308 }
309309
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+
310356 async schema ( ) {
311357 await this . ready ;
312358 if ( this . _schema ) {
0 commit comments