Proj: Select Datum Transformations for EPSG:28992

(FOR REFERENCE, TODO: TO BE UPDATED AND TRANSLATED)

If you startup QGIS 3.8 / Zanzibar the first time to load a data in our national CRS (EPSG:28992) you are being presented with the following dialog:

projqgisveranderingen

I thought it had something todo with the fact that this OSGeo4W install maybe used the newer PROJ (6.0.1), but the About box of QGIS shows:

Compiled against PROJ5.2.0
Running against PROJ Rel. 5.2.0, September 15th, 2018

Checking my older version of QGIS I found the proj/Transformation string used there was:

Proj4: +proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +towgs84=565.2369,50.0087,465.658,-0.406857,0.350733,-1.87035,4.0812 +units=m +no_defs

The first item in the dialog looks most like it…

Strange thing is that the first item is colored GREEN, so it looks like that is the preferred or current one?

But reading the information (from PROJ), you see:

+towgs84=565.237,50.0087,465.658,-0.406857,0.350733,-1.87035,4.0812
EPSG Transformation Code: 15934
Source CRS: Amersfoort
Destination CRS: WGS 84
Remarks: Parameter values from Amersfoort to ETRS89(3) (tfm code 15739) assuming that ETRS89 is equivalent to QGS84 withing the accuracy of the transformation.
Replaces Amersfoort to WGS 84 (2) (code 1672)
Replaced by Amersfoort to WGS 84 (4) (tfm code 4833)

+towgs84=593.16,26.15,478.54,-1.3044,-0.1033,-1.1445,4.0775
EPSG Transformation Code: 1112
Source CRS: Amersfoort
Destination CRS: WGS 84
Remarks: Replaced by Amersfoort to WGS84 (2) (code 1672).

+towgs84=565.04,49.91,465.84,-0.409394,0.359705,-1.86849,4.0772
EPSG Transformation Code: 1672
Source CRS: Amersfoort
Destination CRS: WGS 84
Remarks: Parameter values from Amersfoort to ETRS89(1) (code 1751) assuming that ETRS89 is equivalent to WGS84 within the accuracy of the transformation. Replaces Amersfoort to WGS84 (1) (code 1112). Replaced by Amersfoort to WGS84 (3) (code 15934).

+towgs84=565.417,50.3319,465.552,-0.398957,0.343988,-1.8774,4.0725
EPSG Transformation Code: 4833
Source CRS: Amersfoort
Destination CRS: WGS 84
Remarks: Parameter values from Amersfoort to ETRS89(5) (tfm code 4830) assuming that ETRS89 is equivalent to WGS84 within the accuracy of the transformation.
Replaces Amersfoort to WGS84 (3) (code 15934).

So my preliminary conclusion now is: do not use the GREEN (top) one, but the last one, as that states: Replaces Amersfoort to WGS84 (3) (code 15934)..

Ok, Nyall answered my question on the mailing list.

It appears that the transformations QGIS used earlier was a little messy, and he advices lo look into QGIS with proj6. Funny thing is then you are shown just 2 options (again the first one green). I’ll have to compile projinfo to see what that gives…

screenshot-20190627104509-716x467

Anybody better information or reasoning?

QGISnetworklogger plugin or what are QGIS and my service talking about…

Just released a ‘new’ plugin:
QGIS Network Logger, install via the plugin manager of QGIS version 3.6 or higher (https://plugins.qgis.org/plugins/qgisnetworklogger/).

One of the things QGIS is pretty good in is talking to OGC services (WebMapService/WMS, WebFeatureService/WFS etc etc), QGIS even talks to Esri web services.
Something what was hard in this, is that if you are an average Windows user of QGIS, with a build without debug information, you were never able to see WHAT exactly QGIS was talking about with the server…
So when QGIS fails to show something on your map, it was not always clear if it was a data problem, a QGIS problem or ( very often :-) ) a service issue.

With this plugin, made possible by work of several core-devs in QGIS 3.6 or more, you can ‘justs’ see all the GET/POST/PUT/DELETE requests that QGIS is firing off to the servers. If you are a WebDeveloper: it even listens to F12 (for others: that is the key to show the web-console in most browsers, which also show you internal information of traffic and web pages).

There is a lot to see:

Information and context menu

You see all url’s being fired, the HTTP Operation, status, query, headers from Request and Reply and data/content from the Request etc etc.

You can even ‘replay’ or try out a request in your browser or terminal, by using the context menu on a url:

open

