Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,11 @@ protected synchronized void calcPositions(N node) {
positionX = layoutModel.getWidth() - borderWidth - random.nextDouble() * borderWidth * 2.0;
}

if (positionY < borderWidth) {
positionY = borderWidth + random.nextDouble() * borderWidth * 2.0;
} else if (positionY > layoutModel.getWidth() - borderWidth * 2) {
positionY = layoutModel.getWidth() - borderWidth - random.nextDouble() * borderWidth * 2.0;
double borderHeight = layoutModel.getHeight() / 50.0;
if (positionY < borderHeight) {
positionY = borderHeight + random.nextDouble() * borderHeight * 2.0;
} else if (positionY > layoutModel.getHeight() - borderHeight * 2) {
positionY = layoutModel.getHeight() - borderHeight - random.nextDouble() * borderHeight * 2.0;
}

layoutModel.set(node, positionX, positionY);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2025, the JUNG Project and the Regents of the University
* of California. All rights reserved.
*
* This software is open-source under the BSD license; see
* https://github.com/jrtom/jung/blob/master/LICENSE for a description.
*/
package edu.uci.ics.jung.layout.spatial;

import com.google.common.graph.GraphBuilder;
import com.google.common.graph.MutableGraph;
import edu.uci.ics.jung.layout.algorithms.FRLayoutAlgorithm;
import edu.uci.ics.jung.layout.model.LayoutModel;
import edu.uci.ics.jung.layout.model.LoadingCacheLayoutModel;
import edu.uci.ics.jung.layout.model.Point;
import org.junit.Assert;
import org.junit.Test;

/**
* Tests the fix for incorrect Y-coordinate distribution in FRLayoutAlgorithm. Previously, nodes
* were arranged in a square (width × width), ignoring the configured layout height.
*
* <p>To verify the fix: 1. Generate enough nodes to exceed the layout bounds. 2. Ensure all nodes
* are positioned within the specified width * height area after layout.
*
* @author melanxoluk
*/
public class FRLayoutLocationsTest {
private static final int layoutWidth = 2000;
private static final int layoutHeight = 500;
private static final int iterations = 200;
private static final int nodes = 20;

@Test
public void testTargetCoordinates() {
MutableGraph<Integer> graph = GraphBuilder.directed().build();
LoadingCacheLayoutModel.Builder<Integer, ?> builder =
LoadingCacheLayoutModel.<Integer>builder()
.setGraph(graph)
.setSize(layoutWidth, layoutHeight);

LayoutModel<Integer> layoutModel = new FRLayoutsTest.TestLayoutModel<>(builder, iterations);

for (int i = 0; i < nodes; i++) {
graph.addNode(i);
layoutModel.set(i, Point.of(i, i));
}

FRLayoutAlgorithm algorithm = new FRLayoutAlgorithm();
layoutModel.accept(algorithm);

Assert.assertTrue(
"All points should has coordinates into target layout size",
layoutModel.getLocations().values().stream()
.allMatch(it -> it.y <= layoutHeight && it.x <= layoutWidth));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ private static boolean closeEnough(Map<String, Point> left, Map<String, Point> r
*
* @param <T>
*/
private static class TestLayoutModel<T> extends LoadingCacheLayoutModel<T> {
public static class TestLayoutModel<T> extends LoadingCacheLayoutModel<T> {

// how many steps
private int steps;
Expand Down