Skip to content

dft street manager spike 0003 mapping data

ronano-kainos edited this page Feb 12, 2018 · 29 revisions

Mapping data

WMS/WMTS server comparison

  • Used by Land Registry to draw LA boundary lines, deployment and configuration issues

Source of Mapping Information

The local authority boundaries are available from Ordnance Survey OpenData: https://www.ordnancesurvey.co.uk/opendatadownload/products.html#BDLINE

The shape file called 'district_borough_unitary_region' will show the correct boundary information.

This shape file is in the projection ESPG:27700 and will need to be converted to the same projection as before being deployed to mapserver.

The ms4w windows utility can be used to convert maps to different projections. (See: https://ms4w.com/)

The following command with convert the shape file to the required projection:

ogr2ogr -t_srs WGS84 <<path_to_file>>\district_borough_unitary_region_output.shp <<path_to_file>>\district_borough_unitary_region.shp

The displaying of local boundaries was discussed in the Show & Tell for Sprint 2 and decided that it was not required to be displayed on the map.

Using Mapserver to display external data

The following investigation was completed using mapserver as a docker container. (See. https://github.com/kartoza/docker-mapserver)

The following docker command was used to run the server: docker run --name map -d -p 8182:80 -v <<volume_path>>/map:/map mapserver

The converted shape files should be placed in a directory under <<volume_path>>/map

An example map file used to to serve the boundaries can be seen here.

When this is added as a layer to OpenLayersMap the result looks like the below:

boundary overlay

Boundary zoomed

Integration with Postgis

The following integration was completed using Postgres with Postgis extensions as a docker container. (See: https://hub.docker.com/r/mdillon/postgis/)

The following command is used to start the postgis instance:

docker run --name some-postgis -e POSTGRES_PASSWORD=postgres -e ALLOW_IP_RANGE=0.0.0.0/0 -p 5432:5432 -v <<volume_path>>/map:/map -d mdillon/postgis

And the below command used to connect to the running instance:

docker exec -i -t some-postgis /bin/bash

Displaying map info from postgis

Geometry entries can be saved in postgis in order to be rendered by a mapping server. The below steps show how to insert a mapserver shape file so it can be read from postgis.

createdb -h "$POSTGRES_PORT_5432_TCP_ADDR" -p "$POSTGRES_PORT_5432_TCP_PORT" -U postgres -T template_postgis shape

The above command creates a database called shape using the supplied postgis template.

shp2pgsql -I -s 4326 <<shape_file>> districts | psql -h "$POSTGRES_PORT_5432_TCP_ADDR" -p "$POSTGRES_PORT_5432_TCP_PORT -U postgres -d shape

The shp2pgsql command is used to create the sql to insert a shape file into a new table called 'districts' using the given projection 4326. The output is then piped to a psql command to execute the updates. This can also be done with an intermediary sql file:

shp2pgsql -I -s 4326 /map/counties/dbur_84.shp districts > SHAPEFILE.sql'

psql -h "$POSTGRES_PORT_5432_TCP_ADDR" -U postgres -p "$POSTGRES_PORT_5432_TCP_PORT" -d shape -f SHAPEFILE.sql

Mapserver can then be configured to read the shape file and render it as a map layer. The following lines in the map file indicate the data is being retrieved from postgis, configure the connection and set the data parameters:

CONNECTIONTYPE POSTGIS

CONNECTION "host=192.168.99.100 dbname=shape user=postgres password=postgres port=5432"

DATA "geom from districts"

An example of a map file connecting to postgis can be found here.

Writing map information to Postgis

Areas drawn on a map can be written back to postgis to be saved and rendered back through mapserver.

The below sql command will create a table in the postgis database called drawn_polygon:

CREATE TABLE drawn_polygon ( p_id INTEGER PRIMARY KEY );

Postgis contains a command for adding a geometry column to the table:

SELECT AddGeometryColumn('drawn_polygon','the_geom','3857','POLYGON',2);

This command adds a new column to the drawn_polygon table indicating the type of shape (POLYGON) and the projection of the shape (3857).

To insert a row into this table the following command:

INSERT INTO drawn_polygon(p_id, the_geom) VALUES(1, ST_GeomFromText(?, 3857));

This command will use convert a textual representation of a polygon into a postgis geometry column. The value of the text can be returned from open layers with the following commands:

var writer = new ol.format.WKT()

var geomWKT = writer.writeGeometry(event.feature.getGeometry())

This will generate text in the format: POLYGON((19004.239492803947 6776142.885363474,19057.984278316962 6775892.076364413,19097.397121026508 6775902.825321515,19036.486364111755 6776154.828649143,19004.239492803947 6776142.885363474))

This can be used as the parameter in the ST_GeomFromText command.

To render this back on a map, another layer should be added in the map file:

CONNECTIONTYPE POSTGIS CONNECTION "host=192.168.99.100 dbname=shape user=postgres password=postgres port=5432" DATA "the_geom from drawn_polygon"

The attached map file also contains this example here.

Using MapServer to server WFS

To server a shape file as a WFS layer from MapServer the following needs to be configured in the WEB section of a map file:

METADATA
"wfs_title" "Counties WFS" 
"wfs_onlineresource" "http://127.0.0.1/cgi-bin/mapserv.exe?map=C:/ms4w/apps/map/counties-postgis-wfs.map&"
"wfs_crs" "EPSG:4326 ESPG:3857"
"wfs_enable_request" "*" 
END

The above will specify that the map is to be made available as a Web Feature Service layer. An example of a map configured to serve WFS feature layers can viewed here.

Serving WFS as GeoJSON

By default the features will be returned in GML format. To allow features to be returned in GeoJSON format, then the following lines need to be added to the mapfile:

OUTPUTFORMAT <br/>
  NAME "geojson" <br/>
  DRIVER "OGR/GEOJSON" <br/>
  MIMETYPE "application/json; subtype=geojson" <br/>
  FORMATOPTION "STORAGE=stream" <br/>
  FORMATOPTION "FORM=SIMPLE" <br/>
END

In the layer or application metadata the following line should be added:

"wfs_getfeature_formatlist” "geojson"

WFS GeoJSON and OpenLayers

Open Layers can also render GeoJSON features on a map. See the below code fragment for details:

var featureRequest = new ol.format.WFS().writeGetFeature({ 
   srsName: 'EPSG:3857', 
   featureNS: 'http://mapserver.gis.umn.edu/mapserver', 
          featurePrefix: 'ms', 
          featureTypes: ['drawn_features'],
          outputFormat: 'geojson',
          filter: ol.format.filter.equalTo('works_owner', worksOwner) 
      })
      // then post the request and add the received features to a layer
      fetch('http://127.0.0.1/cgi-bin/mapserv.exe?map=C:/ms4w/apps/map/counties-postgis-wfs.map&SERVICE=WFS', {
          method: 'POST',
          body: new XMLSerializer().serializeToString(featureRequest)
      }).then(function (response) {
          return response.json();
      }).then(function (json) {
          var features = new ol.format.GeoJSON().readFeatures(json);
          MAP_CONFIG.vector_source.clear()
          MAP_CONFIG.vector_source.addFeatures(features);
      });

Filtering WFS features in MapServer

MapServer does provide the ability to filter features shown on the map. This is done by providing a Filter in XML format to the URL request. e.g.

http://demo.mapserver.org/cgi-bin/wfs?&VERSION=1.0.0&SERVICE=WFS
  &REQUEST=GetFeature&TYPENAME=cities&Filter=<Filter>
  <PropertyIsEqualTo><PropertyName>NAME</PropertyName>
  <Literal>Halifax</Literal></PropertyIsEqualTo></Filter>

Questions

  • How do we serve works mapping information so that external tools can access it?
  • Source of mapping information? (OS Mastermap etc.
  • WMTS provider (ourselves/provider)
  • Do we need to display local authority boundary information?
  • How do we serve large volumes of works data on maps without crowding?
  • How do we filter works data by date?
Clone this wiki locally