In this example you can see that you can copy a request as a CURL (https://curl.haxx.se/) command to fetch the data or image again.
OR if it is a GET url, you can just open it in your default browser.

The work was able because in QGIS 3.6 Nyall et al. changed some code, so it was easier to ‘listen’ to all the requests that QgsNetworkManager is doing. So this plugin just listens to the requests and show them in the window.

So as long as the provider (or plugin) is using the QgsNetworkManager interface to connect to online services, you will see the requests flying by in the logger window. I hope this is an argument for plugin builders to not use Requests anymore ;-), but stick to our own network machinery.

As said: this would not have been possible without help of Nyall and Alessandro. Nyall also helped with the treeview in my first rudimentary version.
That treeview also costs me some hair though. Because of the asynchrounous nature of the web, AND the fact that you can filter the requests, I bumped in all kind of threading issues…. The tree(view) is being filled, sorted, changed, updated etc etc so fast, that I suffered a lot of crashes… BUT I think I managed to make it stable now.

If not: let me know: https://github.com/rduivenvoorde/qgisnetworklogger/issues
Also if you want to pick up one of the Feature Requests we already have :-)

Happy QGISsing.

About Layer tree embedded widgets and have your WM(T)S always crispy sharp

Around 2014/2015 Martin updated the whole Legend / Layermanager code in QGIS. He wrote some nice blogs about this new “Layer Tree API”: Part 1, Part 2 and Part 3 so people would better understand how “to talk PyQGIS to the Legend”.

In 2016 Martin merged some code on top of this, which would make it possible to create so called ‘Layer Tree embedded widgets’.

In the image below you see an example of this: a little opacity slider which can be used there to change the opacity of the Layer to which it is connected visible in the Layer Manager.

Such embedded widgets are inserted when you move then in the Layer Properties/Legend tab from ‘Available widgets’ to ‘Used widgets’, ONLY for the layer you are viewing the properties.

embeddedwidget_gui

Continue reading About Layer tree embedded widgets and have your WM(T)S always crispy sharp

WCS QGIS and PDOK

Rant?

This WCS investigation started off because my PDOKServicesPlugin was not working for the PDOK WCS services anymore. I wanted to see all fired network requests, so am creating a future plugin for that: https://github.com/rduivenvoorde/qgisnetworklogger. But I hit all kind of issues when trying out the service(s). This is some write up of my findings and hopefully is interesting enough for some people interested in WCS’s….

WCS?

WCS is the WebCoverageService, an OGC api to serve Coverage data. In OGC terms a Coverage is “raster-data”: like geo tiff’s, ecw’s being rasterized, DEM’s (Digital Elevation Models) etc.

Our national opendata service: ‘PDOK’ has an WCS endpoint to the AHN (our national DEM available at max 50cm, though governmental agencies can go up to 10cm resolution).

One of the drawbacks of WCS is that there are already so many different versions: 1.0.0, 1.0.1, 1.1.2, 2.0.0, 2.1.0 etc etc
QGIS WCS provider supports the versions: 1.0.0, 1.1.0, 1.1.2.

How?

WCS is part of the OWS-family of api’s: the ‘OGC Web Services’.
To determine the capabilities of a service you use (just like every other OWS service) a ‘GetCapabilities’-request, like:

https://geodata.nationaalgeoregister.nl/ahn3/wcs?request=GetCapabilities&service=wcs&version=1.1.2

This shows you the general information of the service, AND which datasets are available.

To fetch more information about one dataset, we use the ‘DescribeCoverage’-request, like:

https://geodata.nationaalgeoregister.nl/ahn3/wcs?request=DescribeCoverage&service=wcs&version=1.1.2
(in newer versions of the WCS you also have to add the CoverageId to the request)

After you received this information (well, actually nothing more then some crs, layernames and dimension information, I’ve never understood why you would not add data statistic in this also…) you are ready to actually GET the data with a so called ‘GetCoverage’-request. In this request you set the desired data type.

And example to retrieve a part of our 5m National DEM around Haarlem as a tiff raster image:

https://geodata.nationaalgeoregister.nl/ahn3/wcs?SERVICE=WCS&VERSION=1.0.0&REQUEST=GetCoverage&FORMAT=image/tiff&COVERAGE=ahn3_5m_dsm&BBOX=99198.4917734710033983,485588.33618855383247137,106915.96004800940863788,494366.81641667388612404&CRS=EPSG:28992&RESPONSE_CRS=EPSG:28992&WIDTH=450&HEIGHT=512

