Es gibt ja so Momente, in denen moechte man ein Problem loesen, und dann schliesst man sich so lange ein, bis man hinreichend nahe an eine Loesung gekommen ist. So in der Art erging es mir am Schwoerwochenende, eigentlich wegen einer ganz trivialen Sache: Ich haette gerne Umgebungsplaene fuer die Bushaltestellen rund um die Uni.
Ein Grund, warum ich hier im Blog nicht mehr so viel schreibe ist naemlich, dass ich seit gut einem Jahr der Mobilitaetsreferent der Uni-Studierendenvertretung bin und in dieser Eigenschaft umso mehr anderswo schreibe. Und ein Problem, auf das ich in diesem Rahmen stiess, war der Umstand, dass es an vielen Haltestellen in der Stadt mittlerweile Orientierungsplaene fuer die naehere Umgebung gibt – es so etwas aber ausgerechnet an der Uni, an die immer wieder Konferenzteilnehmer*innen und sonstige Externe anreisen, ausschliesslich an der Haltestelle Kliniken Eselsberg gibt.
In einer Besprechung hatten die Stadtwerke zugesagt, Plaene nachzuruesten, sofern die Haltestellen dafuer noch freie Plaetze haben – und wir sagten zu, die dazugehoerigen Plaene zu bauen. Und nachdem Stefan Wehrmeyer mir beim occ13 noch einige Funktionen von TileMill naeher brachte, die ich bis dato nicht kannte, war der Weg schon einmal vorgezeichnet 🙂
Die Idee
Lokalen OpenStreetMap-Auszug von Ulm und Umgebung (genauer: Regierungsbezirk Tuebingen) downloaden, mit TileMill stylen, exportieren und aufbereiten
Die Umsetzung
Vorbereitung: TileMill und PostGIS installieren
(Siehe hierzu auch https://github.com/mapbox/osm-bright und http://wiki.openstreetmap.org/wiki/PostGIS/Installation
sudo apt-get install tilemill postgresql postgresql-contrib postgis osm2pgsql sudo -u postgres createuser stk # as superuser sudo -u postgres createdb --encoding=UTF-8 --owner=stk tuebingen sudo -u postgres createlang plpgsql tuebingen
PostGIS einrichten, Karte laden und importieren
sudo -u postgres psql -d tuebingen -f /usr/share/postgresql/9.1/contrib/postgis-1.5/postgis.sql sudo -u postgres psql -d tuebingen -f /usr/share/postgresql/9.1/contrib/postgis-1.5/spatial_ref_sys.sql sudo -u postgres psql -d tuebingen -f /usr/share/postgresql/9.1/contrib/postgis_comments.sql sudo -u postgres psql -d tuebingen -c "ALTER TABLE geometry_columns OWNER TO stk;" sudo -u postgres psql -d tuebingen -c "ALTER TABLE spatial_ref_sys OWNER TO stk;"
wget http://download.geofabrik.de/europe/germany/baden-wuerttemberg/tuebingen-regbez-latest.osm.pbf
osm2pgsql -c -G -d tuebingen tuebingen-regbez-latest.osm.pbf
osm-bright laden und anpassen
git clone https://github.com/mapbox/osm-bright.git cd osm-bright cp configure.py.sample configure.py # edit according to readme ./make.py
Projekteinstellungen in project.mml:
"bounds": [ 9.9376, 48.4151, 9.971, 48.4294 ], "center": [ 9.9535, 48.4243, 15 ]
POIs hinzufuegen
Icons: http://www.sjjb.co.uk/mapicons/downloads (SJJB)
sudo apt-get install librsvg2-bin ./generatepngall.sh
Waehrend die PNGs gerendert werden, Layer in Tilemill hinzufuegen:
{ "geometry": "point", "extent": [ 8.252064998851305, 47.14375559492619, 10.28521039856825, 48.91388219485537 ], "Datasource": { "type": "postgis", "table": "( SELECT name, highway, way\n FROM planet_osm_point\n WHERE building IS NULL AND highway IN ('bus_stop')\n ORDER BY z_order ASC NULLS LAST\n) AS data", "key_field": "", "geometry_field": "way", "extent_cache": "auto", "extent": "918615.673665123,5965570.29255198,1144944.3842703,6260261.61701241", "dbname": "tuebingen", "user": "stk" }, "id": "transit", "class": "", "srs-name": "900913", "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", "advanced": {}, "name": "transit" }, { "geometry": "point", "extent": [ 8.252064998851305, 47.14375559492619, 10.28521039856825, 48.91388219485537 ], "Datasource": { "type": "postgis", "table": "( SELECT name, way, highway\n FROM planet_osm_point\n WHERE building IS NULL AND highway IN ('bus_stop')\n ORDER BY z_order ASC NULLS LAST\n) AS data", "key_field": "", "geometry_field": "way", "extent_cache": "auto", "extent": "918615.673665123,5965570.29255198,1144944.3842703,6260261.61701241", "dbname": "tuebingen", "user": "stk" }, "id": "transitlabel", "class": "", "srs-name": "900913", "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", "advanced": {}, "name": "transitlabel" }, { "geometry": "point", "extent": [ 8.252064998851305, 47.14375559492619, 10.28521039856825, 48.91388219485537 ], "Datasource": { "type": "postgis", "table": "( SELECT *\n FROM planet_osm_point\n WHERE building IS NULL AND amenity IN ('biergarten', 'cafe', 'restaurant', 'bicycle_parking', 'charging_station', 'parking', 'atm') \n ORDER BY z_order ASC NULLS LAST\n) AS data", "key_field": "", "geometry_field": "", "extent_cache": "auto", "extent": "918615.673665123,5965570.29255198,1144944.3842703,6260261.61701241", "dbname": "tuebingen", "user": "stk" }, "id": "uulmpoi", "class": "", "srs-name": "900913", "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", "advanced": {}, "name": "uulmpoi" }
und dann folgendes Styling in uulm.mss:
/* ****************************************************************** */ #transitlabel[zoom >= 16] { text-name: [name]; text-face-name: @sans; text-placement: point; text-wrap-width:60; text-fill: @poi_text; text-halo-radius: 2; text-halo-fill: @road_halo; text-min-distance: 2; text-placement-type: simple; text-allow-overlap: true; text-placements: "S,E,N,W,NE,SE,NW,SW,14,12,10"; text-dx: 10; text-dy: 20; } #transit[zoom = 16] {point-file: url(img/sjjb/transport_bus_station.glow.999999.12.png); } #transit[zoom >= 17] {point-file: url(img/sjjb/transport_bus_station.glow.999999.20.png); } #transit[zoom >= 19] {point-file: url(img/sjjb/transport_bus_station.glow.999999.24.png); } #uulmpoi [amenity='cafe'][zoom <= 16] {point-file: url(img/icon/cafe-12.png); } #uulmpoi [amenity='cafe'][zoom >= 17] {point-file: url(img/icon/cafe-18.png); } #uulmpoi [amenity='cafe'][zoom >= 19] {point-file: url(img/icon/cafe-24.png); } #uulmpoi [amenity='restaurant'][zoom <= 16] {point-file: url(img/sjjb/food_restaurant.glow.8E7409.12.png); } #uulmpoi [amenity='restaurant'][zoom >= 17] {point-file: url(img/sjjb/food_restaurant.glow.8E7409.20.png); } #uulmpoi [amenity='restaurant'][zoom >= 19] {point-file: url(img/sjjb/food_restaurant.glow.8E7409.24.png); } /* #uulmpoi [amenity='bicycle_parking'][zoom <= 16] {point-file: url(img/sjjb/transport_parking_bicycle.n.0092DA.12.png); } #uulmpoi [amenity='bicycle_parking'][zoom >= 17] {point-file: url(img/sjjb/transport_parking_bicycle.n.0092DA.20.png); } #uulmpoi [amenity='bicycle_parking'][zoom >= 19] {point-file: url(img/sjjb/transport_parking_bicycle.n.0092DA.24.png); } */ #uulmpoi[amenity='restaurant'][zoom >= 16] { text-name: [name]; text-face-name: @sans; text-placement: point; text-wrap-width:60; text-fill: @poi_text; text-halo-radius: 2; text-halo-fill: @road_halo; text-min-distance: 2; text-placement-type: simple; text-allow-overlap: true; text-placements: "S,E,N,W,NE,SE,NW,SW,14,12,10"; text-dx: 10; text-dy: 10; }
FIXME die Marker sollten SVG sein, das ist noch TODO
Labelprobleme
Beim Rendern nach SVG oder PDF sehen die Labels (Strassennamen etc) seltsam aus: Buchstaben und Halos werden jeweils einzeln gerendert, so dass die Halos jeweils den naechsten Buchstaben ueberdecken. Das Problem scheint bekannt, siehe http://support.mapbox.com/discussions/tilemill/6001-text-halos-look-bad-in-pdfsvg-export, bleibt wohl nur die manuelle Beschriftung. Ich habe einfach die Labels in einem separaten Layer exportiert, der eingeblendet werden kann (oder auch nicht)
Handarbeit
Die Idealvorstellung war ja, dass sich der Prozess irgendwie automatisieren lassen wuerde, insbesondere wegen der Labels ging das aber nicht so einfach. Deswegen ging ich den folgenden Weg:
- Einzelne Layer nacheinander exportieren, Breite 4000, Zoomlevel 17, Ausgabeformat PDF
- Baselayer (Geometrien)
- Strassenlabels
- Transitmarker
- POIs
- Alle Layer in Illustrator (ich weiss, keine freie Software, gibts aber im PC-Pool an der Uni) zu einem Composite zusammenfuegen
- Haendisch Beschriftungen hinzufuegen, einmal detailliert und einmal fuer den Uebersichtsplan
-
Alles in InDesign fuer den Druck anpassen
- Optional: Versehentlich Schriftfarbe auf Passermarken setzen und sich wundern, warum die Glyphen pixelig rauskommen, bis man den Fehler bemerkt
Eine bessere Variante waere es, die Beschriftungen nochmals als eigene Datenquelle vorzuhalten und einzublenden, dann liesse sich das auch als SlippyMap exportieren, haette aber genau wieder dasselbe Problem, wenn man PDFs fuer den Druck exportieren moechte. Den derzeitigen Weg halte ich fuer einen gangbaren Kompromiss aus Aufwand/Ergebnis.
Betaversionen:
Schick. Bis auf die Straßennamen, die sehen bei mir immer noch seltsam aus.
Das ist noch ein frueher Export, mittlerweile habe ich die Halos und die Buchstaben passend gruppiert. Optimal ist das natuerlich immer noch nicht.
Schick.
Cool wäre, wenn man die Umgebungspläne noch direkt mit Gebäudepläne kombinieren würde, zumindest so dass Eingänge zu den Gebäuden verzeichnet sind (z.B. bei Uni West und Ost nicht klar) und vielleicht noch bestimmte Landmarks, wie Hörsäle, Cafeteria, etc.
Die Eingaenge sind kein Problem, passende PostGIS-Abfrage ist
(SELECT way, building
FROM planet_osm_point
WHERE building in (‚entrance‘) )
AS data
– die Grafiken dazu sahen aber verhunzt aus und ich haette das noch haendisch korrigieren muessen. Manche Landmarks sind sehr exakt erfasst, von der Cafete ueber die Anzahl der Stellplaetze bei den Fahrradabstellanlagen bis zum Schlauchautomaten, bei anderen sieht es sehr mau aus.
Im Idealfall koennte man tatsaechlich mal alle POIs einpflegen, das ganze layerweise stylen und eine eigene SlippyMap daraus exportieren, dann haette man eine sehr detaillierte Custom-OSM der Uni mit schaltbaren Features. Ich hab irgendwann nicht mehr weitergemacht, das zu verfolgen, weil ich die Anordnungs-Algorithmen fuer die Marker nicht so ganz verstanden habe und das eher beschissen aussah, sobald mehrere verschiedene Layer zusammenspielen mussten und ggf. voreinander „ausweichen“ muessen haetten.