In einem ersten Post habe ich die Grundlagen von Processing kurz erläutert und auch schon angekündigt, um was es im zweiten Teil gehen soll: Die Visualisierung von geographischen Daten mittels Processing, also eine Art „Geo-Processing“.
Dazu habe ich als Grundlagedaten einen Datensatz über Erdbeben im Jahr 2009 des Carlton College in Minnesota und ein Satellitenbild-Mosaik aus MODIS-Aufnahmen des Blue Marble-Projekts von NASA Visible Earth verwendet. Das Blue Marble-Bild soll als Hintergrund dienen, vor dem die Erdbebendaten dargestellt werden. Die Projektion des Blue Marble-Bilds ist nicht angegeben, aber aufgrund des Aussehens und der Dimensionen (doppelt so breit als hoch), wird es sich dabei um eine Plate Carrée-Projektion handeln.
Mit Processing kann die Darstellung eines Bilds sehr einfach bewerkstelligt werden:
// Canvas - suitable for Plate Carree projection int wdth = 1000; int hght = 500; PImage img; void setup() { noLoop(); // Draw only once size(wdth, hght); // Define canvas size smooth(); img = loadImage("bluemarble.jpg"); // Load backdrop image img.resize(wdth, hght); // Resize to fit canvas } void draw() { image(img, 0, 0); // Do the actual drawing }
Obiger Code lädt eine JPG-Datei und stellt sie in einer Processing-Sketch dar. Der Befehl um das Bild zu zeichnen (image(img, 0, 0)) könnte dabei auch direkt in der setup-Funktion stehen. Mit noLoop() wird sichergestellt, dass die draw-Methode nur einmal aufgerufen wird. Dies macht hier Sinn, da weder Animationen noch Interaktionen vorgesehen sind.
Durch Erweitern der draw-Methode können wir relativ einfach eine CSV-Datei mit Erdbebendaten einlesen:
void draw() { image(img, 0, 0); // Draw background String[] lines; lines = loadStrings("2009EQ_bearbeitet.csv"); // Read input file int index = 1; // Start from 2nd line in file float x, y; while (index < lines.length) { // Iterate through lines in the file String[] values = split(lines[index], ';'); // Split lines into individual strings x = float(values[2]); // Retrieve x coordinate from 3rd column y = float(values[1]); // Retrieve y coordinate from 2nd column // x and y are in geographic space and in degrees: // x = [-180, 180] and y = [-90, 90] x = (x + 180) / 360 * wdth; y = (-y + 90) / 180 * hght; // x and y are now in "screen space" and in pixels: // x = [0, wdth] and y = [0, hght] stroke(0); fill(255, 0, 0); ellipse(x, y, 4, 4); index = index + 1; } }
Da die Basiskarte wie oben erwähnt in Plate Carrée-Projektion vorliegt, ist die Projektion der Erdbebendaten von WGS 1984 in Grad ziemlich einfach. Bei Plate Carrée werden die geographische Länge und Breite direkt als kartesische Koordinaten umgesetzt. Im obigen Code müssen die geographischen Koordinaten einfach noch in Bildschirm-Koordinaten umgerechnet werden. Dies geschieht in diesem Code-Teil:
x = (x + 180) / 360 * wdth; y = (-y + 90) / 180 * hght;
In der Addition wird der Ursprung verschoben, mit der anschliessenden Division und Multiplikation auf die Spannweite der Bildschirmkoordinaten normiert. Speziell ist bei letzteren ja, dass der Ursprung links oben liegt und die Koordinatenwerte nach rechts und nach unten ansteigen.
Anschliessend werden die Farben fürs Zeichnen der Erdbebenstandorte definiert:
stroke(0); fill(255, 0, 0);
Dabei ist stroke(0) die Kurzform von stroke(0, 0, 0) – wobei die drei Werte RGB (Rot Grün Blau) entsprechen.
Mit:
ellipse(x, y, 4, 4);
wird anschliessend für jedes Beben ein Kreise mit 4 Pixeln Durchmesser gezeichnet.
Das Resultat des Codes sehen Sie hier (mit Klick aufs Bild gelangen Sie zur Ausgabe in Processing (benötigt Java Runtime Environment und JavaScript)):
In der Darstellung sieht man sehr schön die Grenzen der tektonischen Platten, die rege Erdbebenaktivität an der Westküste der beiden Amerika und an der Ostküste der südostasiatischen Länder – der sogenannte Ring of fire rund um die Pazifische Platte:
Hallo,
für ein Projekt versuche ich das grade in Perl umzusetzen.
Leider bekomme ich falsche Ergebnisse auf meiner Karte (lande irgendwo im Meer).
Haben sie vielleicht einen Tipp für mich??
my $file = ‚earth.jpg‘; # Blue-Marble
my $image = GD::Image->newFromJpeg($file);
my $newimage = new GD::Image(1000,500);
$newimage->copyResized($image,0,0,0,0,1000,500,2048,1024);
my $y = 7.1833; # Breite
my $x = 51.2667; # Länge
#Plate Carrée-Projektion
$x = ($x + 180) / 360 * 1000;
$y = (-$y + 90) / 180 * 500; # !
$color = $newimage->colorAllocate(255,0,0);
$newimage->arc($x,$y,200,200,0,360,$color);
Danke
Lieber Daniel
Aus der Ferne ist das natürlich noch schwierig zu beurteilen. Aber eine Vermutung habe ich: Kann es sein, dass Sie versuchen, etwas im Raum Wuppertal/Deutschland darzustellen? Dann hätten Sie nämlich einen Koordinatendreher, d.h. der Wert der Breite sollte derjenige der Länge sein und umgekehrt. Mit ihrem Koordinatenpaar lande ich auch im Ozean – vor dem Horn von Afrika, und da gibt es ja bekanntlich Piraten :-/
Hope this helps,
-Ralph
Jaa, man sieht oftmals den Wald vor lauter Bäumen nicht.
X und Y vertauscht.
Vielen Dank