Java Quadtree Implementation

Hey guys. I have something for you. It’s my implementation of the quadtree, built on top of the Wikipedia Article.

Quadtree.java:

package org.matheusdev.arcengine.collision;

import java.util.List;

/**
 * 
 * @author matheusdev
 *
 */
public class Quadtree<E extends QuadtreeElement> {
	
	private final QuadRect bounds;
	private E[] elements;
	
	private Quadtree<E> topLeft;
	private Quadtree<E> topRight;
	private Quadtree<E> botLeft;
	private Quadtree<E> botRight;
	
	public Quadtree(float size, int elemPerQuad) {
		this(0, 0, size, elemPerQuad);
	}
	
	@SuppressWarnings("unchecked")
	public Quadtree(float x, float y, float size, int elemPerQuad) {
		bounds = new QuadRect(x, y, size);
		elements = (E[])(new QuadtreeElement[elemPerQuad]);
	}
	
	protected boolean set(E e) {
		for (int i = 0; i < maxElem(); i++) {
			if (elements[i] == null) {
				elements[i] = e;
				return true;
			}
		}
		return false;
	}
	
	public int maxElem() {
		return elements.length;
	}
	
	public boolean insert(E e) {
		if (!bounds.contains(e.getX(), e.getY())) {
			return false;
		}
		if (set(e)) {
			return true;
		} else {
			subdivide();
			if (topRight.insert(e)) return true;
			if (topLeft.insert(e)) return true;
			if (botRight.insert(e)) return true;
			if (botLeft.insert(e)) return true;
			
			throw new ImpossibleException();
		}
	}
	
	public void query(StaticRect range, List<E> results) {
		if (!bounds.intersects(range)) {
			return;
		}
		for (int i = 0; i < maxElem(); i++) {
			if (elements[i] != null) {
				if (range.contains(elements[i].getX(), elements[i].getY())) {
					results.add(elements[i]);
				}
			}
		}
		if (!hasChildren()) {
			return;
		}
		topLeft.query(range, results);
		topRight.query(range, results);
		botLeft.query(range, results);
		botRight.query(range, results);
	}
	
	public boolean hasChildren() {
		return topLeft != null;
	}
	
	/**
	 * <p>
	 * Subdivides this Quadtree into 4 other quadtrees.
	 * </p>
	 * <p>
	 * This is usually used, when this Quadtree already has an
	 * Element.
	 * </p>
	 * @return whether this Quadtree was subdivided, or didn't subdivide,
	 * because it was already subdivided.
	 */
	protected boolean subdivide() {
		if (hasChildren()) {
			return false;
		}
		float hs = bounds.s/2;
		topLeft  = new Quadtree<E>(bounds.x, bounds.y, hs, maxElem());
		topRight = new Quadtree<E>(bounds.x+hs, bounds.y, hs, maxElem());
		botLeft  = new Quadtree<E>(bounds.x, bounds.y+hs, hs, maxElem());
		botRight = new Quadtree<E>(bounds.x+hs, bounds.y+hs, hs, maxElem());
		return true;
	}
}

QuadtreeElement.java:


package org.matheusdev.arcengine.collision;

public interface QuadtreeElement {
	
	public float getX();
	public float getY();

}

I won’t post the SolidRect.java and the QuadRect.java code here, because these classes would then require Collidable.java and that would be too much for this topic :slight_smile:
The classes QuadRect.java and SolidRect.java are easy to implement anyways :wink:

As you can see on the package name, this is code from my current work-in-progress engine ArcEngine. I hope, I’ll finish it sometime. It will be built ontop of libGDX with TWL and other stuff :slight_smile:

What is the Random import used for? :wink:

Looks nice from first sight but I think there are some minor issues with your approach.

[Edit]
Because i always switch the words in my text and I think it was written quite unclear I declared a short terminology and use it in my explanation:
Tree: The tree itself which stores the root node and config.
Node: A node defines an area and can have 4 sub nodes.
Item: The effective item, that is stored in the tree.
[/Edit]

Your items are only stored in one node but as I see it rectangles sometimes can be children of multple nodes. This could result in problems. For example imagine the root node has a size of 256x256 units. This is subdivided into 4 128x128 pixel unit sized nodes. When you have an item, that has a size 128x128 (could also be any other size) and it has the location 127, 127, it will fall into the north west / topLeft node, despite the most part of the item lays in the bottom right (and some in the bottom left and top right nodes). If you want to fix this, you would need to insert items in every child node (let the node decide, if the item intersects the node), when you insert into children.

One important thing that is missing is rebalancing. You do not want to recreate the tree every update cycle. There needs to be some logic to update the tree, otherwise it can only be used for static objects, that don’t move at all.

If you want, I can post my implementation of the quad tree, but it isn’t really elegant, commented or anything like that. But take a look at this: http://www.jotschi.de/?p=530

This guy has created a simple (abstract) quad tree and a point and a rect based implementation of it and shared the code on git hub. Look into the rect based implementation to see how he handles it. Unfortunately he also doesn’t do rebalancing.

[x] Let’s say you specify that you can have N elements per quad.
[x] Now put N+1 QuadtreeElement elements at the exact same position.
[x] Kaboom! (infinite recursion)

There was also an ArrayList unused import… That was, because I had some testing code below, and I just clipped it away.

