blob: 199c5b2cd1c261c1863ace93037a1fa3416678b4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 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.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Sorts nodes in a compound directed graph.
*
* @author Randy Hudson
* @since 2.1.2
*/
class CompoundRankSorter extends RankSorter {
static class RowEntry {
double contribution;
int count;
void reset() {
count = 0;
contribution = 0;
}
}
static class RowKey {
int rank;
Subgraph s;
RowKey() {
}
RowKey(Subgraph s, int rank) {
this.s = s;
this.rank = rank;
}
public boolean equals(Object obj) {
RowKey rp = (RowKey) obj;
return rp.s == s && rp.rank == rank;
}
public int hashCode() {
return s.hashCode() ^ (rank * 31);
}
}
boolean init;
RowKey key = new RowKey();
Map map = new HashMap();
void addRowEntry(Subgraph s, int row) {
key.s = s;
key.rank = row;
if (!map.containsKey(key))
map.put(new RowKey(s, row), new RowEntry());
}
protected void assignIncomingSortValues() {
super.assignIncomingSortValues();
}
protected void assignOutgoingSortValues() {
super.assignOutgoingSortValues();
}
void optimize(DirectedGraph g) {
CompoundDirectedGraph graph = (CompoundDirectedGraph) g;
Iterator containment = graph.containment.iterator();
while (containment.hasNext())
graph.removeEdge((Edge) containment.next());
graph.containment.clear();
new LocalOptimizer().visit(graph);
}
double evaluateNodeOutgoing() {
double result = super.evaluateNodeOutgoing();
// result += Math.random() * rankSize * (1.0 - progress) / 3.0;
if (progress > 0.2) {
Subgraph s = node.getParent();
double connectivity = mergeConnectivity(s, node.rank + 1, result,
progress);
result = connectivity;
}
return result;
}
double evaluateNodeIncoming() {
double result = super.evaluateNodeIncoming();
// result += Math.random() * rankSize * (1.0 - progress) / 3.0;
if (progress > 0.2) {
Subgraph s = node.getParent();
double connectivity = mergeConnectivity(s, node.rank - 1, result,
progress);
result = connectivity;
}
return result;
}
double mergeConnectivity(Subgraph s, int row, double result,
double scaleFactor) {
while (s != null && getRowEntry(s, row) == null)
s = s.getParent();
if (s != null) {
RowEntry entry = getRowEntry(s, row);
double connectivity = entry.contribution / entry.count;
result = connectivity * 0.3 + (0.7) * result;
s = s.getParent();
}
return result;
}
RowEntry getRowEntry(Subgraph s, int row) {
key.s = s;
key.rank = row;
return (RowEntry) map.get(key);
}
void copyConstraints(NestingTree tree) {
if (tree.subgraph != null)
tree.sortValue = tree.subgraph.rowOrder;
for (int i = 0; i < tree.contents.size(); i++) {
Object child = tree.contents.get(i);
if (child instanceof Node) {
Node n = (Node) child;
n.sortValue = n.rowOrder;
} else {
copyConstraints((NestingTree) child);
}
}
}
public void init(DirectedGraph g) {
super.init(g);
init = true;
for (int row = 0; row < g.ranks.size(); row++) {
Rank rank = g.ranks.getRank(row);
NestingTree tree = NestingTree.buildNestingTreeForRank(rank);
copyConstraints(tree);
tree.recursiveSort(true);
rank.clear();
tree.repopulateRank(rank);
for (int j = 0; j < rank.count(); j++) {
Node n = rank.getNode(j);
Subgraph s = n.getParent();
while (s != null) {
addRowEntry(s, row);
s = s.getParent();
}
}
}
}
protected void postSort() {
super.postSort();
if (init)
updateRank(rank);
}
void updateRank(Rank rank) {
for (int j = 0; j < rank.count(); j++) {
Node n = rank.getNode(j);
Subgraph s = n.getParent();
while (s != null) {
getRowEntry(s, currentRow).reset();
s = s.getParent();
}
}
for (int j = 0; j < rank.count(); j++) {
Node n = rank.getNode(j);
Subgraph s = n.getParent();
while (s != null) {
RowEntry entry = getRowEntry(s, currentRow);
entry.count++;
entry.contribution += n.index;
s = s.getParent();
}
}
}
}