@@ -29,11 +29,15 @@ public abstract class QuadTree<G extends QuadTree.GeometricObject> {
29
29
public abstract List <G > queryRange (float x , float y , float height , float width );
30
30
31
31
/**
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.
33
37
*/
34
- public static class PointQuadTree <P extends QuadTree .XYPoint > extends QuadTree <P > {
38
+ public static class PointRegionQuadTree <P extends QuadTree .XYPoint > extends QuadTree <P > {
35
39
36
- private PointQuadNode <P > root = null ;
40
+ private PointRegionQuadNode <P > root = null ;
37
41
38
42
/**
39
43
* 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
44
48
* @param height Height of the bounding box containing all points
45
49
* @param width Width of the bounding box containing all points
46
50
*/
47
- public PointQuadTree (float x , float y , float height , float width ) {
51
+ public PointRegionQuadTree (float x , float y , float height , float width ) {
48
52
this (x ,y ,height ,width ,4 ,20 );
49
53
}
50
54
@@ -60,12 +64,12 @@ public PointQuadTree(float x, float y, float height, float width) {
60
64
* @param maxTreeHeight Max height of the quadtree. (Note: If this is defined, the tree will ignore the
61
65
* max capacity defined by leafCapacity)
62
66
*/
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 ) {
64
68
XYPoint xyPoint = new XYPoint (x ,y );
65
69
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 ;
69
73
}
70
74
71
75
/**
@@ -109,7 +113,7 @@ public String toString() {
109
113
return super .toString ();
110
114
}
111
115
112
- protected static class PointQuadNode <XY extends QuadTree .XYPoint > extends QuadNode <XY > {
116
+ protected static class PointRegionQuadNode <XY extends QuadTree .XYPoint > extends QuadNode <XY > {
113
117
114
118
// max number of children before sub-dividing
115
119
protected static int maxCapacity = 0 ;
@@ -119,7 +123,7 @@ protected static class PointQuadNode<XY extends QuadTree.XYPoint> extends QuadNo
119
123
protected List <XY > points = new LinkedList <XY >();
120
124
protected int height = 1 ;
121
125
122
- protected PointQuadNode (AxisAlignedBoundingBox aabb ) {
126
+ protected PointRegionQuadNode (AxisAlignedBoundingBox aabb ) {
123
127
super (aabb );
124
128
}
125
129
@@ -153,23 +157,23 @@ private void subdivide() {
153
157
float w = aabb .width /2 ;
154
158
155
159
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 ;
158
162
159
163
XYPoint xyNE = new XYPoint (aabb .upperLeft .x +w ,aabb .upperLeft .y );
160
164
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 ;
163
167
164
168
XYPoint xySW = new XYPoint (aabb .upperLeft .x ,aabb .upperLeft .y +h );
165
169
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 ;
168
172
169
173
XYPoint xySE = new XYPoint (aabb .upperLeft .x +w ,aabb .upperLeft .y +h );
170
174
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 ;
173
177
174
178
// points live in leaf nodes, so distribute
175
179
for (XY p : points ) {
@@ -228,11 +232,12 @@ public String toString() {
228
232
}
229
233
230
234
/**
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.
232
237
*/
233
- public static class RectangleQuadTree <B extends QuadTree .AxisAlignedBoundingBox > extends QuadTree <B > {
238
+ public static class MxCifQuadTree <B extends QuadTree .AxisAlignedBoundingBox > extends QuadTree <B > {
234
239
235
- private RectangleQuadNode <B > root = null ;
240
+ private MxCifQuadNode <B > root = null ;
236
241
237
242
/**
238
243
* 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>
243
248
* @param height Height of the bounding box containing all points
244
249
* @param width Width of the bounding box containing all points
245
250
*/
246
- public RectangleQuadTree (float x , float y , float height , float width ) {
251
+ public MxCifQuadTree (float x , float y , float height , float width ) {
247
252
XYPoint xyPoint = new XYPoint (x ,y );
248
253
AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox (xyPoint ,height ,width );
249
- root = new RectangleQuadNode <B >(aabb );
254
+ root = new MxCifQuadNode <B >(aabb );
250
255
}
251
256
252
257
/**
@@ -293,11 +298,11 @@ public String toString() {
293
298
return TreePrinter .getString (this );
294
299
}
295
300
296
- protected static class RectangleQuadNode <AABB extends QuadTree .AxisAlignedBoundingBox > extends QuadNode <AABB > {
301
+ protected static class MxCifQuadNode <AABB extends QuadTree .AxisAlignedBoundingBox > extends QuadNode <AABB > {
297
302
298
303
protected List <AABB > aabbs = new LinkedList <AABB >();
299
304
300
- protected RectangleQuadNode (AxisAlignedBoundingBox aabb ) {
305
+ protected MxCifQuadNode (AxisAlignedBoundingBox aabb ) {
301
306
super (aabb );
302
307
}
303
308
@@ -312,52 +317,36 @@ protected boolean insert(AABB b) {
312
317
if (!aabb .intersectsBox (b )) return false ; // object cannot be added
313
318
if (aabbs .contains (b )) return true ; // already exists
314
319
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 );
329
322
boolean inserted = insertIntoChildren (b );
330
323
if (!inserted ) {
331
324
// 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 ;
338
327
} else {
339
328
return true ;
340
329
}
341
330
}
342
331
343
- private void subdivide () {
332
+ private void subdivide (AABB b ) {
344
333
float h = aabb .height /2 ;
345
334
float w = aabb .width /2 ;
346
335
347
336
AxisAlignedBoundingBox aabbNW = new AxisAlignedBoundingBox (aabb .upperLeft ,h ,w );
348
- northWest = new RectangleQuadNode <AABB >(aabbNW );
337
+ northWest = new MxCifQuadNode <AABB >(aabbNW );
349
338
350
339
XYPoint xyNE = new XYPoint (aabb .upperLeft .x +w ,aabb .upperLeft .y );
351
340
AxisAlignedBoundingBox aabbNE = new AxisAlignedBoundingBox (xyNE ,h ,w );
352
- northEast = new RectangleQuadNode <AABB >(aabbNE );
341
+ northEast = new MxCifQuadNode <AABB >(aabbNE );
353
342
354
343
XYPoint xySW = new XYPoint (aabb .upperLeft .x ,aabb .upperLeft .y +h );
355
344
AxisAlignedBoundingBox aabbSW = new AxisAlignedBoundingBox (xySW ,h ,w );
356
- southWest = new RectangleQuadNode <AABB >(aabbSW );
345
+ southWest = new MxCifQuadNode <AABB >(aabbSW );
357
346
358
347
XYPoint xySE = new XYPoint (aabb .upperLeft .x +w ,aabb .upperLeft .y +h );
359
348
AxisAlignedBoundingBox aabbSE = new AxisAlignedBoundingBox (xySE ,h ,w );
360
- southEast = new RectangleQuadNode <AABB >(aabbSE );
349
+ southEast = new MxCifQuadNode <AABB >(aabbSE );
361
350
}
362
351
363
352
private boolean insertIntoChildren (AABB b ) {
0 commit comments