Here's a quick howto to play a bit with some GIS data on OpenBSD (Well, most of this stuff is not OpenBSD-specific). The magic keywords and building bricks are :
geo/mapserver
geo/gdal
geo/qgis
, used for testingQuite simple, nothing more than the usual stuff in chroot. I assume that you already have the basis.. we need to copy PROJ4 files to the chroot, so mapserver recognizes geographical map projections, plus some depending libs.
# pkg_add mapserver ## from mapserver MESSAGE file # mkdir -p /var/www/usr/local/share/{epsg_csv,proj} # cp /usr/local/share/epsg_csv/* /var/www/usr/local/share/epsg_csv # cp /usr/local/share/proj/* /var/www/usr/local/share/proj ## grab needed libs # for i in `ldd /var/www/cgi-bin/mapserv | cut -c57- | grep usr | grep -v libexec` ; do sudo cp $i /var/www/usr/lib/ ; done
Now, time to test mapserver, fire up a browser and point it to http://rhaalovely.net/cgi-bin/mapserv. If the chroot stuff is okay, it should reply :
No query information to decode. QUERY_STRING is set, but empty.
Congratulations, mapserver is correctly installed.
Now, i'm using SCAN1000 data available for download at IGN website. That's not a great data, but perfect for this example.
# mkdir /var/www/data ; cd /var/www/data # ftp http://professionnels.ign.fr/DISPLAY/000/527/535/5275350/SCAN1000_FR_NE_L93.zip # ftp http://professionnels.ign.fr/DISPLAY/000/527/535/5275350/SCAN1000_FR_NO_L93.zip # ftp http://professionnels.ign.fr/DISPLAY/000/527/535/5275350/SCAN1000_FR_SO_L93.zip # ftp http://professionnels.ign.fr/DISPLAY/000/527/535/5275350/SCAN1000_FR_SE_L93.zip # ftp http://professionnels.ign.fr/DISPLAY/000/527/535/5275350/SCAN1000_Corse_L93.zip # for i in *.zip ; do unzip $i ; rm $i ; done
Now, some magic with a GDAL tool, gdaltindex creates a vector data (a shapefile here) from the TIFF rasters. This shapefile will say 'ok, for this area, there's data to get from this TIFF file located here'.
# gdaltindex -write_absolute_path scan1000.shp *.TIF ## let's verify the shapefile content with another GDAL/OGR tool # ogrinfo -al scan1000.shp INFO: Open of `scan1000.shp' using driver `ESRI Shapefile' successful. Layer name: scan1000 Geometry: Polygon Feature Count: 5 Extent: (50000.000000, 6030000.000000) - (1250000.000000, 7130000.000000) Layer SRS WKT: (unknown) location: String (255.0) OGRFeature(scan1000):0 location (String) = SC1000_0050_6580_L93.TIF POLYGON ((50000 6580000,600000 6580000,600000 6030000,50000 6030000,50000 6580000)) OGRFeature(scan1000):1 location (String) = SC1000_0050_7130_L93.TIF POLYGON ((50000 7130000,600000 7130000,600000 6580000,50000 6580000,50000 7130000)) OGRFeature(scan1000):2 location (String) = SC1000_0600_6580_L93.TIF POLYGON ((600000 6580000,1150000 6580000,1150000 6030000,600000 6030000,600000 6580000)) OGRFeature(scan1000):3 location (String) = SC1000_0600_7130_L93.TIF POLYGON ((600000 7130000,1150000 7130000,1150000 6580000,600000 6580000,600000 7130000)) OGRFeature(scan1000):4 location (String) = SC1000_1150_6240_L93.TIF POLYGON ((1150000 6240000,1250000 6240000,1250000 6030000,1150000 6030000,1150000 6240000))
Ok, we have some TIFF rasters, a shapefile to reference them, from now on we can even open it in QGIS. But that's local, and our goal is to go wild on teh intarweb.
Mapfiles are used by mapserver to read, organize, and display GIS data, served either through WMS, or directly converted to images for web publication. Here's the one we're going to use, comments inline.
MAP # our data uses Lambert 93 projection, EPSG code 2154 PROJECTION "init=epsg:2154" END # bounding box of the data (= area covered) EXTENT 50000 6030000 1250000 7130000 WEB METADATA # where to ask for images after getCapabilities.. warning, map path is relative to chroot! "wms_onlineresource" "http://rhaalovely.net/cgi-bin/mapserv?map=/data/scan1000.map&" # necessary since mapserver 6.0 "ows_enable_request" "*" END END LAYER # serving one layer, named Scan1000 NAME "Scan1000" STATUS ON # the 'tile index' file, and where to find the raster files (in 'location' field) TILEINDEX "/data/scan1000.shp" TILEITEM "location" TYPE RASTER END END
That's it ! Now, you can try to get the 'Capabilities' of the mapfile opening this url : http://rhaalovely.net/cgi-bin/mapserv?map=/data/scan1000.map&version=1.1.1&service=WMS&request=GetCapabilities. This will return an xml file, giving all the available layers at this URL.
Now, even crazier, let's try it in QGIS, which can act as WMS client. Fire up QGIS, Layers, Add WMS layer, new, name the layer 'whatever', and enter the following URL : http://rhaalovely.net/cgi-bin/mapserv?map=/data/scan1000.map. Validate, connect, it should propose you the Scan1000 layer. Validate, wait a bit for mapserver to process the request.. BOOM, the france map appears!
Finally, let's do some cool stuff with the JS supa-dupa client GIS lib OpenLayers. The following HTML/JS code (check page source if you don't believe it) :
<head> <script src="http://openlayers.org/api/OpenLayers.js"> </script> <script type="text/javascript"> var map = null; function init(){ map = new OpenLayers.Map('map', {projection: 'epsg:2154', resolutions: [1000,500,250,100,50], maxExtent: new OpenLayers.Bounds(50000,6030000,1250000,7130000)}); var wms = new OpenLayers.Layer.WMS("Local WMS", "http://rhaalovely.net/cgi-bin/mapserv?map=/data/scan1000.map", {layers: 'Scan1000'}); map.addLayers([wms]); map.addControl(new OpenLayers.Control.MousePosition()); map.setCenter(new OpenLayers.LonLat(712000,6508100),3); } </script> </head> <body onload="init()"> <div id="map" style="padding:10px; display:block; border:1px solid; width:800px; height:600px;"></div> </body>
produces this funky result :
Check Examples and library doc for more stuff.