Package org.cytoscape.ClusterViz.internal

Source Code of org.cytoscape.ClusterViz.internal.ClusterLayout$PartialDerivatives

package org.cytoscape.ClusterViz.internal;

/*import giny.view.GraphView;
import giny.view.NodeView;*/

import java.awt.geom.Point2D;
import java.util.*;

import org.cytoscape.model.CyNetwork;
import org.cytoscape.model.CyNode;
import org.cytoscape.view.model.CyNetworkView;
import org.cytoscape.view.model.View;
import org.cytoscape.view.presentation.property.BasicVisualLexicon;

import BiNGO.BiNGO.NodeDistances;



/**
* An implementation of spring embedded layout algorithm.
* Note 1: this was copied from giny.util because it is being phased out.  Eventually
* the layout API will be available to use (TODO: remove layout when layout API is available)
* Note 2: this has been modified so that the doLayout method is interruptable and
* reports progress to the Loader
*  */
public class ClusterLayout {

    public static final int DEFAULT_NUM_LAYOUT_PASSES =
            2;
    public static final double DEFAULT_AVERAGE_ITERATIONS_PER_NODE =
            20.0;

    public static final double[] DEFAULT_NODE_DISTANCE_SPRING_SCALARS =
            new double[]{1.0, 1.0};
    public static final double DEFAULT_NODE_DISTANCE_STRENGTH_CONSTANT =
            15.0;
    public static final double DEFAULT_NODE_DISTANCE_REST_LENGTH_CONSTANT =
            200.0;
    public static final double DEFAULT_DISCONNECTED_NODE_DISTANCE_SPRING_STRENGTH =
            .05;
    public static final double DEFAULT_DISCONNECTED_NODE_DISTANCE_SPRING_REST_LENGTH =
            2500.0;

    public static final double[] DEFAULT_ANTICOLLISION_SPRING_SCALARS =
            new double[]{0.0, 1.0};
    public static final double DEFAULT_ANTICOLLISION_SPRING_STRENGTH =
            100.0;

    protected int numLayoutPasses =
            DEFAULT_NUM_LAYOUT_PASSES;
    protected double averageIterationsPerNode =
            DEFAULT_AVERAGE_ITERATIONS_PER_NODE;

    protected double[] nodeDistanceSpringScalars =
            DEFAULT_NODE_DISTANCE_SPRING_SCALARS;
    protected double nodeDistanceStrengthConstant =
            DEFAULT_NODE_DISTANCE_STRENGTH_CONSTANT;
    protected double nodeDistanceRestLengthConstant =
            DEFAULT_NODE_DISTANCE_REST_LENGTH_CONSTANT;
    protected double disconnectedNodeDistanceSpringStrength =
            DEFAULT_DISCONNECTED_NODE_DISTANCE_SPRING_STRENGTH;
    protected double disconnectedNodeDistanceSpringRestLength =
            DEFAULT_DISCONNECTED_NODE_DISTANCE_SPRING_REST_LENGTH;
    protected double[][] nodeDistanceSpringStrengths;
    protected double[][] nodeDistanceSpringRestLengths;

    protected double[] anticollisionSpringScalars =
            DEFAULT_ANTICOLLISION_SPRING_SCALARS;
    protected double anticollisionSpringStrength =
            DEFAULT_ANTICOLLISION_SPRING_STRENGTH;

    protected CyNetworkView graphView;
    protected int nodeCount;
    protected int edgeCount;
    protected int layoutPass;

    protected HashMap nodeIndexToMatrixIndexMap; //maps a root graph index to a distance matrix index
    protected TreeMap matrixIndexToNodeIndexMap; //maps a distance matrix index to a root graph instance

    private boolean interrupted;

    public ClusterLayout() {}

    public ClusterLayout(CyNetworkView graph_view) {
        setGraphView(graph_view);
        initializeSpringEmbeddedLayouter();
    }

    public void setGraphView(CyNetworkView new_graph_view) {
        graphView = new_graph_view;
    } // setGraphView( GraphView )

