Waarden in samengestelde velden gebruiken

Bij het inlezen van sommige databronnen voegt Qgis meerdere waarden samen in een veld. Dit komt vooral vaak voor bij het inlezen van een gml-bestand zoals een bestand uit de BGT of een bestemmingsplan (IMRO).

Zo’n veld met meerdere waarden ziet er dan uit zoals in de volgende voorbeelden:bgt_1(BGT)

imro_1(IMRO)

De opzet is heel duidelijk. Als er zoiets staat als

(2:10,50)

dan betekent dat dat er twee waarden zijn opgenomen, in dit geval “10” en “50”.

Deze opzet is best goed leesbaar, maar het valt nog niet  mee om bijvoorbeeld labels te maken op basis van zo’n veld, of de waarden uit te splitsen naar verschillende kolommen met behulp van de field calculator.

Gelukkig is het niet moeilijk om een zogenaamde custom functie aan Qgis toe te voegen waarmee het wel gemakkelijk gaat.

In dit voorbeeld gaan we aan de slag met het zetten van labels op de panden in de BGT. Voeg daarvoor de pand laag toe uit de BGT met behulp van de QGIS plugin, en ga daarna via de eigenschappen van de laag naar het tabblad “labels” en kies voor de Expression Builder als in onderstaand voorbeeld:

labels

Kies daarna voor de Function Editoropen_functio_editor

en maak een nieuw bestand aan.  Plak dan vervolgens het volgende script in het venster:

from qgis.core import *
from qgis.gui import *

@qgsfunction(args='auto', group='Custom')
def values_from_list(string, number, feature, parent):
	"""
	Takes the n-th value from a list in a field where 
        the list is written like: (3:value1, value2,value3). 
        Such lists are often a result of importing gml. <br />
	
	<h3>Syntax</h3>
	
	values_from_list(<i>string</i>, <i>number</i>)
	
	<h3>Arguments</h3><br/>
	
	<i>string</i> The string containing the list
                      in format like 
                      (3:value1, value2,value3) <br/>
	<i>number</i> The index number of the value 
                      in the list to return
	
	<h3>Examples</h3>
	
	<pre>values_from_list("text", 1)</pre>
	
	"""
	
	components = string.strip('()').split(':',1)
	values_list = components[1]
	try:
		return values_list.split(',')[number - 1]
	except:
		return None

Dit script kun je ivm het kritisch gebruik van spaties en tabs in Python beter overplakken vanuit GitHub). Het venster ziet er dan als het goed is ongeveer zo uit:
add_functionVergeet daarna niet op de knop “>Load” te drukken!

Daarna kun je via het tabblad “Expression” de functie gebruiken. Je vindt deze onder het item “Custom”. Zoals je ziet wordt er netjes een help getoond.create_expressionDe eerste parameter die je meegeeft aan de functie is het veld waaruit je een waarde wilt opvissen, de tweede parameter is de hoeveelste waarde je wilt hebben. Een “2” geeft je dan de tweede waarde opgenomen in het veld. Indien er geen tweede waarde is komt er niks terug (ook geen fout).

In dit voorbeeld gebruiken we het veld “tekst” waarin de huisnummers staan, en de eerste waarde in dat veld.

Nadat je op “OK” hebt geklikt zullen de labels verschijnen, waarbij het eerste nummer wordt gebruikt voor de labels.

bgt_labelled

Uiteraard kun je deze functie nu ook gebruiken in de Field Calculator om bijvoorbeeld de waarden uit te splitsen naar verschillende kolommen.

Overigens is het daadwerkelijke script gedeelte heel compact, de rest is documentatie. Als je een beetje Python kent is het echt heel gemakkelijk om zo’n soort functie te schrijven.

De QGIS BGT plugin

Jan-Willem van Aalst schreef een mooi stukje over het gebruik van de BGT in QGIS met als voorbeeld weer een van zijn bekende prachtige kaarten. Hiervoor is het wel nodig om de complete BGT in Postgis te laden. Dat is misschien een beetje overkill als je geïnteresseerd bent in pakweg 1 gemeente.

