// **********************************************************************
//
// <copyright>
//
// BBN Technologies
// 10 Moulton Street
// Cambridge, MA 02138
// (617) 873-8000
//
// Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/util/quadtree/QuadTree.java,v $
// $RCSfile: QuadTree.java,v $
// $Revision: 1.3 $
// $Date: 2004/10/14 18:06:31 $
// $Author: dietrick $
//
// **********************************************************************
package com.bbn.openmap.util.quadtree;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import com.bbn.openmap.MoreMath;
import com.bbn.openmap.util.DataOrganizer;
/**
* The QuadTree lets you organize objects in a grid, that redefines itself and
* refines the gridding over locations where more objects are gathered.
*/
public class QuadTree<T> implements DataOrganizer<T>, Serializable {
static final long serialVersionUID = -7707825592455579873L;
protected QuadTreeNode<T> top;
public QuadTree() {
this(90.0, -180.0, -90.0, 180.0, 20, QuadTreeNode.NO_MIN_SIZE);
}
public QuadTree(double north, double west, double south, double east, int maxItems) {
this(north, west, south, east, maxItems, QuadTreeNode.NO_MIN_SIZE);
}
public QuadTree(int up, int left, int down, int right, int maxItems) {
this(up, left, down, right, maxItems, QuadTreeNode.DEFAULT_MIN_SIZE);
}
public QuadTree(double north, double west, double south, double east, int maxItems,
double minSize) {
top = new QuadTreeNode<T>(north, west, south, east, maxItems, minSize);
}
/**
* Add a object into the tree at a location.
*
* @param lat up-down location in QuadTree Grid (latitude, y)
* @param lon left-right location in QuadTree Grid (longitude, x)
* @param obj the object to insert into the tree
* @return true if the insertion worked.
*/
public boolean put(double lat, double lon, T obj) {
return top.put(lat, lon, obj);
}
/**
* Remove a object out of the tree at a location.
*
* @param lat up-down location in QuadTree Grid (latitude, y)
* @param lon left-right location in QuadTree Grid (longitude, x)
* @param obj the object to remove
* @return the object removed, null if the object not found.
*/
public T remove(double lat, double lon, T obj) {
return top.remove(lat, lon, obj);
}
/** Clear the tree. */
public void clear() {
top.clear();
}
/**
* Get an object closest to a lat/lon.
*
* @param lat up-down location in QuadTree Grid (latitude, y)
* @param lon left-right location in QuadTree Grid (longitude, x)
* @return the object that was found.
*/
public T get(double lat, double lon) {
return top.get(lat, lon);
}
/**
* Get an object closest to a lat/lon, within a maximum distance.
*
* @param lat up-down location in QuadTree Grid (latitude, y)
* @param lon left-right location in QuadTree Grid (longitude, x)
* @param withinDistance the maximum distance to get a hit, in decimal
* degrees.
* @return the object that was found, null if nothing is within the maximum
* distance.
*/
public T get(double lat, double lon, double withinDistance) {
return top.get(lat, lon, withinDistance);
}
/**
* Get all the objects within a bounding box.
*
* @param north top location in QuadTree Grid (latitude, y)
* @param west left location in QuadTree Grid (longitude, x)
* @param south lower location in QuadTree Grid (latitude, y)
* @param east right location in QuadTree Grid (longitude, x)
* @return Vector of objects.
*/
public Collection get(double north, double west, double south, double east) {
return get(north, west, south, east, null);
}
/**
* Get all the objects within a bounding box, and return the objects in the
* provided Collection.
*
* @param north top location in QuadTree Grid (latitude, y)
* @param west left location in QuadTree Grid (longitude, x)
* @param south lower location in QuadTree Grid (latitude, y)
* @param east right location in QuadTree Grid (longitude, x)
* @param collection a Collection to add objects to.
* @return Collection of objects.
*/
public Collection get(double north, double west, double south, double east,
Collection collection) {
if (collection == null) {
collection = new ArrayList<Object>();
}
// crossing the dateline, right?? Or at least containing the
// entire earth. Might be trouble for VERY LARGE scales. The
// last check is for micro-errors that happen to lon points
// where there might be a smudge overlap for very small
// scales.
if (west > east || MoreMath.approximately_equal(west, east, .001)) {
return top.get(north, west, south, 180, top.get(north, -180, south, east, collection));
} else
return top.get(north, west, south, east, collection);
}
}