blob: ac28844200738b0d8fae065c2f221fc4e5e6a3e2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.draw2d.graph;
import java.util.Collection;
/**
* A group of nodes which are interlocked and cannot be separately placed.
*
* @since 3.1
*/
class NodeCluster extends NodeList {
int hashCode = new Object().hashCode();
boolean isSetMember;
boolean isDirty;
boolean leftDirty;
boolean rightDirty;
int leftFreedom;
int rightFreedom;
int leftNonzero;
int rightNonzero;
int leftCount = 0;
int rightCount = 0;
CollapsedEdges leftLinks[] = new CollapsedEdges[10];
CollapsedEdges rightLinks[] = new CollapsedEdges[10];
NodeCluster leftNeighbors[] = new NodeCluster[10];
NodeCluster rightNeighbors[] = new NodeCluster[10];
int effectivePull;
int weightedTotal;
int weightedDivisor;
int unweightedTotal;
int unweightedDivisor;
void addLeftNeighbor(NodeCluster neighbor, CollapsedEdges link) {
// Need to grow array in the following case
if (leftNeighbors.length == leftCount) {
int newSize = leftNeighbors.length * 2;
NodeCluster newNeighbors[] = new NodeCluster[newSize];
CollapsedEdges newLinks[] = new CollapsedEdges[newSize];
System.arraycopy(leftNeighbors, 0, newNeighbors, 0,
leftNeighbors.length);
System.arraycopy(leftLinks, 0, newLinks, 0, leftLinks.length);
leftNeighbors = newNeighbors;
leftLinks = newLinks;
}
leftNeighbors[leftCount] = neighbor;
leftLinks[leftCount++] = link;
}
void addRightNeighbor(NodeCluster neighbor, CollapsedEdges link) {
if (rightNeighbors.length == rightCount) {
int newSize = rightNeighbors.length * 2;
NodeCluster newNeighbors[] = new NodeCluster[newSize];
CollapsedEdges newLinks[] = new CollapsedEdges[newSize];
System.arraycopy(rightNeighbors, 0, newNeighbors, 0,
rightNeighbors.length);
System.arraycopy(rightLinks, 0, newLinks, 0, rightLinks.length);
rightNeighbors = newNeighbors;
rightLinks = newLinks;
}
rightNeighbors[rightCount] = neighbor;
rightLinks[rightCount++] = link;
}
public void adjustRank(int delta, Collection affected) {
adjustRank(delta);
NodeCluster neighbor;
CollapsedEdges edges;
for (int i = 0; i < leftCount; i++) {
neighbor = leftNeighbors[i];
if (neighbor.isSetMember)
continue;
edges = leftLinks[i];
neighbor.weightedTotal += delta * edges.collapsedWeight;
neighbor.unweightedTotal += delta * edges.collapsedCount;
weightedTotal -= delta * edges.collapsedWeight;
unweightedTotal -= delta * edges.collapsedCount;
neighbor.rightDirty = leftDirty = true;
if (!neighbor.isDirty) {
neighbor.isDirty = true;
affected.add(neighbor);
}
}
for (int i = 0; i < rightCount; i++) {
neighbor = rightNeighbors[i];
if (neighbor.isSetMember)
continue;
edges = rightLinks[i];
neighbor.weightedTotal += delta * edges.collapsedWeight;
neighbor.unweightedTotal += delta * edges.collapsedCount;
weightedTotal -= delta * edges.collapsedWeight;
unweightedTotal -= delta * edges.collapsedCount;
neighbor.leftDirty = rightDirty = true;
if (!neighbor.isDirty) {
neighbor.isDirty = true;
affected.add(neighbor);
}
}
isDirty = true;
affected.add(this);
}
public boolean equals(Object o) {
return o == this;
}
CollapsedEdges getLeftNeighbor(NodeCluster neighbor) {
for (int i = 0; i < leftCount; i++) {
if (leftNeighbors[i] == neighbor)
return leftLinks[i];
}
return null;
}
int getPull() {
return effectivePull;
}
CollapsedEdges getRightNeighbor(NodeCluster neighbor) {
for (int i = 0; i < rightCount; i++) {
if (rightNeighbors[i] == neighbor)
return rightLinks[i];
}
return null;
}
public int hashCode() {
return hashCode;
}
/**
* Initializes pull and freedom values.
*/
void initValues() {
weightedTotal = 0;
weightedDivisor = 0;
unweightedTotal = 0;
int slack;
leftNonzero = rightNonzero = leftFreedom = rightFreedom = Integer.MAX_VALUE;
for (int i = 0; i < leftCount; i++) {
CollapsedEdges edges = leftLinks[i];
weightedTotal -= edges.getWeightedPull();
unweightedTotal -= edges.tightestEdge.getSlack();
unweightedDivisor += edges.collapsedCount;
weightedDivisor += edges.collapsedWeight;
slack = edges.tightestEdge.getSlack();
leftFreedom = Math.min(slack, leftFreedom);
if (slack > 0)
leftNonzero = Math.min(slack, leftNonzero);
}
for (int i = 0; i < rightCount; i++) {
CollapsedEdges edges = rightLinks[i];
weightedTotal += edges.getWeightedPull();
unweightedDivisor += edges.collapsedCount;
unweightedTotal += edges.tightestEdge.getSlack();
weightedDivisor += edges.collapsedWeight;
slack = edges.tightestEdge.getSlack();
rightFreedom = Math.min(slack, rightFreedom);
if (slack > 0)
rightNonzero = Math.min(slack, rightNonzero);
}
updateEffectivePull();
}
/**
* Refreshes the left and right freedom.
*/
void refreshValues() {
int slack;
isDirty = false;
if (leftDirty) {
leftDirty = false;
leftNonzero = leftFreedom = Integer.MAX_VALUE;
for (int i = 0; i < leftCount; i++) {
CollapsedEdges edges = leftLinks[i];
slack = edges.tightestEdge.getSlack();
leftFreedom = Math.min(slack, leftFreedom);
if (slack > 0)
leftNonzero = Math.min(slack, leftNonzero);
}
}
if (rightDirty) {
rightDirty = false;
rightNonzero = rightFreedom = Integer.MAX_VALUE;
for (int i = 0; i < rightCount; i++) {
CollapsedEdges edges = rightLinks[i];
slack = edges.tightestEdge.getSlack();
rightFreedom = Math.min(slack, rightFreedom);
if (slack > 0)
rightNonzero = Math.min(slack, rightNonzero);
}
}
updateEffectivePull();
}
private void updateEffectivePull() {
if (weightedDivisor != 0)
effectivePull = weightedTotal / weightedDivisor;
else if (unweightedDivisor != 0)
effectivePull = unweightedTotal / unweightedDivisor;
else
effectivePull = 0;
}
}