Skip to content

Commit c50e2e6

Browse files
Directly create barycenter point
Signed-off-by: Nathan Dissoubray <nathan.dissoubray@rte-france.com>
1 parent b0f5455 commit c50e2e6

1 file changed

Lines changed: 20 additions & 13 deletions

File tree

  • diagram-util/src/main/java/com/powsybl/diagram/util/layout/geometry

diagram-util/src/main/java/com/powsybl/diagram/util/layout/geometry/Quadtree.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ public static class QuadtreeNode {
3333
*/
3434
Point nodeBarycenter;
3535

36+
QuadtreeNode() {
37+
this.nodeBarycenter = null;
38+
}
39+
3640
QuadtreeNode(Point nodeBarycenter) {
3741
this.nodeBarycenter = nodeBarycenter;
3842
}
@@ -136,9 +140,7 @@ private int buildQuadtree(
136140
|| points.size() == previousSize && checkPointPositionEquality(points)
137141
) {
138142
int newNodeIndex = nodesList.size();
139-
Point nodeBarycenter = new Point(0, 0);
140-
nodesList.add(new QuadtreeNode(nodeBarycenter));
141-
setLeafBarycenter(points, nodeBarycenter, massGetter);
143+
nodesList.add(new QuadtreeNode(createLeafBarycenter(points, massGetter)));
142144
return newNodeIndex;
143145
}
144146

@@ -161,15 +163,15 @@ private int buildQuadtree(
161163

162164
int newNodeIndex = nodesList.size();
163165
//need to add it first here even though we modify it just after, because buildQuadtree is recursive. Need to conserve order
164-
Point nodeBarycenter = new Point(0, 0);
165-
QuadtreeNode node = new QuadtreeNode(nodeBarycenter);
166+
QuadtreeNode node = new QuadtreeNode();
166167
nodesList.add(node);
167168

168169
node.topLeftIndex = buildQuadtree(nodesList, points.subList(0, xLowerSplitIndex), bottomLeftBb, massGetter, points.size(), remainingDepth - 1);
169170
node.topRightIndex = buildQuadtree(nodesList, points.subList(xLowerSplitIndex, ySplitIndex), bottomRightBb, massGetter, points.size(), remainingDepth - 1);
170171
node.bottomLeftIndex = buildQuadtree(nodesList, points.subList(ySplitIndex, xUpperSplitIndex), topLeftBb, massGetter, points.size(), remainingDepth - 1);
171172
node.bottomRightIndex = buildQuadtree(nodesList, points.subList(xUpperSplitIndex, points.size()), topRightBb, massGetter, points.size(), remainingDepth - 1);
172-
setNodeBarycenter(nodesList, nodesList.get(newNodeIndex), nodeBarycenter);
173+
174+
setNodeBarycenter(nodesList, node);
173175

174176
return newNodeIndex;
175177

@@ -212,11 +214,17 @@ private int partitionPoints(List<Point> points, Predicate<Vector2D> splitPredica
212214
* Set the mass and position of the barycenter of a node, use this only if it's a leaf node. This function assumes all points in the [startIndex, endIndex[ range have the same position
213215
* (so either the common case of having a single point, or the rarer case of have multiple points on the same position)
214216
* @param points the list of all the points
215-
* @param nodeBarycenter the barycenter
216217
* @param massGetter the function that associates a point to its mass
218+
* @return the barycenter of the leaf node
217219
*/
218-
private void setLeafBarycenter(List<Point> points, Point nodeBarycenter, ToDoubleFunction<Point> massGetter) {
220+
private Point createLeafBarycenter(List<Point> points, ToDoubleFunction<Point> massGetter) {
219221
Point leafPoint = points.getFirst();
222+
Point nodeBarycenter = new Point(0, 0);
223+
// We are using the same Vector2D position object instead of copying the X and Y position of the leafPoint
224+
// This is on purpose. The quadtree is not updated at every iteration of the force layout algorithm. But by doing this,
225+
// we get a free update on the position of the barycenter of all leaf nodes. The point's Vector2D will change as we move the point.
226+
// Non-leaf nodes are only updated when the entire quadtree is calculated again though (even if leaf nodes change).
227+
// This gives a better visual result.
220228
nodeBarycenter.setPosition(leafPoint.getPosition());
221229
double totalMass = massGetter.applyAsDouble(leafPoint);
222230
for (int i = 1; i < points.size(); ++i) {
@@ -225,16 +233,16 @@ private void setLeafBarycenter(List<Point> points, Point nodeBarycenter, ToDoubl
225233
totalMass += massGetter.applyAsDouble(points.get(i));
226234
}
227235
nodeBarycenter.setMass(totalMass);
236+
return nodeBarycenter;
228237
}
229238

230239
/**
231240
* Set the mass and position of the barycenter of a node that is not a leaf node (ie it has at least one children node, otherwise it would be a leaf node,
232-
* in which case, use {@link #setLeafBarycenter(List, Point, ToDoubleFunction)}
241+
* in which case, use {@link #createLeafBarycenter(List, ToDoubleFunction)}
233242
* @param nodeList all the nodes
234243
* @param node the node for which we are calculating the barycenter
235-
* @param nodeBarycenter the barycenter of the node, the one we are setting the mass and position of
236244
*/
237-
private void setNodeBarycenter(List<QuadtreeNode> nodeList, QuadtreeNode node, Point nodeBarycenter) {
245+
private void setNodeBarycenter(List<QuadtreeNode> nodeList, QuadtreeNode node) {
238246
int[] barycenterIndex = node.getRealChildrenNodeIndex();
239247
Vector2D barycenterPosition = new Vector2D();
240248
double totalBarycenterMass = 0;
@@ -247,8 +255,7 @@ private void setNodeBarycenter(List<QuadtreeNode> nodeList, QuadtreeNode node, P
247255
totalBarycenterMass += quadrantMass;
248256
}
249257
barycenterPosition.divideBy(totalBarycenterMass);
250-
nodeBarycenter.setPosition(barycenterPosition);
251-
nodeBarycenter.setMass(totalBarycenterMass);
258+
node.nodeBarycenter = new Point(barycenterPosition.getX(), barycenterPosition.getY(), totalBarycenterMass);
252259
}
253260

254261
/**

0 commit comments

Comments
 (0)