/** * Cools down the movement on the node. * * @param current Node to cool * @param numOfIterations current state of layout process (heat) */ private void calculateNodeCooling(Node current, double numOfIterations) { /* Check if cooling should start */ if (COOLING_START_DELAY < numOfIterations) { double coolingFactor = 1 - ((numOfIterations - COOLING_START_DELAY) / COOLING_DIVIDER); // double coolingFactor = 1 / COOLING_DIVIDER; coolingFactor = Math.max(COOLING_FACTOR_MINIMUM, coolingFactor); /* Do some cooling, to stop the mad bouncing */ double vx = current.getVX() * coolingFactor; double vy = current.getVY() * coolingFactor; /* if(vx > MIN_VX) { current.setVX(vx); } else { current.setVX(0); } if(vy > MIN_VY) { current.setVY(vy); } else { current.setVY(0); }*/ current.setVX(current.getVX() * coolingFactor); current.setVY(current.getVY() * coolingFactor); } }
/** * This function slows down a node's velocity based on it's weight. So that the heavier the node * the less it moves. * * @param n node to apply friction for. */ private void applyNodeFriction(Node n) { n.setVX(n.getVX() / n.getWeight()); n.setVY(n.getVY() / n.getWeight()); }
/** * Layout core logic. * * <p>This iterates over all the nodes and determines their velocities based on a force directed * layout approach, performs collision detection/avoidance and then ultimately their new positions * as they move. */ private void doLayout() { double maxVelocity = 100; double numOfIterations = 0; double step = 100; double skip = step; int counter = 1; boolean dividerChanged = false; // active = true; while (maxVelocity > 1 && active && (numOfIterations < MAX_NUM_OF_ITERATIONS)) { counter++; maxVelocity = 0; numOfIterations++; Iterator<Node> outer = controller.getNodeIterator(); startTime = System.currentTimeMillis(); double systemMovement = 0; double kineticEnergy = 0; /* Iterate over all nodes and calculate velocity */ while (outer.hasNext()) { Node current = outer.next(); current.resetVelocity(); current.resetAcceleration(); /* * If current node is not pinned or selected, * perform force directed layout calculations here. */ if (!((current == controller.getGraphSelected()) || current.isPinned())) { calculateNodeAttractiveForce(current); calculateNodeRepulsiveForces(current); // applyNodeFriction(current); // if (IS_COOLING) { // calculateNodeCooling(current, numOfIterations); // } // calculate velocities current.setVX(current.getVX() + current.accelx * TIMESTEP * DAMPING); current.setVY(current.getVY() + current.accely * TIMESTEP * DAMPING); double speedSquared = current.getVX() * current.getVX() + current.getVY() * current.getVY(); kineticEnergy += 0.5 * current.weight * speedSquared; // cap the velocity if (current.getVX() >= 0) { current.setVX(Math.min(current.getVX(), MAX_DIST_PER_MOVE)); } else { current.setVX(Math.max(current.getVX(), -MAX_DIST_PER_MOVE)); } if (current.getVY() >= 0) { current.setVY(Math.min(current.getVY(), MAX_DIST_PER_MOVE)); } else { current.setVY(Math.max(current.getVY(), -MAX_DIST_PER_MOVE)); } // System.out.println("vy "+ current.getVY() + ", vx " + current.getVX()); } } /* Iterate over all nodes move them after all the velocities are set */ outer = controller.getNodeIterator(); while (outer.hasNext()) { Node current = outer.next(); int xStart = current.getX(); int yStart = current.getY(); /* update node position */ int xEnd = current.getX() + (int) current.getVX(); int yEnd = current.getY() + (int) current.getVY(); int dX = Math.abs(xStart - xEnd); int dY = Math.abs(yStart - yEnd); // systemMovement += dX; // systemMovement += dY; // if(dX + dY > 6) { controller.moveNode(current, xEnd, yEnd); // } // controller.moveNode(current, Math.min(current.getX() + (int) // current.getVX(),MAX_DIST_PER_MOVE), Math.min(current.getY() + (int) current.getVY(), // MAX_DIST_PER_MOVE)); /* compute maxVelocity for layout iteration */ maxVelocity = Math.max( maxVelocity, Math.sqrt(Math.pow(current.getVX(), 2) + Math.pow(current.getVY(), 2))); } if (kineticEnergy < ENERGY_THRESHOLD) { numOfIterations = MAX_NUM_OF_ITERATIONS; } /* Make animation slower */ try { Thread.sleep(sleepInterval); } catch (InterruptedException ex) { } /* Calculate how long the iteration took */ stopTime = System.currentTimeMillis(); long duration = stopTime - startTime; if ((duration > MAX_ITERATION_TIME) && (sleepInterval > 5)) { sleepInterval -= 5; } else if (duration < MIN_ITERATION_TIME) { sleepInterval += 5; } if (numOfIterations > skip) { skip += step; System.out.print('.'); } } /* We've reached a stable layout, hold on for now */ stable = true; // System.out.println("ran in " + numOfIterations + " iterations."); }