Authentication / Authorization

  • Implemented via "JWT"

    • contact geo support mail for a username and password that can be used to obtain the JWT and get onboarded
    • the JWT has limited time valability so you can use a refresh token if you are using a HTML application.
    • to obtain the JWT you will have to perform a POST to the right endpoint with the right credentials:i.e

    curl -XPOST https://qarta-dev.quarticle.ro/graph/api/v1/login -d '{"username":"yourUsername","password":"yourPassword"}'

  • to refresh it you need to call the https://qarta-dev.quarticle.ro/graph/api/v1/refresh-token endpoint if you use a browser as a client or to pass the username and password again if you are not.
  • list of endpoints:
    • /graph/api/v1/login - accesible without prior authentication. This is used to obtain the JWT token and the refresh-token
    • /graph/api/v1/credentials - accesible only with a valid JWT. Only the users that have the right to access this will succeed in the request. This returns the list of available credentials, adds, modifies and deletes the credentials depending on the used REST verb
    • /graph/geoserver - accesible only with a valid JWT. This will serve the Geo functions as needed by a REST client. There is one "improvement" in the sense that the GetCapabilities endpoint is translated to JSON before returning to the client. to see the /graph/api/v1... endpoints in detail please see the swagger
  • Important calls:
    • GetMap - you will have to change the bbox to a valid one and also the layer to a valid one

    curl -i -H "Authorization: Bearer YOUR_JWT" "https://qarta-dev.quarticle.ro/graph/geoserver/wms?service=WMS&version=1.3.0&request=GetMap&layers=binefacem:Spitale&bbox=-9770913.659834247,4964098.496527512,-8518569.388584249,6216442.767777512&width=256&height=256&srs=EPSG%3A3857&format=image/png8styles=&crs=EPSG%3A3857"

  • GetCapabilities
  • curl "https://qarta-dev.quarticle.ro/graph/geoserver/wms?service=WMS&version=1.3.0&request=GetCapabilities" -H "Authorization: Bearer YOUR_JWT"

WMS Opersations

WMS requests can perform the following operations:

Operation Description
Exceptions If an exception occur
GetCapabilities Retrieves metadata about the service, including supported operations and parameters, and a list of the available layers
GetMap Retrieves a map image for a specified area and content
GetFeatureInfo Retrieves the underlying data, including geometry and attribute values, for a pixel location on a map
DescribeLayer Indicates the WFS or WCS to retrieve additional information about the layer.
GetLegendGraphic Retrieves a generated legend for a map

GetMap Request

This operation requests the server to generate a map. The core parameters specify a bounding box for the map extent, a target spatial reference system, and a width, height, and format for the output.

Parameter Required? Description Value
service Yes Service name Value is WMS
version Yes Service version Value is one of 1.0.0, 1.1.0, 1.1.1, 1.3.0.
request yes Operation name Value is GetMap.
layers yes Layers to display on map Only one recomended
styles Yes Styles in which layers are to be rendered. Value is a comma-separated list of style names, or empty if default styling is required. Style names may be empty in the list, to use default layer styling. Value is WMS.
srs or crs Yes Spatial Reference System for map output. Value is in form EPSG:nnn. crs is the parameter key used in WMS 1.3.0. EPSG 3857
bbox Yes Bounding box for map extent. Value is minx,miny,maxx,maxy in units of the SRS. See above formating corect bbox
width Yes Width of map output, in pixels size is always 256
height Yes Height of map output, in pixels size is always 256
format Yes Image format png8,geojson,mapbox-vector-tile
transparent Yes Whether the map background should be transparent. Values are true or false Default is false

GetMap can also retrieve data in form of vectors from Vector Tiles. These are simplified vectors with limited number of vertices which are from quality point of view very similar to the rendered images in png format.

GetFeatureInfo

This request is designed to extract information for a specific coordinate. The source of the coordinate can me a pointer on the map of a coordinate sent by the user. For a performat request the BBOX around the coordinate should be as small as possible (see below).

