/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2001-2006 Vivid Solutions
* (C) 2001-2008, Open Source Geospatial Foundation (OSGeo)
*
* 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;
* version 2.1 of the License.
*
* 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.
*/
package org.geotools.geometry.iso.index.quadtree;
import org.geotools.geometry.iso.topograph2D.Coordinate;
import org.geotools.geometry.iso.topograph2D.Envelope;
import org.geotools.geometry.iso.util.Assert;
/**
* Represents a node of a {@link Quadtree}. Nodes contain items which have a
* spatial extent corresponding to the node's position in the quadtree.
*
*
* @source $URL$
* @version 1.7.2
*/
public class Node extends NodeBase {
public static Node createNode(Envelope env) {
Key key = new Key(env);
Node node = new Node(key.getEnvelope(), key.getLevel());
return node;
}
public static Node createExpanded(Node node, Envelope addEnv) {
Envelope expandEnv = new Envelope(addEnv);
if (node != null)
expandEnv.expandToInclude(node.env);
Node largerNode = createNode(expandEnv);
if (node != null)
largerNode.insertNode(node);
return largerNode;
}
private Envelope env;
private Coordinate centre;
private int level;
public Node(Envelope env, int level) {
// this.parent = parent;
this.env = env;
this.level = level;
centre = new Coordinate();
centre.x = (env.getMinX() + env.getMaxX()) / 2;
centre.y = (env.getMinY() + env.getMaxY()) / 2;
}
public Envelope getEnvelope() {
return env;
}
protected boolean isSearchMatch(Envelope searchEnv) {
return env.intersects(searchEnv);
}
/**
* Returns the subquad containing the envelope. Creates the subquad if it
* does not already exist.
*/
public Node getNode(Envelope searchEnv) {
int subnodeIndex = getSubnodeIndex(searchEnv, centre);
// if subquadIndex is -1 searchEnv is not contained in a subquad
if (subnodeIndex != -1) {
// create the quad if it does not exist
Node node = getSubnode(subnodeIndex);
// recursively search the found/created quad
return node.getNode(searchEnv);
} else {
return this;
}
}
/**
* Returns the smallest <i>existing</i> node containing the envelope.
*/
public NodeBase find(Envelope searchEnv) {
int subnodeIndex = getSubnodeIndex(searchEnv, centre);
if (subnodeIndex == -1)
return this;
if (subnode[subnodeIndex] != null) {
// query lies in subquad, so search it
Node node = subnode[subnodeIndex];
return node.find(searchEnv);
}
// no existing subquad, so return this one anyway
return this;
}
void insertNode(Node node) {
Assert.isTrue(env == null || env.contains(node.env));
// System.out.println(env);
// System.out.println(quad.env);
int index = getSubnodeIndex(node.env, centre);
// System.out.println(index);
if (node.level == level - 1) {
subnode[index] = node;
// System.out.println("inserted");
} else {
// the quad is not a direct child, so make a new child quad to
// contain it
// and recursively insert the quad
Node childNode = createSubnode(index);
childNode.insertNode(node);
subnode[index] = childNode;
}
}
/**
* get the subquad for the index. If it doesn't exist, create it
*/
private Node getSubnode(int index) {
if (subnode[index] == null) {
subnode[index] = createSubnode(index);
}
return subnode[index];
}
private Node createSubnode(int index) {
// create a new subquad in the appropriate quadrant
double minx = 0.0;
double maxx = 0.0;
double miny = 0.0;
double maxy = 0.0;
switch (index) {
case 0:
minx = env.getMinX();
maxx = centre.x;
miny = env.getMinY();
maxy = centre.y;
break;
case 1:
minx = centre.x;
maxx = env.getMaxX();
miny = env.getMinY();
maxy = centre.y;
break;
case 2:
minx = env.getMinX();
maxx = centre.x;
miny = centre.y;
maxy = env.getMaxY();
break;
case 3:
minx = centre.x;
maxx = env.getMaxX();
miny = centre.y;
maxy = env.getMaxY();
break;
}
Envelope sqEnv = new Envelope(minx, maxx, miny, maxy);
Node node = new Node(sqEnv, level - 1);
return node;
}
}