/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * 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 2.1 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.revolsys.geometry.index.bintree; import com.revolsys.geometry.util.Assert; /** * A node of a {@link Bintree}. * * @version 1.7 */ public class Node extends NodeBase { public static Node newNode(final Interval itemInterval) { final Key key = new Key(itemInterval); // System.out.println("input: " + env + " binaryEnv: " + // key.getEnvelope()); final Node node = new Node(key.getInterval(), key.getLevel()); return node; } public static Node newNodeExpanded(final Node node, final Interval addInterval) { final Interval expandInt = new Interval(addInterval); if (node != null) { expandInt.expandToInclude(node.interval); } final Node largerNode = newNode(expandInt); if (node != null) { largerNode.insert(node); } return largerNode; } private final double centre; private final Interval interval; private final int level; public Node(final Interval interval, final int level) { this.interval = interval; this.level = level; this.centre = (interval.getMin() + interval.getMax()) / 2; } /** * Returns the smallest <i>existing</i> * node containing the envelope. */ public NodeBase find(final Interval searchInterval) { final int subnodeIndex = getSubnodeIndex(searchInterval, this.centre); if (subnodeIndex == -1) { return this; } if (this.subnode[subnodeIndex] != null) { // query lies in subnode, so search it final Node node = this.subnode[subnodeIndex]; return node.find(searchInterval); } // no existing subnode, so return this one anyway return this; } public Interval getInterval() { return this.interval; } /** * Returns the subnode containing the envelope. * Creates the node if * it does not already exist. */ public Node getNode(final Interval searchInterval) { final int subnodeIndex = getSubnodeIndex(searchInterval, this.centre); // if index is -1 searchEnv is not contained in a subnode if (subnodeIndex != -1) { // create the node if it does not exist final Node node = getSubnode(subnodeIndex); // recursively search the found/created node return node.getNode(searchInterval); } else { return this; } } /** * get the subnode for the index. * If it doesn't exist, create it */ private Node getSubnode(final int index) { if (this.subnode[index] == null) { this.subnode[index] = newSubnode(index); } return this.subnode[index]; } void insert(final Node node) { Assert.isTrue(this.interval == null || this.interval.contains(node.interval)); final int index = getSubnodeIndex(node.interval, this.centre); if (node.level == this.level - 1) { this.subnode[index] = node; } else { // the node is not a direct child, so make a new child node to contain it // and recursively insert the node final Node childNode = newSubnode(index); childNode.insert(node); this.subnode[index] = childNode; } } @Override protected boolean isSearchMatch(final Interval itemInterval) { // System.out.println(itemInterval + " overlaps " + interval + " : " // + itemInterval.overlaps(interval)); return itemInterval.overlaps(this.interval); } private Node newSubnode(final int index) { // Construct a new new subnode in the appropriate interval double min = 0.0; double max = 0.0; switch (index) { case 0: min = this.interval.getMin(); max = this.centre; break; case 1: min = this.centre; max = this.interval.getMax(); break; } final Interval subInt = new Interval(min, max); final Node node = new Node(subInt, this.level - 1); return node; } }