modules/core/tree.js (81 lines of code) (raw):

import RBush from 'rbush'; import { coreDifference } from './difference'; export function coreTree(head) { var rtree = new RBush(); var bboxes = {}; var tree = {}; function entityBBox(entity) { var bbox = entity.extent(head).bbox(); bbox.id = entity.id; bboxes[entity.id] = bbox; return bbox; } function updateParents(entity, insertions, memo) { head.parentWays(entity).forEach(function(way) { if (bboxes[way.id]) { rtree.remove(bboxes[way.id]); insertions[way.id] = way; } updateParents(way, insertions, memo); }); head.parentRelations(entity).forEach(function(relation) { if (memo[entity.id]) return; memo[entity.id] = true; if (bboxes[relation.id]) { rtree.remove(bboxes[relation.id]); insertions[relation.id] = relation; } updateParents(relation, insertions, memo); }); } tree.rebase = function(entities, force) { var insertions = {}; for (var i = 0; i < entities.length; i++) { var entity = entities[i]; if (!entity.visible) continue; if (head.entities.hasOwnProperty(entity.id) || bboxes[entity.id]) { if (!force) { continue; } else if (bboxes[entity.id]) { rtree.remove(bboxes[entity.id]); } } insertions[entity.id] = entity; updateParents(entity, insertions, {}); } rtree.load(Object.values(insertions).map(entityBBox)); return tree; }; tree.intersects = function(extent, graph) { if (graph !== head) { var diff = coreDifference(head, graph); var changed = diff.didChange; if (changed.addition || changed.deletion || changed.geometry) { var insertions = {}; head = graph; if (changed.deletion) { diff.deleted().forEach(function(entity) { rtree.remove(bboxes[entity.id]); delete bboxes[entity.id]; }); } if (changed.geometry) { diff.modified().forEach(function(entity) { rtree.remove(bboxes[entity.id]); insertions[entity.id] = entity; updateParents(entity, insertions, {}); }); } if (changed.addition) { diff.created().forEach(function(entity) { insertions[entity.id] = entity; }); } rtree.load(Object.values(insertions).map(entityBBox)); } } return rtree.search(extent.bbox()) .map(function(bbox) { return graph.entity(bbox.id); }); }; return tree; }