    public CyNetworkView getGraphView() {
        return graphView;
    } // getGraphView()

    protected void initializeSpringEmbeddedLayouter() {
        // Do nothing.
        // TODO: Something?
    } // initializeSpringEmbeddedLayouter()

    public void interruptDoLayout() {
        this.interrupted = true;
    }

    public void resetDoLayout() {
        this.interrupted = false;
    }

    /**
     * Performs the layout of nodes.
     *
     * @param weightLayout Weighting of this process as calculated by MCODEUtil.convertNetworkToImage
     * @param goalTotal Numerical aim as calculated by MCODEUtil.convertNetworkToImage based on number of processes required
     * @param progress Amount of work completed in finding the cluster before this process started
     * @param loader Loading animation which displays the progress of this process
     * @return true if the layout was completed without interruption, false otherwise
     */
    public boolean doLayout(int weightLayout, int goalTotal, double progress, Loader loader) {
        // initialize the layout.
     
      nodeCount = ((CyNetwork)graphView.getModel()).getNodeCount();
    edgeCount = ((CyNetwork)graphView.getModel()).getEdgeCount();
/*        nodeCount = graphView.getNodeViewCount();
        edgeCount = graphView.getEdgeViewCount();*/

        //initialize the index map
        nodeIndexToMatrixIndexMap = new HashMap();
        matrixIndexToNodeIndexMap = new TreeMap();
        Iterator nodes = ((CyNetwork)graphView.getModel()).getNodeList().iterator();
        //Iterator nodes = graphView.getNodeViewsIterator();
       
        for (int count = 0; nodes.hasNext(); count++)
    {
      CyNode n = (CyNode)nodes.next();
      nodeIndexToMatrixIndexMap.put(n.getSUID(), Integer.valueOf(count));
      matrixIndexToNodeIndexMap.put(Integer.valueOf(count), n.getSUID());
    }
       
/*        int count=0;
        while (nodes.hasNext()) {
            NodeView nodeView = (NodeView) nodes.next();
            nodeIndexToMatrixIndexMap.put(new Integer(nodeView.getRootGraphIndex()), new Integer(count));
            matrixIndexToNodeIndexMap.put(new Integer(count), new Integer(nodeView.getRootGraphIndex()));
            count++;
        }*/

        // Stop if all nodes are closer together than this euclidean distance.
        // TODO: Why is this an appropriate threshold?
        double euclidean_distance_threshold =
                (0.5 * (nodeCount + edgeCount));

        // Stop if the potential energy doesn't go down anymore.
        double potential_energy_percent_change_threshold = .001;
        int num_iterations = (int)
                ((nodeCount * averageIterationsPerNode) / numLayoutPasses);

        List partials_list = createPartialsList();
        PotentialEnergy potential_energy = new PotentialEnergy();
        Iterator node_views_iterator;
//        CyNetworkView node_view;
//        PartialDerivatives partials;
        PartialDerivatives furthest_node_partials = null;
        double current_progress_temp;
        double setup_progress = 0.0;
        for (layoutPass = 0; layoutPass < numLayoutPasses; layoutPass++) {

            setupForLayoutPass();

            // initialize this layout pass
            potential_energy.reset();
            partials_list.clear();

            // Calculate all node distances.  Keep track of the furthest.
           
            for (Iterator iterator = graphView.getNodeViews().iterator(); iterator.hasNext();)
      {
              View node_view = (View)iterator.next();
        PartialDerivatives partials = new PartialDerivatives(node_view);
        calculatePartials(partials, null, potential_energy, false);
        partials_list.add(partials);
        if (furthest_node_partials == null || partials.euclideanDistance > furthest_node_partials.euclideanDistance)
          furthest_node_partials = partials;
      }
           
            /*node_views_iterator = graphView.getNodeViewsIterator();
            while (node_views_iterator.hasNext()) {
                node_view = (NodeView) node_views_iterator.next();

                partials = new PartialDerivatives(node_view);
                calculatePartials(partials,
                        null,
                        potential_energy,
                        false);
                partials_list.add(partials);
                if ((furthest_node_partials == null) ||
                        (partials.euclideanDistance >
                        furthest_node_partials.euclideanDistance)
                ) {
                  furthest_node_partials = partials;
                }
            }*/

            // Until num_iterations, or the farthest node is not-so-far, move the
            // farthest node towards where it wants to be.
            for (int iterations_i = 0;
                 ((iterations_i < num_iterations) &&
                    (furthest_node_partials.euclideanDistance >=
                    euclidean_distance_threshold));
                 iterations_i++
                    ) {              
                if (interrupted) {
                    System.err.println("Interrupted: Layouter");
                    //Before we short circuit the method, we reset the interruption so that the method can run without
                    //problems for the next cluster
                    resetDoLayout();
                    return false;
                }
                furthest_node_partials =
                        moveNode(furthest_node_partials, partials_list, potential_energy);

                progress += 100.0 * (((double) 1 / (double) (num_iterations * numLayoutPasses))) * ((double) weightLayout / (double) goalTotal);

                if (loader != null) {
                    loader.setProgress((int) progress, "Laying out");
                }

            } // End for each iteration, attempt to minimize the total potential
              // energy by moving the node that is farthest from where it should be.
        } // End for each layout pass
        //Just in case an interruption occurred right before we exit the method, we reset it, such an interruption
        //will be dealt with in the MCODEUtil class
        resetDoLayout();
        return true;
    } // End for doLayout()

