-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathBHTree.java
155 lines (127 loc) · 4.16 KB
/
BHTree.java
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/**
* BHTree.java
*
* Represents a quadtree for the Barnes-Hut algorithm.
*
* Dependencies: Body.java Quad.java
*
* @author chindesaurus
* @version 1.00
*/
import java.awt.Color;
public class BHTree {
// threshold value
private final double Theta = 0.5;
private Body body; // body or aggregate body stored in this node
private Quad quad; // square region that the tree represents
private BHTree NW; // tree representing northwest quadrant
private BHTree NE; // tree representing northeast quadrant
private BHTree SW; // tree representing southwest quadrant
private BHTree SE; // tree representing southeast quadrant
/**
* Constructor: creates a new Barnes-Hut tree with no bodies.
* Each BHTree represents a quadrant and an aggregate body
* that represents all bodies inside the quadrant.
*
* @param q the quadrant this node is contained within
*/
public BHTree(Quad q) {
this.quad = q;
this.body = null;
this.NW = null;
this.NE = null;
this.SW = null;
this.SE = null;
}
/**
* Adds the Body b to the invoking Barnes-Hut tree.
*/
public void insert(Body b) {
// if this node does not contain a body, put the new body b here
if (body == null) {
body = b;
return;
}
// internal node
if (! isExternal()) {
// update the center-of-mass and total mass
body = body.plus(b);
// recursively insert Body b into the appropriate quadrant
putBody(b);
}
// external node
else {
// subdivide the region further by creating four children
NW = new BHTree(quad.NW());
NE = new BHTree(quad.NE());
SE = new BHTree(quad.SE());
SW = new BHTree(quad.SW());
// recursively insert both this body and Body b into the appropriate quadrant
putBody(this.body);
putBody(b);
// update the center-of-mass and total mass
body = body.plus(b);
}
}
/**
* Inserts a body into the appropriate quadrant.
*/
private void putBody(Body b) {
if (b.in(quad.NW()))
NW.insert(b);
else if (b.in(quad.NE()))
NE.insert(b);
else if (b.in(quad.SE()))
SE.insert(b);
else if (b.in(quad.SW()))
SW.insert(b);
}
/**
* Returns true iff this tree node is external.
*/
private boolean isExternal() {
// a node is external iff all four children are null
return (NW == null && NE == null && SW == null && SE == null);
}
/**
* Approximates the net force acting on Body b from all bodies
* in the invoking Barnes-Hut tree, and updates b's force accordingly.
*/
public void updateForce(Body b) {
if (body == null || b.equals(body))
return;
// if the current node is external, update net force acting on b
if (isExternal())
b.addForce(body);
// for internal nodes
else {
// width of region represented by internal node
double s = quad.length();
// distance between Body b and this node's center-of-mass
double d = body.distanceTo(b);
// compare ratio (s / d) to threshold value Theta
if ((s / d) < Theta)
b.addForce(body); // b is far away
// recurse on each of current node's children
else {
NW.updateForce(b);
NE.updateForce(b);
SW.updateForce(b);
SE.updateForce(b);
}
}
}
/**
* Returns a string representation of the Barnes-Hut tree
* in which spaces represent external nodes, and asterisks
* represent internal nodes.
*
* @return a string representation of this quadtree
*/
public String toString() {
if (isExternal())
return " " + body + "\n";
else
return "*" + body + "\n" + NW + NE + SW + SE;
}
}