Animations Beispielprogramm : Dijkstra - Algorithmus
// Animierter Dijkstra Algorithmus
import gabl.graph.*;
import gabl.prop.*;
import gabl.data.*;
import gabl.util.*;
import gabl.export.*;
import gabl.anim.*;
import java.util.Comparator;
import java.io.*;
import java.awt.*;
public class AnimatedDijkstra implements AnimatedAlgorithm
{
Digraph D;
EdgeRProperty C;
AnimationManager manager; // Animations-Manager (steuert die Fenster etc.)
AnimatedGraphFrame anim; // verwaltet die visuellen Eigenschaften des Programms
static final Color colorNotVisited = Color.black; // Kanten sind schwarz falls nicht betrachtet
static final Color colorCurrent = Color.red; // Farbe der Knoten falls gerade betrachtet
static final Color colorInTree = Color.orange; // Knoten und Kanten im aktuellen KW-Baum
static final Color colorNotInTree = Color.black; // Kante die nicht im KW-Baum sind
// Konstruktor der die Daten aus dem Bundle einliest.
AnimatedDijkstra(GraphBundle bundle, String filename, AnimatedGraphFrame anim)
{
// Digraphen einlesen geht genauso wie bei ungerichteten Graphen
// man muss nur anders casten:
this.D = (Digraph)bundle.getGraph();
this.C = bundle.getEdgeIntegerRProperty("weight");
this.anim = anim;
this.manager = new AnimationManager(); // erzeuge neuen Manager
this.manager.setAnimatedAlgorithm(this); // Dies muss immer der letzte Aufruf sein!!!!
}
// Methode jedes animierten Algorithmus zum Initialisieren (setzen der Farben ...)
public void init()
{
// Im Fenster der Animationssteuerung ist unten eingeblendet wie lange der
// Algorithmus voraussichtlich noch braucht. Hier setzt man die maximale
// Anzahl von Schritten die der Algorithmus braucht:
// hier die Anzahl der Kanten + die Anzahl der Knoten
manager.setProgressBarLength(D.getNumberOfEdges()+D.getNumberOfVertices());
// Zuerst die Animation abstellen, damit die Farben geaendert werden koennen:
anim.setAnimationEnabled(false);
VertexIterator vit=D.createVertexIterator();
for (; ! vit.atEnd(); vit.increment())
{
anim.setVertexColor(vit.getVertex(), Color.white); // alle Knoten normal faerben
anim.setVertexLabel(vit.getVertex(), ""); // Jeder Knoten ohne Label
}
EdgeIterator eit=D.createEdgeIterator();
for(; !eit.atEnd(); eit.increment())
{
anim.setEdgeWidth(eit.getEdge(), 2);
anim.setEdgeColor(eit.getEdge(), colorNotVisited); // alle Kanten unbetrachtet
anim.setEdgeLabel(eit.getEdge(), "" + ((Integer) C.get(eit.getEdge())).intValue()); // Kantengewicht
}
// Animation wieder anstellen.
anim.setAnimationEnabled(true);
}
// Methode jedes animierten Algorithmus: hier laeuft der eigentliche Algorithmus ab
public void run()
{
// Rufe den Dijsktra-Algorithmus auf (mit beliebigen Startknoten)
Dijkstra(D.createVertexIterator().getVertex(),this.D,this.C);
}
public void Dijkstra (Vertex s,Digraph D,EdgeRProperty C)
{
VertexProperty l = GraphPropertyFactory.createVertexProperty(D, "distance");
VertexProperty treeEdge = GraphPropertyFactory.createVertexProperty(D, "treeEdge",null);
VertexProperty heapItem = GraphPropertyFactory.createVertexProperty(D, "heapItem",null);
VertexProperty visited = GraphPropertyFactory.createVertexProperty(D, "visited", Boolean.FALSE);
PairingHeap heap = new PairingHeap(new VertexIntPropComparator(l));
l.set(s, new Integer(0));
heapItem.set(s, heap.add(s));
Vertex oldv=s;
anim.setVertexLabel(s, "0"); // setze Label auf Entfernung
while(! heap.isEmpty())
{
Vertex v = (Vertex) heap.removeMin();
heapItem.set(v, null);
anim.setVertexColor(oldv, colorInTree); // markiere abgearbeiteten Knoten
oldv=v;
anim.setVertexColor(v, colorCurrent); // markiere betrachteten Knoten
manager.stepProgressBar(); // ein Schritt im Algorithmus abgeschlossen
manager.pause("betrachte Knoten: " + D.toString(v)); // Nachricht zur Information
EdgeIterator eit = D.createOutEdgeIterator(v);
for (; !eit.atEnd(); eit.increment())
{
Vertex w = D.getTarget(eit);
if (! ((Boolean) visited.get(w)).booleanValue() )
{
Edge e = eit.getEdge();
int newDist = ((Integer)l.get(v)).intValue() + ((Integer)C.get(e)).intValue();
Object oldDist = l.get(w);
if (oldDist == null)
{
treeEdge.set(w, e);
l.set(w, new Integer(newDist));
heapItem.set(w, heap.add(w));
treeEdge.set(w, e);
anim.setVertexLabel(w, "" + newDist);
anim.setVertexColor(w, colorInTree); // Knoten im Heap
anim.setEdgeColor(e, colorInTree); // dazugehoerige Kante
manager.stepProgressBar(); // ein Schritt im Algorithmus abgeschlossen
manager.pause("neuer Knoten im Heap: " + D.toString(w) + " Distanz: " + newDist);
}
else
{
if (newDist < ((Integer)oldDist).intValue())
{
anim.setEdgeColor((Edge) treeEdge.get(w), colorNotInTree);
treeEdge.set(w, e);
l.set(w, new Integer(newDist));
heap.decreaseKey((Iterator)heapItem.get(w));
anim.setVertexLabel(w, "" + newDist); // setze Label auf entfernung
anim.setEdgeColor(e, colorInTree); // Kante im KW-Baum
manager.stepProgressBar(); // ein Schritt im Algorithmus abgeschlossen
manager.pause("Knoten aktualisiert: " + D.toString(w) + " Distanz: " + newDist);
}
}
}
}
visited.set(v, Boolean.TRUE);
}
}
// ---------------------------------------------
public static void main ( String[] argv )
{
if (argv.length != 1)
{
System.err.println("Error: need filename");
return;
}
GraphFactory factory = new GraphFactory();
String filename = argv[0];
File infile = new File(filename);
try
{
GraphBundle bundle = GraphFormatGML.readGraph(infile, factory);
AnimatedGraphFrame anim = new AnimatedGraphFrame(bundle);
AnimatedDijkstra instance = new AnimatedDijkstra(bundle, filename, anim);
}
catch (NoSuchGraphImplementationException e) {
System.err.println(e.toString());
}
catch (ClassCastException e) {
System.err.println("Error: graph has wrong type '" + e.toString() + "'");
e.printStackTrace();
}
catch (IOException e) {
System.err.println("Error: reading file '" + infile + "' failed.\n" + e);
e.printStackTrace();
}
}
}