    /**
     * Called at the beginning of each layoutPass iteration.
     */
    protected void setupForLayoutPass() {
        setupNodeDistanceSprings();
    } // setupForLayoutPass()

    protected void setupNodeDistanceSprings() {
        // We only have to do this once.
        if (layoutPass != 0) {
            return;
        }

        nodeDistanceSpringRestLengths = new double[nodeCount][nodeCount];
        nodeDistanceSpringStrengths = new double[nodeCount][nodeCount];

        if (nodeDistanceSpringScalars[layoutPass] == 0.0) {
            return;
        }

        //create a list of nodes that has the same indices as the nodeIndexToMatrixIndexMap
        ArrayList nodeList = new ArrayList();
        Collection matrixIndices = matrixIndexToNodeIndexMap.values();
        int i=0;
        for (Iterator iterator = matrixIndices.iterator(); iterator.hasNext();) {
            Integer nodeIndex = (Integer) iterator.next();
            nodeList.add(i, ((CyNetwork)graphView.getModel()).getNode(nodeIndex.longValue()));
            /*nodeList.add(i, graphView.getGraphPerspective().getNode(nodeIndex.intValue()));*/
            i++;
        }
        NodeDistances ind = new NodeDistances(nodeList, (CyNetwork)graphView.getModel(), nodeIndexToMatrixIndexMap);
        /*NodeDistance ind = new NodeDistance(nodeList, graphView.getGraphPerspective(), nodeIndexToMatrixIndexMap);*/
        int[][] node_distances = (int[][]) ind.calculate();

        if (node_distances == null) {
            return;
        }

        // TODO: A good strength_constant is the characteristic path length of the
        // graph.  For now we'll just use nodeDistanceStrengthConstant.
        double node_distance_strength_constant = nodeDistanceStrengthConstant;

        // TODO: rest_length_constant can be chosen to scale the whole graph.
        // To make it the size of the current view, try
        // rest_length_constant = Math.sqrt( ( ( graphView.getViewRect().width / graphView.getViewRect.height() ) / 4 ) / graphView.getGraphDiameter() );
        // To make it bigger, try
        // rest_length_constant = graphView.averageEdgeLength();
        // To make it smaller, try
        // rest_length_constant = Math.sqrt( ( graphView.getViewRect().width * graphView.getViewRect.height() ) / graphView.getGraphDiameter() );
        // For now we'll just use nodeDistanceRestLengthConstant.
        double node_distance_rest_length_constant = nodeDistanceRestLengthConstant;

        // Calculate the rest lengths and strengths based on the node distance data
        for (int node_i = 0; node_i < nodeCount; node_i++) {
            for (int node_j = (node_i + 1); node_j < nodeCount; node_j++) {

                if (node_distances[node_i][node_j] == Integer.MAX_VALUE) {
                    nodeDistanceSpringRestLengths[node_i][node_j] =
                            disconnectedNodeDistanceSpringRestLength;
                } else {
                    nodeDistanceSpringRestLengths[node_i][node_j] =
                            (node_distance_rest_length_constant *
                            node_distances[node_i][node_j]);
                }
                // Mirror over the diagonal.
                nodeDistanceSpringRestLengths[node_j][node_i] =
                        nodeDistanceSpringRestLengths[node_i][node_j];

                if (node_distances[node_i][node_j] == Integer.MAX_VALUE) {
                    nodeDistanceSpringStrengths[node_i][node_j] =
                            disconnectedNodeDistanceSpringStrength;
                } else {
                    nodeDistanceSpringStrengths[node_i][node_j] =
                            (node_distance_strength_constant /
                            (node_distances[node_i][node_j] *
                            node_distances[node_i][node_j])
                            );
                }
                // Mirror over the diagonal.
                nodeDistanceSpringStrengths[node_j][node_i] =
                        nodeDistanceSpringStrengths[node_i][node_j];


            }

        }
        // currentProgress has been increased by ( nodeCount * nodeCount ).

    } // setupNodeDistanceSprings()

