Search in sources :

Example 1 with SplitHistory

use of de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.xtree.util.SplitHistory in project elki by elki-project.

the class AbstractXTree method createNewRoot.

/**
 * Creates a new root node that points to the two specified child nodes and
 * return the path to the new root.
 *
 * @param oldRoot the old root of this RTree
 * @param newNode the new split node
 * @param splitAxis the split axis used for the split causing this new root
 * @return the path to the new root node that points to the two specified
 *         child nodes
 */
protected IndexTreePath<SpatialEntry> createNewRoot(final N oldRoot, final N newNode, int splitAxis) {
    N root = createNewDirectoryNode();
    writeNode(root);
    // get split history
    SplitHistory sh = null;
    // TODO: see whether root entry is ALWAYS a directory entry .. it SHOULD!
    sh = ((XTreeDirectoryEntry) getRootEntry()).getSplitHistory();
    if (sh == null) {
        sh = new SplitHistory(getDimensionality());
    }
    sh.setDim(splitAxis);
    // switch the ids
    oldRoot.setPageID(root.getPageID());
    if (!oldRoot.isLeaf()) {
        // TODO: test whether this is neccessary
        for (int i = 0; i < oldRoot.getNumEntries(); i++) {
            N node = getNode(oldRoot.getEntry(i));
            writeNode(node);
        }
    }
    // adjust supernode id
    if (oldRoot.isSuperNode()) {
        supernodes.remove(new Long(getRootID()));
        supernodes.put(new Long(oldRoot.getPageID()), oldRoot);
    }
    root.setPageID(getRootID());
    SpatialEntry oldRootEntry = createNewDirectoryEntry(oldRoot);
    SpatialEntry newNodeEntry = createNewDirectoryEntry(newNode);
    ((SplitHistorySpatialEntry) oldRootEntry).setSplitHistory(sh);
    try {
        ((SplitHistorySpatialEntry) newNodeEntry).setSplitHistory((SplitHistory) sh.clone());
    } catch (CloneNotSupportedException e) {
        throw new RuntimeException("Clone of a split history should not throw an Exception", e);
    }
    root.addDirectoryEntry(oldRootEntry);
    root.addDirectoryEntry(newNodeEntry);
    writeNode(root);
    writeNode(oldRoot);
    writeNode(newNode);
    if (getLogger().isDebugging()) {
        getLogger().debugFine(// 
        new StringBuilder(1000).append("Create new Root: ID=").append(root.getPageID()).append("\nchild1 ").append(oldRoot).append(' ').append(// 
        new HyperBoundingBox(oldRootEntry)).append("\nchild2 ").append(newNode).append(' ').append(new HyperBoundingBox(newNodeEntry)));
    }
    // the root entry still needs to be set to the new root node's MBR
    return new IndexTreePath<>(null, getRootEntry(), 0);
}
Also used : IndexTreePath(de.lmu.ifi.dbs.elki.index.tree.IndexTreePath) ModifiableHyperBoundingBox(de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox) HyperBoundingBox(de.lmu.ifi.dbs.elki.data.HyperBoundingBox) SplitHistory(de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.xtree.util.SplitHistory) SpatialEntry(de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry)

Example 2 with SplitHistory

use of de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.xtree.util.SplitHistory in project elki by elki-project.

the class AbstractXTree method adjustTree.

/**
 * Adjusts the tree after insertion of some nodes.
 *
 * @param subtree the subtree to be adjusted
 */