Parameter Required? Description Value
service Yes Service name Value is WMS
version Yes Service version Value is one of 1.0.0, 1.1.0, 1.1.1, 1.3.0.
request yes Operation name Value is GetFeatureInfo
layers tes Layers to display on map Only one recomended
styles Yes Styles in which layers are to be rendered. Value is a comma-separated list of style names, or empty if default styling is required. Style names may be empty in the list, to use default layer styling. Value is WMS.
srs or crs Yes Spatial Reference System for map output. Value is in form EPSG:nnn. crs is the parameter key used in WMS 1.3.0. EPSG 3857
bbox Yes Bounding box for map extent. Value is minx,miny,maxx,maxy in units of the SRS. See above formating corect bbox
width Yes Width of map output, in pixels size is always 256
height Yes Height of map output, in pixels size is always 256
query_layers Yes Comma-separated list of one or more layers to query. Minimum 1 layer
info_format No Format for the feature information response. See below for values. application/json or text/html
feature_count No Maximum number of features to return. Default is 1. value is 1
x or i Yes X ordinate of query point on map, in pixels. 0 is left side. i is the parameter key used in WMS 1.3.0. value is always 6
y or j Yes Y ordinate of query point on map, in pixels. 0 is left side. i is the parameter key used in WMS 1.3.0. value is always 6
exceptions No Format in which to report exceptions The default value is application/vnd.ogc.se_xml

For efficient GetFeatureInfo requests you will have to adjust the zoom level to the viewport of the map.

Important: For RiskLookup you should always use zoomlevel 29 as this is efficient and involves low quantities of data. Batch Risklookup is always made on the RiskLookup layer group.

// EPSG:3857 WGS 84 / Pseudo-Mercator var pixelSizes = [{ tileSize: 20037508.34, zoom: 0 }, { tileSize: 10018754.17, zoom: 1 }, { tileSize: 5009377.085, zoom: 2 }, { tileSize: 2504688.5425, zoom: 3 }, { tileSize: 1252344.27125, zoom: 4 }, { tileSize: 626172.135625, zoom: 5 }, { tileSize: 313086.0678125, zoom: 6 }, { tileSize: 156543.03390625, zoom: 7 }, { tileSize: 78271.516953125, zoom: 8 }, { tileSize: 39135.7584765625, zoom: 9 }, { tileSize: 19567.87923828125, zoom: 10 }, { tileSize: 9783.939619140625, zoom: 11 }, { tileSize: 4891.9698095703125, zoom: 12 }, { tileSize: 2445.9849047851562, zoom: 13 }, { tileSize: 1222.9924523925781, zoom: 14 }, { tileSize: 611.4962261962891, zoom: 15 }, { tileSize: 305.74811309814453, zoom: 16 }, { tileSize: 152.87405654907226, zoom: 17 }, { tileSize: 76.43702827453613, zoom: 18 }, { tileSize: 38.218514137268066, zoom: 19 }, { tileSize: 19.109257068634033, zoom: 20 }, { tileSize: 9.554628534317017, zoom: 21 }, { tileSize: 4.777314267158508, zoom: 22 }, { tileSize: 2.388657133579254, zoom: 23 }, { tileSize: 1.194328566789627, zoom: 24 }, { tileSize: 0.5971642833948135, zoom: 25 }, { tileSize: 0.29858214169740677, zoom: 26 }, { tileSize: 0.14929107084870338, zoom: 27 }, { tileSize: 0.07464553542435169, zoom: 28 }, { tileSize: 0.037322767712175846, zoom: 29 }] function getBBoxAroundPoint(x, y, step) { var bBox var minX = x - step; var minY = y - step; var maxX = x + step; var maxY = y + step; bBox = [minX, minY, maxX, maxY]; return bBox } function GetFeatureInfoUrlBuilder(layerName,width,height,x,y,pointOnMapX,pointOnMapY,zoom_step) { var url = 'https://qarta-dev.quarticle.ro/graph/geoserver/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetFeatureInfo&QUERY_LAYERS=' + layerName + '&layers=' + layerName + '&INFO_FORMAT=text%2Fhtml&FEATURE_COUNT=1&x='+x+'&y='+y+'&WIDTH='+width+'&HEIGHT='+height+'&CRS=EPSG%3A3857&STYLES=&BBOX=' + getBBoxAroundPoint(pointOnMapX, pointOnMapY, zoom_step) console.log(url) } GetFeatureInfoUrlBuilder('graphraster:SEISM',10,10,6,6,2375051.342877,5810437.142126,pixelSizes[29].tileSize)

