UNPKG

tapspace

Version:

A zoomable user interface lib for web apps

90 lines (77 loc) 2.4 kB
module.exports = function (id, depth) { // @TreeLoader:getFrontier(id, depth) // // Find a frontier for the given root space id until the given depth. // In other words, find spaces that have unopened parents or children // and the distance to the root space is depth or smaller. // The root space itself can belong to the frontier. // // Parameters: // id // a string, the root space id // depth // a number, the maximum search distance from the root space. // // Return // an array: { id, space, depth } // if (!this.spaces[id]) { return [] } // Skip if negative depth to stop recursion. // Depth 0 means that the root may still belong to the frontier, so it's ok. if (depth < 0) { return [] } // Collect results here. const frontier = [] // Iteration cursors. Space ids. Their spaces must exist. const cursors = [id] // Track and limit depth. const depths = [0] // Track already visited to avoid propagating back-and-forth. // Visiting means that it has been a cursor. const visits = {} visits[id] = true while (cursors.length > 0) { const cursor = cursors.pop() const cursorDepth = depths.pop() const cursorSpace = this.spaces[cursor] // Assert cursorSpace exists. // Find adjacent let nextIds = [this.backtracker(cursor, cursorSpace)] const childIds = this.tracker(cursor, cursorSpace) nextIds = nextIds.concat(childIds) // Avoid expanding where already visited. nextIds = nextIds.filter((nid) => { if (visits[nid]) { return false } return true }) // Prevent cursor being pushed to frontier multiple times. let cursorInFrontier = false // Find if all nexts exist for (let i = 0; i < nextIds.length; i += 1) { const nid = nextIds[i] const nextSpace = this.spaces[nid] if (nextSpace) { // Continue search with the next if they are not too far. if (cursorDepth < depth) { cursors.push(nid) depths.push(cursorDepth + 1) visits[nid] = true } } else if (!cursorInFrontier) { // Not every children is open: cursor belongs to the frontier. frontier.push({ id: cursor, space: cursorSpace, depth: cursorDepth }) cursorInFrontier = true } } } return frontier }