Yes. As you can see, the Quadtree only supports Points. I have an Idea in mind, how to add rectangles anyways.

Yep. That’s right. I wanted to use it for static objects only :slight_smile:
That is, because I’m following some specific Game-Idea I randomly had and in that game I won’t need any dynamic objects, or at least I don’t need them to be in a quad-tree.

This worked:


	private static class Element implements QuadtreeElement {
		float x, y;
		Element(float x, float y) {
			this.x = x;
			this.y = y;
		}
		public float getX() {
			return x;
		}
		public float getY() {
			return y;
		}
	}
	
	public static void main(String[] args) {
		Quadtree<Element> tree = new Quadtree<Element>(512, 1);
		tree.insert(new Element(20, 20));
		tree.insert(new Element(20, 20));
		System.out.println("Finished...");
	}

I completely disagree with the usage of arrays here. Since you are using generics, you should be using a simple ArrayList that holds all the elements. The max size should be an integer field.

Using an ArrayList makes dynamically removing and adding elements faster, since there should be no null check nor loop through to find the first null element.

EDIT: Riven just noticed that you’re not splitting the elements into the sub-quad. In a quadtree, elements are usually in the leafs. When a quad divides, it splits all its elements into their suitable sub-quad.

Which will cause the infinite recursion I mentioned earlier, so you have to ensure to have a max-depth of your tree.

Oh. I’m not having such a leaf-concept here…
Is this bad approach or should I leave it like that?

It’s a bad approach. It ruins the point of a quad tree actually, as you can’t query a tiny region in a vast area, without checking a lot of elements in nodes you don’t care about.

I’ve always found that edge based works better…sadly I can’t think of a good way to do it in java.

Could you elaborate? My Google-fu seems insufficient.

Sure. Here’s a quick sketch.

Classic version. Store an entity in the smallest node that will contain it. It’s easy to write but not very efficient as it requires a fair amount of tree walking for pretty much all queries (at least one leaf-> root or vise-versa is required). So the next version we only store entities in leaf nodes. Opens up a can of worms about handling all entities that have volumes that cross boundaries but significant drops the required tree walks.

Step back. How often do we need to perform global operations? Virtually never. Probably no: “Hey, I’ve randomly chosen the origin of a circle with this radius: What entities are inside it?” Pretty much everything is going to be related to an existing entity. What can I see? What might I collide with? Spawn a missile here with respect to me. etc. etc. So the non-leaf nodes should not need to be visited often. (Actually they can not exist at all, but that’s a little trickier)

So in edge based, each leaf stores its edges, where each edge can connect to two leaves on the opposite side. The two comes from adding the additional requirement that all touching leaves be within one level of each other. (This shouldn’t be a big deal as is a normal distribution). Now since almost always start with a known leaf, then operations can simply directly walk other leaves within the needed volume.

And yeah Riven, using your MappedObject library would work pretty well for this.

I still jave to fully understand the quadtree. Would it be possible to query any shapy of the area covered? If the entities are moving, do they all have to be updated every frame, and is the tree thus defined? Also, can the nodes cover smaller areas themselves, such as tiny rectangles? Usually, baddied in games take up more than just a single point :slight_smile:

The first question should be: do I even want to use a quadtree. They were very interesting say from the mid-90s and earlier, but are less-so now. They’re good at reducing memory footprint if you have clustering of entities…but memory footprint isn’t quite the issue that it used to be. Also the gap is speed between reading/writing to main memory and CPU speeds have made them a little trickier to get really fast. I think that most people would be better simply using one or more uniform grids which is much easier to write. For example any space query is pretty much the same thing as a scanline method of rendering that shape with more expensive checks along the edge and ‘is-inside’ is auto-magic for interior cells.

WRT quadtrees. Yeah, any shape can be queried…you have to code it up. When entities move, they need to be moved to the appropriate node if they go across a boundary (or multiple nodes if you’re tracking stuff that way). Entities can be any shape…typically will be modeled by a sphere, AABBox or extruded versions of the previous. Typically you’ll query for potential sets and then refine from there.

I agree on the grid, but I’m trying to understand this now. What happens when a box/shape is overlapping a line, split between two nodes? Are there any solid and extendable implementations of this in java, that I can play with?

Uniform grid or quadtree you’ll have to deal with the issue of an entity crossing one or more boundaries. Assuming that collision detection is instantaneous and that the maximum extent (radius if circle or edge length if AABBox) of the largest entity is relatively small, then the easy solution is to simply store each entity in the cell or node of its center and to expand all queries by half that maximal extent. Minor extension is to logically break large entities into smaller proxies if they are relatively few. Another option is to simply store references in every node/cell that entity is within…that’s pretty much a PITA.

People people, I’m here to solve all the problems with my google-fu:

S2 all of you =)

Ah. No need of google here. This topic is old. Also there are already like thousands of Quadtree implementations out there now.
And my last point: I’ve never used the quadtree.
Functional people like quadtrees.
The other use grids.
The pure functional people just have no other choice ;D

Grids are very good for handeling objects the same size. But when size varies quadtrees can do a bit better.

People people, I’m here to solve all the problems with my google-fu:

S2 all of you =)

Ah. No need of google here. This topic is old. Also there are already like thousands of Quadtree implementations out there now.
And my last point: I’ve never used the quadtree.
Functional people like quadtrees.
The other use grids.
The pure functional people just have no other choice ;D