Zou QGIS ook op een makkelijker manier overweg kunnen met de BGT? Laten we als proef eens van de BGT download site (https://www.pdok.nl/nl/producten/pdok-downloads/download-basisregistratie-grootschalige-topografie) een deel van de BGT downloaden (hier de gemeente Bodegraven-Reeuwijk):

selection_268

Als resultaat krijg je een zipfile met flink wat gml-bestanden. Deze kun je vanuit de verkenner zo in QGIS slepen en het resultaat is (na soms flink wachten) een stuk of 30 kaartlagen en een niet zo mooi opgemaakt kaartbeeld:

selection_272

Een kenner ziet direct dat er iets mis is gegaan. De BGT is vlakdekkend, en de getoonde kaart niet!

Om te begrijpen waar dit probleem vandaan komt is het nodig iets meer te weten van gml. De Nederlandse overheid heeft ervoor gekozen om de open standaard gml te gebruiken voor het uitwissel van geo-informatie. Gml is daarbij inderdaad een standaard en geen bestandsformaat! De standaard is zeer rijk en staat een hele mooie objectgerichte modellering toe waarbij objecten zowel een punt-, een lijn- als een vlakgeometrie hebben. Maar zulke objecten zijn natuurlijk wel moeilijk te gebruiken in de meeste GIS-programma’s die net zoals QGIS graag punten, lijnen en vlakken in aparte kaartlagen zetten.

Als voorbeeld zien we hier de panden (bgt_pand.gml) die zowel een puntlocatie als een vlak aan zich hebben:selection_270

Indien we dan in de gml gaan kijken (dat kan, het is een gewoon tekstbestand), dan zien we dat zo’n pand een imgeo:geometrie2dGrondvlak attribuut heeft, en een imgeo:nummeraanduidingreeks.

In het bgt_vegetatieobject.gml zien we zelfs punten, lijnen en vlakken:

selection_269

Er zijn hier meerdere objecten zichtbaar, twee punten boven op elkaar (de sterren), een lijn (rood gestippeld) en een vlak (groen).

Het gebruik van de identify tool leert dat het vlak, de lijn en een van de punten een “haag” betreft. Het andere punt betreft een boom.

Bij het inlezen van dit soort bestanden waarbij bij sommige objecten wel, en bij andere objecten niet meerdere typen geometrieen zijn opgenomen wordt het voor de onderliggend software die het bestand in moet lezen moeilijk te bepalen wat ingelezen moet worden. Zo krijg je al gauw de nummeraanduidingreeks van de panden terwijl je QGIS vraagt de vlakken in te lezen.

Gelukkig is de software niet al te moeilijk ervan te overtuigen om de juiste dingen in te lezen. Bij FOSS4GNL (28 juni 2017) werd door mij al een plugin aangekondigd die dat zou regelen. De BGT import plugin staat inmiddels bij de QGIS plugins en regelt het inlezen door een klein bestandje aan te maken waarin precies staat waar de geometrie elementen in het gml bestand zitten. QGIS gebruikt dat vervolgens om het gml bestand goed in te lezen.

selection_271

Indien je een BGT bestand importeert met de plugin, dan maakt de plugin een kopie (of een symlink als dat kan) van het gml bestand, met de toevoeging _P, _V, _L in de bestandsnaam voor punten, lijnen en vlakken respectievelijk. Vervolgens wordt naast elk _X.gml bestand een _X.gfs bestand geplaatst op basis waarvan QGIS op de juiste manier de punten, lijnen of vlakken kan inlezen. Je hebt de plugin daarna dus niet meer nodig om zo’n _X.gml bestand goed in te lezen!

Als voorbeeld de bgt_pand.gml direct ingelezen met QGIS (er zijn alleen punten ingelezen):

selection_275

En met gebruik van de plugin (zowel de punten als de vlakken zijn ingelezen):

selection_276

Overigens is het voor de snelheid belangrijk om alleen die geometrie typen aan te vinken die daadwerkelijk in het gml bestand zitten. Anders moet de plugin de hele gml uitpluizen op zoek naar een geometrie type dat er niet is. Dat kan lang duren!

Met behulp van de plugin is het gebruik van de BGT gml bestanden niet zo moeilijk meer en hoef je niet over te gaan tot het gebruik van Postgis en/ of NL-extract.

Wel is het jammer dat je niet zomaar de prachtige visualisatie van Jan-Willem van Aalst kunt gebruiken. Nu maar hopen dat iemand een mooie visualisatie maakt (en deelt!)voor de bestanden die je rechtstreeks met de BGT import plugin inleest.