@Override
protected void adjustTree(IndexTreePath<SpatialEntry> subtree) {
    if (getLogger().isDebugging()) {
        getLogger().debugFine("Adjust tree " + subtree);
    }
    // get the root of the subtree
    N node = getNode(subtree.getEntry());
    // overflow in node
    if (hasOverflow(node)) {
        if (node.isSuperNode()) {
            int new_capacity = node.growSuperNode();
            getLogger().finest("Extending supernode to new capacity " + new_capacity);
            if (isRoot(node)) {
                // is root
                node.adjustEntry(getRootEntry());
            } else {
                N parent = getNode(subtree.getParentPath().getEntry());
                SpatialEntry e = parent.getEntry(subtree.getIndex());
                HyperBoundingBox mbr = new HyperBoundingBox(e);
                node.adjustEntry(e);
                if (!SpatialUtil.equals(mbr, e)) {
                    // MBR has changed
                    // write changes in parent to file
                    writeNode(parent);
                    adjustTree(subtree.getParentPath());
                }
            }
        } else {
            int[] splitAxis = { -1 };
            // treatment of overflow: reinsertion or split
            N split = overflowTreatment(node, subtree, splitAxis);
            // node was split
            if (split != null) {
                // split nodes
                if (isRoot(node)) {
                    IndexTreePath<SpatialEntry> newRootPath = createNewRoot(node, split, splitAxis[0]);
                    height++;
                    adjustTree(newRootPath);
                } else // node is not root
                {
                    // get the parent and add the new split node
                    N parent = getNode(subtree.getParentPath().getEntry());
                    if (getLogger().isDebugging()) {
                        getLogger().debugFine("parent " + parent);
                    }
                    SpatialEntry newEntry = createNewDirectoryEntry(split);
                    parent.addDirectoryEntry(newEntry);
                    // The below variant does not work in the persistent version
                    // E oldEntry = subtree.getEntry();
                    // [reason: if oldEntry is modified, this must be permanent]
                    SpatialEntry oldEntry = parent.getEntry(subtree.getIndex());
                    // adjust split history
                    SplitHistory sh = ((SplitHistorySpatialEntry) oldEntry).getSplitHistory();
                    if (sh == null) {
                        // not yet initialized (dimension not known of this tree)
                        sh = new SplitHistory(oldEntry.getDimensionality());
                        sh.setDim(splitAxis[0]);
                        ((SplitHistorySpatialEntry) oldEntry).setSplitHistory(sh);
                    } else {
                        ((SplitHistorySpatialEntry) oldEntry).addSplitDimension(splitAxis[0]);
                    }
                    try {
                        ((SplitHistorySpatialEntry) newEntry).setSplitHistory((SplitHistory) sh.clone());
                    } catch (CloneNotSupportedException e) {
                        throw new RuntimeException("Clone of a split history should not throw an Exception", e);
                    }
                    // adjust the entry representing the (old) node, that has
                    // been split
                    node.adjustEntry(oldEntry);
                    // write changes in parent to file
                    writeNode(parent);
                    adjustTree(subtree.getParentPath());
                }
            }
        }
    } else // no overflow, only adjust parameters of the entry representing the
    // node
    {
        if (!isRoot(node)) {
            N parent = getNode(subtree.getParentPath().getEntry());
            SpatialEntry e = parent.getEntry(subtree.getIndex());
            HyperBoundingBox mbr = new HyperBoundingBox(e);
            node.adjustEntry(e);
            if (// we already know that mbr is extended
            node.isLeaf() || !SpatialUtil.equals(mbr, e)) {
                // MBR has changed
                // write changes in parent to file
                writeNode(parent);
                adjustTree(subtree.getParentPath());
            }
        } else // root level is reached
        {
            node.adjustEntry(getRootEntry());
        }
    }
}
Also used : ModifiableHyperBoundingBox(de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox) HyperBoundingBox(de.lmu.ifi.dbs.elki.data.HyperBoundingBox) SpatialEntry(de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry) SplitHistory(de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.xtree.util.SplitHistory)

Aggregations

HyperBoundingBox (de.lmu.ifi.dbs.elki.data.HyperBoundingBox)2 ModifiableHyperBoundingBox (de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox)2 SpatialEntry (de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry)2 SplitHistory (de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.xtree.util.SplitHistory)2 IndexTreePath (de.lmu.ifi.dbs.elki.index.tree.IndexTreePath)1