@@ -26,7 +26,7 @@ public abstract class QuadTree<G extends QuadTree.GeometricObject> {
26
26
/**
27
27
* Range query of the quadtree.
28
28
*/
29
- public abstract List <G > queryRange (float x , float y , float height , float width );
29
+ public abstract List <G > queryRange (float x , float y , float width , float height );
30
30
31
31
/**
32
32
* A PR (Point Region) Quadtree is a four-way search trie. This means that each node has either
@@ -45,11 +45,11 @@ public static class PointRegionQuadTree<P extends QuadTree.XYPoint> extends Quad
45
45
*
46
46
* @param x Upper left X coordinate
47
47
* @param y Upper left Y coordinate
48
- * @param height Height of the bounding box containing all points
49
48
* @param width Width of the bounding box containing all points
49
+ * @param height Height of the bounding box containing all points
50
50
*/
51
- public PointRegionQuadTree (float x , float y , float height , float width ) {
52
- this (x ,y ,height , width ,4 ,20 );
51
+ public PointRegionQuadTree (float x , float y , float width , float height ) {
52
+ this (x ,y ,width , height ,4 ,20 );
53
53
}
54
54
55
55
/**
@@ -58,18 +58,32 @@ public PointRegionQuadTree(float x, float y, float height, float width) {
58
58
*
59
59
* @param x Upper left X coordinate
60
60
* @param y Upper left Y coordinate
61
+ * @param width Width of the bounding box containing all points
61
62
* @param height Height of the bounding box containing all points
63
+ * @param leafCapacity Max capacity of leaf nodes. (Note: All data is stored in leaf nodes)
64
+ */
65
+ public PointRegionQuadTree (float x , float y , float width , float height , int leafCapacity ) {
66
+ this (x ,y ,width ,height ,leafCapacity ,20 );
67
+ }
68
+
69
+ /**
70
+ * Create a quadtree who's upper left coordinate is located at x,y and it's bounding box is described
71
+ * by the height and width.
72
+ *
73
+ * @param x Upper left X coordinate
74
+ * @param y Upper left Y coordinate
62
75
* @param width Width of the bounding box containing all points
76
+ * @param height Height of the bounding box containing all points
63
77
* @param leafCapacity Max capacity of leaf nodes. (Note: All data is stored in leaf nodes)
64
78
* @param maxTreeHeight Max height of the quadtree. (Note: If this is defined, the tree will ignore the
65
79
* max capacity defined by leafCapacity)
66
80
*/
67
- public PointRegionQuadTree (float x , float y , float height , float width , int leafCapacity , int maxTreeHeight ) {
81
+ public PointRegionQuadTree (float x , float y , float width , float height , int leafCapacity , int maxTreeHeight ) {
68
82
XYPoint xyPoint = new XYPoint (x ,y );
69
- AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox (xyPoint ,height ,width );
70
- root = new PointRegionQuadNode <P >(aabb );
83
+ AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox (xyPoint ,width ,height );
71
84
PointRegionQuadNode .maxCapacity = leafCapacity ;
72
85
PointRegionQuadNode .maxHeight = maxTreeHeight ;
86
+ root = new PointRegionQuadNode <P >(aabb );
73
87
}
74
88
75
89
/**
@@ -96,11 +110,11 @@ public void insert(float x, float y) {
96
110
* {@inheritDoc}
97
111
*/
98
112
@ Override
99
- public List <P > queryRange (float x , float y , float height , float width ) {
113
+ public List <P > queryRange (float x , float y , float width , float height ) {
100
114
List <P > pointsInRange = new LinkedList <P >();
101
115
if (root ==null ) return (List <P >)pointsInRange ;
102
116
XYPoint xyPoint = new XYPoint (x ,y );
103
- AxisAlignedBoundingBox range = new AxisAlignedBoundingBox (xyPoint ,height , width );
117
+ AxisAlignedBoundingBox range = new AxisAlignedBoundingBox (xyPoint ,width , height );
104
118
root .queryRange (range ,pointsInRange );
105
119
return (List <P >)pointsInRange ;
106
120
}
@@ -156,22 +170,22 @@ private void subdivide() {
156
170
float h = aabb .height /2 ;
157
171
float w = aabb .width /2 ;
158
172
159
- AxisAlignedBoundingBox aabbNW = new AxisAlignedBoundingBox (aabb .upperLeft ,h , w );
173
+ AxisAlignedBoundingBox aabbNW = new AxisAlignedBoundingBox (aabb .upperLeft ,w , h );
160
174
northWest = new PointRegionQuadNode <XY >(aabbNW );
161
175
((PointRegionQuadNode <XY >)northWest ).height = height +1 ;
162
176
163
177
XYPoint xyNE = new XYPoint (aabb .upperLeft .x +w ,aabb .upperLeft .y );
164
- AxisAlignedBoundingBox aabbNE = new AxisAlignedBoundingBox (xyNE ,h , w );
178
+ AxisAlignedBoundingBox aabbNE = new AxisAlignedBoundingBox (xyNE ,w , h );
165
179
northEast = new PointRegionQuadNode <XY >(aabbNE );
166
180
((PointRegionQuadNode <XY >)northEast ).height = height +1 ;
167
181
168
182
XYPoint xySW = new XYPoint (aabb .upperLeft .x ,aabb .upperLeft .y +h );
169
- AxisAlignedBoundingBox aabbSW = new AxisAlignedBoundingBox (xySW ,h , w );
183
+ AxisAlignedBoundingBox aabbSW = new AxisAlignedBoundingBox (xySW ,w , h );
170
184
southWest = new PointRegionQuadNode <XY >(aabbSW );
171
185
((PointRegionQuadNode <XY >)southWest ).height = height +1 ;
172
186
173
187
XYPoint xySE = new XYPoint (aabb .upperLeft .x +w ,aabb .upperLeft .y +h );
174
- AxisAlignedBoundingBox aabbSE = new AxisAlignedBoundingBox (xySE ,h , w );
188
+ AxisAlignedBoundingBox aabbSE = new AxisAlignedBoundingBox (xySE ,w , h );
175
189
southEast = new PointRegionQuadNode <XY >(aabbSE );
176
190
((PointRegionQuadNode <XY >)southEast ).height = height +1 ;
177
191
@@ -245,12 +259,29 @@ public static class MxCifQuadTree<B extends QuadTree.AxisAlignedBoundingBox> ext
245
259
*
246
260
* @param x Upper left X coordinate
247
261
* @param y Upper left Y coordinate
262
+ * @param width Width of the bounding box containing all points
248
263
* @param height Height of the bounding box containing all points
264
+ */
265
+ public MxCifQuadTree (float x , float y , float width , float height ) {
266
+ this (x ,y ,width ,height ,0 ,0 );
267
+ }
268
+
269
+ /**
270
+ * Create a quadtree who's upper left coordinate is located at x,y and it's bounding box is described
271
+ * by the height and width. This uses a default leafCapacity of 4 and a maxTreeHeight of 20.
272
+ *
273
+ * @param x Upper left X coordinate
274
+ * @param y Upper left Y coordinate
249
275
* @param width Width of the bounding box containing all points
276
+ * @param height Height of the bounding box containing all points
277
+ * @param minWidth The tree will stop splitting when leaf node's width <= minWidth
278
+ * @param minHeight The tree will stop splitting when leaf node's height <= minHeight
250
279
*/
251
- public MxCifQuadTree (float x , float y , float height , float width ) {
280
+ public MxCifQuadTree (float x , float y , float width , float height , float minWidth , float minHeight ) {
252
281
XYPoint xyPoint = new XYPoint (x ,y );
253
- AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox (xyPoint ,height ,width );
282
+ AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox (xyPoint ,width ,height );
283
+ MxCifQuadNode .minWidth = minWidth ;
284
+ MxCifQuadNode .minHeight = minHeight ;
254
285
root = new MxCifQuadNode <B >(aabb );
255
286
}
256
287
@@ -267,25 +298,25 @@ public QuadTree.QuadNode<B> getRoot() {
267
298
*
268
299
* @param x X position of upper-left hand corner.
269
300
* @param y Y position of upper-left hand corner.
270
- * @param height Height of the rectangle.
271
301
* @param width Width of the rectangle.
302
+ * @param height Height of the rectangle.
272
303
*/
273
304
@ SuppressWarnings ("unchecked" )
274
- public void insert (float x , float y , float height , float width ) {
305
+ public void insert (float x , float y , float width , float height ) {
275
306
XYPoint xyPoint = new XYPoint (x ,y );
276
- AxisAlignedBoundingBox range = new AxisAlignedBoundingBox (xyPoint ,height , width );
307
+ AxisAlignedBoundingBox range = new AxisAlignedBoundingBox (xyPoint ,width , height );
277
308
root .insert ((B )range );
278
309
}
279
310
280
311
/**
281
312
* {@inheritDoc}
282
313
*/
283
314
@ Override
284
- public List <B > queryRange (float x , float y , float height , float width ) {
315
+ public List <B > queryRange (float x , float y , float width , float height ) {
285
316
List <B > geometricObjectsInRange = new LinkedList <B >();
286
317
if (root ==null ) return (List <B >)geometricObjectsInRange ;
287
318
XYPoint xyPoint = new XYPoint (x ,y );
288
- AxisAlignedBoundingBox range = new AxisAlignedBoundingBox (xyPoint ,height , width );
319
+ AxisAlignedBoundingBox range = new AxisAlignedBoundingBox (xyPoint ,width , height );
289
320
root .queryRange (range ,geometricObjectsInRange );
290
321
return (List <B >)geometricObjectsInRange ;
291
322
}
@@ -300,6 +331,9 @@ public String toString() {
300
331
301
332
protected static class MxCifQuadNode <AABB extends QuadTree .AxisAlignedBoundingBox > extends QuadNode <AABB > {
302
333
334
+ protected static float minWidth = 1 ;
335
+ protected static float minHeight = 1 ;
336
+
303
337
protected List <AABB > aabbs = new LinkedList <AABB >();
304
338
305
339
protected MxCifQuadNode (AxisAlignedBoundingBox aabb ) {
@@ -319,7 +353,15 @@ protected boolean insert(AABB b) {
319
353
320
354
// Subdivide then add the objects to whichever node will accept it
321
355
if (isLeaf ()) subdivide (b );
322
- boolean inserted = insertIntoChildren (b );
356
+
357
+ boolean inserted = false ;
358
+ if (isLeaf ()) {
359
+ aabbs .add (b );
360
+ inserted = true ;
361
+ } else {
362
+ inserted = insertIntoChildren (b );
363
+ }
364
+
323
365
if (!inserted ) {
324
366
// Couldn't insert into children (it could strattle the bounds of the box)
325
367
aabbs .add (b );
@@ -329,24 +371,27 @@ protected boolean insert(AABB b) {
329
371
}
330
372
}
331
373
332
- private void subdivide (AABB b ) {
333
- float h = aabb .height /2 ;
374
+ private boolean subdivide (AABB b ) {
334
375
float w = aabb .width /2 ;
376
+ float h = aabb .height /2 ;
377
+ if (w <minWidth || h <minHeight ) return false ;
335
378
336
- AxisAlignedBoundingBox aabbNW = new AxisAlignedBoundingBox (aabb .upperLeft ,h , w );
379
+ AxisAlignedBoundingBox aabbNW = new AxisAlignedBoundingBox (aabb .upperLeft ,w , h );
337
380
northWest = new MxCifQuadNode <AABB >(aabbNW );
338
381
339
382
XYPoint xyNE = new XYPoint (aabb .upperLeft .x +w ,aabb .upperLeft .y );
340
- AxisAlignedBoundingBox aabbNE = new AxisAlignedBoundingBox (xyNE ,h , w );
383
+ AxisAlignedBoundingBox aabbNE = new AxisAlignedBoundingBox (xyNE ,w , h );
341
384
northEast = new MxCifQuadNode <AABB >(aabbNE );
342
385
343
386
XYPoint xySW = new XYPoint (aabb .upperLeft .x ,aabb .upperLeft .y +h );
344
- AxisAlignedBoundingBox aabbSW = new AxisAlignedBoundingBox (xySW ,h , w );
387
+ AxisAlignedBoundingBox aabbSW = new AxisAlignedBoundingBox (xySW ,w , h );
345
388
southWest = new MxCifQuadNode <AABB >(aabbSW );
346
389
347
390
XYPoint xySE = new XYPoint (aabb .upperLeft .x +w ,aabb .upperLeft .y +h );
348
- AxisAlignedBoundingBox aabbSE = new AxisAlignedBoundingBox (xySE ,h , w );
391
+ AxisAlignedBoundingBox aabbSE = new AxisAlignedBoundingBox (xySE ,w , h );
349
392
southEast = new MxCifQuadNode <AABB >(aabbSE );
393
+
394
+ return true ;
350
395
}
351
396
352
397
private boolean insertIntoChildren (AABB b ) {
@@ -421,7 +466,7 @@ protected QuadNode(AxisAlignedBoundingBox aabb) {
421
466
/**
422
467
* Find all objects which appear within a range.
423
468
*
424
- * @param range Upper-left and height, width of a axis-aligned bounding box.
469
+ * @param range Upper-left and width,height of a axis-aligned bounding box.
425
470
* @param geometricObjectsInRange Geometric objects inside the bounding box.
426
471
*/
427
472
protected abstract void queryRange (AxisAlignedBoundingBox range , List <G > geometricObjectsInRange );
@@ -567,10 +612,10 @@ public static class AxisAlignedBoundingBox extends GeometricObject implements Co
567
612
private float maxX = 0 ;
568
613
private float maxY = 0 ;
569
614
570
- public AxisAlignedBoundingBox (XYPoint upperLeft , float height , float width ) {
615
+ public AxisAlignedBoundingBox (XYPoint upperLeft , float width , float height ) {
571
616
this .upperLeft = upperLeft ;
572
- this .height = height ;
573
617
this .width = width ;
618
+ this .height = height ;
574
619
575
620
minX = upperLeft .x ;
576
621
minY = upperLeft .y ;
0 commit comments