/*
* Copyright (c) 2016 Vivid Solutions.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
*
* http://www.eclipse.org/org/documents/edl-v10.php.
*/
package org.locationtech.jts.index.bintree;
import org.locationtech.jts.util.Assert;
/**
* A node of a {@link Bintree}.
*
* @version 1.7
*/
public class Node
extends NodeBase
{
public static Node createNode(Interval itemInterval)
{
Key key = new Key(itemInterval);
//System.out.println("input: " + env + " binaryEnv: " + key.getEnvelope());
Node node = new Node(key.getInterval(), key.getLevel());
return node;
}
public static Node createExpanded(Node node, Interval addInterval)
{
Interval expandInt = new Interval(addInterval);
if (node != null) expandInt.expandToInclude(node.interval);
Node largerNode = createNode(expandInt);
if (node != null) largerNode.insert(node);
return largerNode;
}
private Interval interval;
private double centre;
private int level;
public Node(Interval interval, int level)
{
this.interval = interval;
this.level = level;
centre = (interval.getMin() + interval.getMax()) / 2;
}
public Interval getInterval() { return interval; }
protected boolean isSearchMatch(Interval itemInterval)
{
// System.out.println(itemInterval + " overlaps " + interval + " : "
// + itemInterval.overlaps(interval));
return itemInterval.overlaps(interval);
}
/**
* Returns the subnode containing the envelope.
* Creates the node if
* it does not already exist.
*/
public Node getNode(Interval searchInterval)
{
int subnodeIndex = getSubnodeIndex(searchInterval, centre);
// if index is -1 searchEnv is not contained in a subnode
if (subnodeIndex != -1) {
// create the node if it does not exist
Node node = getSubnode(subnodeIndex);
// recursively search the found/created node
return node.getNode(searchInterval);
}
else {
return this;
}
}
/**
* Returns the smallest <i>existing</i>
* node containing the envelope.
*/
public NodeBase find(Interval searchInterval)
{
int subnodeIndex = getSubnodeIndex(searchInterval, centre);
if (subnodeIndex == -1)
return this;
if (subnode[subnodeIndex] != null) {
// query lies in subnode, so search it
Node node = subnode[subnodeIndex];
return node.find(searchInterval);
}
// no existing subnode, so return this one anyway
return this;
}
void insert(Node node)
{
Assert.isTrue(interval == null || interval.contains(node.interval));
int index = getSubnodeIndex(node.interval, centre);
if (node.level == level - 1) {
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
Node childNode = createSubnode(index);
childNode.insert(node);
subnode[index] = childNode;
}
}
/**
* get the subnode 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 subnode in the appropriate interval
double min = 0.0;
double max = 0.0;
switch (index) {
case 0:
min = interval.getMin();
max = centre;
break;
case 1:
min = centre;
max = interval.getMax();
break;
}
Interval subInt = new Interval(min, max);
Node node = new Node(subInt, level - 1);
return node;
}
}