Mercurial > projects > dwt-addons
diff dwtx/draw2d/graph/NodeCluster.d @ 98:95307ad235d9
Added Draw2d code, still work in progress
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sun, 03 Aug 2008 00:52:14 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/draw2d/graph/NodeCluster.d Sun Aug 03 00:52:14 2008 +0200 @@ -0,0 +1,243 @@ +/******************************************************************************* + * 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 + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ +module dwtx.draw2d.graph.NodeCluster; + +import dwt.dwthelper.utils; +import dwtx.dwtxhelper.Collection; +import dwtx.draw2d.graph.NodeList; +import dwtx.draw2d.graph.CollapsedEdges; + +/** + * A group of nodes which are interlocked and cannot be separately placed. + * @since 3.1 + */ +class NodeCluster : NodeList { + +alias NodeList.adjustRank adjustRank; + +int toHash_; + +bool isSetMember; +bool isDirty; +bool leftDirty; +bool rightDirty; + +int leftFreedom; +int rightFreedom; +int leftNonzero; +int rightNonzero; +int leftCount = 0; +int rightCount = 0; + +CollapsedEdges[] leftLinks; +CollapsedEdges[] rightLinks; +NodeCluster[] leftNeighbors; +NodeCluster[] rightNeighbors; + +int effectivePull; +int weightedTotal; +int weightedDivisor; +int unweightedTotal; +int unweightedDivisor; + +public this(){ + toHash_ = (new Object()).toHash(); + leftLinks = new CollapsedEdges[10]; + rightLinks = new CollapsedEdges[10]; + leftNeighbors = new NodeCluster[10]; + rightNeighbors = new NodeCluster[10]; +} + +void addLeftNeighbor(NodeCluster neighbor, CollapsedEdges link) { + //Need to grow array in the following case + if (leftNeighbors.length is 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 is 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 override int opEquals(Object o) { + return o is this; +} + +CollapsedEdges getLeftNeighbor(NodeCluster neighbor) { + for (int i = 0; i < leftCount; i++) { + if (leftNeighbors[i] is neighbor) + return leftLinks[i]; + } + return null; +} + +int getPull() { + return effectivePull; +} + +CollapsedEdges getRightNeighbor(NodeCluster neighbor) { + for (int i = 0; i < rightCount; i++) { + if (rightNeighbors[i] is neighbor) + return rightLinks[i]; + } + return null; +} + +public override hash_t toHash() { + return toHash_; +} + +/** + * 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 !is 0) + effectivePull = weightedTotal / weightedDivisor; + else if (unweightedDivisor !is 0) + effectivePull = unweightedTotal / unweightedDivisor; + else + effectivePull = 0; +} + +}