/** * @param <T> * @param storagePath * absolute path to the file * @return a new instance * @throws IOException */ public static <T> RTree<T> loadFromDisk( String storagePath ) throws IOException { RTree<T> tree = null; File storageFile = new File( storagePath ); DataInputStream dis = new DataInputStream( new FileInputStream( storageFile ) ); float[] loadedBbox = loadBboxFromDisk( dis ); int loadedBigM = dis.readInt(); tree = new RTree<T>( loadedBbox, loadedBigM ); tree.root = tree.loadNodeFromDisk( dis ); dis.close(); return tree; }
if ( removed ) { removeFromArray( entries, entryIndex ); if ( notNullLength( entries ) < smallm ) { for ( int i = 0; i < entries.length; i++ ) { if ( entries[i] != null ) { addOrphanedEntries( entries[i] ); entries[i] = null; condenseTree( trace, traceIndex + 1, true ); condenseTree( trace, traceIndex + 1, false ); insertNode( orphaned.bbox, orphaned.entryValue, trace[traceIndex].node ); trace[traceIndex].node[entryIndex].bbox = mbb( copyBoxesFromRange( trace[traceIndex - 1].node, 0, trace[traceIndex - 1].node.length ) ); condenseTree( trace, traceIndex + 1, false ); insert( orphaned.bbox, orphaned.entryValue );
/** * @param env * @return a list of objects intersecting the given boundingbox. */ @Override public LinkedList<T> query( float[] env ) { if ( root != null ) { // final float[] bbox = new float[] { env.getMin().get0(), env.getMin().get1(), // env.getMax().get0(), env.getMax().get1() }; if ( intersects( env, this.rootbbox, 2 ) ) { return query( env, root ); } } LOG.debug( "Querying either a null tree or with a envelope that does not intersect it... returning." ); return new LinkedList<T>(); }
@SuppressWarnings("unchecked") private void insertNode( float[] insertBox, T object, NodeEntry<T>[] entries ) { List<TraceCell<T>> trace = new ArrayList<TraceCell<T>>(); NodeEntry<T>[] leafNode = chooseLeaf( insertBox, entries, trace ); NodeEntry<T> newEntry = new NodeEntry<T>(); newEntry.bbox = insertBox; newEntry.entryValue = object; newEntry.next = null; int index = lastNotNull( leafNode ); leafNode[index + 1] = newEntry; if ( leafNode[bigM] != null ) { int splitIndex = split( leafNode, insertBox, object ); NodeEntry<T>[] addedNode = new NodeEntry[bigM + 1]; Arrays.fill( addedNode, null ); System.arraycopy( leafNode, splitIndex + 1, addedNode, 0, bigM - splitIndex ); Arrays.fill( leafNode, splitIndex + 1, bigM + 1, null ); adjustTree( leafNode, addedNode, trace, trace.size() - 1 ); } else { adjustTree( leafNode, null, trace, trace.size() - 1 ); } }
int nLeftEntries = lastNotNull( leftEntries ); parent[parentIndex].bbox = mbb( copyBoxesFromRange( leftEntries, 0, nLeftEntries + 1 ) ); parent[parentIndex].next = leftEntries; int nRightEntries = lastNotNull( rightEntries ); newEntry.bbox = mbb( copyBoxesFromRange( rightEntries, 0, nRightEntries + 1 ) ); newEntry.next = rightEntries; addAfterLast( newEntry, parent, parentIndex ); int splitIndex = split( parent, newEntry.bbox, null ); Arrays.fill( parent, splitIndex + 1, bigM + 1, null ); adjustTree( parent, addedNode, trace, traceIndex - 1 ); } else { adjustTree( parent, null, trace, traceIndex - 1 ); parent[parentIndex].bbox = mbb( copyBoxesFromRange( leftEntries, 0, nLeftEntries ) ); adjustTree( parent, null, trace, traceIndex - 1 );
/** * @param shapeReader */ private static Pair<RTree<Long>, Boolean> createIndex( SHPReader shapeReader ) { Envelope env = shapeReader.getEnvelope(); // use 128 values per rect. RTree<Long> result = new RTree<Long>( createEnvelope( env ), -1 ); // to work around Java's non-existent variant type LOG.debug( "Read envelopes from shape file..." ); Pair<ArrayList<Pair<float[], Long>>, Boolean> p = shapeReader.readEnvelopes(); LOG.debug( "done reading envelopes." ); result.insertBulk( p.first ); return new Pair<RTree<Long>, Boolean>( result, p.second ); }
/** * Adds the given {@link Feature} instance and updates the index structures. * * @param features * feature to be added, must not be <code>null</code> and must have an id (as well as every geometry) */ void addFeature( Feature feature ) { FeatureType ft = feature.getType(); FeatureCollection fc = ftToFeatures.get( ft ); if ( fc == null ) { fc = new GenericFeatureCollection(); ftToFeatures.put( ft, fc ); } fc.add( feature ); idToObject.put( feature.getId(), feature ); if ( feature.getEnvelope() != null ) { RTree<Feature> rTree = ftToIndex.get( ft ); float[] insertBox = toFloats( feature.getEnvelope() ); if ( rTree == null ) { rTree = new RTree<Feature>( insertBox, 16 ); } rTree.insert( insertBox, feature ); } }
LinkedList<LinkedList<Pair<float[], ?>>> slices = slice( sortEnvelopes( rects, 0 ), bigM * bigM ); ArrayList<Pair<float[], NodeEntry<T>[]>> newRects = new ArrayList<Pair<float[], NodeEntry<T>[]>>(); TreeMap<Float, LinkedList<Pair<float[], ?>>> map = sort( slice, 1 ); return buildFromFloat( (List) newRects );
LinkedList<LinkedList<Pair<float[], ?>>> slices = slice( sort( rects, 0 ), bigM * bigM ); ArrayList<Pair<float[], NodeEntry<T>[]>> newRects = new ArrayList<Pair<float[], NodeEntry<T>[]>>(); TreeMap<Float, LinkedList<Pair<float[], ?>>> map = sort( slice, 1 ); return buildFromFloat( (List) newRects );
fc = new GenericFeatureCollection( null, index.query( floats ) );
/** * Builds the index from the given objects with their envelope. * * @param listOfObjects */ @SuppressWarnings("unchecked") @Override public void insertBulk( List<Pair<float[], T>> listOfObjects ) { root = buildTree( (List) listOfObjects ); }
/** * @param entry */ private void addOrphanedEntries( NodeEntry<T> entry ) { if ( entry.next == null ) { removedNodeEntries.add( entry ); return; } NodeEntry<T>[] nextLevelEntries = entry.next; for ( int i = 0; i < nextLevelEntries.length; i++ ) { if ( nextLevelEntries[i] != null ) { addOrphanedEntries( nextLevelEntries[i] ); } } }
private void rebuildRtrees() { ftToIndex.clear(); for ( FeatureType ft : ftToFeatures.keySet() ) { FeatureCollection fc = ftToFeatures.get( ft ); Envelope env = fc.getEnvelope(); if ( env != null ) { RTree<Feature> index = new RTree<Feature>( toFloats( env ), 16 ); List<Pair<float[], Feature>> fBboxes = new ArrayList<Pair<float[], Feature>>( fc.size() ); for ( Feature f : fc ) { Envelope fEnv = f.getEnvelope(); if ( fEnv != null ) { float[] floats = toFloats( fEnv ); fBboxes.add( new Pair<float[], Feature>( floats, f ) ); } } index.insertBulk( fBboxes ); ftToIndex.put( ft, index ); } } }
private LinkedList<T> query( final float[] bbox, NodeEntry<T>[] node ) { LinkedList<T> list = new LinkedList<T>(); for ( NodeEntry<T> e : node ) { if ( e != null && intersects( bbox, e.bbox, 2 ) ) { if ( e.next == null ) { list.add( e.entryValue ); // rb: uncommented if ( ( list.size() >= bigM * 10 && outputWarning ) ) { outputWarning = false; // LOG.warn( // "Collecting features should stop because {} features were loaded, which was 10 times larger then the maxNumberOfObjects {} (which is currently hardcoded). Continue filling the list though.", // list.size(), this.maxNumberOfObjects ); // return list; } } else { list.addAll( query( bbox, e.next ) ); if ( ( list.size() >= bigM * 10 ) && outputWarning ) { outputWarning = false; // LOG.warn( // "Collecting features should stop because {} features were loaded, which was 10 times larger then the maxNumberOfObjects {} (which is currently hardcoded). Continue filling the list though.", // list.size(), this.maxNumberOfObjects ); // return list; } } } } return list; }