10 Dezember 2009

Ruby, Shapefiles und SVG

Durch den Blogpost auf dianacht.de wurde ich darauf aufmerksam, daß es bei NaturalEarth freie Shapefiles und Rasterdaten gibt, um schöne Karten zu bauen. Nun gibt es ja die Shapefile C library und auch entsprechende bindings für Ruby - was lag also näher, als sich mal so ein Shapefile zu ziehen, das mit Ruby auszulesen und daraus ein SVG zu erstellen?
Na also, nichts eigentlich.
Gesagt, getan: Da Küstenlinien recht anschaulich sind, zog ich mir die in 1:50, jagte die ausgelesenen Daten durch ein Rubyscript und erzeugte nebenbei mit SVuGy ein SVG, indem die Arcs aus dem Shapefile einfach in Polylines umgewandelt wurden. Das Resultat war ein knapp 3MB großes SVG, das Bild zeigt einen Ausschnitt mit einem Zoomfaktor von ca. 2000% und einer Liniendicke (in SVG) für die Küstenlinien (Polylines) von 0.1 (das häßliche grün kommt durch manuelles Nachcolorieren und dient nur der Anschauung) - das Ganze wurde nachträglich auf ein paar verträgliche Pixel runtergerastert.
Natürlich lassen sich mit den Daten von NaturalEarth noch viele andere schöne Dinge anstellen, hier aber erst mal nur der kleine shapelib-Test.

Labels: , , , ,

27 August 2009

Contourplot mit R

Neulich hab ich ja schon angedeutet, daß ich mal versuchen wollte, Höhenlinien mit dem Contourplot von R zu bauen. Gesagt, getan.
(Es folgt eigentlich weniger ein genaues "Rezept" als eine kurze Notiz - an mich? - ohne Gewähr):
Aus den srtm-Daten hab ich mir mit extractdata.pl einen Bereich um Trier ausgeschnitten, aus diesem Datensatz (trier.data) die Kopfzeilen per Hand gelöscht und diesen dann mit mosel <- as.matrix(read.table("trier.data", header=FALSE)) in R eingelesen. Um die Matrix zu "norden" (damit der plot dann auch "richtig rum" erscheint), muß diese gedreht werden (Funktionen dazu siehe hier): mosel = rotate270.matrix(mosel).
Danach geht's los mit dem Plot. Da hinter dem eigentlichen Contourplot die Höheninformationen als farbige Fläche angezeigt werden sollen*, bauen wir uns mit colpal = colorpanel(40,"green","red") zuerst eine Palette mit 40 Stufen aus den Farben grün bis rot. Mit image(mosel, col=colpal, axes=FALSE) kann man diesen "Hintergrund" dann schon mal plotten. (Die schöne Funktion filled.contour gibt es auch, diese erzeugt jedoch zwingend(?) eine Legende).
Den eigentlichen Contourplot legt man dann mit contour(mosel, nlevels=30, drawlabels = FALSE, axes = FALSE, add=TRUE) darüber. Ich hab hierbei mal auf alle Label und Achsenbeschriftungen verzichtet.
Den Plot kann man mit R auch gleich in ein Bitmap (z.B. mit jpeg) oder besser in ein SVG schreiben lassen: Zuerst ein device öffnen svg("mosel.svg"), die obigen Plots ausführen, danach das device schließen dev.off() und fertig ist das SVG.
Auf dem Bild sieht man das Ergebnis (SVG (~15MB) - mit GIMP nach Bitmap umgewandelt) für einen Ausschnitt (49,6522/6,5416 bis 49,8354/6,785), der als Matix aus srtm-Daten 292 Zeilen und 220 Spalten (also eigentlich wenige) umfasst. Als kleinen Test hab ich auch mal einen Contourplot einer kompletten srtm-Kachel (~140MB) erstellen lassen - wie man sich denken kann ist der Rechner dann bei 'vielen' Höhenstufen ganz gut ausgelastet, der import solcher Matrizen in R funktioniert aber noch ohne weiteres. Nur möchte ich nicht wissen, wie das Ganze aussieht, wenn man Contourplots von großen Gebieten erstellen möchte für die man Höheninformationen mit kleiner Rasterweite hat.

* um es mit Ivar Combrinck zu sagen: bunt "gibt die Anweisungen".

Labels: , , , , ,

25 Juni 2008

Bézierkurven 2

