Flow-Map Viewer
Christoph Bösch (0226079)
Reinhold Preiner (0430380)


VO InfoVis, SS 2008, TU Wien

Dokumentation

 

Einführung

 

Mit dem  Flow-Map Viewer stellen wir ein Tool zur Verfügung, dass aus einem geeigneten Datenset automatisch eine Flow-Map generiert und diese am Bildschirm darstellt.

Flow Map Layouts sind ein geeignetes Mittel zur Visualisierung von quantitativen Objektbewegungen in einem geographischen Kontext (meist Landkarten). Sie werden verwendet zur Darstellung von Statistiken wie Warenexporte, Migrationen u.a. Charakteristischerweise visualisieren solche Graphen eine gegebene Menge von Bewegungsvektoren mit einem einheitlichem Ursprung, sowie unterschiedlichen Zielen und Gewichtungen. Der Nachteil von simplen computergestützten Visualisierungsverfahren, in denen diese Vektoren als geradlinige Pfeile dargestellt werden, die radial vom Ursprungspunkt ausgehen, ist die visuelle Überladung, die durch eng beieinander liegende Pfeile entsteht. Vor allem bei großen Datenmengen geht aufgrund dieses Effektes die Anschaulichkeit einer Grafik schnell verloren.

D. Phan et al beschreiben in ihrem Paper „Flow Map Layout“ [1] einen Weg, durch geeignete Zusammenfassung geographisch benachbarter Vektoren die einzelnen Pfeile herkömmlicher Visualisierungssysteme durch eine anschauliche Baumstruktur zu ersetzen (hierarchisches Clustering), welche eine allumfassende Verzweigungsgrafik in der Massenbewegung zu erhalten.

 

Anschließend eine detaillierte Beschreibung der Umsetzung der Rendering-Pipeline sowie die Handhabung des Tools.

 

 

Dateneingabe

 

Für das Einlesen von Datenfiles ist ein CSVReader zuständig. Folgendes Datenformat wurde spezifiziert:

Eine Zeile steht für einen Knoten im Graph. Als Trennzeichen dient der Beistrich. In einer Zeile stehen die x-Koordinate, die y-Koordinate und das Knotengewicht als double-Wert, mit dem Punkt um die Nachkommastellen abzugrenzen. Als vierter Wert in der Zeile steht der Labeltext für den Knoten als String. Die Werte müssen in der eben verwendeten Reihenfolge stehen. Der Root-Knoten zeichnet sich durch ein Gewicht von -1 aus.

 

Bsp: Input-CSV-File

csv.PNG


Diese Werte werden in einem FMPoint-Objekt gespeichert. Nach dem Einlesevorgang liegt ein java.util.Vector-Objekt gefüllt mit FMPoint-Objekten vor. Dieser wird nun in sechs Schritten zu einem übersichtlichen Baum umgestaltet, der für die Darstellung als Flow Map geeignet ist. Diese Schritte werden nun näher beschrieben.

 

 

Layout-Adjustment

 

Zuerst gilt es die Abstände der Knoten soweit zu erhöhen, dass sowohl für Labels als auch für Kanten zwischen diesen Labels genügend Platz vorhanden ist. Dafür verwenden wir, dem Paper folgend, den Force Scan Algorithmus, wie von Kazuo Misue et al. 1995 im Paper „Layoutadjustment and the Mental Map“ beschrieben. Der Punkt-Vector wird zuerst nach aufsteigendem x-Wert sortiert, dann wird die Abstände der Knoten untereinander verglichen. Falls ein Abstand zu gering ist, wird eine Force für die beiden betroffenen Knoten errechnet und der Knoten mit dem höheren x Wert, sowie alle ihm nachfolgenden Knoten um diese Force verschoben. Dasselbe geschieht für die y-Dimension.

 

 

Primary-Hierarchical-Clustering

 

Im zweiten Schritt werden jeweils die zwei nächsten Punkte bzw. Cluster zu einem neuen Cluster zusammengefasst. So entsteht ein binärer Baum dessen Blätter die ursprünglichen Knoten darstellen. Je mehr Kanten zwischen zwei Blättern liegen, desto größer auch ihr realer Abstand.

 

 

Rooted-Hierarchical-Clustering

 

