diff --git a/src/main/java/at/jotschi/quadtree/AbstractNode.java b/src/main/java/at/jotschi/quadtree/AbstractNode.java new file mode 100644 index 0000000..696a0c3 --- /dev/null +++ b/src/main/java/at/jotschi/quadtree/AbstractNode.java @@ -0,0 +1,83 @@ +package at.jotschi.quadtree; + +import java.awt.Dimension; +import java.awt.Point; + +public abstract class AbstractNode { + + /** + * Default value for amount of elements + */ + protected final int MAX_ELEMENTS = 4; + + /** + * Default value for max depth + */ + protected final int MAX_DEPTH = 4; + + public static enum Cell { + TOP_LEFT, BOTTOM_RIGHT, BOTTOM_LEFT, TOP_RIGHT + } + + protected Dimension bounds; + protected Point startCoordinates; + protected int maxDepth; + protected int maxElements; + protected int depth; + + public AbstractNode(Point startCoordinates, Dimension bounds, int depth) { + this.startCoordinates = startCoordinates; + this.bounds = bounds; + this.depth = depth; + this.maxDepth = MAX_DEPTH; + this.maxElements = MAX_ELEMENTS; + } + + public AbstractNode(Point startCoordinates, Dimension bounds, int depth, + int maxDepth, int maxChildren) { + this.startCoordinates = startCoordinates; + this.bounds = bounds; + this.maxDepth = maxDepth; + this.maxElements = maxChildren; + this.depth = depth; + } + + /** + * Returns the bounds for this Node + * + * @return + */ + public Dimension getBounds() { + return this.bounds; + } + + /** + * Returns the startCoordinates for this Node + * + * @return + */ + public Point getStartCoordinates() { + return this.startCoordinates; + } + + /** + * Returns the max elements + * + * @return + */ + public int getMaxElements() { + return this.maxElements; + } + + /** + * Returns the max depth + * + * @return + */ + public int getMaxDepth() { + return this.maxDepth; + } + + public abstract void subdivide(); + +} diff --git a/src/main/java/at/jotschi/quadtree/NodeElement.java b/src/main/java/at/jotschi/quadtree/AbstractNodeElement.java similarity index 73% rename from src/main/java/at/jotschi/quadtree/NodeElement.java rename to src/main/java/at/jotschi/quadtree/AbstractNodeElement.java index 8e5b2a2..7a6d93d 100644 --- a/src/main/java/at/jotschi/quadtree/NodeElement.java +++ b/src/main/java/at/jotschi/quadtree/AbstractNodeElement.java @@ -9,7 +9,7 @@ * */ @SuppressWarnings("serial") -public class NodeElement extends Point { +public abstract class AbstractNodeElement extends Point { private T element; @@ -20,10 +20,13 @@ public class NodeElement extends Point { * @param y * @param element */ - public NodeElement(Point coordinates, T element) { + public AbstractNodeElement(Point coordinates, T element) { super(coordinates); this.element = element; + } + public AbstractNodeElement(T element) { + this.element = element; } /** diff --git a/src/main/java/at/jotschi/quadtree/AbstractQuadTree.java b/src/main/java/at/jotschi/quadtree/AbstractQuadTree.java new file mode 100644 index 0000000..174f57c --- /dev/null +++ b/src/main/java/at/jotschi/quadtree/AbstractQuadTree.java @@ -0,0 +1,49 @@ +package at.jotschi.quadtree; + +import java.awt.Dimension; +import java.awt.Point; + +import at.jotschi.quadtree.impl.PointNode; + +public abstract class AbstractQuadTree { + + protected Dimension size; + protected Point startCoordinates; + + public AbstractQuadTree(Point startCoordinates, Dimension size) { + this.size = size; + this.startCoordinates = startCoordinates; + } + + /** + * Returns the size + * + * @return + */ + public Dimension getSize() { + return this.size; + } + + /** + * Returns the startCoordinates + * + * @return + */ + public Point getStartCoordinates() { + return this.startCoordinates; + } + + /** + * Clear the QuadTree + */ + public abstract void clear(); + + + /** + * Return the root node of this quad tree + * @return + */ + public abstract PointNode getRootNode(); + + +} diff --git a/src/main/java/at/jotschi/quadtree/BoundsNode.java b/src/main/java/at/jotschi/quadtree/BoundsNode.java deleted file mode 100644 index 3c5cd3e..0000000 --- a/src/main/java/at/jotschi/quadtree/BoundsNode.java +++ /dev/null @@ -1,18 +0,0 @@ -package at.jotschi.quadtree; - -import java.awt.Dimension; -import java.awt.Point; - -public class BoundsNode extends Node { - - public BoundsNode(Point startCoordinates, Dimension bounds, int depth) { - super(startCoordinates, bounds, depth); - } - - public BoundsNode(Point startCoordinates, Dimension bounds, int depth, - int maxDepth, int maxChildren) { - super(startCoordinates, bounds, depth, maxDepth, maxChildren); - - } - -} diff --git a/src/main/java/at/jotschi/quadtree/BoundsNodeElement.java b/src/main/java/at/jotschi/quadtree/BoundsNodeElement.java deleted file mode 100644 index 09d61e4..0000000 --- a/src/main/java/at/jotschi/quadtree/BoundsNodeElement.java +++ /dev/null @@ -1,24 +0,0 @@ -package at.jotschi.quadtree; - -import java.awt.Dimension; -import java.awt.Point; - -@SuppressWarnings("serial") -public class BoundsNodeElement extends NodeElement { - - protected Dimension bounds; - - public BoundsNodeElement(Point coordinates, Dimension bounds, T element) { - super(coordinates, element); - this.bounds = bounds; - } - - public int getWidth() { - return this.bounds.width; - } - - public int getHeight() { - return this.bounds.height; - } - -} diff --git a/src/main/java/at/jotschi/quadtree/Node.java b/src/main/java/at/jotschi/quadtree/impl/PointNode.java similarity index 60% rename from src/main/java/at/jotschi/quadtree/Node.java rename to src/main/java/at/jotschi/quadtree/impl/PointNode.java index 7525c52..304345d 100644 --- a/src/main/java/at/jotschi/quadtree/Node.java +++ b/src/main/java/at/jotschi/quadtree/impl/PointNode.java @@ -1,4 +1,4 @@ -package at.jotschi.quadtree; +package at.jotschi.quadtree.impl; import java.awt.Dimension; import java.awt.Point; @@ -8,54 +8,32 @@ import org.apache.log4j.Logger; +import at.jotschi.quadtree.AbstractNode; +import at.jotschi.quadtree.AbstractNodeElement; + /** * Node that represents each 'cell' within the quadtree. The Node will contains - * elements {@link NodeElement} that itself will contain the final data within - * the tree. + * elements {@link AbstractNodeElement} that itself will contain the final data + * within the tree. * * @author jotschi * * @param */ -public class Node { - - protected static Logger log = Logger.getLogger(Node.class); - - public static enum Cell { - TOP_LEFT, BOTTOM_RIGHT, BOTTOM_LEFT, TOP_RIGHT - } - - protected Dimension bounds; - protected Point startCoordinates; - protected int maxDepth; - protected int maxElements; - protected int depth; +public class PointNode extends AbstractNode { - /** - * Default value for amount of elements - */ - protected final int MAX_ELEMENTS = 4; - - /** - * Default value for max depth - */ - protected final int MAX_DEPTH = 4; + protected static Logger log = Logger.getLogger(PointNode.class); - protected Map> nodes = new HashMap>(); + protected Map> nodes = new HashMap>(); /** * Holds all elements for this node */ - private Vector> elements = new Vector>(); + protected Vector> elements = new Vector>(); - public Node(Point startCoordinates, Dimension bounds, int depth) { + public PointNode(Point startCoordinates, Dimension bounds, int depth) { + super(startCoordinates, bounds, depth); log.debug("Creating new Node at depth " + depth); - this.startCoordinates = startCoordinates; - this.bounds = bounds; - this.depth = depth; - this.maxDepth = MAX_DEPTH; - this.maxElements = MAX_ELEMENTS; - } /** @@ -66,15 +44,10 @@ public Node(Point startCoordinates, Dimension bounds, int depth) { * @param maxDepth * @param maxChildren */ - public Node(Point startCoordinates, Dimension bounds, int depth, + public PointNode(Point startCoordinates, Dimension bounds, int depth, int maxDepth, int maxChildren) { + super(startCoordinates, bounds, depth, maxDepth, maxChildren); log.debug("Creating new Node at depth " + depth); - this.startCoordinates = startCoordinates; - this.bounds = bounds; - this.maxDepth = maxDepth; - this.maxElements = maxChildren; - this.depth = depth; - } /** @@ -82,53 +55,18 @@ public Node(Point startCoordinates, Dimension bounds, int depth, * * @return */ - public Map> getSubNodes() { + public Map> getSubNodes() { return this.nodes; } - /** - * Returns the bounds for this Node - * - * @return - */ - public Dimension getBounds() { - return this.bounds; - } - - /** - * Returns the startCoordinates for this Node - * - * @return - */ - public Point getStartCoordinates() { - return this.startCoordinates; - } - - /** - * Returns the max elements - * - * @return - */ - public int getMaxElements() { - return this.maxElements; - } - - /** - * Returns the max depth - * - * @return - */ - public int getMaxDepth() { - return this.maxDepth; - } - + /** * Returns the cell of this element * * @param element * @return */ - private Cell findIndex(Point coordinates) { + protected Cell findIndex(Point coordinates) { // Compute the sector for the coordinates boolean left = (coordinates.x > (startCoordinates.x + bounds.width / 2)) ? false : true; @@ -164,23 +102,24 @@ private Cell findIndex(Point coordinates) { * * @return */ - public Vector> getElements() { + public Vector> getElements() { return this.elements; } /** - * Returns all elements wihtin the cell that matches the given coordinates + * Returns all elements within the cell that matches the given coordinates * * @param coordinates * @return */ - public Vector> getElements(Point coordinates) { + public Vector> getElements( + Point coordinates) { // Check if this node has already been subdivided. Therefor this node // should contain no elements if (nodes.size() > 0) { Cell index = findIndex(coordinates); - Node node = this.nodes.get(index); + PointNode node = this.nodes.get(index); return node.getElements(coordinates); } else { return this.elements; @@ -188,12 +127,12 @@ public Vector> getElements(Point coordinates) { } /** - * Insert the element into this node. If needed a subdivison will be + * Insert the element into this node. If needed a subdivision will be * performed * * @param element */ - public void insert(NodeElement element) { + public void insert(PointNodeElement element) { log.debug("Inserting element into Node at depth " + depth); // If this Node has already been subdivided just add the elements to the // appropriate cell @@ -214,7 +153,7 @@ public void insert(NodeElement element) { // Recall insert for each element. This will move all elements of // this node into the new nodes at the appropriate cell - for (NodeElement current : elements) { + for (PointNodeElement current : elements) { this.insert(current); } // Remove all elements from this node since they were moved into @@ -244,24 +183,24 @@ public void subdivide() { int newXStartCoordinate = bx + newBounds.width; int newYStartCoordinate = by + newBounds.height; - Node cellNode = null; + PointNode cellNode = null; // top left - cellNode = new Node(new Point(bx, by), newBounds, depth); + cellNode = new PointNode(new Point(bx, by), newBounds, depth); this.nodes.put(Cell.TOP_LEFT, cellNode); // top right - cellNode = new Node(new Point(newXStartCoordinate, by), newBounds, - depth); + cellNode = new PointNode(new Point(newXStartCoordinate, by), + newBounds, depth); this.nodes.put(Cell.TOP_RIGHT, cellNode); // bottom left - cellNode = new Node(new Point(bx, newYStartCoordinate), newBounds, - depth); + cellNode = new PointNode(new Point(bx, newYStartCoordinate), + newBounds, depth); this.nodes.put(Cell.BOTTOM_LEFT, cellNode); // bottom right - cellNode = new Node(new Point(newXStartCoordinate, + cellNode = new PointNode(new Point(newXStartCoordinate, newYStartCoordinate), newBounds, depth); this.nodes.put(Cell.BOTTOM_RIGHT, cellNode); } @@ -270,7 +209,7 @@ public void subdivide() { * Clears this node and all subnodes */ public void clear() { - for (Node node : nodes.values()) { + for (PointNode node : nodes.values()) { node.clear(); } elements.clear(); diff --git a/src/main/java/at/jotschi/quadtree/impl/PointNodeElement.java b/src/main/java/at/jotschi/quadtree/impl/PointNodeElement.java new file mode 100644 index 0000000..57b2daa --- /dev/null +++ b/src/main/java/at/jotschi/quadtree/impl/PointNodeElement.java @@ -0,0 +1,15 @@ +package at.jotschi.quadtree.impl; + +import java.awt.Point; + +import at.jotschi.quadtree.AbstractNodeElement; + +@SuppressWarnings("serial") +public class PointNodeElement extends AbstractNodeElement { + + public PointNodeElement(Point coordinates, T element) { + super(coordinates, element); + // TODO Auto-generated constructor stub + } + +} diff --git a/src/main/java/at/jotschi/quadtree/QuadTree.java b/src/main/java/at/jotschi/quadtree/impl/PointQuadTree.java similarity index 72% rename from src/main/java/at/jotschi/quadtree/QuadTree.java rename to src/main/java/at/jotschi/quadtree/impl/PointQuadTree.java index 20de43b..96d3a82 100644 --- a/src/main/java/at/jotschi/quadtree/QuadTree.java +++ b/src/main/java/at/jotschi/quadtree/impl/PointQuadTree.java @@ -1,9 +1,12 @@ -package at.jotschi.quadtree; +package at.jotschi.quadtree.impl; import java.awt.Dimension; import java.awt.Point; import java.util.Vector; +import at.jotschi.quadtree.AbstractNodeElement; +import at.jotschi.quadtree.AbstractQuadTree; + /** * Creates a new QuadTree that can hold the given type of elements * @@ -11,11 +14,9 @@ * * @param */ -public class QuadTree { +public class PointQuadTree extends AbstractQuadTree { - protected Node rootNode; - protected Dimension size; - protected Point startCoordinates; + protected PointNode rootNode; /** * Create a new QuadTree with the give start coordinates and size @@ -23,29 +24,9 @@ public class QuadTree { * @param startCorrdinates * @param size */ - public QuadTree(Point startCoordinates, Dimension size) { - - this.size = size; - this.startCoordinates = startCoordinates; - this.rootNode = new Node(startCoordinates, size, 0); - } - - /** - * Returns the size - * - * @return - */ - public Dimension getSize() { - return this.size; - } - - /** - * Returns the startCoordinates - * - * @return - */ - public Point getStartCoordinates() { - return this.startCoordinates; + public PointQuadTree(Point startCoordinates, Dimension size) { + super(startCoordinates, size); + this.rootNode = new PointNode(startCoordinates, size, 0); } /** @@ -81,24 +62,23 @@ public void insert(Point point, Dimension size, T element) { "The y coordinate must be within bounds of [" + startCoordinates.y + "] to [" + size.height + "]"); } - - //Check if the right bottom corner is within bounds - if (point.x+size.width > startCoordinates.x + size.width + + // Check if the right bottom corner is within bounds + if (point.x + size.width > startCoordinates.x + size.width || point.x < startCoordinates.x) { throw new IndexOutOfBoundsException( "The x coordinate must be within bounds of [" + startCoordinates.x + "] to [" + size.width + "]"); } - if (point.y+size.width > startCoordinates.y + size.height + if (point.y + size.width > startCoordinates.y + size.height || point.y < startCoordinates.y) { throw new IndexOutOfBoundsException( "The y coordinate must be within bounds of [" + startCoordinates.y + "] to [" + size.height + "]"); } - - - this.rootNode.insert(new NodeElement(point, element)); - + + this.rootNode.insert(new PointNodeElement(point, element)); + } /** @@ -123,14 +103,7 @@ public void insert(Point point, T element) { + startCoordinates.y + "] to [" + size.height + "]"); } - this.rootNode.insert(new NodeElement(point, element)); - } - - /** - * Clear the QuadTree - */ - public void clear() { - this.rootNode.clear(); + this.rootNode.insert(new PointNodeElement(point, element)); } /** @@ -138,7 +111,7 @@ public void clear() { * * @return */ - public Node getRootNode() { + public PointNode getRootNode() { return this.rootNode; } @@ -148,7 +121,12 @@ public Node getRootNode() { * @param coordinates * @return */ - public Vector> getElements(Point coordinates) { + public Vector> getElements(Point coordinates) { return this.rootNode.getElements(coordinates); } + + @Override + public void clear() { + this.rootNode.clear(); + } } diff --git a/src/main/java/at/jotschi/quadtree/impl/SpacialNode.java b/src/main/java/at/jotschi/quadtree/impl/SpacialNode.java new file mode 100644 index 0000000..47cd19c --- /dev/null +++ b/src/main/java/at/jotschi/quadtree/impl/SpacialNode.java @@ -0,0 +1,60 @@ +package at.jotschi.quadtree.impl; + +import java.awt.Dimension; +import java.awt.Point; +import java.util.HashMap; +import java.util.Map; + +import at.jotschi.quadtree.AbstractNodeElement; + +public class SpacialNode extends PointNode { + + protected Map> nodes = new HashMap>(); + + protected AbstractNodeElement element; + + public SpacialNode(Point startCoordinates, Dimension bounds, int depth) { + super(startCoordinates, bounds, depth); + } + + public SpacialNode(Point startCoordinates, Dimension bounds, int depth, + int maxDepth, int maxChildren) { + super(startCoordinates, bounds, depth, maxDepth, maxChildren); + + } + + /** + * Insert the element into this node. If needed a subdivision will be + * performed + * + * @param element + */ + public void insert(SpacialNodeElement element) { + log.debug("Inserting element into Node at depth " + depth); + + boolean wMatch = element.getWidth() == this.getBounds().width; + boolean hMatch = element.getHeight() == this.getBounds().height; + + // Check if the element fits into this node + if (wMatch && hMatch && this.element == null) { + element.x = this.startCoordinates.x; + element.y = this.startCoordinates.y; + this.element = element; + return; + } + + // We need to subdivide the node if the element is smaller than then the + // dimensions of this node. + if (!(this.depth >= MAX_DEPTH)) { + this.subdivide(); + } + + // Recall insert for the element. This will try to add the element into + // one of the subnodes. + for (SpacialNode current : nodes.values()) { + current.insert(element); + } + + } + +} diff --git a/src/main/java/at/jotschi/quadtree/impl/SpacialNodeElement.java b/src/main/java/at/jotschi/quadtree/impl/SpacialNodeElement.java new file mode 100644 index 0000000..1c48a17 --- /dev/null +++ b/src/main/java/at/jotschi/quadtree/impl/SpacialNodeElement.java @@ -0,0 +1,32 @@ +package at.jotschi.quadtree.impl; + +import java.awt.Dimension; +import java.awt.Point; + +import at.jotschi.quadtree.AbstractNodeElement; + + +@SuppressWarnings("serial") +public class SpacialNodeElement extends AbstractNodeElement { + + protected Dimension elementSize; + + public SpacialNodeElement(T element, Dimension elementSize) { + super(element); + this.elementSize = elementSize; + } + + public SpacialNodeElement(Point coordinates, Dimension elementSize, T element) { + super(coordinates, element); + this.elementSize = elementSize; + } + + public int getWidth() { + return this.elementSize.width; + } + + public int getHeight() { + return this.elementSize.height; + } + +} diff --git a/src/main/java/at/jotschi/quadtree/BoundsQuadTree.java b/src/main/java/at/jotschi/quadtree/impl/SpacialQuadTree.java similarity index 72% rename from src/main/java/at/jotschi/quadtree/BoundsQuadTree.java rename to src/main/java/at/jotschi/quadtree/impl/SpacialQuadTree.java index bfb3984..6078054 100644 --- a/src/main/java/at/jotschi/quadtree/BoundsQuadTree.java +++ b/src/main/java/at/jotschi/quadtree/impl/SpacialQuadTree.java @@ -1,8 +1,10 @@ -package at.jotschi.quadtree; +package at.jotschi.quadtree.impl; import java.awt.Dimension; import java.awt.Point; +import at.jotschi.quadtree.AbstractQuadTree; + /** * Creates a new QuadTree that can hold the given type of elements. Each element * can also have a certain dimension. @@ -11,9 +13,9 @@ * * @param */ -public class BoundsQuadTree extends QuadTree { +public class SpacialQuadTree extends AbstractQuadTree { - protected BoundsNode rootNode; + protected SpacialNode rootNode; /** * Create a new QuadTree with the give start coordinates and size @@ -21,11 +23,22 @@ public class BoundsQuadTree extends QuadTree { * @param startCorrdinates * @param size */ - public BoundsQuadTree(Point startCoordinates, Dimension size) { - + public SpacialQuadTree(Point startCoordinates, Dimension size) { super(startCoordinates, size); + this.rootNode = new SpacialNode(startCoordinates, size, 0); + } + + /** + * Insert the element with the given size in the next free cell + * + * @param element + * @param elementSize + */ + public void insert(T element, Dimension elementSize) { + + // TODO check element size + this.rootNode.insert(new SpacialNodeElement(element, elementSize)); - this.rootNode = new BoundsNode(startCoordinates, size, 0); } /** @@ -61,6 +74,7 @@ public void insert(Point point, Dimension elementSize, T element) { + startCoordinates.x + "] to [" + size.width + "] / [" + point.x + elementSize.width + "]"); } + if (point.y + elementSize.height > startCoordinates.y + size.height || point.y < startCoordinates.y) { throw new IndexOutOfBoundsException( @@ -69,7 +83,7 @@ public void insert(Point point, Dimension elementSize, T element) { + "] / [" + point.x + elementSize.height + "]"); } - this.rootNode.insert(new BoundsNodeElement(point, elementSize, + this.rootNode.insert(new SpacialNodeElement(point, elementSize, element)); } @@ -79,8 +93,13 @@ public void insert(Point point, Dimension elementSize, T element) { * * @return */ - public BoundsNode getRootNode() { + public SpacialNode getRootNode() { return this.rootNode; } + @Override + public void clear() { + this.rootNode.clear(); + } + } diff --git a/src/test/java/at/jotschi/quadtree/QuadTreeTest.java b/src/test/java/at/jotschi/quadtree/QuadTreeTest.java index 12b8445..53be60d 100644 --- a/src/test/java/at/jotschi/quadtree/QuadTreeTest.java +++ b/src/test/java/at/jotschi/quadtree/QuadTreeTest.java @@ -6,6 +6,9 @@ import org.junit.Test; +import at.jotschi.quadtree.impl.PointQuadTree; +import at.jotschi.quadtree.impl.SpacialQuadTree; + /** * Unit test for simple tree setup. */ @@ -13,7 +16,7 @@ public class QuadTreeTest { @Test public void testApp() { - QuadTree tree = new QuadTree(new Point(0, 0), + PointQuadTree tree = new PointQuadTree(new Point(0, 0), new Dimension(600, 600)); tree.insert(1, 3, "1"); tree.insert(11, 32, "2"); @@ -24,10 +27,10 @@ public void testApp() { tree.insert(552, 555, "6"); tree.insert(551, 555, "7"); - Vector> elements = (Vector>) tree + Vector> elements = (Vector>) tree .getElements(new Point(500, 550)); - for (NodeElement element : elements) { + for (AbstractNodeElement element : elements) { System.out.println("[" + element.getX() + "-" + element.getY() + "] " + element.getElement()); } @@ -35,7 +38,7 @@ public void testApp() { @Test public void quadTreeBoundsTest() { - BoundsQuadTree tree = new BoundsQuadTree( + SpacialQuadTree tree = new SpacialQuadTree( new Point(0, 0), new Dimension(600, 600)); tree.insert(new Point(11, 3), new Dimension(10, 10), "1"); tree.insert(new Point(22, 3), new Dimension(30, 10), "2"); diff --git a/src/test/java/at/jotschi/quadtree/RenderBoundsQuadTree.java b/src/test/java/at/jotschi/quadtree/RenderBoundsQuadTree.java deleted file mode 100644 index 549bc3a..0000000 --- a/src/test/java/at/jotschi/quadtree/RenderBoundsQuadTree.java +++ /dev/null @@ -1,71 +0,0 @@ -package at.jotschi.quadtree; - -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Point; -import java.util.Vector; - -import at.jotschi.quadtree.gui.QuadTreePanel; - -@SuppressWarnings("serial") -public class RenderBoundsQuadTree extends QuadTreePanel { - - protected BoundsQuadTree tree; - - public static void main(String[] args) { - new RenderBoundsQuadTree(); - } - - /** - * Create a new jframe and display it - */ - protected RenderBoundsQuadTree() { - tree = createQuadTree(); - setupGui(); - } - - /** - * Create the QuadTree and add some random points - * - * @return - */ - private BoundsQuadTree createQuadTree() { - Point startCoordinates = new Point(100, 100); - BoundsQuadTree tree = new BoundsQuadTree( - startCoordinates, new Dimension(400, 400)); - - for (int i = 0; i < 200; i++) { - int x = (int) (Math.random() * 1000 * 0.3) + startCoordinates.x; - int y = (int) (Math.random() * 1000 * 0.3) + startCoordinates.y; - Point point = new Point(x, y); - Dimension dimension = new Dimension(50, 50); - tree.insert(point, dimension, "test"); - } - - return tree; - } - - @Override - protected void paintComponent(Graphics g) { - BoundsNode rootNode = tree.getRootNode(); - drawCells(rootNode, g); - } - - - /** - * Draw all elements of the node - * - * @param g - */ - @Override - public void drawElements(Node node, Graphics g) { - - Vector> elements = (Vector>) node - .getElements(); - for (NodeElement element : elements) { - g.drawRect((int) element.getX(), (int) element.getY(), - node.getBounds().width, node.getBounds().height); - } - } - -} diff --git a/src/test/java/at/jotschi/quadtree/RenderPointQuadTree.java b/src/test/java/at/jotschi/quadtree/RenderPointQuadTree.java new file mode 100644 index 0000000..713971b --- /dev/null +++ b/src/test/java/at/jotschi/quadtree/RenderPointQuadTree.java @@ -0,0 +1,126 @@ +package at.jotschi.quadtree; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.event.MouseEvent; +import java.util.Map; +import java.util.Vector; + +import at.jotschi.quadtree.AbstractNode.Cell; +import at.jotschi.quadtree.gui.QuadTreePanel; +import at.jotschi.quadtree.impl.PointNode; +import at.jotschi.quadtree.impl.PointQuadTree; + +@SuppressWarnings("serial") +public class RenderPointQuadTree extends QuadTreePanel { + + protected PointQuadTree tree; + + protected Vector> selectedElements = new Vector>(); + + public static void main(String[] args) { + new RenderPointQuadTree(); + } + + protected RenderPointQuadTree() { + tree = createQuadTree(); + setupGui(); + } + + /** + * Create the QuadTree and add some random points + * + * @return + */ + protected PointQuadTree createQuadTree() { + PointQuadTree tree = new PointQuadTree(new Point(100, + 100), new Dimension(400, 400)); + + for (int i = 0; i < 200; i++) { + int x = (int) (Math.random() * 1000 * 0.4) + 100; + int y = (int) (Math.random() * 1000 * 0.4) + 100; + System.out.println(x + " " + y); + tree.insert(x, y, "test"); + } + + return tree; + } + + @Override + protected void paintComponent(Graphics g) { + PointNode rootNode = tree.getRootNode(); + drawCells(rootNode, g); + } + + /** + * Draws the tree content + * + * @param node + * @param g + */ + protected void drawCells(PointNode node, Graphics g) { + + Dimension bounds = node.getBounds(); + Point startCoordinates = node.getStartCoordinates(); + // Draw node bounds + g.drawRect(startCoordinates.x, startCoordinates.y, bounds.width, + bounds.height); + + // Draw subnodes + Map> subNodes = node.getSubNodes(); + for (PointNode subNode : subNodes.values()) { + drawCells(subNode, g); + } + + // Draw points of this node + drawElements(node, g); + + // Draw selected elements + drawSelectedElements(g); + } + + public void drawSelectedElements(Graphics g) { + g.setColor(Color.RED); + for (AbstractNodeElement element : selectedElements) { + g.drawOval((int) element.getX(), (int) element.getY(), 4, 4); + } + g.setColor(Color.BLACK); + } + + /** + * Draw all elements of the node + * + * @param g + */ + public void drawElements(PointNode node, Graphics g) { + + Vector> elements = (Vector>) node + .getElements(); + for (AbstractNodeElement element : elements) { + g.drawOval((int) element.getX(), (int) element.getY(), 4, 4); + } + } + + public void mouseClicked(MouseEvent e) { + + Point p = e.getPoint(); + // Somehow my mousepoints do not match the coordinates at the window + // (maybe this is a xorg releated bug) + p.x -= 8; + p.y -= 30; + + if (e.getButton() == 1) { + try { + tree.insert(p, "MouseClick"); + } catch (IndexOutOfBoundsException e1) { + log.info("Out of bounds - omitting."); + } + } else if (e.getButton() == 3) { + selectedElements = (Vector>) tree + .getElements(p); + } + repaint(); + } +} diff --git a/src/test/java/at/jotschi/quadtree/RenderQuadTree.java b/src/test/java/at/jotschi/quadtree/RenderQuadTree.java deleted file mode 100644 index 634cfaa..0000000 --- a/src/test/java/at/jotschi/quadtree/RenderQuadTree.java +++ /dev/null @@ -1,15 +0,0 @@ -package at.jotschi.quadtree; - -import at.jotschi.quadtree.gui.QuadTreePanel; - - - -@SuppressWarnings("serial") -public class RenderQuadTree extends QuadTreePanel { - - public static void main(String[] args) { - new RenderQuadTree(); - } - - -} diff --git a/src/test/java/at/jotschi/quadtree/RenderSpacialQuadTree.java b/src/test/java/at/jotschi/quadtree/RenderSpacialQuadTree.java new file mode 100644 index 0000000..e34c57b --- /dev/null +++ b/src/test/java/at/jotschi/quadtree/RenderSpacialQuadTree.java @@ -0,0 +1,95 @@ +package at.jotschi.quadtree; + +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Point; +import java.util.Map; +import java.util.Vector; + +import at.jotschi.quadtree.AbstractNode.Cell; +import at.jotschi.quadtree.gui.QuadTreePanel; +import at.jotschi.quadtree.impl.PointNode; +import at.jotschi.quadtree.impl.SpacialNode; +import at.jotschi.quadtree.impl.SpacialQuadTree; + +@SuppressWarnings("serial") +public class RenderSpacialQuadTree extends QuadTreePanel { + + protected SpacialQuadTree tree; + + public static void main(String[] args) { + new RenderSpacialQuadTree(); + } + + /** + * Create a new jframe and display it + */ + public RenderSpacialQuadTree() { + tree = createSpacialQuadTree(); + setupGui(); + } + + /** + * Create the QuadTree and add some random points + * + * @return + */ + protected SpacialQuadTree createSpacialQuadTree() { + + Point startCoordinates = new Point(100, 100); + Dimension size = new Dimension(512, 512); + + SpacialQuadTree tree = new SpacialQuadTree( + startCoordinates, size); + + for (int i = 0; i < 200; i++) { + // int x = (int) (Math.random() * 1000 * 0.3) + startCoordinates.x; + // int y = (int) (Math.random() * 1000 * 0.3) + startCoordinates.y; + // Point point = new Point(x, y); + Dimension dimension = new Dimension(128, 128); + tree.insert("test", dimension); + } + + return tree; + } + + protected void paintComponent(Graphics g) { + SpacialNode rootNode = tree.getRootNode(); + drawCells(rootNode, g); + } + + protected void drawCells(PointNode node, Graphics g) { + Dimension bounds = node.getBounds(); + Point startCoordinates = node.getStartCoordinates(); + // Draw node bounds + g.drawRect(startCoordinates.x, startCoordinates.y, bounds.width, + bounds.height); + + // Draw subnodes + Map> subNodes = node.getSubNodes(); + for (PointNode subNode : subNodes.values()) { + drawCells(subNode, g); + } + + // Draw points of this node + drawElements(node, g); + + } + + /** + * Draw all elements of the node + * + * @param g + */ + + public void drawElements(PointNode node, Graphics g) { + + Vector> elements = (Vector>) node + .getElements(); + for (AbstractNodeElement element : elements) { + g.drawRect((int) element.getX(), (int) element.getY(), + node.getBounds().width, node.getBounds().height); + } + } + +} diff --git a/src/test/java/at/jotschi/quadtree/gui/QuadTreePanel.java b/src/test/java/at/jotschi/quadtree/gui/QuadTreePanel.java index 0b6bf66..acc2d6c 100644 --- a/src/test/java/at/jotschi/quadtree/gui/QuadTreePanel.java +++ b/src/test/java/at/jotschi/quadtree/gui/QuadTreePanel.java @@ -1,14 +1,9 @@ package at.jotschi.quadtree.gui; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Point; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; -import java.util.Map; import java.util.Vector; import javax.swing.JFrame; @@ -16,26 +11,19 @@ import org.apache.log4j.Logger; -import at.jotschi.quadtree.Node; -import at.jotschi.quadtree.NodeElement; -import at.jotschi.quadtree.QuadTree; -import at.jotschi.quadtree.Node.Cell; +import at.jotschi.quadtree.AbstractNodeElement; @SuppressWarnings("serial") public class QuadTreePanel extends JPanel implements KeyListener, MouseListener { - protected QuadTree tree; - protected Vector> selectedElements = new Vector>(); - protected static Logger log = Logger.getLogger(QuadTreePanel.class); /** - * Create a new jframe and display it + * Create a new panel */ protected QuadTreePanel() { - tree = createQuadTree(); - setupGui(); + } protected void setupGui() { @@ -45,84 +33,10 @@ protected void setupGui() { f.addMouseListener(this); f.add(this); f.setLocationRelativeTo(null); - f.setSize(600, 600); + f.setSize(700, 700); f.setVisible(true); } - /** - * Create the QuadTree and add some random points - * - * @return - */ - private QuadTree createQuadTree() { - QuadTree tree = new QuadTree(new Point(100, 100), - new Dimension(400, 400)); - - for (int i = 0; i < 200; i++) { - int x = (int) (Math.random() * 1000 * 0.4) + 100; - int y = (int) (Math.random() * 1000 * 0.4) + 100; - System.out.println(x + " " + y); - tree.insert(x, y, "test"); - } - - return tree; - } - - @Override - protected void paintComponent(Graphics g) { - Node rootNode = tree.getRootNode(); - drawCells(rootNode, g); - } - - /** - * Draws the tree content - * - * @param node - * @param g - */ - protected void drawCells(Node node, Graphics g) { - - Dimension bounds = node.getBounds(); - Point startCoordinates = node.getStartCoordinates(); - // Draw node bounds - g.drawRect(startCoordinates.x, startCoordinates.y, bounds.width, - bounds.height); - - // Draw subnodes - Map> subNodes = node.getSubNodes(); - for (Node subNode : subNodes.values()) { - drawCells(subNode, g); - } - - // Draw points of this node - drawElements(node, g); - - // Draw selected elements - drawSelectedElements(g); - } - - public void drawSelectedElements(Graphics g) { - g.setColor(Color.RED); - for (NodeElement element : selectedElements) { - g.drawOval((int) element.getX(), (int) element.getY(), 4, 4); - } - g.setColor(Color.BLACK); - } - - /** - * Draw all elements of the node - * - * @param g - */ - public void drawElements(Node node, Graphics g) { - - Vector> elements = (Vector>) node - .getElements(); - for (NodeElement element : elements) { - g.drawOval((int) element.getX(), (int) element.getY(), 4, 4); - } - } - public void keyTyped(KeyEvent e) { // TODO Auto-generated method stub @@ -141,27 +55,6 @@ public void keyReleased(KeyEvent e) { } - public void mouseClicked(MouseEvent e) { - - Point p = e.getPoint(); - // Somehow my mousepoints do not match the coordinates at the window - // (maybe this is a xorg releated bug) - p.x -= 8; - p.y -= 30; - - if (e.getButton() == 1) { - try { - tree.insert(p, "MouseClick"); - } catch (IndexOutOfBoundsException e1) { - log.info("Out of bounds - omitting."); - } - } else if (e.getButton() == 3) { - selectedElements = (Vector>) tree - .getElements(p); - } - repaint(); - } - public void mousePressed(MouseEvent e) { // TODO Auto-generated method stub @@ -181,4 +74,9 @@ public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } + + public void mouseClicked(MouseEvent e) { + // TODO Auto-generated method stub + + } }