protected List boundablesAtLevel(int level) { ArrayList boundables = new ArrayList(); boundablesAtLevel(level, root, boundables); return boundables; }
/** * Also builds the tree, if necessary. */ protected void query(Object searchBounds, ItemVisitor visitor) { build(); if (isEmpty()) { // nothing in tree, so return //Assert.isTrue(root.getBounds() == null); return; } if (getIntersectsOp().intersects(root.getBounds(), searchBounds)) { queryInternal(searchBounds, root, visitor); } }
/** * Creates parent nodes, grandparent nodes, and so forth up to the root * node, for the data that has been inserted into the tree. Can only be * called once, and thus can be called only after all of the data has been * inserted into the tree. */ public synchronized void build() { if (built) return; root = itemBoundables.isEmpty() ? createNode(0) : createHigherLevels(itemBoundables, -1); // the item list is no longer needed itemBoundables = null; built = true; }
/** * Sorts the childBoundables then divides them into groups of size M, where * M is the node capacity. */ protected List createParentBoundables(List childBoundables, int newLevel) { Assert.isTrue(!childBoundables.isEmpty()); ArrayList parentBoundables = new ArrayList(); parentBoundables.add(createNode(newLevel)); ArrayList sortedChildBoundables = new ArrayList(childBoundables); Collections.sort(sortedChildBoundables, getComparator()); for (Iterator i = sortedChildBoundables.iterator(); i.hasNext(); ) { Boundable childBoundable = (Boundable) i.next(); if (lastNode(parentBoundables).getChildBoundables().size() == getNodeCapacity()) { parentBoundables.add(createNode(newLevel)); } lastNode(parentBoundables).addChildBoundable(childBoundable); } return parentBoundables; }
/** * Removes an item from the tree. * (Builds the tree, if necessary.) */ protected boolean remove(Object searchBounds, Object item) { build(); if (getIntersectsOp().intersects(root.getBounds(), searchBounds)) { return remove(searchBounds, root, item); } return false; }
private boolean remove(Object searchBounds, AbstractNode node, Object item) { // first try removing item from this node boolean found = removeItem(node, item); if (found) return true; AbstractNode childToPrune = null; // next try removing item from lower nodes for (Iterator i = node.getChildBoundables().iterator(); i.hasNext(); ) { Boundable childBoundable = (Boundable) i.next(); if (!getIntersectsOp().intersects(childBoundable.getBounds(), searchBounds)) { continue; } if (childBoundable instanceof AbstractNode) { found = remove(searchBounds, (AbstractNode) childBoundable, item); // if found, record child for pruning and exit if (found) { childToPrune = (AbstractNode) childBoundable; break; } } } // prune child if possible if (childToPrune != null) { if (childToPrune.getChildBoundables().isEmpty()) { node.getChildBoundables().remove(childToPrune); } } return found; }
private void queryInternal(Object searchBounds, AbstractNode node, List matches) { List childBoundables = node.getChildBoundables(); for (int i = 0; i < childBoundables.size(); i++) { Boundable childBoundable = (Boundable) childBoundables.get(i); if (! getIntersectsOp().intersects(childBoundable.getBounds(), searchBounds)) { continue; } if (childBoundable instanceof AbstractNode) { queryInternal(searchBounds, (AbstractNode) childBoundable, matches); } else if (childBoundable instanceof ItemBoundable) { matches.add(((ItemBoundable)childBoundable).getItem()); } else { Assert.shouldNeverReachHere(); } } }
/** * Gets a tree structure (as a nested list) * corresponding to the structure of the items and nodes in this tree. * <p> * The returned {@link List}s contain either {@link Object} items, * or Lists which correspond to subtrees of the tree * Subtrees which do not contain any items are not included. * <p> * Builds the tree if necessary. * * @return a List of items and/or Lists */ public List itemsTree() { build(); List valuesTree = itemsTree(root); if (valuesTree == null) return new ArrayList(); return valuesTree; }
/** * Creates the levels higher than the given level * * @param boundablesOfALevel * the level to build on * @param level * the level of the Boundables, or -1 if the boundables are item * boundables (that is, below level 0) * @return the root, which may be a ParentNode or a LeafNode */ private AbstractNode createHigherLevels(List boundablesOfALevel, int level) { Assert.isTrue(!boundablesOfALevel.isEmpty()); List parentBoundables = createParentBoundables(boundablesOfALevel, level + 1); if (parentBoundables.size() == 1) { return (AbstractNode) parentBoundables.get(0); } return createHigherLevels(parentBoundables, level + 1); }
public int compare(Object o1, Object o2) { return compareDoubles( centreX((Envelope)((Boundable)o1).getBounds()), centreX((Envelope)((Boundable)o2).getBounds())); } };
/** * Returns the number of items in the tree. * * @return the number of items in the tree */ public int depth() { return super.depth(); }
/** * Gets the root node of the tree. * * @return the root node */ public AbstractNode getRoot() { build(); return root; }
protected List createParentBoundablesFromVerticalSlice(List childBoundables, int newLevel) { return super.createParentBoundables(childBoundables, newLevel); }
private void queryInternal(Object searchBounds, AbstractNode node, ItemVisitor visitor) { List childBoundables = node.getChildBoundables(); for (int i = 0; i < childBoundables.size(); i++) { Boundable childBoundable = (Boundable) childBoundables.get(i); if (! getIntersectsOp().intersects(childBoundable.getBounds(), searchBounds)) { continue; } if (childBoundable instanceof AbstractNode) { queryInternal(searchBounds, (AbstractNode) childBoundable, visitor); } else if (childBoundable instanceof ItemBoundable) { visitor.visitItem(((ItemBoundable)childBoundable).getItem()); } else { Assert.shouldNeverReachHere(); } } }
public int compare(Object o1, Object o2) { return compareDoubles( centreY((Envelope)((Boundable)o1).getBounds()), centreY((Envelope)((Boundable)o2).getBounds())); } };
protected int depth(AbstractNode node) { int maxChildDepth = 0; for (Iterator i = node.getChildBoundables().iterator(); i.hasNext(); ) { Boundable childBoundable = (Boundable) i.next(); if (childBoundable instanceof AbstractNode) { int childDepth = depth((AbstractNode) childBoundable); if (childDepth > maxChildDepth) maxChildDepth = childDepth; } } return maxChildDepth + 1; }
/** * Also builds the tree, if necessary. */ protected List query(Object searchBounds) { build(); ArrayList matches = new ArrayList(); if (isEmpty()) { //Assert.isTrue(root.getBounds() == null); return matches; } if (getIntersectsOp().intersects(root.getBounds(), searchBounds)) { queryInternal(searchBounds, root, matches); } return matches; }
public int compare(Object o1, Object o2) { return compareDoubles( ((Interval)((Boundable)o1).getBounds()).getCentre(), ((Interval)((Boundable)o2).getBounds()).getCentre()); } };