User:Maxbe/csv-Dateien mit Mapserver darstellen
Am Beispiel der Haltestellendaten vom VBB
Zutaten
Ein (umn-)mapserver von mapserver.org. Der sollte als Input-Format OGR können:
max@d3:~$ /home/www/wms/cgi-bin/mapserv6 -v MapServer version 6.0.3 OUTPUT=PNG OUTPUT=JPEG ... INPUT=OGR
Ausserdem die ogrtools von gdal.org/ogr/, die als Input-Format CSV können:
max@d3:~$ ogrinfo --formats Supported Formats: .. -> "CSV" (read/write) ..
Ich weiss nicht mehr, ob das der Standard bei der Installation war, ich glaube schon, jedenfalls habe ich mich nie darum gekümmert...
Die CSV-Datei
Ausserdem braucht man die Daten der Haltestellen in einer CSV-Datei. Die vom VBB sieht z.B. so aus:
stop_id,stop_code,stop_name,stop_desc,stop_lat,stop_lon,zone_id,stop_url,location_type,parent_station 5100071,,"Zbaszynek",,52.2389370,15.8215110,,,0, 5100081,,"Poznan Gl.",,52.3986540,16.9088520,,,0, 5100083,,"Kunowice",,52.3430780,14.6425210,,,0, 5100319,,"Bedow",,52.0724110,15.3135220,,,0, 5100397,,"Boczow",,52.3264190,14.9480280,,,0,
Die erste Zeile enthält die Namen der Felder, alle weiteren Zeilen enthalten die Daten dazu. Hier interessiert uns eigentlich nur stop_name sowie stop_lat und stop_lon.
Diese Datei laden wir runter und legen sie als vbb-stops.csv ab (.csv als Endung ist wichtig).
Die OVF-Datei
Der Mapserver kann nicht selbst die CSV-Dateien lesen, möglicherweise geht das mit einkompilierter csv-Unterstützung, ich weiss aber nicht, ob es sowas gibt. Also der Umweg über OGR.
OGR hat einen Treiber "Virtual Format", wo ich mit XML-Steuerdaten sagen kann wo die Daten liegen und was davon die Koordinaten sind. Diese Steuerdatei vbb-stops.ovf müssen wir erzeugen:
<OGRVRTDataSource> <OGRVRTLayer name="vbb-stops"> <SrcDataSource>(PFAD zur CSV-Datei)/vbb-stops.csv</SrcDataSource> <GeometryType>wkbPoint</GeometryType> <LayerSRS>WGS84</LayerSRS> <GeometryField encoding="PointFromColumns" x="stop_lon" y="stop_lat"/> </OGRVRTLayer> </OGRVRTDataSource>
Das einzig wichtige in dieser Datei ist der Pfad zur CSV-Datei, der Name des Layers "vbb-stops", sowie die Angabe, welche der Felder dort x und y-Koordinaten sind.
Testen der OVF-Datei
max@d3:/home/www/wms/maps$ ogrinfo -al vbb-stops.ovf | more Warning 4: Failed to open ../maps/vbb-stops.csv, Permission denied. Warning 1: Cannot open datasource `../maps/vbb-stops.csv' in update mode. Trying again in read-only mode INFO: Open of `vbb-stops.ovf' using driver `VRT' successful. Layer name: vbb-stops Geometry: 3D Point Feature Count: 12812 Extent: (10.700868, 50.839245) - (16.908852, 54.524383) Layer SRS WKT: GEOGCS["WGS 84", DATUM["WGS_1984", SPHEROID["WGS 84",6378137,298.257223563, AUTHORITY["EPSG","7030"]], TOWGS84[0,0,0,0,0,0,0], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich",0, AUTHORITY["EPSG","8901"]], UNIT["degree",0.0174532925199433, AUTHORITY["EPSG","9108"]], AUTHORITY["EPSG","4326"]] stop_id: String (0.0) stop_code: String (0.0) stop_name: String (0.0) stop_desc: String (0.0) stop_lat: String (0.0) stop_lon: String (0.0) zone_id: String (0.0) stop_url: String (0.0) OGRFeature(vbb-stops):1 stop_id (String) = 5100071 stop_code (String) = stop_name (String) = Zbaszynek stop_desc (String) = stop_lat (String) = 52.2389370 stop_lon (String) = 15.8215110 zone_id (String) = stop_url (String) = location_type (String) = 0 parent_station (String) = POINT (15.821511 52.238937) OGRFeature(vbb-stops):2 stop_id (String) = 5100081 stop_code (String) = stop_name (String) = Poznan Gl. stop_desc (String) = stop_lat (String) = 52.3986540 stop_lon (String) = 16.9088520 zone_id (String) = stop_url (String) = location_type (String) = 0 parent_station (String) = POINT (16.908852 52.398654)
Falls hier jede Menge Haltestellen vorbeirauschen, hat man gewonnen. Man sieht auch, welche Felder vorhanden sind. Und vor allen sieht man bei jeden OGRFeature einen Eintrag "POINT()", der die Koordinate des Features enthält.
Das Mapfile
Jetzt müssen wir dem Mapserver nur noch sagen, dass wir ein Bild aus dieser ovf-Datei erstellen wollen. Das teilen wir ihm im Mapfile "vbb-stops.map" mit:
MAP OUTPUTFORMAT NAME agg DRIVER AGG/PNG8 FORMATOPTION "INTERLACE=OFF" MIMETYPE "image/png" TRANSPARENT ON IMAGEMODE RGBA END FONTSET "osmfonts.lst" MAXSIZE 10000 SIZE 800 800 EXTENT -180 -85 180 85 WEB METADATA "ows_enable_request" "*" wms_srs "EPSG:900913 EPSG:4326 EPSG:3857" wms_title "vbb-stops" END END PROJECTION "init=epsg:900913" END SYMBOL NAME "circle" TYPE ELLIPSE POINTS 1 1 END FILLED TRUE END LAYER NAME "vbb-stops" STATUS OFF MAXSCALEDENOM 500000 PROJECTION "init=epsg:4326" END TYPE ANNOTATION CONNECTIONTYPE OGR CONNECTION "vbb-stops.ovf" LABELITEM 'stop_name' CLASS STYLE SYMBOL "circle" SIZE 6 COLOR "#000000" OUTLINECOLOR "#ffffff" OUTLINEWIDTH 2 END LABEL TYPE TRUETYPE FONT sc PARTIALS FALSE OUTLINEWIDTH 2 SIZE 9 COLOR "#000000" POSITION auto STYLE GEOMTRANSFORM labelpoly COLOR "#ffffff" END END END END END
Den oberen Teil habe ich mir irgendwo rauskopiert, wichtig ist im Layer der Verweis auf "CONNECTIONTYPE OGR" und CONNECTION "vbb-stops.ovf", wo die Verbindung zur ovf geschaffen wird. LABELITEM ist der Name des Feldes, den ich für die Beschriftung verwenden möchte.
Da ist noch eine Datei "osmfonts.lst" dabei, da steht einfach nur drin,
welchen TTF-Font ich nehmen will, wenn ich "FONT sc" im Mapfile verwende:
sc osmfonts/DejaVuSansCondensed.ttf scb osmfonts/DejaVuSansCondensed-Bold.ttf sci osmfonts/DejaVuSerifCondensed-Italic.ttf
Testen des Mapfiles
Ich baue mir da immer eine kleine html-Seite, wo ich diesen WMS-Layer einbinde, z.B. mit
map.addLayer (new OpenLayers.Layer.WMS("vbb-stops","http://wms.dianacht.de/pfad-zum-mapserver/mapserv?map=/pfad-zum-mapfile/vbb-stops.map", {layers:'vbb-stops',format:"agg"}, {projection:new OpenLayers.Projection("EPSG:900913"), numZoomLevels:19, isBaseLayer:false, visibility:true, singleTile:true } ));
Und freue mich, falls ich da ein Bild sehe.