/* XXL: The eXtensible and fleXible Library for data processing Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger Head of the Database Research Group Department of Mathematics and Computer Science University of Marburg Germany This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; If not, see <http://www.gnu.org/licenses/>. http://code.google.com/p/xxl/ */ package xxl.core.indexStructures; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Stack; import xxl.core.comparators.ComparableComparator; import xxl.core.comparators.FeatureComparator; import xxl.core.cursors.Cursors; import xxl.core.cursors.sources.Enumerator; import xxl.core.functions.AbstractFunction; import xxl.core.spatial.rectangles.Rectangle; /** An <tt>RTree</tt> implementing the split-strategy proposed by D. Greene. * * For a detailed discussion see D. Greene: * "An Implementation and Performance Analysis of Spatial Data Access Methods", * Proc. 5th Int. Conf. on Data Engineering, 606-615, 1989. * * @see Tree * @see ORTree * @see RTree */ public class GreenesRTree extends RTree { /* (non-Javadoc) * @see xxl.core.indexStructures.Tree#createNode(int) */ public Tree.Node createNode (int level) { return new Node().initialize(level, new LinkedList()); } /** A modification of {@link RTree.Node node} implementing Greenes split-algorithm. * * @see RTree.Node */ public class Node extends RTree.Node { /* (non-Javadoc) * @see xxl.core.indexStructures.Tree.Node#split(java.util.Stack) */ protected Tree.Node.SplitInfo split (final Stack path) { final Node node = (Node)node(path); final int splitNumber = (node.splitMinNumber()+node.splitMaxNumber())/2; final int dimensions = ((Rectangle)rootDescriptor()).dimensions(); final int splitDimension = ((Integer)Cursors.maxima(new Enumerator(dimensions), new AbstractFunction() { Rectangle MBR = rectangle(indexEntry(path)); public Object invoke (Object object) { final int dimension = ((Integer)object).intValue(); Object e1 = Cursors.minima(node.entries(), new AbstractFunction() { public Object invoke (Object object) { return new Double(rectangle(object).getCorner(true).getValue(dimension)); } } ).getFirst(); Object e2 = Cursors.maxima(node.entries(), new AbstractFunction() { public Object invoke (Object object) { return new Double(rectangle(object).getCorner(false).getValue(dimension)); } } ).getLast(); return new Double( (rectangle(e2).getCorner(false).getValue(dimension)-rectangle(e1).getCorner(true).getValue(dimension))/ (MBR.getCorner(true).getValue(dimension)-MBR.getCorner(false).getValue(dimension)) ); } } ).getFirst()).intValue(); List entries = new ArrayList(node.entries); node.entries.clear(); Collections.sort(entries, new FeatureComparator(new ComparableComparator(), new AbstractFunction() { public Object invoke (Object entry) { return new Double(rectangle(entry).getCorner(false).getValue(splitDimension)); } } )); node.entries.addAll(entries.subList(0, splitNumber)); this.entries.addAll(entries.subList(splitNumber, entries.size())); ((IndexEntry)indexEntry(path)).descriptor = computeDescriptor(node.entries); return new SplitInfo(path).initialize(computeDescriptor(this.entries)); } } }