private static void solveComponentPositions(BMGraph b) { int i = 0; if (b.getNodes().size() < 2) { for (BMNode n : b.getNodes()) n.put(BMGraphAttributes.POS_KEY, "0.0,0.0"); return; } else if (b.getNodes().size() > 500) { Logging.warning( "enduser", "Not doing initial layout due to large graph size (over 500 nodes)."); for (BMNode n : b.getNodes()) { n.put( BMGraphAttributes.POS_KEY, 500 * (Math.random() - 0.5) + "," + 500 * (Math.random() - 0.5)); n.put(BMGraphAttributes.PINNED_KEY, "0"); } return; } if (b.getNodes().size() == 2) { double x = -0.75; for (BMNode n : b.getNodes()) { n.put(BMGraphAttributes.POS_KEY, x + ",0.0"); n.put(BMGraphAttributes.PINNED_KEY, "0"); x += 1.5; } return; } Matrix m = LayoutUtils.bmToMatrix(b); BMNode[] idToNode = new BMNode[m.cols()]; for (BMNode node : b.getNodes()) { idToNode[i] = node; i++; } int n = m.cols(); Vec2[] startPositions = new Vec2[n]; Random random = new Random(); for (i = 0; i < n; i++) { int hash = idToNode[i].getId().hashCode(); random.setSeed(hash); double x = random.nextDouble(), y = random.nextDouble(); startPositions[i] = new Vec2(x, y); } StressMinimizer sm = new StressMinimizer(m, startPositions); sm.iterate(); Vec2[] pos = sm.getPositions(); for (i = 0; i < n; i++) { double scale = SCALE; Vec2 p = pos[i].scaled(scale); idToNode[i].put(BMGraphAttributes.POS_KEY, p.x + "," + p.y); idToNode[i].put(BMGraphAttributes.PINNED_KEY, "0"); } scaleGraph(b); }
private static int graphWidth(BMGraph g) { if (g.getNodes().size() < 2) return 1; double minx, miny, maxx, maxy; minx = miny = Double.MAX_VALUE; maxy = maxx = -Double.MAX_VALUE; for (BMNode n : g.getNodes()) { String[] posstr = n.get(BMGraphAttributes.POS_KEY).split(","); double x = Double.parseDouble(posstr[0]); double y = Double.parseDouble(posstr[1]); minx = Math.min(x, minx); miny = Math.min(y, miny); maxx = Math.max(x, minx); maxy = Math.max(y, maxx); } // System.out.println("minx = "+minx+" maxx = "+maxx+" miny = "+miny+" maxy = "+maxy); return 5 * (int) (Math.max(1, (Math.ceil(Math.max(maxx - minx, maxy - miny)) / SCALE))); }
/** * Uses distance scaling to solve initial layout. * * @param b */ public static void solvePositions(BMGraph b) { if (b.getNodes().size() < 1) { Logging.info("layout", "Not doing initial layout on an empty graph."); return; } Logging.info( "layout", "Solving initial layout positions for a graph of " + b.getNodes().size() + " nodes"); BMGraph[] components = connectedComponents(b); for (int i = 0; i < components.length; i++) { solveComponentPositions(components[i]); } Comparator<BMGraph> graphCmp = new Comparator<BMGraph>() { public int compare(BMGraph arg0, BMGraph arg1) { return graphWidth(arg1) - graphWidth(arg0); } }; Arrays.sort(components, graphCmp); SquarePacker pack = new SquarePacker(2 * graphWidth(components[0])); for (int i = 0; i < components.length; i++) { int wh = graphWidth(components[i]); Point p = pack.pack(wh); // System.out.println("p = "+p); for (BMNode cnode : components[i].getNodes()) { String[] posstr = cnode.get(BMGraphAttributes.POS_KEY).split(","); double x = Double.parseDouble(posstr[0]); double y = Double.parseDouble(posstr[1]); double whd = wh / 5.0; BMNode node = b.getNode(cnode); x = (p.x / 5.0 * SCALE + SCALE * whd / 2 + 0.5 * (x * 0.9)); y = (p.y / 5.0 * SCALE + SCALE * whd / 2 + 0.5 * (y * 0.9)); node.put(BMGraphAttributes.POS_KEY, x + "," + y); } } Logging.info("layout", "Solved initial layout positions."); }