All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.uci.ics.jung.visualization.spatial.rtree.RTree Maven / Gradle / Ivy

package edu.uci.ics.jung.visualization.spatial.rtree;

import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;
import edu.uci.ics.jung.visualization.spatial.TreeNode;
import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * R-Tree or R*-Tree implementation, depending on the type of Splitters passed in the
 * SplitterContext
 *
 * 

Based on * The R*-tree: An Efficient and Robust Access Method for Points and Rectangles+ Norbert * Beckmann, Hans-Peter begel, Ralf Schneider, Bernhard Seeger Praktuche Informatlk, Umversltaet * Bremen, D-2800 Bremen 33, West Germany * * @author Tom Nelson */ public class RTree { private static final Logger log = LoggerFactory.getLogger(RTree.class); /** the root of the R-Tree */ private final Optional> root; /** @return the root of the R-Tree */ public Optional> getRoot() { return root; } /** create an empty R-Tree */ private RTree() { root = Optional.empty(); } /** * create an R-Tree with the passed Node as the root * * @param node the node that will be the root */ private RTree(Node node) { Preconditions.checkArgument( !node.getParent().isPresent(), "Error creating R-Tree with root that has parent"); root = Optional.of(node); } /** * create and return an empty R-Tree * * @param * @return an empty R-Tree */ public static RTree create() { return new RTree(); } /** * add one element to the RTree * * @param splitterContext the R*Tree or R-Tree rules * @param element to add to the tree * @param bounds for the element to add * @return a new RTree containing the added element */ public RTree add(SplitterContext splitterContext, T element, Rectangle2D bounds) { // see if the root is not present (i.e. the RTree is empty if (!root.isPresent()) { // The first element addded to an empty RTree // Return a new RTree with the new LeafNode as its root return new RTree(LeafNode.create(element, bounds)); } // otherwise... Node node = root.get(); if (node instanceof LeafNode) { // the root is a LeafNode LeafNode leafNode = (LeafNode) node; Node got = leafNode.add(splitterContext, element, bounds); Preconditions.checkArgument( !got.getParent().isPresent(), "return from LeafNode add has a parent"); return new RTree(got); } else { InnerNode innerNode = (InnerNode) node; Node got = innerNode.add(splitterContext, element, bounds); Preconditions.checkArgument( !got.getParent().isPresent(), "return from InnerNode add has a parent"); return new RTree(got); } } /** * remove an element from the tree * * @param element * @return */ public RTree remove(T element) { log.trace("want to remove {} from tree of size {}", element, count()); if (!root.isPresent()) { // this tree is empty return new RTree(); } Node rootNode = root.get(); Node newRoot = rootNode.remove(element); return new RTree(newRoot); } /** * return an object at point p * * @param p point to search * @return an element that contains p or null */ public T getPickedObject(Point2D p) { Node root = this.root.get(); if (root instanceof LeafNode) { LeafNode leafNode = (LeafNode) root; return leafNode.getPickedObject(p); } else if (root instanceof InnerNode) { InnerNode innerNode = (InnerNode) root; return innerNode.getPickedObject(p); } else { return null; } } /** @return a collection of rectangular bounds of the R-Tree nodes */ public Set getGrid() { Set areas = Sets.newHashSet(); if (root.isPresent()) { Node node = root.get(); node.collectGrids(areas); } return areas; } /** * get the R-Tree leaf nodes that would contain the passed point * * @param p the point to search * @return a Collection of R-Tree nodes that would contain p */ public Collection getContainingLeafs(Point2D p) { if (root.isPresent()) { Node theRoot = root.get(); if (theRoot instanceof LeafNode) { return Collections.singleton(theRoot); } else if (theRoot instanceof InnerNode) { return ((InnerNode) theRoot).getContainingLeafs(Sets.newHashSet(), p); } } return Collections.emptySet(); } /** * count all the elements in the R-Tree * * @return the count */ public int count() { int count = 0; if (root.isPresent()) { Node node = root.get(); count += node.count(); } return count; } private String asString() { if (root.isPresent()) { return root.get().asString(""); } else { return "Empty RTree"; } } private static final String marginIncrement = " "; private static String asString(Rectangle2D r) { return "[" + (int) r.getX() + "," + (int) r.getY() + "," + (int) r.getWidth() + "," + (int) r.getHeight() + "]"; } private static String asString(Collection> trees) { StringBuilder sb = new StringBuilder(); for (RTree tree : trees) { if (sb.length() > 0) { sb.append('\n'); } sb.append(tree.asString()); } return sb.toString(); } private static String asString(Map map) { StringBuilder sb = new StringBuilder(); for (Map.Entry entry : map.entrySet()) { if (sb.length() > 0) { sb.append('\n'); } sb.append(asString(entry)); } return sb.toString(); } private static String asString(Map.Entry entry) { return entry.getKey() + "->" + asString(entry.getValue()); } @Override public String toString() { return this.asString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy