Mercurial > projects > dwt-addons
view 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 source
/******************************************************************************* * 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; } }