diff --git a/workshop/content/docs/outputs/wcs.md b/workshop/content/docs/outputs/wcs.md index 25b07a8..b465b55 100644 --- a/workshop/content/docs/outputs/wcs.md +++ b/workshop/content/docs/outputs/wcs.md @@ -1,50 +1,183 @@ -# Web Coverage Services +# Web Coverage Services (WCS) -TODO +## Overview -https://mapserver.org/ogc/wcs_server.html +This tutorial demonstrates the [WCS Server](https://mapserver.org/ogc/wcs_server.html) capabilities of MapServer. +We'll be using [WCS 2.0](https://mapserver.org/ogc/wcs_server.html#wcs-2-0) for this tutorial, and will serve a +Cloud-Optimized GeoTIFF (COG) from the Estonian Land Board as the source dataset. The dataset is a Digital Terrain Model (DTM) with a 1 m resolution. -https://mapserver.org/ogc/wcs_format.html +
+ +
-We'll be using [WCS 2.0](https://mapserver.org/ogc/wcs_server.html#wcs-2-0) for this tutorial. +## WCS Requests -# GetCapabilities -http://localhost:7000/?map=/etc/mapserver/wcs.map&SERVICE=WCS&REQUEST=GetCapabilities +Some sample MapServer requests for testing the WCS service are listed below. You can test these in your browser. -# DescribeCoverage 2.0 -http://localhost:7000/?map=/etc/mapserver/wcs.map&SERVICE=WCS&VERSION=2.0.1&REQUEST=DescribeCoverage&COVERAGEID=dtm +- [GetCapabilities](http://localhost:7000/?map=/etc/mapserver/wcs.map&SERVICE=WCS&REQUEST=GetCapabilities&VERSION=2.0.1) +- [DescribeCoverage 2.0](http://localhost:7000/?map=/etc/mapserver/wcs.map&SERVICE=WCS&VERSION=2.0.1&REQUEST=DescribeCoverage&COVERAGEID=dtm) +- [GetCoverage 2.0 image/tiff full](http://localhost:7000/?map=/etc/mapserver/wcs.map&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=dtm&FORMAT=image/tiff) -# GetCoverage 2.0 image/tiff full -http://localhost:7000/?map=/etc/mapserver/wcs.map&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=dtm&FORMAT=image/tiff +You can also connect to the MapServer Docker container and use `mapserv` to test the requests from the command line. ```bash -gdalinfo /etc/mapserver/data/raster/54752_dtm_1m.tif +docker exec -it mapserver bash +mapserv -nh "QUERY_STRING=map=/etc/mapserver/wcs.map&SERVICE=WCS&REQUEST=GetCapabilities&VERSION=2.0.1" ``` -NoData Value=-9999 -Size is 5002, 5002 +## Source Dataset -curl "http://localhost:7000/?map=/etc/mapserver/wcs.map&SERVICE=WCS&REQUEST=GetCapabilities" +Let's get some information about the source dataset using the GDAL CLI command[gdal raster info](https://gdal.org/en/latest/programs/gdal_raster_info.html) +(the modern equivalent of `gdalinfo`). -!!! tip +```bash +gdal raster info /etc/mapserver/data/raster/54752_dtm_1m.tif +``` - The `COVERAGEID` will be the `LAYER` `NAME` +The truncated output is shown below. +``` +Driver: GTiff/GeoTIFF +Files: /etc/mapserver/data/raster/54752_dtm_1m.tif + /etc/mapserver/data/raster/54752_dtm_1m.tif.aux.xml +Size is 5000, 5000 +Coordinate System is: +PROJCRS["Estonian Coordinate System of 1997", +... + ID["EPSG",3301]] +Origin = (655000.000000000000000,6475000.000000000000000) +Pixel Size = (1.000000000000000,-1.000000000000000) +... +Image Structure Metadata: + LAYOUT=COG +... +Center ( 657500.000, 6472500.000) ( 26d41'30.35"E, 58d21'52.44"N) +Band 1 Block=512x512 Type=Float32, ColorInterp=Gray + Min=30.680 Max=83.205 + Minimum=30.680, Maximum=83.205, Mean=60.461, StdDev=9.347 + NoData Value=-9999 + Overviews: 2500x2500, 1250x1250, 625x625, 312x312 + Metadata: + STATISTICS_MAXIMUM=83.205001831055 +... +``` +From the output we can see that the dataset is in the [EPSG:3301](https://spatialreference.org/ref/epsg/3301/) coordinate reference system, with an origin at (655000, 6475000) +and a pixel size of 1 × 1 (with a negative Y resolution, as is typical for north-up rasters). The `LAYOUT=COG` indicates that the file is structured as a Cloud-Optimized GeoTIFF (COG). + +## Configuring a Mapfile for WCS + +The Mapfile for the WCS service is similar to a WMS Mapfile, but with some differences. The `LAYER` type is set to `RASTER`, and the `METADATA` section contains +keywords prefixed with `wcs_` to specify the WCS parameters. + +```scala +WEB + METADATA + "wcs_enable_request" "*" + "wcs_srs" "EPSG:4326 EPSG:3857" + "wcs_title" "Example WCS Mapfile" + "wcs_description" "Test description" + "wcs_onlineresource" "http://localhost:7000/" + END +END ``` -msWCSGetCoverage20(): WCS server error. Raster size out of range, width and height of resulting coverage must be no more than MAXSIZE=4096. + +If the Mapfile is used for multiple services such as WMS and WCS, a single metadata item can be specified using the `ows_` prefix, for example `ows_title`. + +[LAYER METADATA](https://mapserver.org/ogc/wcs_server.html#layer-object-metadata) can also be used to specify additional information about the coverage, +but is not required for this tutorial. + +The [OUTPUTFORMAT](https://mapserver.org/mapfile/outputformat.html) defines the properties of the output format. +In this case we are defining a custom output format for GeoTIFFs with a `FLOAT32` data type to match the source raster +and ensure that the full precision of the source raster is preserved in WCS responses. + +```scala +OUTPUTFORMAT + NAME "GEOTIFF" + DRIVER "GDAL/GTiff" + MIMETYPE "image/tiff" + IMAGEMODE FLOAT32 + EXTENSION "tif" +END ``` -Set the [MAXSIZE](https://mapserver.org/mapfile/map.html#mapfile-map-maxsize) directive on the `MAP` to a larger value. By default this is set to 4096. +We can use the full power of GDAL to define custom output formats. For example, we could define a COG output format +by switching to the [COG Driver](https://gdal.org/en/latest/drivers/raster/cog.htm), and add statistics to the output file by adding the `STATISTICS=YES` format option: + +```scala +OUTPUTFORMAT + NAME "GEOTIFF_COG" + DRIVER "GDAL/COG" + MIMETYPE "image/tiff" + IMAGEMODE FLOAT32 + EXTENSION "tif" + FORMATOPTION "STATISTICS=YES" +END +``` + +## Requesting a WCS in OpenLayers -[WCS and NULL Values](https://github.com/geographika/wcs-test) +Typically WCS requests are made from client applications such as QGIS, ArcGIS Pro, or custom JS code in web applications to download the raw raster data, +rather than to display it as a map image. However, for the purposes of this tutorial we will be using OpenLayers to make requests to the WCS and display the results. +WCS is not natively supported in OpenLayers, but we can use the [ImageWMS](https://openlayers.org/en/latest/apidoc/module-ol_source_ImageWMS.html) source as a workaround +by overriding the request parameters to call WCS, and display the results as an image layer on the map. + +!!! tip + The `COVERAGEID` corresponds to the MapServer `LAYER` `NAME` +## Code + +??? JavaScript "wcs.js" + + ```js + --8<-- "wcs.js" + ``` + +??? Mapfile "wcs.map" + + ``` scala title="wcs.map" + --8<-- "wcs.map" + ``` + +## Exercises + +1. From the command line, test the WCS 2.0.1 protocol by making a `GetCoverage` request and saving the output as a GeoTIFF using the configured `OUTPUTFORMAT` (MapServer format name, not a MIME type). + Then use `gdal raster info` to check the output file. + +``` +mapserv -nh "QUERY_STRING=map=/etc/mapserver/wcs.map&SERVICE=WCS&VERSION=2.0.1&REQUEST=GetCoverage&COVERAGEID=dtm&FORMAT=GEOTIFF&SUBSETTINGCRS=http://www.opengis.net/def/crs/EPSG/0/4326&SUBSET=x(26.6507,26.7362)&SUBSET=y(58.3414,58.3879)&SCALESIZE=x(400),y(400)" \ +> output.tif +gdal raster info output.tif ``` -mapserv -nh "QUERY_STRING=map=test.map&SERVICE=WCS&VERSION=2.0.0&REQUEST=GetCoverage&CoverageId=test&FORMAT=GEOTIFF_INT16&BBOX=-69.955,3.420,-69.701,3.5896&CRS=EPSG:4326&WIDTH=500&HEIGHT=500" > output2.tif -gdalinfo output.tif + +2. Add the COG output format to the Mapfile and make a `GetCoverage` request to download a COG-formatted output. Check the output file with `gdal raster info` to see the difference in metadata. + +3. Update the JavaScript code to test the WCS 1.0.0 protocol. This requires different parameters to be passed in the requests, + for example `COVERAGEID` becomes `COVERAGE`, and the CRS parameters are different. You can also remove the entire `imageLoadFunction` as WCS 1.0.0 + more closely matches the WMS protocol, using `BBOX`,`WIDTH`, and `HEIGHT` parameters to specify the area and size of the output image. + +```js +params: { + SERVICE: 'WCS', + VERSION: '1.0.0', + REQUEST: 'GetCoverage', + FORMAT: 'image/png', + COVERAGE: 'dtm', + CRS: 'EPSG:3857', + RESPONSE_CRS: 'EPSG:3857', +}, +``` + +## Possible Errors + ``` +msWCSGetCoverage20(): WCS server error. Raster size out of range, width and height of resulting coverage must be no more than MAXSIZE=4096. +``` + +Set the [MAXSIZE](https://mapserver.org/mapfile/map.html#mapfile-map-maxsize) directive in the `MAP` to a larger value. By default, this is set to 4096. + +## Further Reading - +- [MapServer WCS Use Cases](https://mapserver.org/ogc/wcs_format.html) +- [WCS and NULL Values](https://github.com/geographika/wcs-test) diff --git a/workshop/content/mkdocs.yml b/workshop/content/mkdocs.yml index 481a599..6da3dae 100644 --- a/workshop/content/mkdocs.yml +++ b/workshop/content/mkdocs.yml @@ -25,6 +25,7 @@ nav: - Outputs: - WMS: outputs/wms.md - WFS: outputs/wfs.md + - WCS: outputs/wcs.md - Tiles: outputs/tiles.md - Vector Tiles: outputs/vector-tiles.md - OGC API - Features: outputs/ogcapi-features.md @@ -35,6 +36,7 @@ nav: - Clusters: advanced/clusters.md - SLD: advanced/sld.md - STAC: advanced/stac.md + # - WCS and non-EPSG Projections: advanced/wcs-projections.md # - Apache: advanced/apache.md # - MapScript: advanced/mapscript.md - Summary: summary.md diff --git a/workshop/exercises/app/index.html b/workshop/exercises/app/index.html index ac0d767..291c8c7 100644 --- a/workshop/exercises/app/index.html +++ b/workshop/exercises/app/index.html @@ -22,10 +22,11 @@

Inputs

  • Raster
  • Stars (Vector)
  • PostGIS (Databases)
  • - +

    Outputs

    Miscellaneous