/******************************************************************************* * Copyright (c) 2005 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; } }