    /**
     * If partials_list is given, adjust all partials (bidirectional) for the
     * current location of the given partials and return the new farthest node's
     * partials.  Otherwise, just adjust the given partials (using the
     * graphView's nodeViewsIterator), and return it.  If reversed is true then
     * partials_list must be provided and all adjustments made by a non-reversed
     * call (with the same partials with the same graphNodeView at the same
     * location) will be undone.
     * Complexity is O( #Nodes ).
     */
    protected PartialDerivatives calculatePartials(PartialDerivatives partials,
                                                   List partials_list,
                                                   PotentialEnergy potential_energy,
                                                   boolean reversed) {

        partials.reset();

       /* NodeView node_view = partials.getNodeView();*/
        View node_view = partials.getNodeView();
       
        int node_view_index = ((Integer)nodeIndexToMatrixIndexMap.get(((CyNode)node_view.getModel()).getSUID())).intValue();
    double node_view_radius = ((Double)node_view.getVisualProperty(BasicVisualLexicon.NODE_WIDTH)).doubleValue();
    double node_view_x = ((Double)node_view.getVisualProperty(BasicVisualLexicon.NODE_X_LOCATION)).doubleValue();
    double node_view_y = ((Double)node_view.getVisualProperty(BasicVisualLexicon.NODE_Y_LOCATION)).doubleValue();
   
       
/*        int node_view_index = ((Integer) nodeIndexToMatrixIndexMap.get(
                new Integer(node_view.getRootGraphIndex()))).intValue();
        double node_view_radius = node_view.getWidth();
        double node_view_x = node_view.getXPosition();
        double node_view_y = node_view.getYPosition();*/

        PartialDerivatives other_node_partials = null;
        View other_node_view;
        int other_node_view_index;
        double other_node_view_radius;

        PartialDerivatives furthest_partials = null;

        Iterator iterator;
        if (partials_list == null) {
          iterator = graphView.getNodeViews().iterator();
            //iterator = graphView.getNodeViewsIterator();
           
        } else {
            iterator = partials_list.iterator();
        }
        double delta_x;
        double delta_y;
        double euclidean_distance;
        double euclidean_distance_cubed;
        double distance_from_rest;
        double distance_from_touching;
        double incremental_change;
        while (iterator.hasNext()) {
            if (partials_list == null) {
                other_node_view = (View) iterator.next();
            } else {
                other_node_partials = (PartialDerivatives) iterator.next();
                other_node_view = other_node_partials.getNodeView();
            }
            if (((CyNode)node_view.getModel()).getSUID() == ((CyNode)other_node_view.getModel()).getSUID()){
           // if (node_view.getRootGraphIndex() == other_node_view.getRootGraphIndex()) {                //System.out.println( "Nodes are the same. " );
                continue;
            }

           
            other_node_view_index = ((Integer)nodeIndexToMatrixIndexMap.get(((CyNode)other_node_view.getModel()).getSUID())).intValue();
      other_node_view_radius = Math.max(((Double)other_node_view.getVisualProperty(BasicVisualLexicon.NODE_WIDTH)).doubleValue(), ((Double)other_node_view.getVisualProperty(BasicVisualLexicon.NODE_HEIGHT)).doubleValue());
      delta_x = node_view_x - ((Double)other_node_view.getVisualProperty(BasicVisualLexicon.NODE_X_LOCATION)).doubleValue();
      delta_y = node_view_y - ((Double)other_node_view.getVisualProperty(BasicVisualLexicon.NODE_Y_LOCATION)).doubleValue();
   
     
      /*
            other_node_view_index = ((Integer) nodeIndexToMatrixIndexMap.get(
                    new Integer(other_node_view.getRootGraphIndex()))).intValue();
            other_node_view_radius = other_node_view.getWidth();

            delta_x = (node_view_x - other_node_view.getXPosition());
            delta_y = (node_view_y - other_node_view.getYPosition());
*/
            euclidean_distance =
                    Math.sqrt((delta_x * delta_x) + (delta_y * delta_y));
            euclidean_distance_cubed = Math.pow(euclidean_distance, 3);

            distance_from_touching =
                    (euclidean_distance -
                    (node_view_radius + other_node_view_radius));

            incremental_change =
                    (nodeDistanceSpringScalars[layoutPass] *
                    (nodeDistanceSpringStrengths[node_view_index][other_node_view_index] *
                    (delta_x -
                    (
                    (nodeDistanceSpringRestLengths[node_view_index][other_node_view_index] *
                    delta_x) /
                    euclidean_distance
                    )
                    )
                    )
                    );

            if (!reversed) {
                partials.x += incremental_change;
            }
            if (other_node_partials != null) {
                incremental_change =
                        (nodeDistanceSpringScalars[layoutPass] *
                        (nodeDistanceSpringStrengths[other_node_view_index][node_view_index] *
                        (-delta_x -
                        (
                        (nodeDistanceSpringRestLengths[other_node_view_index][node_view_index] *
                        -delta_x) /
                        euclidean_distance
                        )
                        )
                        )
                        );
                if (reversed) {
                    other_node_partials.x -= incremental_change;
                } else {
                    other_node_partials.x += incremental_change;
                }
            }
            if (distance_from_touching < 0.0) {
                incremental_change =
                        (anticollisionSpringScalars[layoutPass] *
                        (anticollisionSpringStrength *
                        (delta_x -
                        (
                        ((node_view_radius + other_node_view_radius) *
                        delta_x) /
                        euclidean_distance
                        )
                        )
                        )
                        );
                if (!reversed) {
                    partials.x += incremental_change;
                }
                if (other_node_partials != null) {
                    incremental_change =
                            (anticollisionSpringScalars[layoutPass] *
                            (anticollisionSpringStrength *
                            (-delta_x -
                            (
                            ((node_view_radius + other_node_view_radius) *
                            -delta_x) /
                            euclidean_distance
                            )
                            )
                            )
                            );
                    if (reversed) {
                        other_node_partials.x -= incremental_change;
                    } else {
                        other_node_partials.x += incremental_change;
                    }
                }
            }
            incremental_change =
                    (nodeDistanceSpringScalars[layoutPass] *
                    (nodeDistanceSpringStrengths[node_view_index][other_node_view_index] *
                    (delta_y -
                    (
                    (nodeDistanceSpringRestLengths[node_view_index][other_node_view_index] *
                    delta_y) /
                    euclidean_distance
                    )
                    )
                    )
                    );
            if (!reversed) {
                partials.y += incremental_change;
            }
            if (other_node_partials != null) {
                incremental_change =
                        (nodeDistanceSpringScalars[layoutPass] *
                        (nodeDistanceSpringStrengths[other_node_view_index][node_view_index] *
                        (-delta_y -
                        (
                        (nodeDistanceSpringRestLengths[other_node_view_index][node_view_index] *
                        -delta_y) /
                        euclidean_distance
                        )
                        )
                        )
                        );
                if (reversed) {
                    other_node_partials.y -= incremental_change;
                } else {
                    other_node_partials.y += incremental_change;
                }
            }
            if (distance_from_touching < 0.0) {
                incremental_change =
                        (anticollisionSpringScalars[layoutPass] *
                        (anticollisionSpringStrength *
                        (delta_y -
                        (
                        ((node_view_radius + other_node_view_radius) *
                        delta_y) /
                        euclidean_distance
                        )
                        )
                        )
                        );
                if (!reversed) {
                    partials.y += incremental_change;
                }
                if (other_node_partials != null) {
                    incremental_change =
                            (anticollisionSpringScalars[layoutPass] *
                            (anticollisionSpringStrength *
                            (-delta_y -
                            (
                            ((node_view_radius + other_node_view_radius) *
                            -delta_y) /
                            euclidean_distance
                            )
                            )
                            )
                            );
                    if (reversed) {
                        other_node_partials.y -= incremental_change;
                    } else {
                        other_node_partials.y += incremental_change;
                    }
                }
            }

            incremental_change =
                    (nodeDistanceSpringScalars[layoutPass] *
                    (nodeDistanceSpringStrengths[node_view_index][other_node_view_index] *
                    (1.0 -
                    (
                    (nodeDistanceSpringRestLengths[node_view_index][other_node_view_index] *
                    (delta_y * delta_y)
                    ) /
                    euclidean_distance_cubed
                    )
                    )
                    )
                    );

            if (reversed) {
                if (other_node_partials != null) {
                    other_node_partials.xx -= incremental_change;
                }
            } else {
                partials.xx += incremental_change;
                if (other_node_partials != null) {
                    other_node_partials.xx += incremental_change;
                }
            }
            if (distance_from_touching < 0.0) {
                incremental_change =
                        (anticollisionSpringScalars[layoutPass] *
                        (anticollisionSpringStrength *
                        (1.0 -
                        (
                        ((node_view_radius + other_node_view_radius) *
                        (delta_y * delta_y)
                        ) /
                        euclidean_distance_cubed
                        )
                        )
                        )
                        );
                if (reversed) {
                    if (other_node_partials != null) {
                        other_node_partials.xx -= incremental_change;
                    }
                } else {
                    partials.xx += incremental_change;
                    if (other_node_partials != null) {
                        other_node_partials.xx += incremental_change;
                    }
                }
            }
            incremental_change =
                    (nodeDistanceSpringScalars[layoutPass] *
                    (nodeDistanceSpringStrengths[node_view_index][other_node_view_index] *
                    (1.0 -
                    (
                    (nodeDistanceSpringRestLengths[node_view_index][other_node_view_index] *
                    (delta_x * delta_x)
                    ) /
                    euclidean_distance_cubed
                    )
                    )
                    )
                    );

            if (reversed) {
                if (other_node_partials != null) {
                    other_node_partials.yy -= incremental_change;
                }
            } else {
                partials.yy += incremental_change;
                if (other_node_partials != null) {
                    other_node_partials.yy += incremental_change;
                }
            }
            if (distance_from_touching < 0.0) {
                incremental_change =
                        (anticollisionSpringScalars[layoutPass] *
                        (anticollisionSpringStrength *
                        (1.0 -
                        (
                        ((node_view_radius + other_node_view_radius) *
                        (delta_x * delta_x)
                        ) /
                        euclidean_distance_cubed
                        )
                        )
                        )
                        );
                if (reversed) {
                    if (other_node_partials != null) {
                        other_node_partials.yy -= incremental_change;
                    }
                } else {
                    partials.yy += incremental_change;
                    if (other_node_partials != null) {
                        other_node_partials.yy += incremental_change;
                    }
                }
            }
            incremental_change =
                    (nodeDistanceSpringScalars[layoutPass] *
                    (nodeDistanceSpringStrengths[node_view_index][other_node_view_index] *
                    ((nodeDistanceSpringRestLengths[node_view_index][other_node_view_index] *
                    (delta_x * delta_y)
                    ) /
                    euclidean_distance_cubed
                    )
                    )
                    );

            if (reversed) {
                if (other_node_partials != null) {
                    other_node_partials.xy -= incremental_change;
                }
            } else {
                partials.xy += incremental_change;
                if (other_node_partials != null) {
                    other_node_partials.xy += incremental_change;
                }
            }
            if (distance_from_touching < 0.0) {
                incremental_change =
                        (anticollisionSpringScalars[layoutPass] *
                        (anticollisionSpringStrength *
                        (
                        ((node_view_radius + other_node_view_radius) *
                        (delta_x * delta_y)
                        ) /
                        euclidean_distance_cubed
                        )
                        )
                        );
                if (reversed) {
                    if (other_node_partials != null) {
                        other_node_partials.xy -= incremental_change;
                    }
                } else {
                    partials.xy += incremental_change;
                    if (other_node_partials != null) {
                        other_node_partials.xy += incremental_change;
                    }
                }
            }

            distance_from_rest =
                    (euclidean_distance -
                    nodeDistanceSpringRestLengths[node_view_index][other_node_view_index]
                    );
            incremental_change =
                    (nodeDistanceSpringScalars[layoutPass] *
                    ((nodeDistanceSpringStrengths[node_view_index][other_node_view_index] *
                    (distance_from_rest * distance_from_rest)
                    ) /
                    2
                    )
                    );

            if (reversed) {
                if (other_node_partials != null) {
                    potential_energy.totalEnergy -= incremental_change;
                }
            } else {
                potential_energy.totalEnergy += incremental_change;
                if (other_node_partials != null) {
                    potential_energy.totalEnergy += incremental_change;
                }
            }
            if (distance_from_touching < 0.0) {
                incremental_change =
                        (anticollisionSpringScalars[layoutPass] *
                        ((anticollisionSpringStrength *
                        (distance_from_touching * distance_from_touching)
                        ) /
                        2
                        )
                        );
                if (reversed) {
                    if (other_node_partials != null) {
                        potential_energy.totalEnergy -= incremental_change;
                    }
                } else {
                    potential_energy.totalEnergy += incremental_change;
                    if (other_node_partials != null) {
                        potential_energy.totalEnergy += incremental_change;
                    }
                }
            }
            if (other_node_partials != null) {
                other_node_partials.euclideanDistance =
                        Math.sqrt((other_node_partials.x * other_node_partials.x) +
                        (other_node_partials.y * other_node_partials.y));
                if ((furthest_partials == null) ||
                        (other_node_partials.euclideanDistance >
                        furthest_partials.euclideanDistance)
                ) {
                    furthest_partials = other_node_partials;
                }
            }

        }

        if (!reversed) {
            partials.euclideanDistance =
                    Math.sqrt((partials.x * partials.x) +
                    (partials.y * partials.y));
        }

        if ((furthest_partials == null) ||
                (partials.euclideanDistance >
                furthest_partials.euclideanDistance)
        ) {
            furthest_partials = partials;
        }


        return furthest_partials;
    }

