Пример #1
0
  /**
   * This helper method calculates the repulsive forces acting on a node from all the other nodes in
   * the graph. BIG O( number of nodes )
   *
   * <p>There is a repulsive force between every nodes depending on the distance separating them and
   * their size.
   *
   * @param current node to calculate forces for.
   */
  private void calculateNodeRepulsiveForces(Node current) {
    Iterator<Node> inner = controller.getNodeIterator();
    int current_radius, n_radius, dx, dy;
    Node n;
    current_radius =
        (int) Math.sqrt(Math.pow(current.getWidth(), 2) + Math.pow(current.getHeight(), 2));
    while (inner.hasNext()) {
      n = inner.next();
      if (n != current) {
        dx = current.getX() - n.getX();
        dy = current.getY() - n.getY();
        n_radius = (int) Math.sqrt(Math.pow(n.getWidth(), 2) + Math.pow(n.getHeight(), 2));

        // only repel if nodes are connected or within diameter * MAX_REPEL_DISTANCE
        //  if (Math.sqrt(dx * dx + dy * dy) < (Math.max(current_radius, n_radius) *
        // MAX_REPEL_MULTIPLIER)) {
        double l = (dx * dx + dy * dy) + .1;
        if (l > 0) {
          // current.setVX(current.getVX() + dx * (current_radius * SPACING) / l);
          // current.setVY(current.getVY() + dy * (current_radius * SPACING) / l);

          current.accelx += (dx * REPULSION / (l)) / current.weight;
          current.accely += (dy * REPULSION / (l)) / current.weight;
          // current.accelx += (dx * SPACING / (l * .5)) / current.weight;
          // current.accely += (dy * SPACING / (l * .5)) / current.weight;
          // n.accelx += (dx * SPACING / (l * -0.5)) / n.weight;
          // n.accely += (dy * SPACING / (l * -0.5)) / n.weight;

        }
        //  }
      }
    }
  }
Пример #2
0
  /**
   * This helper calculates all the attractive forces onto a node. Attractive forces from from the
   * edges pulling nodes towards each other, this will love through the edges of this node.
   *
   * @param current Node to calculate forces for.
   */
  private void calculateNodeAttractiveForce(Node current) {
    // get all the edges of the current node
    ArrayList<Edge> nodeEdgeList = current.getEdgeList();
    // of each of this node's edge do attactive forces
    Iterator<Edge> nodeEdges = nodeEdgeList.iterator();
    ///
    int numOfEdgesWeight = 10 * (int) Math.round(nodeEdgeList.size() + SPACING);

    // Loop through edges and find edges containing current node
    while (nodeEdges.hasNext()) {
      Edge e = nodeEdges.next();
      double edgeStrength = e.getStrength();
      Node n;
      int dx, dy;
      double sign = 1.0;
      if (current == e.getNode1()) {
        n = e.getNode2();
        dx = current.getX() - n.getX();
        dy = current.getY() - n.getY();

      } else {
        n = e.getNode1();
        dx = current.getX() - n.getX();
        dy = current.getY() - n.getY();
        sign = -1.0;
      }

      double distance = Math.sqrt(dx * dx + dy * dy) + .1;

      // multiply by the strength of edge
      // current.setVX(current.getVX() - dx / numOfEdgesWeight * edgeStrength);
      // current.setVY(current.getVY() - dy / numOfEdgesWeight * edgeStrength);

      current.accelx += sign * (dx * STIFFNESS * (SPRING_LENGTH - distance)) / current.weight;
      current.accely += sign * (dy * STIFFNESS * (SPRING_LENGTH - distance)) / current.weight;
      // current.accelx += sign * (dx * (e.getStrength() + 1) * (SPRING_LENGTH - distance) * 0.5) /
      // current.weight;
      // current.accely += sign * (dy * (e.getStrength() + 1) * (SPRING_LENGTH - distance) * 0.5) /
      // current.weight;
      // n.accelx += sign * (dx * (e.getStrength() + 1) * (SPRING_LENGTH - distance) * 0.5) /
      // n.weight;
      // n.accely += sign * (dy * (e.getStrength() + 1) * (SPRING_LENGTH - distance) * 0.5) /
      // n.weight;

    }
  }
Пример #3
0
  /**
   * The graph was resize so the algorithm must be adapted to the new size. Then mark dirty.
   *
   * @param w new width
   * @param h new height
   */
  private void setGraphSize(int w, int h) {
    int oldWidth = width;
    int oldHeight = height;
    double relativeWidth, relativeHeight;
    int newX, newY;

    width = w;
    height = h;

    // Move the pinned nodes to adjust to the new size
    ArrayList<Node> pinnedNodes = controller.getGraphPinned();
    if (pinnedNodes != null) {
      for (Node n : pinnedNodes) {
        relativeWidth = (double) n.getX() / oldWidth;
        relativeHeight = (double) n.getY() / oldHeight;
        newX = (int) Math.round(width * relativeWidth);
        newY = (int) Math.round(height * relativeHeight);
        n.setX(newX);
        n.setY(newY);
      }
    }
  }
Пример #4
0
  /**
   * 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.");
  }