In diesem Schritt wird der als Wurzelknoten gekennzeichnete Knoten wirklich an die Wurzel des Baumes gebracht. Dies geschieht mit dem Hierarchical-Clustering Algorithmus. Der angestrebte Root Knoten wird Ebene für Ebene im Baum nach oben geschoben, die Lücken die er auf höheren Ebenen hinterlässt, werden automatisch aufgefüllt.

 

 

Weight-Calculation

 

Dieser Schritt wird in [1] eigentlich zusammen mit dem Vorschritt erwähnt. Aufgrund unserer individuellen Implementierung (siehe Abschnitt 'Edge-Uncrossing') wurde er jedoch separat herausgenommen, um ihn später evtl. erneut aufzurufen.

Die Weight-Calculation ist dafür verantwortlich rekursiv die Gewichte aller Endknoten des Baumes aufzusummieren, und die Zwischensummen der Gewichte in den Verzweigungsknoten des Baumes zu speichern (bottom-up: von den Endknoten bis zum Rootknoten). Diese Informationen werden später im Rendering für die Berechnung der Kanten-Dicke herangezogen.

 

 

Spatial Layout

 

Hierbei müssen an den Punkten an denen sich der Baum aufspaltet um zwei Subcluster zu erreichen Verzweigungsknoten erstellt werden. Die Verzweigungsknoten werden rekursiv erzeugt, und zwar immer auf einer direkten Linie zwischen dem aktuellen Ausgangsknoten und dem schwereren Kind bzw. Subcluster. Diese neuen Knoten besitzen keine Label.

 

 

Edge-Routing

 

Der Edge-Routing-Schritt im Algorithmus dient dem Auffinden von Kanten, die durch den Bereich des Graphen verläuft, die dem Ast einer Schwesterkante angehört. Für solche Fälle soll das Edge-Routing den durchkreuzenden Ast um diesen Bereich "herumleiten". Im Allgemeinen wurde der Edge-Routing Algorithmus so umgesetzt, wie er in [1] beschrieben wurde.

 

 

Edge-Uncrossing

 

D. Phan et al verweisen in ihrem Paper bereits auf das Problem, dass trotz des Edge-Routings im Vorschritt es im Ergebnis-Graphen zu sich überkreuzenden Kanten kommen kann [1]. Da auch wir mit dieser Problematik konfrontiert wurden, haben wir einen neuen Rendering-Schritt eingeführt, das "Edge-Uncrossing".

In diesem Schritt werden restliche, sich überkreuzende Kanten aufgesucht und die Überkreuzungen aufgelöst. Dies geschieht durch einen Algorithmus, das iterativ folgende Schritte durchführt:

 

·         Suche zwei sich überkreuzende Kanten im Graphen

·         Wurden zwei Kanten a und b gefunden, deren Liniensegmente sich überkreuzen, unterscheide:

 

o   Ist der Root-Knoten des Graphen der einzige gemeinsame Vorfahre der beiden Vaterknoten von a und b, dann löse die Überkreuzung, indem die Vaterknoten von a und b getauscht werden.

uncross1.PNG

o   Ist der Kindknoten von b in der Hierarchie ein Vorfahre des Vaterknotens von a, so wird am Schnittpunkt c zwischen a und b ein neuer Knoten eingefügt, der die Kante b in zwei neue Kanten aufteilt, und der neue Vaterknoten von a ist.

uncross2.PNG

 

·         Diese Schritte werden solange ausgeführt, bis der Graph frei von Überkreuzungen ist

·         Da aufgrund des Relinks der Teiläste der Graphen jedoch wieder neue Überkreuzungen entstehen können, besteht die Gefahr einer Endlosschleife. Daher wird der Vorgang nach einer gewissen Anzahl von Iterationen beendet.

 

Hinweis: Da nach einem Neu-Verlinken des Baumes die im Schritt "Weight-Calculation" berechnete Gewicht-Hierarchie zerstört wird, wird nach einem eventuellen Edge-Uncrossing die Weight-Calculation erneut durchgeführt.

 

 

Rendering

 

Das Rendering wird grundsätzlich vom prefuse Framework übernommen, bzw. kann durch bestehende Komponenten realisiert werden. Wichtige Funktionen wie das Zoomen sind so schnell umsetzbar. Der Flow-Map Layout Ansatz, den wir verfolgen, erfordert allerdings eine Erweiterung der prefuse-Standartfunktionalität.

 

