|
12 | 12 | import java.util.List; |
13 | 13 | import java.util.function.Predicate; |
14 | 14 | import java.util.function.ToDoubleFunction; |
| 15 | +import java.util.stream.Stream; |
15 | 16 |
|
16 | 17 | /** |
17 | 18 | * A quadtree is a structure that recursively divides a space in 4 until only a given number of points reside in each subdivided area. In this case, |
|
23 | 24 | public class Quadtree { |
24 | 25 | public static class QuadtreeNode { |
25 | 26 | // package private |
26 | | - int[][] childrenNodeId = { |
| 27 | + int[][] childrenNodeIndex = { |
27 | 28 | {NO_CHILDREN, NO_CHILDREN}, |
28 | 29 | {NO_CHILDREN, NO_CHILDREN} |
29 | 30 | }; |
30 | 31 |
|
31 | | - public int[] getChildrenNodeIdFlatten() { |
32 | | - return new int[] { |
33 | | - childrenNodeId[0][0], |
34 | | - childrenNodeId[0][1], |
35 | | - childrenNodeId[1][0], |
36 | | - childrenNodeId[1][1] |
37 | | - }; |
| 32 | + /** |
| 33 | + * @return all the index of children that actually exists (ie all quadrants that have at least a point in them) |
| 34 | + */ |
| 35 | + public int[] getRealChildrenNodeIndex() { |
| 36 | + return Stream.of( |
| 37 | + childrenNodeIndex[0][0], |
| 38 | + childrenNodeIndex[0][1], |
| 39 | + childrenNodeIndex[1][0], |
| 40 | + childrenNodeIndex[1][1] |
| 41 | + ).filter(id -> id != NO_CHILDREN) |
| 42 | + .mapToInt(Integer::intValue) |
| 43 | + .toArray(); |
38 | 44 | } |
39 | 45 | } |
40 | 46 |
|
@@ -158,10 +164,10 @@ private int buildQuadtree( |
158 | 164 | BoundingBox topLeftBb = new BoundingBox(boundingBox.left(), boundingBox.top(), boundingBoxCenter.getX(), boundingBoxCenter.getY()); |
159 | 165 | BoundingBox topRightBb = new BoundingBox(boundingBoxCenter.getX(), boundingBox.top(), boundingBox.right(), boundingBoxCenter.getY()); |
160 | 166 |
|
161 | | - nodesList.get(newNodeIndex).childrenNodeId[0][0] = buildQuadtree(nodesList, barycentersList, points, bottomLeftBb, firstIndex, xLowerSplitIndex, massGetter, firstIndex, lastIndex, remainingDepth - 1); |
162 | | - nodesList.get(newNodeIndex).childrenNodeId[0][1] = buildQuadtree(nodesList, barycentersList, points, bottomRightBb, xLowerSplitIndex, ySplitIndex, massGetter, firstIndex, lastIndex, remainingDepth - 1); |
163 | | - nodesList.get(newNodeIndex).childrenNodeId[1][0] = buildQuadtree(nodesList, barycentersList, points, topLeftBb, ySplitIndex, xUpperSplitIndex, massGetter, firstIndex, lastIndex, remainingDepth - 1); |
164 | | - nodesList.get(newNodeIndex).childrenNodeId[1][1] = buildQuadtree(nodesList, barycentersList, points, topRightBb, xUpperSplitIndex, lastIndex, massGetter, firstIndex, lastIndex, remainingDepth - 1); |
| 167 | + nodesList.get(newNodeIndex).childrenNodeIndex[0][0] = buildQuadtree(nodesList, barycentersList, points, bottomLeftBb, firstIndex, xLowerSplitIndex, massGetter, firstIndex, lastIndex, remainingDepth - 1); |
| 168 | + nodesList.get(newNodeIndex).childrenNodeIndex[0][1] = buildQuadtree(nodesList, barycentersList, points, bottomRightBb, xLowerSplitIndex, ySplitIndex, massGetter, firstIndex, lastIndex, remainingDepth - 1); |
| 169 | + nodesList.get(newNodeIndex).childrenNodeIndex[1][0] = buildQuadtree(nodesList, barycentersList, points, topLeftBb, ySplitIndex, xUpperSplitIndex, massGetter, firstIndex, lastIndex, remainingDepth - 1); |
| 170 | + nodesList.get(newNodeIndex).childrenNodeIndex[1][1] = buildQuadtree(nodesList, barycentersList, points, topRightBb, xUpperSplitIndex, lastIndex, massGetter, firstIndex, lastIndex, remainingDepth - 1); |
165 | 171 | setNodeBarycenter(barycentersList, nodesList.get(newNodeIndex), nodeBarycenter); |
166 | 172 |
|
167 | 173 | return newNodeIndex; |
@@ -234,19 +240,16 @@ private void setLeafBarycenter(Point[] points, Point nodeBarycenter, int startIn |
234 | 240 | * @param nodeBarycenter the barycenter of the node, the one we are setting the mass and position of |
235 | 241 | */ |
236 | 242 | private void setNodeBarycenter(List<Point> barycentersList, QuadtreeNode node, Point nodeBarycenter) { |
237 | | - int[] barycenterIndex = node.getChildrenNodeIdFlatten(); |
| 243 | + int[] barycenterIndex = node.getRealChildrenNodeIndex(); |
238 | 244 | Vector2D barycenterPosition = new Vector2D(); |
239 | 245 | double totalBarycenterMass = 0; |
240 | 246 | for (int index : barycenterIndex) { |
241 | | - // index is only -1 in the case of nothing being there |
242 | | - if (index != NO_CHILDREN) { |
243 | | - // get the mass / position of each quadrant and do a weighted sum (quite literally) |
244 | | - Point quadrantBarycenter = barycentersList.get(index); |
245 | | - // do not use the massGetter, that's only for leaf nodes, quadrants contain leaf which already have their correct mass set |
246 | | - double quadrantMass = quadrantBarycenter.getMass(); |
247 | | - barycenterPosition.addScaled(quadrantBarycenter.getPosition(), quadrantMass); |
248 | | - totalBarycenterMass += quadrantMass; |
249 | | - } |
| 247 | + // get the mass / position of each quadrant and do a weighted sum (quite literally) |
| 248 | + Point quadrantBarycenter = barycentersList.get(index); |
| 249 | + // do not use the massGetter, that's only for leaf nodes, quadrants contain leaf which already have their correct mass set |
| 250 | + double quadrantMass = quadrantBarycenter.getMass(); |
| 251 | + barycenterPosition.addScaled(quadrantBarycenter.getPosition(), quadrantMass); |
| 252 | + totalBarycenterMass += quadrantMass; |
250 | 253 | } |
251 | 254 | barycenterPosition.divideBy(totalBarycenterMass); |
252 | 255 | nodeBarycenter.setPosition(barycenterPosition); |
|
0 commit comments