001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/io/quadtree/MemPointNode.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 This file is part of deegree. 004 Copyright (C) 2001-2007 by: 005 Department of Geography, University of Bonn 006 http://www.giub.uni-bonn.de/deegree/ 007 lat/lon GmbH 008 http://www.lat-lon.de 009 This library is free software; you can redistribute it and/or 010 modify it under the terms of the GNU Lesser General Public 011 License as published by the Free Software Foundation; either 012 version 2.1 of the License, or (at your option) any later version. 013 This library is distributed in the hope that it will be useful, 014 but WITHOUT ANY WARRANTY; without even the implied warranty of 015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 016 Lesser General Public License for more details. 017 You should have received a copy of the GNU Lesser General Public 018 License along with this library; if not, write to the Free Software 019 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 Contact: 021 Andreas Poth 022 lat/lon GmbH 023 Aennchenstrasse 19 024 53177 Bonn 025 Germany 026 E-Mail: poth@lat-lon.de 027 Jens Fitzke 028 lat/lon GmbH 029 Aennchenstrasse 19 030 53177 Bonn 031 Germany 032 E-Mail: jens.fitzke@uni-bonn.de 033 ---------------------------------------------------------------------------*/ 034 package org.deegree.io.quadtree; 035 036 import java.util.ArrayList; 037 import java.util.List; 038 039 import org.deegree.model.spatialschema.Envelope; 040 import org.deegree.model.spatialschema.GeometryFactory; 041 042 /** 043 * <code>MemPointNode</code> is the node class of a memory based implementation of a quadtree. 044 * 045 * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a> 046 * @author last edited by: $Author: apoth $ 047 * 048 * @version 2.0, $Revision: 7845 $, $Date: 2007-07-25 09:45:35 +0200 (Mi, 25 Jul 2007) $ 049 * 050 * @since 2.0 051 */ 052 053 public class MemPointNode implements Node { 054 055 private final Envelope envelope; 056 057 private final int level; 058 059 private MemPointNode[] subnodes; 060 061 private List<Object> items; 062 063 private List<Envelope> itemsEnvelope; 064 065 private Quadtree owner; 066 067 /** 068 * Constructs a new node with the given envelope, object, location and level. 069 * 070 * @param owner 071 * @param env 072 * the envelope 073 * @param lvl 074 * the level 075 */ 076 public MemPointNode( Quadtree owner, Envelope env, int lvl ) { 077 envelope = env; 078 level = lvl; 079 this.owner = owner; 080 } 081 082 /** 083 * @return the deepest level of this subtree 084 */ 085 public int getDepth() { 086 if ( subnodes == null ) { 087 return level; 088 } 089 090 int max = 0; 091 int d = 0; 092 093 for ( MemPointNode node : subnodes ) { 094 if ( node != null ) { 095 d = node.getDepth(); 096 if ( d > max ) { 097 max = d; 098 } 099 } 100 } 101 102 return max; 103 } 104 105 /** 106 * @return the region of this node 107 */ 108 public Envelope getEnvelope() { 109 return envelope; 110 } 111 112 /** 113 * This method does not make sense for the memory implementation. 114 * 115 * @return null 116 */ 117 public String getId() { 118 return null; 119 } 120 121 /** 122 * Inserts the item into the quadtree. 123 * 124 * @param item 125 * the item 126 * @param itemEnv 127 * the envelope of the item 128 */ 129 public void insert( Object item, Envelope itemEnv ) 130 throws IndexException { 131 132 if ( !envelope.intersects( itemEnv ) ) { 133 throw new IndexException( "Item envelope does not intersect with node envelope!" ); 134 } 135 136 if ( level < ( (MemPointQuadtree) owner ).maxDepth ) { 137 Envelope[] envs = split(); 138 139 if ( subnodes == null ) { 140 subnodes = new MemPointNode[4]; 141 } 142 143 for ( int i = 0; i < 4; ++i ) { 144 if ( envs[i].intersects( itemEnv ) ) { 145 if ( subnodes[i] == null ) { 146 subnodes[i] = new MemPointNode( owner, envs[i], level + 1 ); 147 } 148 subnodes[i].insert( item, itemEnv ); 149 } 150 } 151 } else { 152 if ( items == null ) { 153 items = new ArrayList<Object>( 50 ); 154 itemsEnvelope = new ArrayList<Envelope>( 50 ); 155 } 156 items.add( item ); 157 itemsEnvelope.add( itemEnv ); 158 } 159 160 } 161 162 /** 163 * Searches for all items intersecting the search envelope. 164 * 165 * @param searchEnv 166 * the search envelope 167 * @param visitor 168 * the resulting list 169 * @param level 170 * unused by this implementation 171 * @return a list with all found items 172 */ 173 public List<Object> query( Envelope searchEnv, List<Object> visitor, int level ) 174 throws IndexException { 175 176 if ( subnodes == null ) { 177 return visitor; 178 } 179 180 for ( int i = 0; i < 4; ++i ) { 181 if ( subnodes[i] != null ) { 182 MemPointNode node = subnodes[i]; 183 if ( node.items != null ) { 184 if ( subnodes[i].envelope.intersects( searchEnv ) ) { 185 for ( int j = 0; j < node.itemsEnvelope.size(); j++ ) { 186 Envelope env = node.itemsEnvelope.get( j ); 187 if ( env.intersects( searchEnv ) ) { 188 visitor.addAll( node.items ); 189 } 190 } 191 } 192 } else { 193 if ( node.envelope.intersects( searchEnv ) ) { 194 node.query( searchEnv, visitor, level ); 195 } 196 } 197 } 198 } 199 200 return visitor; 201 } 202 203 /** 204 * Deletes the item from the quadtree. Untested method! 205 * 206 * @param item 207 * the item to be deleted 208 */ 209 public void deleteItem( Object item ) { 210 211 if ( subnodes == null ) { 212 return; 213 } 214 215 for ( int i = 0; i < 4; ++i ) { 216 if ( subnodes[i] != null ) { 217 MemPointNode node = subnodes[i]; 218 if ( node.items.contains( item ) ) { 219 node.items.remove( item ); 220 } else { 221 node.deleteItem( item ); 222 } 223 } 224 } 225 226 } 227 228 /** 229 * Deletes all items intersecting the envelope. Untested method! 230 * 231 * @param envelope 232 */ 233 public void deleteRange( Envelope envelope ) { 234 235 if ( subnodes == null ) { 236 return; 237 } 238 239 for ( int i = 0; i < 4; ++i ) { 240 if ( subnodes[i] != null ) { 241 MemPointNode node = subnodes[i]; 242 if ( node.envelope.intersects( envelope ) ) { 243 subnodes[i] = null; 244 } else { 245 if ( node.envelope.intersects( envelope ) ) { 246 node.deleteRange( envelope ); 247 } 248 } 249 } 250 } 251 252 } 253 254 // splits the envelope of this node in four pieces 255 private Envelope[] split() { 256 Envelope[] envs = new Envelope[4]; 257 double nW = envelope.getWidth() / 2d; 258 double nH = envelope.getHeight() / 2d; 259 260 envs[0] = GeometryFactory.createEnvelope( envelope.getMin().getX(), envelope.getMin().getY(), 261 envelope.getMin().getX() + nW, envelope.getMin().getY() + nH, null ); 262 envs[1] = GeometryFactory.createEnvelope( envelope.getMin().getX() + nW, envelope.getMin().getY(), 263 envelope.getMin().getX() + ( 2 * nW ), envelope.getMin().getY() + nH, 264 null ); 265 envs[2] = GeometryFactory.createEnvelope( envelope.getMin().getX() + nW, envelope.getMin().getY() + nH, 266 envelope.getMin().getX() + ( 2 * nW ), envelope.getMin().getY() 267 + ( 2 * nH ), null ); 268 envs[3] = GeometryFactory.createEnvelope( envelope.getMin().getX(), envelope.getMin().getY() + nH, 269 envelope.getMin().getX() + nW, envelope.getMin().getY() + ( 2 * nH ), 270 null ); 271 272 return envs; 273 } 274 275 }