@Override public void insertBulk( List<Pair<float[], T>> listOfObjects ) { for ( Pair<float[], T> p : listOfObjects ) { if ( p != null ) { insert( p.first, p.second ); } } }
/** * @param son * one of {@link QTree#LOWER_LEFT},{@link QTree#LOWER_RIGHT},{@link QTree#UP_LEFT},{@link QTree#UP_RIGHT} * @return a new QTree created from the given index. */ protected QTree<T> createNode( int son ) { float[] newEnv = bboxForSon( son ); return new QTree<T>( numberOfObjects, newEnv, (byte) ( currentDepth + 1 ) ); }
@SuppressWarnings("unchecked") private final void split() { children = new QTree[4]; for ( Entry<T> e : leafObjects ) { List<QTree<T>> treeNodes = getObjectNodes( e.entryEnv ); for ( QTree<T> node : treeNodes ) { node.addObject( e ); } } objectsInLeaf = 0; leafObjects = null; }
/** * Calculate the indices of the sons touching this envelope * * @param envelope * @return the indices of the sons touching the envelope */ private final int[] getIndizes( float[] envelope ) { int min = getIndex( envelope, 0 ); int max = getIndex( envelope, maxOffset ); return analyzeIndizes( envelope, min, max ); }
/** * @param entryEnv * @return the nodes the given envelope will intersect. */ final protected List<QTree<T>> getObjectNodes( float[] entryEnv ) { List<QTree<T>> list = new LinkedList<QTree<T>>(); // if the object covers the whole of this node if ( objectCoversEnvelope( entryEnv ) ) { list.add( this ); } else { if ( !isLeaf() ) { int[] indizes = getIndizes( entryEnv ); for ( int index : indizes ) { QTree<T> child = children[index]; // No children in that area create a new one if ( child == null ) { child = createNode( index ); children[index] = child; list.add( child ); } else { // traverse tree list.addAll( child.getObjectNodes( entryEnv ) ); } } } else { list.add( this ); } } return list; }
/** * @param info * @param files * @param rasters * @param options */ public DiskBasedTileContainer( QTreeInfo info, List<File> files, List<AbstractRaster> rasters, RasterIOOptions options ) { qtree = new QTree<File>( createEnvelope( info.envelope ), info.numberOfObjects ); envelope = info.envelope; AbstractRaster raster = rasters.iterator().next(); rasterDataInfo = raster.getRasterDataInfo(); rasterGeoReference = info.rasterGeoReference; resolutionInfo = raster.getResolutionInfo(); this.options = options; Iterator<File> iter = files.iterator(); for ( AbstractRaster r : rasters ) { File f = iter.next(); qtree.insert( createEnvelope( r.getEnvelope() ), f ); cache.put( f, new SoftReference<AbstractRaster>( r ) ); } initialized = true; }
/** * @param envelope * of the object * @param object * to insert * @return true if the object was inserted, false otherwise. */ @Override public boolean insert( float[] envelope, T object ) { if ( object != null ) { if ( intersects( this.envelope, envelope, maxOffset ) ) { Entry<T> obj = new Entry<T>( envelope, object ); if ( isLeaf() ) { addObject( obj ); } else { List<QTree<T>> treeNodes = getObjectNodes( obj.entryEnv ); for ( QTree<T> node : treeNodes ) { if ( node != null ) { node.addObject( obj ); } } } return true; } } return false; }
/** * */ private void merge() { if ( !isLeaf() ) { Set<Entry<T>> mergableObjects = validateChildrenSize(); if ( mergableObjects != null ) { // calculate the size of the set, after removing duplicates ArrayList<Entry<T>> objects = new ArrayList<Entry<T>>( mergableObjects ); int size = mergableObjects.size() - duplicateEnvelopes( objects ); if ( size <= numberOfObjects ) { // we can merge the children. leafObjects = objects; // leafObjects.addAll( mergableObjects ); for ( QTree<T> n : children ) { if ( n != null ) { n.objectsCoveringEnv = null; n.leafObjects = null; n = null; } } children = null; } } } }
/** * @return the number of all objects in this node, e.g. the leafObjects and the objects covering the entire * envelope. */ private final int totalSize() { return size() + ( ( objectsCoveringEnv == null ) ? 0 : ( objectsCoveringEnv.size() - duplicateEnvelopes( objectsCoveringEnv ) ) ); }
/** * Uses a QTree as a spatial index. * * @param domain * @param rasterReference * @param objectsInLeaf */ public IndexedMemoryTileContainer( Envelope domain, RasterGeoReference rasterReference, int objectsInLeaf ) { this.rasterReference = rasterReference; this.index = new QTree<AbstractRaster>( createEnvelope( domain ), objectsInLeaf ); this.domain = domain; }
private final boolean hasDuplicateLocation( final float[] objectEnvelope ) { for ( Entry<T> obj : leafObjects ) { float[] second = obj.entryEnv; double minD = calcDist( objectEnvelope, second, 0, maxOffset ); double maxD = calcDist( objectEnvelope, second, maxOffset, maxOffset ); // if min and max have distance 0, then just count as one because they are equals, this might // prevent a stack overflow if ( ( minD < SPLIT_CRITERIA_EPSILON && maxD < SPLIT_CRITERIA_EPSILON ) ) { return true; } } return false; }
/** * @param object * to insert * @return true if the object was inserted, false otherwise. */ public boolean insert( T object ) { if ( object == null ) { return false; } this.maxError = Math.max( object.getErrorScalar(), maxError ); return super.insert( object.getModelBBox(), object ); }
/** * Adds a new tile to the container. * * @param raster * new tile */ public void addTile( AbstractRaster raster ) { if ( raster != null ) { if ( this.rdi == null ) { this.rdi = raster.getRasterDataInfo(); } if ( this.resolutionInfo == null ) { this.resolutionInfo = raster.getResolutionInfo(); } index.insert( createEnvelope( raster.getEnvelope() ), raster ); } }