GeoServer provides the following vendor-specific parameters for the GetCapabilities operation. They are fully documented in the WMS vendor parameters section.

GetCapabilities

Parameter Required? Description Value
service Yes Service name Value is WMS
version Yes Service version Value is one of 1.0.0, 1.1.0, 1.1.1, 1.3.0.
request Yes Operation name Value is GetCapabilities
namespace No limits response to layers in a given namespace Value is any given workspace such as "Events"

GetLegendGraphic

The legend can be extracted in image or json form. you will just have to adjust the retrieval format: format=application/json or format=image/png

Data Gridset in Qarta

A gridset defines a spatial reference system, bounding box (extent), a list of zoom levels (resolutions or scale denominators), and tile dimensions. Tile requests must conform to the gridset matrix, otherwise caching will not occur.

In Quarta we use as Coordinate Reference System (CRS) EPSG:3857 . The Pseudo Mercator projection is used also in Google Maps and Open Streetmap.

Grid bounds

Min X Min Y Max X Max Y
-20,037,508.34 -20,037,508.34 20,037,508.34 20,037,508.34

Layers are cached and it is essential for performant image retrieval is to always requests tiles of 256x256 pixels and use the exact BBOX of each tile based on the GRIDSET.

This is not only important for (consuming) performance. Depending on layer and zoom level, wrongly formed requests destabilize the server and put excessive load on the database.

Example of BBOX exact superimposed on the GridSet of the data in Geoserver for zoom level 1.

"zoom_1":[ "-20037508.34,-20037508.34,0,0", "0,-20037508.34,20037508.34,0", "-20037508.34,0,0,20037508.34", "0,0,20037508.34,20037508.34"]

Layer Cache

Layers designed for performant rendering images are cached.

Formating corect BBOX Request

Here a JS sample code for computing request BBOX at various levels

Algorithm for exact zoom level BBOX

var Decimal = require('decimal.js'); function getBbox() { const originX = -20037508.34 const originY = -20037508.34 var pixelSizes = Array() var obj = {zoom_1: [], zoom_2: [],zoom_3: [], zoom_4: [],zoom_5: [], zoom_6: [],zoom_7: [], zoom_8: [],zoom_9: [], zoom_10: [], zoom_11: [], zoom_12: [],}; zoom = 0 for (j = 1; j <= 30; j++) { zoom=1 << j pixelSizes.push(Math.abs(originX) * 2 / zoom) } for (zoom=1; zoom <=8; zoom++) { for (i=1; i <=2 ** zoom; i++) { for (j=1; j <=2 ** zoom; j++) { minx=Decimal.add(originX,Decimal.mul(Decimal.sub(j,1),pixelSizes[zoom-1])) miny=Decimal.add(originY,Decimal.mul(Decimal.sub(i,1),pixelSizes[zoom-1])) maxx=Decimal.add(originX,Decimal.mul(j,pixelSizes[zoom-1])) maxy=Decimal.add(originY,Decimal.mul(i,pixelSizes[zoom-1])) eval('obj.zoom_'+zoom+'.push([minx,miny,maxx,maxy].toString())') } } } var json=JSON.stringify(obj); fs.writeFileSync('myjsonfile.json', json,'utf8', function (err) {if (err) console.log(err) }) } getBbox()