LabelRenderer

Um den Text für ein Label aus einer FMPoint Variablen auszulesen ist es nötig die getText(VisualItem item) Methode der LabelRenderer Klasse zu überschreiben. Diese neue Methode holt zuerst das FMPoint Objekt aus dem VisualItem und gibt anschließend den label String zurück. Für diesen Zweck haben wir die Klasse FMPointRenderer erstellt, die von prefuse.renderer.LabelRenderer abgeleitet ist.

 

TreeLayout

Für die Positionierung der Knoten der Flow Map sollen auch die Koordinaten aus dem FMPoint des VisualItem Objekts verwendet werden. Dafür musste die Klasse FixedPositionTreeLayout  von prefuse.action.layout.graph.TreeLayout abgeleitet werden. Um die richtigen Koordinaten zu erhalten haben wir die Funktion getLayoutAnchor() so überschrieben, dass sie auf die Daten des FMPoint Objekts zugreift.

 

EdgeRenderer

Um dem Baum ein möglichst organisches Aussehen zu geben wird im Paper die Darstellung der Kanten als Catmull-Rom Splines vorgeschlagen. Auch diese Splines werden von prefuse nicht standartmäßig unterstützt. Um diesen Mangel auszugleichen haben wir einen eigenen CatmullRomSplineEdgeRenderer geschrieben, der eine Unterklasse von prefuse.renderer.EdgeRenderer ist. In dieser Klasse ist die getRawShape(VisualItem item)

Methode dafür zuständig, eine visuelle Repräsentation einer Kante als java.awt.Shape Objekt zu liefern.

Der Start- und Endpunkt des Splines und der Kante sind identisch, der Spline benötigt aber an jedem Ende noch einen Kontrollpunkt. Dafür wird der Vaterknoten des Startpunktes und ein gewichteter Mittelwert aus den Kindknoten des Endknotens verwendet. Gewichtet wird mit dem Knotengewicht das ohnehin jeder Knoten im angehängten FMPoint gespeichert hat.

Durch diese Wahl der Kontrollpunkte entsteht ein fließender Übergang zwischen aufeinander folgenden Kanten.

 

 

Interface

 

Das Interface besteht aus einem großzügigen Fenster, durch das der Baum betrachtet werden kann. Der Baum kann hier mit der Maus verschoben werden. As kann mit dem Mausrad hin oder weg gezoomt werden.

 

In einer Leiste unterhalb dieses Fensters können einige Einstellungen gemacht werden. Hier lassen sich die Punkte

 

·         Layout-Adjustment,

·         Edge-Routing und

·         Edge-Uncrossing

 

durch eine Checkbox optional ein- und ausschalten. Werden sie nicht durchführt, generiert das Programm trotzdem einen Baum der die Kriterien einer Flow-Map erfüllt, die Übersichtlichkeit und Lesbarkeit sind allerdings unter Umständen stark eingeschränkt. (Primary- und Rooted-Hierarchical-Clustering sowie Spatial-Layout sind obligatorische Schritte. Sie überführen die Ausgangsdaten in die für eine Flow-Map nötige Baumstruktur.) Über einen FileChooser kann auch eine neue Datenquelle in Form eines CSV-Files ausgewählt werden.

 

 

Screenshots

 

ss.PNG

 

Links: Flow Map-Datensatz ohne Edge-Routing und ohne Edge-Uncrossing.

Mitte: Derselbe Datensatz mit Edge-Routing. Baumzweige werden bereits um andere Punktcluster herumgeführt, einzelne Kanten-Überkreuzungen tretten jedoch immer noch auf.

Rechts: Derselbe Datensatz mit Edge-Routing und Edge-Uncrossing. Wie man sieht, wurden alle restlichen Kantenkreuzungen entfernt.

 

 

Download

 

Flow-Map Viewer V 1.0      

Einige Testdaten-CSV-Files

 

Referenzen

[1] D. Phan, L. Xiao, R. Yeh, P. Hanrahan, T. Winograd, "Flow Map Layout", 
INFOVIS '05: Proceedings of the Proceedings of the 2005 IEEE Symposium on Information Visualization (2005), 
IEEE Computer Society, p. 29,