-
Notifications
You must be signed in to change notification settings - Fork 0
/
Quadtree.pde
141 lines (118 loc) · 3.64 KB
/
Quadtree.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
public class Quadtree {
private int MAX_OBJECTS = 10;
private int MAX_LEVELS = 5;
private int level;
private List<Rectangle> objects;
private Rectangle bounds;
private Quadtree[] nodes;
/*
* Constructor
*/
public Quadtree(int pLevel, Rectangle pBounds) {
level = pLevel;
objects = new ArrayList();
bounds = pBounds;
nodes = new Quadtree[4];
}
/*
* Clears the quadtree
*/
public void clear() {
objects.clear();
for (int i = 0; i < nodes.length; i++) {
if (nodes[i] != null) {
nodes[i].clear();
nodes[i] = null;
}
}
}
/*
* Splits the node into 4 subnodes
* The split method splits the node into four subnodes
* by dividing the node into four equal parts and initializing
*the four subnodes with the new bounds.
*/
private void split() {
int subWidth = (int)(bounds.getWidth() / 2);
int subHeight = (int)(bounds.getHeight() / 2);
int x = (int)bounds.getX();
int y = (int)bounds.getY();
nodes[0] = new Quadtree(level+1, new Rectangle(x + subWidth, y, subWidth, subHeight));
nodes[1] = new Quadtree(level+1, new Rectangle(x, y, subWidth, subHeight));
nodes[2] = new Quadtree(level+1, new Rectangle(x, y + subHeight, subWidth, subHeight));
nodes[3] = new Quadtree(level+1, new Rectangle(x + subWidth, y + subHeight, subWidth, subHeight));
}
/*
* Determine which node the object belongs to. -1 means
* object cannot completely fit within a child node and is part
* of the parent node
*/
private int getIndex(Rectangle pRect) {
int index = -1;
double verticalMidpoint = bounds.getX() + (bounds.getWidth() / 2);
double horizontalMidpoint = bounds.getY() + (bounds.getHeight() / 2);
// Object can completely fit within the top quadrants
boolean topQuadrant = (pRect.getY() < horizontalMidpoint && pRect.getY() + pRect.getHeight() < horizontalMidpoint);
// Object can completely fit within the bottom quadrants
boolean bottomQuadrant = (pRect.getY() > horizontalMidpoint);
// Object can completely fit within the left quadrants
if (pRect.getX() < verticalMidpoint && pRect.getX() + pRect.getWidth() < verticalMidpoint) {
if (topQuadrant) {
index = 1;
} else if (bottomQuadrant) {
index = 2;
}
}
// Object can completely fit within the right quadrants
else if (pRect.getX() > verticalMidpoint) {
if (topQuadrant) {
index = 0;
} else if (bottomQuadrant) {
index = 3;
}
}
return index;
}
/*
* Insert the object into the quadtree. If the node
* exceeds the capacity, it will split and add all
* objects to their corresponding nodes.
*/
public void insert(Rectangle pRect) {
if (nodes[0] != null) {
int index = getIndex(pRect);
if (index != -1) {
nodes[index].insert(pRect);
return;
}
}
objects.add(pRect);
if (objects.size() > MAX_OBJECTS && level < MAX_LEVELS) {
if (nodes[0] == null) {
split();
}
int i = 0;
while (i < objects.size()) {
int index = getIndex(objects.get(i));
if (index != -1) {
//nodes[index].insert(objects.remove(i));
nodes[index].insert(objects.get(i));
objects.remove(i);
} else {
i++;
}
}
}
}
/*
* Return all objects that could collide with the given object
*/
public List retrieve(List returnObjects, Rectangle pRect) {
int index = getIndex(pRect);
if (index != -1 && nodes[0] != null) {
nodes[index].retrieve(returnObjects, pRect);
}
returnObjects.addAll(objects);
return returnObjects;
}
}