    /**
     * Move the node with the given partials and adjust all partials in the given
     * List to reflect that move, and adjust the potential energy too.
     *
     * @return the PartialDerivatives of the farthest node after the move.
     */
    protected PartialDerivatives moveNode(PartialDerivatives partials,
                                          List partials_list,
                                          PotentialEnergy potential_energy) {
        View node_view = partials.getNodeView();

        PartialDerivatives starting_partials = new PartialDerivatives(partials);
        calculatePartials(partials,
                partials_list,
                potential_energy,
                true);
        simpleMoveNode(starting_partials);
        return
                calculatePartials(partials,
                        partials_list,
                        potential_energy,
                        false);
    } // moveNode( PartialDerivatives, List, PotentialEnergy )

    protected void simpleMoveNode(PartialDerivatives partials) {
      /*      View node_view = partials.getNodeView();
        double denomenator =
                ((partials.xx * partials.yy) -
                (partials.xy * partials.xy));
        double delta_x =
                (
                ((-partials.x * partials.yy) -
                (-partials.y * partials.xy)) /
                denomenator
                );
        double delta_y =
                (
                ((-partials.y * partials.xx) -
                (-partials.x * partials.xy)) /
                denomenator
                );

        // TODO: figure out movement
        //node_view.setXPosition(
        //  node_view.getXPosition() + delta_x
        //);
        //node_view.setYPosition(
        //  node_view.getYPosition() + delta_y
        //);

        Point2D p = node_view.getOffset();
        node_view.setOffset(p.getX() + delta_x, p.getY() + delta_y);
        */
        View node_view = partials.getNodeView();
    double denomenator = partials.xx * partials.yy - partials.xy * partials.xy;
    double delta_x = (-partials.x * partials.yy - -partials.y * partials.xy) / denomenator;
    double delta_y = (-partials.y * partials.xx - -partials.x * partials.xy) / denomenator;
    double x = ((Double)node_view.getVisualProperty(BasicVisualLexicon.NODE_X_LOCATION)).doubleValue();
    double y = ((Double)node_view.getVisualProperty(BasicVisualLexicon.NODE_Y_LOCATION)).doubleValue();
    node_view.setVisualProperty(BasicVisualLexicon.NODE_X_LOCATION, Double.valueOf(x + delta_x));
    node_view.setVisualProperty(BasicVisualLexicon.NODE_Y_LOCATION, Double.valueOf(y + delta_y));

    } // simpleMoveNode( PartialDerivatives )