Save this to disk and you can automagically load it in QGIS, because this is besides a true tiff-image also a geotiff, meaning it has some metadata in it keeping information about the crs (Coordinate Reference System/Projection) and it’s scale and place on earth:

ahn3tiff

As you can see, for example by using the identify tool, in this image there is just one ‘band': Band 1. Where I clicked the data shows 43, note that this is NOT the height there, but the RGB value of the pixel in the position, going from 0 to 255. So this is NOT the actual data?

You can also load the following url in your browser to ask the service to provide a png image:

https://geodata.nationaalgeoregister.nl/ahn3/wcs?SERVICE=WCS&VERSION=1.0.0&REQUEST=GetCoverage&FORMAT=image/png&COVERAGE=ahn3_5m_dsm&BBOX=99198.4917734710033983,485588.33618855383247137,106915.96004800940863788,494366.81641667388612404&CRS=EPSG:28992&RESPONSE_CRS=EPSG:28992&WIDTH=450&HEIGHT=512

Saving THAT one to disk and loading it in QGIS shows you that it will NOT be placed nicely in the right position of the map. That is because a png image does NOT contain the mentioned metadata (you can provide it as a separate worldfile next to it though).

When you use QGIS to look into the png image, you will find 3 bands: 1,2 and 3 (actually RGB) all holding the same values.
So the service encoded the (actual) raster data into some kind of image where the values are spread over the range 0 till 255…. It is still possible to have some general view of the height variations in this area (actually not that much, besides the dunes in the west :-) ) by providing some styling to the png or tiff:

ahn3png

But what are the real data values of the cells of the raster?

To find that you can (either use the capabilities url and load the service via QGIS, OR use the following request, which should get exact the same data but encoded as 32 bit floats in a tiff (GEOTIFF_FLOAT32):

https://geodata.nationaalgeoregister.nl/ahn3/wcs?SERVICE=WCS&VERSION=1.0.0&REQUEST=GetCoverage&FORMAT=GEOTIFF_FLOAT32&COVERAGE=ahn3_05m_dsm&BBOX=99198.4917734710033983,485588.33618855383247137,106915.96004800940863788,494366.81641667388612404&CRS=EPSG:28992&RESPONSE_CRS=EPSG:28992&WIDTH=450&HEIGHT=512

NOW you receive actual data, data in every cell has it’s (modelled) height in meters, ranging from -4.485 meter below seelevel (in the lower right corner) upto 55.5212 meter: I think some ‘high’ dunes in the west or maybe some tower :-)

ahn3floattiff

Mmm, not sure what is going on here, because measuring the cellen, they are not 0.5 meter x 0.5 meter ???

Let’s try the actual service then: use the GetCapabilities service url from above, create a WCS connection and request the ahn3_05m_dsm (raw data) in the format FLOAT32. This takes some time but NOW you will have 0.5×0.5m cells (though it takes some time to retrieve the data….

Open the Layer props, and from the ‘Render type’ dropdown just select ‘Hillshade’. Zoomed in at Haarlem, you will see:

hillshade

Nice and easy he? The ‘mountain’ in the middle is an old ‘landfill’, now ‘recreation area’, 17 meters high.

So?

What are the issues I hit with WCS?

WCS as Standard

– There are just too many variables and options in the ‘standard’. Because of that both WCS client-implementations AND WCS server-implementations often do not play well together. In my case the server change at PDOK from Geoserver -> Mapserver made the Formats totally different. NOT so much a problem if you have a highly configurable client like QGIS. But if you have a more simple client (as my plugin, or some OpenLayers or Leaflet plugin) it would be good if those formats stay more or like the same.

– All the capability documents are (very) different in the different versions

– So: please OGC: Keep It Simple and backward compatible please!

WCS and Server and Services

– the idea is that a WCS is able to server actual data. Why then are most server implementations also serving those image/rgb format (why a PNG with values of 0 – 255 if you want to know the height???). IF you want something like that, use a WMS to serve the data. So PDOK, maybe just only server the FLOAT32 version? As the height/data is in meters so having integers makes the height-resolution rather low.

– why do you not get back the real data if you request an area in float32 in a browser?

– Not sure how realistic it is to server a DEM from a small country like NL via WCS. As you can imagine the actual data is HUGE, so I was thinking: why did we not come up with WCTC (a Tiled version of the WCS) ???

WCS as client

– looking at all the requests QGIS is firing to the server, it seems like it tries to find out some stats first (for the whole dataset), killing the WCS or at least timing out pretty often. Not sure how valid the stats are from the whole extent (but created from the pyramid by gdal?). Anyway: in my view QGIS fires way to much requests to the server. In case of a tiny tiff serving as wcs that is not a problem, but the AHN/DEM of NL is just to big for that. WHY is that raster-statistics info not available in the GetCapabilities or DescribeCoverage response?

PDOK serving WCS’s

– why is PDOK (or it’s data-providers) using different values for the NODATA value for every different service. Can we try to use some standard for that (at least between those services of the same kin)? Like -9999 (as we know nowhere in NL we go that low…).

– should the AHN not being served as float32 only (and a WMS next to it if you want images)?

Conclusion

Serving the AHN as WCS is doable, but you really have to be patient, raise your network timeout value, hope that PDOK internally does not time out, find out about the data first by a lot of trial and error and THEN you can have fun.

Locatieserver: about parcels and roadnumbers

For those interested in dutch OpenData: our national OpenData service PDOK has a Solr based geocoding service available.

Since this week it is possible to search for ‘parcel’ codes to find cadastral parcels, but also to search on so called ‘hectometer-paaltjes': the little green number signs you see when you drive the dutch highways.

So in QGIS with the ‘PDOK services plugin’ you can use different filters to search for such objects.

Below a screenie with both a search and one of the reference maps from PDOK:

pdokservicesplugingeocoderopentopo

Happy QGISsing :-)

