Skip to content

Commit 6eb5438

Browse files
author
phishman3579
committed
Renamed the quadtrees to be more descriptive
git-svn-id: https://java-algorithms-implementation.googlecode.com/svn/trunk@396 032fbc0f-8cab-eb90-e552-f08422b9a96a
1 parent 4972a62 commit 6eb5438

File tree

2 files changed

+53
-55
lines changed

2 files changed

+53
-55
lines changed

src/com/jwetherell/algorithms/DataStructures.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7328,7 +7328,7 @@ private static boolean testQuadTree() {
73287328
int size = 16000;
73297329
java.util.List<QuadTree.XYPoint>[] lists = new java.util.List[listSize];
73307330
for (int i=0; i<listSize; i++) {
7331-
java.util.List<QuadTree.XYPoint> list = new java.util.LinkedList<QuadTree.XYPoint>();
7331+
java.util.List<QuadTree.XYPoint> list = new java.util.ArrayList<QuadTree.XYPoint>(size);
73327332
for (int j=0; j<size; j++) {
73337333
float x = RANDOM.nextInt(size);
73347334
float y = RANDOM.nextInt(size);
@@ -7341,7 +7341,7 @@ private static boolean testQuadTree() {
73417341
java.util.List<QuadTree.XYPoint>[] queries = new java.util.List[listSize];
73427342

73437343
for (int i=0; i<listSize; i++) {
7344-
java.util.List<QuadTree.XYPoint> query = new java.util.LinkedList<QuadTree.XYPoint>();
7344+
java.util.List<QuadTree.XYPoint> query = new java.util.ArrayList<QuadTree.XYPoint>(size);
73457345
for (int j=0; j<size; j++) {
73467346
float x = RANDOM.nextInt(size);
73477347
float y = RANDOM.nextInt(size);
@@ -7368,7 +7368,7 @@ private static boolean testQuadTree() {
73687368

73697369
// Point based quad tree
73707370
{
7371-
QuadTree.PointQuadTree<QuadTree.XYPoint> tree = new QuadTree.PointQuadTree<QuadTree.XYPoint>(0,0,size,size);
7371+
QuadTree.PointRegionQuadTree<QuadTree.XYPoint> tree = new QuadTree.PointRegionQuadTree<QuadTree.XYPoint>(0,0,size,size);
73727372
beforeMemory = DataStructures.getMemoryUse();
73737373
avgInsertTime = 0;
73747374
for (int i=0; i<listSize; i++) {
@@ -7431,7 +7431,7 @@ private static boolean testQuadTree() {
74317431

74327432
// Rectangle base quadtree
74337433
{
7434-
QuadTree.RectangleQuadTree<QuadTree.AxisAlignedBoundingBox> tree = new QuadTree.RectangleQuadTree<QuadTree.AxisAlignedBoundingBox>(0,0,size,size);
7434+
QuadTree.MxCifQuadTree<QuadTree.AxisAlignedBoundingBox> tree = new QuadTree.MxCifQuadTree<QuadTree.AxisAlignedBoundingBox>(0,0,size,size);
74357435
beforeMemory = DataStructures.getMemoryUse();
74367436
avgInsertTime = 0;
74377437
for (int i=0; i<listSize; i++) {
@@ -7480,10 +7480,19 @@ private static boolean testQuadTree() {
74807480

74817481
// Result set should not contain duplicates
74827482
beforeTreeQuery = System.currentTimeMillis();
7483-
tree.queryRange(0, 0, size, size);
7483+
java.util.List<QuadTree.AxisAlignedBoundingBox> result = tree.queryRange(0, 0, size, size);
74847484
afterTreeQuery = System.currentTimeMillis();
74857485
treeQuery = afterTreeQuery - beforeTreeQuery;
74867486
System.out.println("treeQuery="+treeQuery);
7487+
Collections.sort(result);
7488+
QuadTree.AxisAlignedBoundingBox prev = null;
7489+
for (QuadTree.AxisAlignedBoundingBox p : result) {
7490+
if (prev!=null && prev.equals(p)) {
7491+
System.out.println("prev==p. p="+p.toString()+" "+prev.toString());
7492+
return false;
7493+
}
7494+
prev = p;
7495+
}
74877496
}
74887497

74897498
return true;

src/com/jwetherell/algorithms/data_structures/QuadTree.java

Lines changed: 39 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,15 @@ public abstract class QuadTree<G extends QuadTree.GeometricObject> {
2929
public abstract List<G> queryRange(float x, float y, float height, float width);
3030

3131
/**
32-
* QuadTree which holds 2D objects.
32+
* A PR (Point Region) Quadtree is a four-way search trie. This means that each node has either
33+
* four (internal guide node) or zero (leaf node) children. Keys are only stored in the leaf nodes,
34+
* all internal nodes act as guides towards the keys.
35+
*
36+
* This implementation is a PR QuadTree which uses "Buckets" to prevent stalky trees.
3337
*/
34-
public static class PointQuadTree<P extends QuadTree.XYPoint> extends QuadTree<P> {
38+
public static class PointRegionQuadTree<P extends QuadTree.XYPoint> extends QuadTree<P> {
3539

36-
private PointQuadNode<P> root = null;
40+
private PointRegionQuadNode<P> root = null;
3741

3842
/**
3943
* Create a quadtree who's upper left coordinate is located at x,y and it's bounding box is described
@@ -44,7 +48,7 @@ public static class PointQuadTree<P extends QuadTree.XYPoint> extends QuadTree<P
4448
* @param height Height of the bounding box containing all points
4549
* @param width Width of the bounding box containing all points
4650
*/
47-
public PointQuadTree(float x, float y, float height, float width) {
51+
public PointRegionQuadTree(float x, float y, float height, float width) {
4852
this(x,y,height,width,4,20);
4953
}
5054

@@ -60,12 +64,12 @@ public PointQuadTree(float x, float y, float height, float width) {
6064
* @param maxTreeHeight Max height of the quadtree. (Note: If this is defined, the tree will ignore the
6165
* max capacity defined by leafCapacity)
6266
*/
63-
public PointQuadTree(float x, float y, float height, float width, int leafCapacity, int maxTreeHeight) {
67+
public PointRegionQuadTree(float x, float y, float height, float width, int leafCapacity, int maxTreeHeight) {
6468
XYPoint xyPoint = new XYPoint(x,y);
6569
AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox(xyPoint,height,width);
66-
root = new PointQuadNode<P>(aabb);
67-
PointQuadNode.maxCapacity = leafCapacity;
68-
PointQuadNode.maxHeight = maxTreeHeight;
70+
root = new PointRegionQuadNode<P>(aabb);
71+
PointRegionQuadNode.maxCapacity = leafCapacity;
72+
PointRegionQuadNode.maxHeight = maxTreeHeight;
6973
}
7074

7175
/**
@@ -109,7 +113,7 @@ public String toString() {
109113
return super.toString();
110114
}
111115

112-
protected static class PointQuadNode<XY extends QuadTree.XYPoint> extends QuadNode<XY> {
116+
protected static class PointRegionQuadNode<XY extends QuadTree.XYPoint> extends QuadNode<XY> {
113117

114118
// max number of children before sub-dividing
115119
protected static int maxCapacity = 0;
@@ -119,7 +123,7 @@ protected static class PointQuadNode<XY extends QuadTree.XYPoint> extends QuadNo
119123
protected List<XY> points = new LinkedList<XY>();
120124
protected int height = 1;
121125

122-
protected PointQuadNode(AxisAlignedBoundingBox aabb) {
126+
protected PointRegionQuadNode(AxisAlignedBoundingBox aabb) {
123127
super(aabb);
124128
}
125129

@@ -153,23 +157,23 @@ private void subdivide() {
153157
float w = aabb.width/2;
154158

155159
AxisAlignedBoundingBox aabbNW = new AxisAlignedBoundingBox(aabb.upperLeft,h,w);
156-
northWest = new PointQuadNode<XY>(aabbNW);
157-
((PointQuadNode<XY>)northWest).height = height+1;
160+
northWest = new PointRegionQuadNode<XY>(aabbNW);
161+
((PointRegionQuadNode<XY>)northWest).height = height+1;
158162

159163
XYPoint xyNE = new XYPoint(aabb.upperLeft.x+w,aabb.upperLeft.y);
160164
AxisAlignedBoundingBox aabbNE = new AxisAlignedBoundingBox(xyNE,h,w);
161-
northEast = new PointQuadNode<XY>(aabbNE);
162-
((PointQuadNode<XY>)northEast).height = height+1;
165+
northEast = new PointRegionQuadNode<XY>(aabbNE);
166+
((PointRegionQuadNode<XY>)northEast).height = height+1;
163167

164168
XYPoint xySW = new XYPoint(aabb.upperLeft.x,aabb.upperLeft.y+h);
165169
AxisAlignedBoundingBox aabbSW = new AxisAlignedBoundingBox(xySW,h,w);
166-
southWest = new PointQuadNode<XY>(aabbSW);
167-
((PointQuadNode<XY>)southWest).height = height+1;
170+
southWest = new PointRegionQuadNode<XY>(aabbSW);
171+
((PointRegionQuadNode<XY>)southWest).height = height+1;
168172

169173
XYPoint xySE = new XYPoint(aabb.upperLeft.x+w,aabb.upperLeft.y+h);
170174
AxisAlignedBoundingBox aabbSE = new AxisAlignedBoundingBox(xySE,h,w);
171-
southEast = new PointQuadNode<XY>(aabbSE);
172-
((PointQuadNode<XY>)southEast).height = height+1;
175+
southEast = new PointRegionQuadNode<XY>(aabbSE);
176+
((PointRegionQuadNode<XY>)southEast).height = height+1;
173177

174178
// points live in leaf nodes, so distribute
175179
for (XY p : points) {
@@ -228,11 +232,12 @@ public String toString() {
228232
}
229233

230234
/**
231-
* Quad-tree which holds rectangles as axis-aligned bounding boxes.
235+
* MX-CIF quadtree is a variant of quadtree data structure which supports area-based query. It is designed for storing a
236+
* set of rectangles (axis-aligned bounded box) in a dynamic environment.
232237
*/
233-
public static class RectangleQuadTree<B extends QuadTree.AxisAlignedBoundingBox> extends QuadTree<B> {
238+
public static class MxCifQuadTree<B extends QuadTree.AxisAlignedBoundingBox> extends QuadTree<B> {
234239

235-
private RectangleQuadNode<B> root = null;
240+
private MxCifQuadNode<B> root = null;
236241

237242
/**
238243
* Create a quadtree who's upper left coordinate is located at x,y and it's bounding box is described
@@ -243,10 +248,10 @@ public static class RectangleQuadTree<B extends QuadTree.AxisAlignedBoundingBox>
243248
* @param height Height of the bounding box containing all points
244249
* @param width Width of the bounding box containing all points
245250
*/
246-
public RectangleQuadTree(float x, float y, float height, float width) {
251+
public MxCifQuadTree(float x, float y, float height, float width) {
247252
XYPoint xyPoint = new XYPoint(x,y);
248253
AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox(xyPoint,height,width);
249-
root = new RectangleQuadNode<B>(aabb);
254+
root = new MxCifQuadNode<B>(aabb);
250255
}
251256

252257
/**
@@ -293,11 +298,11 @@ public String toString() {
293298
return TreePrinter.getString(this);
294299
}
295300

296-
protected static class RectangleQuadNode<AABB extends QuadTree.AxisAlignedBoundingBox> extends QuadNode<AABB> {
301+
protected static class MxCifQuadNode<AABB extends QuadTree.AxisAlignedBoundingBox> extends QuadNode<AABB> {
297302

298303
protected List<AABB> aabbs = new LinkedList<AABB>();
299304

300-
protected RectangleQuadNode(AxisAlignedBoundingBox aabb) {
305+
protected MxCifQuadNode(AxisAlignedBoundingBox aabb) {
301306
super(aabb);
302307
}
303308

@@ -312,52 +317,36 @@ protected boolean insert(AABB b) {
312317
if (!aabb.intersectsBox(b)) return false; // object cannot be added
313318
if (aabbs.contains(b)) return true; // already exists
314319

315-
// If this is the biggest bounding box which completely contains the aabb.
316-
float nextLevelsHeight = aabb.height/2;
317-
float nextLevelsWidth = aabb.width/2;
318-
if (nextLevelsHeight<b.height && nextLevelsWidth<b.width) {
319-
if (aabb.insideThis(b)) {
320-
// If the aabb completely fits into this aabb.
321-
aabbs.add(b);
322-
return true;
323-
}
324-
return false;
325-
}
326-
327-
// Otherwise, we need to subdivide then add the objects to whichever node will accept it
328-
if (isLeaf()) subdivide();
320+
// Subdivide then add the objects to whichever node will accept it
321+
if (isLeaf()) subdivide(b);
329322
boolean inserted = insertIntoChildren(b);
330323
if (!inserted) {
331324
// Couldn't insert into children (it could strattle the bounds of the box)
332-
if (aabb.insideThis(b)) {
333-
// If it fits completely into this box
334-
aabbs.add(b);
335-
return true;
336-
}
337-
return false;
325+
aabbs.add(b);
326+
return true;
338327
} else {
339328
return true;
340329
}
341330
}
342331

343-
private void subdivide() {
332+
private void subdivide(AABB b) {
344333
float h = aabb.height/2;
345334
float w = aabb.width/2;
346335

347336
AxisAlignedBoundingBox aabbNW = new AxisAlignedBoundingBox(aabb.upperLeft,h,w);
348-
northWest = new RectangleQuadNode<AABB>(aabbNW);
337+
northWest = new MxCifQuadNode<AABB>(aabbNW);
349338

350339
XYPoint xyNE = new XYPoint(aabb.upperLeft.x+w,aabb.upperLeft.y);
351340
AxisAlignedBoundingBox aabbNE = new AxisAlignedBoundingBox(xyNE,h,w);
352-
northEast = new RectangleQuadNode<AABB>(aabbNE);
341+
northEast = new MxCifQuadNode<AABB>(aabbNE);
353342

354343
XYPoint xySW = new XYPoint(aabb.upperLeft.x,aabb.upperLeft.y+h);
355344
AxisAlignedBoundingBox aabbSW = new AxisAlignedBoundingBox(xySW,h,w);
356-
southWest = new RectangleQuadNode<AABB>(aabbSW);
345+
southWest = new MxCifQuadNode<AABB>(aabbSW);
357346

358347
XYPoint xySE = new XYPoint(aabb.upperLeft.x+w,aabb.upperLeft.y+h);
359348
AxisAlignedBoundingBox aabbSE = new AxisAlignedBoundingBox(xySE,h,w);
360-
southEast = new RectangleQuadNode<AABB>(aabbSE);
349+
southEast = new MxCifQuadNode<AABB>(aabbSE);
361350
}
362351

363352
private boolean insertIntoChildren(AABB b) {

0 commit comments

Comments
 (0)