    protected List createPartialsList() {
        return new ArrayList();
    } // createPartialsList()

    class PartialDerivatives {
        protected View nodeView;
        public double x;
        public double y;
        public double xx;
        public double yy;
        public double xy;
        public double euclideanDistance;

        public PartialDerivatives(View node_view) {
            nodeView = node_view;
        }

        public PartialDerivatives(PartialDerivatives copy_from) {
            nodeView = copy_from.getNodeView();
            copyFrom(copy_from);
        }

        public void reset() {
            x = 0.0;
            y = 0.0;
            xx = 0.0;
            yy = 0.0;
            xy = 0.0;
            euclideanDistance = 0.0;
        } // reset()

        public View getNodeView() {
            return nodeView;
        } // getNodeView()

        public void copyFrom(PartialDerivatives other_partial_derivatives) {
            x = other_partial_derivatives.x;
            y = other_partial_derivatives.y;
            xx = other_partial_derivatives.xx;
            yy = other_partial_derivatives.yy;
            xy = other_partial_derivatives.xy;
            euclideanDistance = other_partial_derivatives.euclideanDistance;
        } // copyFrom( PartialDerivatives )

        public String toString() {
            return "PartialDerivatives( \"" + getNodeView() + "\", x=" + x + ", y=" + y + ", xx=" + xx + ", yy=" + yy + ", xy=" + xy + ", euclideanDistance=" + euclideanDistance + " )";
        } // toString()

    } // inner class PartialDerivatives

    class PotentialEnergy {

        public double totalEnergy = 0.0;

        public void reset() {
            totalEnergy = 0.0;
        } // reset()

    } // class PotentialEnergy

} // class SpringEmbeddedLayouter
TOP

Related Classes of org.cytoscape.ClusterViz.internal.ClusterLayout$PartialDerivatives

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.