AmsterdamTimeMachine

Via twitter: AmsterdamTimeMachine.nl.

Jan Hartman’s and WebMappers hard work of georeferencing a set of Old Amsterdam maps: http://amsterdamtimemachine.nl.

6 XYZ-Map services with maps old as 1625 to have a look into history, off course also to be loaded in QGIS :-)

Wanna see ‘the red light district’ in 1625?

debroen

Or see Dutch 17th century glory on a map (well, 135 degrees rotated :-) ):

vbercenrode

Or see that there was also a ‘Waag’ (“weigh house”) on Dam Square?

vberckenrodededam

Go grab the xyz-urls from http://amsterdamtimemachine.nl or download this zip containing a QGIS project file.

The zip contains a .qgs file which you can load as project with both QGIS 2.18 and QGIS 3.x NOW. But also a file ‘amsterdamtimemachine.nl.xml’ which you can load as a set of XYZ-services IF you have a QGIS newer then 3.1 (so you either run a nighly, or wait for 3.2 to come out)..

Happy QGISsing…

Coding a QgsLocator (Plugin)

What is a Locator (plugin)

Some months ago, Nyall Dawson silently dropped a nice widget into the lower left corner of your QGIS screen:

locatorbel

People familiar with QtCreator (the Qt-development environment) should recognize it as a QtCreator Locator look-a-like: a way to (very) quickly search in your project for words, classes, bookmarks, help topics, files etc etc.. It is actually a multipurpose tool to ‘quickly’ search for something, or ‘start’ something. See the original Qt documentation.

Nyall had the brilliant idea to add something like that to QGIS too… and he did. In the code it is called a QgsLocator and it can load/register all kind of so called ‘QgsLocatorFilters’.
Out of the box by starting to type in the search field, you search for: Actions, Processing Algorithms, Spatial Bookmarks, Active Layer Features, Project Layers and Project Layouts.
Just start to type ‘bel…’ and you will see there are a lot of buff(er) related Processing Algorithms available.

Then by clicking on one of the algorithms, you actually start it in processing, super fast, super cool.
Or if you have a world map loaded like in the image and click on ‘Belgium’ you zoom to that ‘feature’.

BUT the coolest thing is, that as a (python) developer you can ‘easily’ implement such a QgsLocatorFilter yourself.

The thing that came up with me first is: ‘Wow, what about using this for a fast searching geocoder…’

So, let’s try…

How to create one

The crux is, to implement/code a so called ‘QgsLocatorFilter’ (see the QgsLocatorFilter api docs, the PyQGIS api or the cpp headerfile).

YOUR implementation of this piece of code is actually the work horse of your Locator Filter. It will take the user input, do something with it (in our case: throw it to an Online Geocoder Api), get back the results, create ‘QgsLocatorResult’s from that, which then will be shown to the user AND describe what happens when a user double clicks on the result.

Off course you need some ‘glue’ to put it in QGIS after this:
– a plugin which you can put in the QGIS plugin repository so a user can download your filter
– the ‘registering’ of your filter to QGIS so it is ‘picked up’ and shown in the Locator search widget
(see the nominatim locator plugin code)

