Skip to content

Commit 697f9ec

Browse files
committed
Added sample images and added a working spatialquadtree example
1 parent 986bac6 commit 697f9ec

31 files changed

+259
-96
lines changed

src/main/java/at/jotschi/quadtree/AbstractNode.java

+20-10
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,19 @@
22

33
import java.awt.Dimension;
44
import java.awt.Point;
5+
import java.util.Map;
56

6-
public abstract class AbstractNode {
7+
public abstract class AbstractNode<T> {
78

89
/**
910
* Default value for amount of elements
1011
*/
11-
protected final int MAX_ELEMENTS = 4;
12+
protected final static int MAX_ELEMENTS = 4;
1213

1314
/**
1415
* Default value for max depth
1516
*/
16-
protected final int MAX_DEPTH = 4;
17+
protected final static int MAX_DEPTH = 4;
1718

1819
public static enum Cell {
1920
TOP_LEFT, BOTTOM_RIGHT, BOTTOM_LEFT, TOP_RIGHT
@@ -26,11 +27,7 @@ public static enum Cell {
2627
protected int depth;
2728

2829
public AbstractNode(Point startCoordinates, Dimension bounds, int depth) {
29-
this.startCoordinates = startCoordinates;
30-
this.bounds = bounds;
31-
this.depth = depth;
32-
this.maxDepth = MAX_DEPTH;
33-
this.maxElements = MAX_ELEMENTS;
30+
this(startCoordinates, bounds, depth, MAX_ELEMENTS, MAX_DEPTH);
3431
}
3532

3633
public AbstractNode(Point startCoordinates, Dimension bounds, int depth,
@@ -69,6 +66,15 @@ public int getMaxElements() {
6966
return this.maxElements;
7067
}
7168

69+
/**
70+
* Returns the depth of this node
71+
*
72+
* @return
73+
*/
74+
public int getDepth() {
75+
return this.depth;
76+
}
77+
7278
/**
7379
* Returns the max depth
7480
*
@@ -77,7 +83,11 @@ public int getMaxElements() {
7783
public int getMaxDepth() {
7884
return this.maxDepth;
7985
}
80-
81-
public abstract void subdivide();
86+
87+
public abstract void subdivide();
88+
89+
public abstract void clear();
90+
91+
public abstract Map<Cell, AbstractNode<T>> getSubNodes();
8292

8393
}

src/main/java/at/jotschi/quadtree/AbstractQuadTree.java

+4-7
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import java.awt.Dimension;
44
import java.awt.Point;
55

6-
import at.jotschi.quadtree.impl.PointNode;
7-
86
public abstract class AbstractQuadTree<T> {
97

108
protected Dimension size;
@@ -14,7 +12,7 @@ public AbstractQuadTree(Point startCoordinates, Dimension size) {
1412
this.size = size;
1513
this.startCoordinates = startCoordinates;
1614
}
17-
15+
1816
/**
1917
* Returns the size
2018
*
@@ -32,18 +30,17 @@ public Dimension getSize() {
3230
public Point getStartCoordinates() {
3331
return this.startCoordinates;
3432
}
35-
33+
3634
/**
3735
* Clear the QuadTree
3836
*/
3937
public abstract void clear();
4038

41-
4239
/**
4340
* Return the root node of this quad tree
41+
*
4442
* @return
4543
*/
46-
public abstract PointNode<T> getRootNode();
44+
public abstract AbstractNode<T> getRootNode();
4745

48-
4946
}

src/main/java/at/jotschi/quadtree/point/PointNode.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package at.jotschi.quadtree.impl;
1+
package at.jotschi.quadtree.point;
22

33
import java.awt.Dimension;
44
import java.awt.Point;
@@ -59,7 +59,6 @@ public Map<Cell, PointNode<T>> getSubNodes() {
5959
return this.nodes;
6060
}
6161

62-
6362
/**
6463
* Returns the cell of this element
6564
*
@@ -112,8 +111,7 @@ public Vector<PointNodeElement<T>> getElements() {
112111
* @param coordinates
113112
* @return
114113
*/
115-
public Vector<PointNodeElement<T>> getElements(
116-
Point coordinates) {
114+
public Vector<PointNodeElement<T>> getElements(Point coordinates) {
117115

118116
// Check if this node has already been subdivided. Therefor this node
119117
// should contain no elements

src/main/java/at/jotschi/quadtree/point/PointNodeElement.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package at.jotschi.quadtree.impl;
1+
package at.jotschi.quadtree.point;
22

33
import java.awt.Point;
44

@@ -9,7 +9,6 @@ public class PointNodeElement<T> extends AbstractNodeElement<T> {
99

1010
public PointNodeElement(Point coordinates, T element) {
1111
super(coordinates, element);
12-
// TODO Auto-generated constructor stub
1312
}
1413

1514
}

src/main/java/at/jotschi/quadtree/point/PointQuadTree.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package at.jotschi.quadtree.impl;
1+
package at.jotschi.quadtree.point;
22

33
import java.awt.Dimension;
44
import java.awt.Point;
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
1-
package at.jotschi.quadtree.impl;
1+
package at.jotschi.quadtree.spacial;
22

33
import java.awt.Dimension;
44
import java.awt.Point;
55
import java.util.HashMap;
66
import java.util.Map;
77

8-
import at.jotschi.quadtree.AbstractNodeElement;
8+
import org.apache.log4j.Logger;
99

10-
public class SpacialNode<T> extends PointNode<T> {
10+
import at.jotschi.quadtree.AbstractNode;
1111

12-
protected Map<Cell, SpacialNode<T>> nodes = new HashMap<Cell, SpacialNode<T>>();
12+
public class SpatialNode<T> extends AbstractNode {
1313

14-
protected AbstractNodeElement<T> element;
14+
protected Map<Cell, SpatialNode<T>> nodes = new HashMap<Cell, SpatialNode<T>>();
1515

16-
public SpacialNode(Point startCoordinates, Dimension bounds, int depth) {
16+
protected SpatialNodeElement<T> element;
17+
18+
protected static Logger log = Logger.getLogger(SpatialNode.class);
19+
20+
public SpatialNode(Point startCoordinates, Dimension bounds, int depth) {
1721
super(startCoordinates, bounds, depth);
1822
}
1923

20-
public SpacialNode(Point startCoordinates, Dimension bounds, int depth,
24+
public SpatialNode(Point startCoordinates, Dimension bounds, int depth,
2125
int maxDepth, int maxChildren) {
2226
super(startCoordinates, bounds, depth, maxDepth, maxChildren);
2327

@@ -29,32 +33,120 @@ public SpacialNode(Point startCoordinates, Dimension bounds, int depth,
2933
*
3034
* @param element
3135
*/
32-
public void insert(SpacialNodeElement<T> element) {
33-
log.debug("Inserting element into Node at depth " + depth);
36+
public boolean insert(SpatialNodeElement<T> element) {
3437

3538
boolean wMatch = element.getWidth() == this.getBounds().width;
3639
boolean hMatch = element.getHeight() == this.getBounds().height;
40+
boolean fits = wMatch && hMatch;
41+
42+
boolean wSmaller = element.getWidth() < this.getBounds().width;
43+
boolean hSmaller = element.getHeight() < this.getBounds().height;
44+
boolean smaller = wSmaller && hSmaller;
45+
46+
log.debug("Inserting element " + element.getHeight() + " - "
47+
+ element.getWidth());
48+
49+
// Check if this node already contains a element
50+
if (this.element != null) {
51+
return false;
52+
}
3753

3854
// Check if the element fits into this node
39-
if (wMatch && hMatch && this.element == null) {
55+
if (fits && this.nodes.size() == 0) {
4056
element.x = this.startCoordinates.x;
4157
element.y = this.startCoordinates.y;
4258
this.element = element;
43-
return;
44-
}
45-
46-
// We need to subdivide the node if the element is smaller than then the
47-
// dimensions of this node.
48-
if (!(this.depth >= MAX_DEPTH)) {
59+
log.debug("Inserting element at coordinates [" + element.x + "-"
60+
+ element.y + "]");
61+
return true;
62+
} else if (!(this.depth >= MAX_DEPTH) && nodes.size() == 0 && smaller) {
63+
// We need to subdivide the node if the element is smaller than then
64+
// the dimensions of this node.
4965
this.subdivide();
66+
// After subdivision we try to insert the element into one of the subnodes
67+
for (SpatialNode<T> current : nodes.values()) {
68+
if (current.insert(element)) {
69+
return true;
70+
}
71+
}
72+
73+
} else {
74+
// Recall insert for the element. This will try to add the element
75+
// into
76+
// one of the subnodes.
77+
for (SpatialNode<T> current : nodes.values()) {
78+
if (current.insert(element)) {
79+
return true;
80+
}
81+
}
82+
5083
}
5184

52-
// Recall insert for the element. This will try to add the element into
53-
// one of the subnodes.
54-
for (SpacialNode<T> current : nodes.values()) {
55-
current.insert(element);
85+
return false;
86+
}
87+
88+
@Override
89+
/**
90+
* Subdivide the current node and add subnodes
91+
*/
92+
public void subdivide() {
93+
log.debug("Subdividing node at depth " + depth);
94+
int depth = this.depth + 1;
95+
96+
int bx = this.startCoordinates.x;
97+
int by = this.startCoordinates.y;
98+
99+
// Create the bounds for the new cell
100+
Dimension newBounds = new Dimension(this.bounds.width / 2,
101+
this.bounds.height / 2);
102+
103+
// Add new bounds to current start coordinates to calculate the new
104+
// start coordinates
105+
int newXStartCoordinate = bx + newBounds.width;
106+
int newYStartCoordinate = by + newBounds.height;
107+
108+
SpatialNode<T> cellNode = null;
109+
110+
// top left
111+
cellNode = new SpatialNode<T>(new Point(bx, by), newBounds, depth);
112+
this.nodes.put(Cell.TOP_LEFT, cellNode);
113+
114+
// top right
115+
cellNode = new SpatialNode<T>(new Point(newXStartCoordinate, by),
116+
newBounds, depth);
117+
this.nodes.put(Cell.TOP_RIGHT, cellNode);
118+
119+
// bottom left
120+
cellNode = new SpatialNode<T>(new Point(bx, newYStartCoordinate),
121+
newBounds, depth);
122+
this.nodes.put(Cell.BOTTOM_LEFT, cellNode);
123+
124+
// bottom right
125+
cellNode = new SpatialNode<T>(new Point(newXStartCoordinate,
126+
newYStartCoordinate), newBounds, depth);
127+
this.nodes.put(Cell.BOTTOM_RIGHT, cellNode);
128+
}
129+
130+
/**
131+
* Clears this node and all subnodes
132+
*/
133+
public void clear() {
134+
for (SpatialNode<T> node : nodes.values()) {
135+
node.clear();
56136
}
137+
}
138+
139+
public SpatialNodeElement<T> getElement() {
140+
return this.element;
141+
}
57142

143+
/**
144+
* Returns the subnodes of this node
145+
*
146+
* @return
147+
*/
148+
public Map<Cell, SpatialNode<T>> getSubNodes() {
149+
return this.nodes;
58150
}
59151

60152
}

src/main/java/at/jotschi/quadtree/spacial/SpatialNodeElement.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package at.jotschi.quadtree.impl;
1+
package at.jotschi.quadtree.spacial;
22

33
import java.awt.Dimension;
44
import java.awt.Point;
@@ -7,16 +7,16 @@
77

88

99
@SuppressWarnings("serial")
10-
public class SpacialNodeElement<T> extends AbstractNodeElement<T> {
10+
public class SpatialNodeElement<T> extends AbstractNodeElement<T> {
1111

1212
protected Dimension elementSize;
1313

14-
public SpacialNodeElement(T element, Dimension elementSize) {
14+
public SpatialNodeElement(T element, Dimension elementSize) {
1515
super(element);
1616
this.elementSize = elementSize;
1717
}
1818

19-
public SpacialNodeElement(Point coordinates, Dimension elementSize, T element) {
19+
public SpatialNodeElement(Point coordinates, Dimension elementSize, T element) {
2020
super(coordinates, element);
2121
this.elementSize = elementSize;
2222
}

0 commit comments

Comments
 (0)