...ich meine mich ja daran erinnern zu können, irgendwann mal mit Vektorrechnung in Berührung gekommen zu sein: Für das 'Problem', aus der in SVG mit 'smooth curveto' angegebenen Kurve eine 'normale' zu bauen, stellt sich nun also die Frage nach dem Startpunkt und dessen Kontrollpunkt. Erstmal das Triviale: Der Startpunkt der zweiten Bézierkurve ist der Endpunkt der ersten, also der Punkt B (250,200) - man kann demnach als Daten für den Pfad statt d="M100,200 C100,100 320,80 250,200 S400,300 400,200" auch d="M100,200 C100,100 320,80 250,200 M 250,200 C x,y 400,300 400,200" angeben.
Es fehlen die Koordinaten (x,y) des gespiegelten Kontrollpunktes S2 (hier S2'), die sich aber (SVG macht das schließlich auch) recht einfach aus den Punkten S2 und B berechnen lassen: Zuerst 'bauen' wir uns den Richtungsvektor aus B-S2, also (250,200)-(320,80)=(-70,120), und gehen dann von B aus in diese Richtung zu unserem neuen Kontrollpunkt S2', also (x,y)=(250,200)+(-70,120)=(180,320). Der Kontrollpunkt für unseren Startpunkt B ist also S2' (180,320).
Die Daten für unsere zwei hintereinandergehängten Kurven sind also:
d="M100,200 C100,100 320,80 250,200 M 250,200 C 180,320 400,300 400,200"
Das Bild zeigt neben den Anfangs-, End- und Kontrollpunken (der berechnete Kontrollpunkt in blau) und den Tangenten die beiden Bézierkurven, in rot den Pfad mit 'smooth curveto', in schwarz den mit der Angabe von M, C und wieder M, C. Sieht fast so aus, als würde es stimmen - hoffen wir mal das Beste.

Labels: , ,

Bézierkurven 1

...mit SVG ist es sehr einfach, Bézierkurven auszugeben. Hiezu genügt es, im 'path data'-Attribut (d) des path-Tags (path) einen Startpunkt (mit dem Kommando M) und die Kontrollpunkte und den Endpunkt der gewünschten Kurve (mit C) anzugeben. Das Bild zeigt eine kubische Bézierkurve mit Startpunkt A (100,200), Endpunkt B (250,200) und den jeweiligen Kontrollpunkten S1 (100,100) und S2 (320,80). Mit diesen absoluten Koordinaten sieht das Data-Attribut für den Pfad dann so aus: d="M100,200 C100,100 320,80 250,200"
Danach ist die aktuelle Position zum Weiterzeichen der angegebene Endpunkt B (250,200).
Soll eine weiter Bézierkurve folgen, kann man diese einfach (mit S für 'smooth curveto') anschließen, indem man einen weiteren Kontroll- und einen Endpunkt angibt. Der angegebene Kontrollpunkt S3 (400,300) gehört zu dem angegebenen Endpunkt C (400,200), der 'fehlende' Kontrollpunkt für den Anfang der Kurve wird von SVG berechnet. Beim W3C steht dazu: "The first control point is assumed to be the reflection of the second control point on the previous command relative to the current point." Die Pfaddaten für die beiden Bézierkurven sehen dann so aus:
d="M100,200 C100,100 320,80 250,200 S400,300 400,200"
Das ist, so wie es ist, erstmal recht elegant. 'Problematisch' wird es erst, wenn man aus diesem SVG die einzelnen Kurven der Pfade mit jeweils allen Koordinaten braucht.

Labels: ,

01 November 2007

Graphen

...im Zusammenhang mit einem Kurs in Automatentheorie und der Implementierung des FSA2DFA-Algos bin ich damals auch über die Programmbibliothek graphviz von AT&T gestolpert, da diese Automaten sehr schön darstellen kann. Neulich kamen mir diese Programme wieder in den Sinn, als es darum ging, wie und womit man bestimmte Daten als ungerichtete Graphen darstellen könnte. Da diese Graphen in XHTML eingebunden werden sollen, fiel mir (neben Rasterdaten) sofort SVG ein - Grund genug, nochmal nach der alten graphviz-Installation zu suchen und... ja, es kann SVG exportieren - super! Ein paar kleine Veränderungen am SVG - z.B. Links auf die Label der Kanten setzen - und schon hätte man den Graphen, den man braucht. Der Paketmanager verriet mir auch gleich, daß es wohl sogar bindings für PHP gibt - dazu nur leider noch nicht die entsprechenden Einträge im Manual.

Labels: , ,