Some geocoders (notably the Google one), need a personal api key to work.
When you left click on the little magnifier-icon a menu will appear in which you can select ‘Configure’

configuremenu

That will bring you to the Locator tab in the Options dialog:

locatoroptions

There you can choose to always enable a Locator Filter, or fully disable it.

As you can see in the right, there is also an (now inactive) configure button. If your locator returns True as a result of calling hasConfigWidget(), then that button becomes active and you can for example implement your own Geocoder configuration window.

An example geocoder: Nominatim_Locator_Plugin

Nominatim (from the Latin, ‘by name’) is “a tool to search OSM data by name and address and to generate synthetic addresses of OSM points (reverse geocoding)”. You can read the OSM wiki or the OSM api information.

I have created a plugin called the ‘Nominatim_Locator_Plugin’ which implements this QgsLocatorFilter interface. Install it in QGIS by enabling the experimental plugins, search for ‘Nominatim’ and install the ‘Nominatim Locator Filter’ plugin. Or … have a look into the python code.

As you can see in the ‘fetchResults’ we wait until we have at least 2 characters, and then we start searching.

One special case with the Nominatim service is that it is a free service, but you are NOT allowed to use it as a ‘suggest’ service. That is: only search a full place name. To handle this, I added the gesture that you have to finish your place- or address-term with a ‘space’, and THEN the request is fired.

The cool thing with Nominatim and OpenStreetMap is that it handles all kind of languages. If you type the dutch word of Statue of Liberty: ‘vrijheidsbeeld’, it will just show up:

vrijheidsbeeld

Some technical details

Which methods you have to define you can find in qgslocatorfilter.h.

One thing to be aware of is that the searching/retrieving/showing of the results is all done in multiple threads! I thought to be clever and tried to use asynchronous GET requests to the services, but ended up fighting ‘thread troubles’. So my tip: just use synchronous HTTP for your requests.

Which brings me to which library to use for the HTTP traffic. In QGIS 2 plugins you see people use the Requests-module pretty often, or plain httplib2 or implement their own NetworkAccessManagers.
Disadvantage of using external modules or home-brew solutions is that often QGIS-configurations like Proxy Settings or Network Timeout values are ignored…

For my experiments I used this module: networkaccessmanager.py.
The nice thing is that it tries to be a thin Python wrapper around QGIS’s own QgsNetworkAccessManager (which in this case is actually a thin wrapper around Qt’s QnetworkAccessManager).
It uses the Proxy settings that a User configured and if needed it can use QGIS’s authorisation module so the HTTP traffix is authenticated against the users own systems.

This boundless solution is a great one, but it would be even cooler if the (rather naive) QgsNetworkAccessManager Cpp implementation could be extended to be more Python/User friendly. So it is easier to handle redirects, timouts, headers etc. And like in the boundless module you could choose between synchronous (blocking) or asynchronous (non-blocking) calls.

I created a QEP (QGIS Enhancement Proposal) for it, and hope others are interested and chime in.

Future Ideas

Off course FOSS is never ‘finished’, as in the good sense of being ‘never finished’ :-)

New ideas always pop up when you are coding:

– use a Nominatim configuration screen, to for example only search for certain osm tags (what about: “find all pubs in current mapcanvas view”, best to be done with a map of your current surroundings :-) )

– use the accept-language option of Nominatim (use current QGIS language) in the query, so you can use ‘Эйфелева башня’ or ‘eiffeltoren’ and get your results back in your preferred language.

eiffeltowerrussion

– a Locator for Google Maps api searching. You will need a key for that one, so create a configuration Window for it too (actually: done :-) )

– the PDOK locatieserver interface, our national geocoder service (actually: done :-) )

– YOUR national geocoder service

So, I hope we get you interested in Locators and will see your plugins appear at plugins.qgis.org

Ah, and some last tips for Python QGIS / PyQGIS programmers:

Latest Python API docs (thanks Denis): https://qgis.org/pyqgis/master/

https://qgis.org/api/api_break.html (all QGIS2.x – QGIS3.x api breaks and fixes)

New version of dutch PDOK services plugin

A short post in Dutch, to let us dutchies know of a new version of the ‘PDOK services plugin’ which eases the use of our national OWS services.

If you want you can install it, and for example view the different soli types of The Netherlands:

De Bodemkaart 1:50000 als WMS en WFS
De Bodemkaart 1:50000 als WMS en WFS

Another nice service is the 25cm Aerial Map of The Netherlands (Luchtfoto 2016 Ortho 25cm RGB).

Happy QGIS’ing all!