Pdok gml naar postgis, of de data is incompleet of ik doe iets fout

Momenteel gebruik ik dit (​/full​/predefined​/bgt-citygml-nl.zip) pdok endpoint om de bgt te downloaden.

Alleen lijkt de data incompleet te zijn, of ik doe iets fout. Ik heb ook de andere endpoints geprobeerd maar daarin lijkt ook informatie te missen.

Ik gebruik ogr2ogr om gml om te zetten naar postgis. Commando: ogr2ogr -f "PostgreSQL" PG:"host=localhost port=5432 dbname=test_gdal user=postgres password=test" -lco SCHEMA=public "/d/mapdata/bgt-citygml-nl/bgt_pand.gml" -progress -lco OVERWRITE=Yes -explodecollections

Als voorbeeld bgt_pand.gml laat niet alle panden zien. Als ik de data uit postgis als laag toevoeg in qgis krijg ik alleen schuurtjes en willekeurige gebouwen te zien.

Wat doe ik fout?

Hiervoor is NLExtract bedoeld. Je kan met de tool zelf de GML inlezen en verwerken of je pakt gewoon de Postgres dump Download BAG, BRT, BGT, BRK als Hapklare Geodata. :slight_smile:

1 like

De oorzaak is dat panden in de BGT GML niet alleen het pandvlak bevatten, maar ook een puntgeometrie voor de nummeraanduiding. Als het goed is, heb je in je Postgres database ook een puntenlaag van de panden. Dit is het gevolg van hoe OGR met GML met meerdere geometry-properties omgaat. Daarvoor hebben we inderdaad NLExtract opgezet, zoals Edward aangeeft. Hier wordt bijv.ook rekening gehouden met kruinlijnen bij diverse BGT objecten en ook met openbareruimtelabels, die meerdere posities en hoeken hebben.

Mocht je alleen interesse hebben in een klein gebied (stad, wijk, of die orde van grootte), dan kun je ook de BGT Import Plugin van QGIS gebruiken, ontwikkeld door Marco Duiker: BGT Import plugin vernieuwd – Nederlandse QGIS gebruikerscommunity

1 like

Mocht je GML willen downloaden voor een specifiek gebied dan kan dat hier: https://download.pdok.io/lv/bgt/viewer/ui

Ik weet dat NLExtract bestaat. Echter zou ik graag weten hoe ik zelf de data vanuit PDOK op de juiste manier kan omzetten. Zou jij hier meer over kunnen uitwijden? Ik ben nu de sourcecode van NLExtract aan het uitpluizen.

De reden is dat een klant meer frequent de data wil vernieuwen dan NLExtract dit doet. Zelf zou ik het ook uit NLExtract halen, zoals ik altijd al doe.

Hoe doet NLExtract het?

Ook met OGR, maar wel met een specifiek GFS bestand: NLExtract/imgeo-v2.1.1.gfs at master · nlextract/NLExtract · GitHub. Verder met een aantal voor- en nabewerkingen. Deze staan hier beschreven: NLExtract/etl-imgeo-v2.1.1.cfg at master · nlextract/NLExtract · GitHub. Dit gebeurt m.b.t. Stetl, dat door Just van den Broecke is ontwikkeld. Just is ook bij NLExtract betrokken.

De stappen in het config bestand zijn als volgt:

  • Database opschonen, d.m.v. deze SQL-bestanden: sql/create-schema.sql,sql/drop-tables-v2.1.1.sql,sql/drop-final-tables-v2.1.1.sql
  • ZIP-bestand verwerken, per bestand:
    • Openbareruimtelabels uitsplitsen naar 1 feature per positie met bijbehorende hoek.
    • Pandfeatures uitsplitsen naar 1 feature voor het pandvlak en 1 feature per nummeraanduiding (tekst, positie en hoek)
    • Het GFS-bestand dat ik noem bewerken. Door o.a. het aantal features hierin op te nemen, wordt het door OGR veel sneller in Postgis geladen.
  • Na afloop wordt er een “dummy” bestand verwerkt met de originele GFS, zodat van alle featuretypen tabellen worden aangemaakt, ook waarvan in het ZIP-bestand geen data aanwezig is.
  • SQL nabewerkingen, d.m.v. deze bestanden: sql/create-final-tables-v2.1.1.sql,sql/fix-eindregistratie.sql

Het inlezen van het volledige CityGML ZIP-bestand duurt op mijn server 2 uur 10 minuten. De nabewerkingen duren ca. 50 minuten, dus het hele proces doet er 3 uur over. De nabewerkingen zijn nodig, omdat we niet geheel tevreden zijn met hoe OGR de data initieel inleest. Er worden o.a. kolommen hernoemd (zou misschien nu ook door OGR opgepakt kunnen worden), geometrieen gecast (je wilt geen “unknown” geometrietype) en aanvullende indexen en views gemaakt.

1 like

Oke super, bedankt voor je uitleg en info. Ik was dit inderdaad al tegengekomen. Ik ga er mee aan de slag! En als het lukt laat ik het ook even weten.

Beste @fsteggink,

Ik krijg een lxml.etree.SerialisationError: unknown error -2029986190 error.

Deze komt na het aanroepen van xf.flush() vanuit lxml.etree.

Weet jij misschien hoe dit zou kunnen?

Het gebeurt alleen bij het verwerken van ‘bgt_148.zip’.

Hier is de volledige foutmelding:

2019-09-13 14:51:44,792 fileinput INFO Pop file record: {'file_path': './todo/bgt_148.zip', 'name': u'bgt_pand.gml'}
2019-09-13 14:51:51,877 subfeaturehandler INFO In SubFeatureHandler.invoke
2019-09-13 14:51:51,879 subfeaturehandler INFO In SubFeatureHandler.invoke
2019-09-13 14:53:51,806 component INFO ZipFileInput invokes=33 time(total, min, max, avg) = 0.032 0.001 0.002 0.001
2019-09-13 14:53:51,808 component INFO ZipFileExtractor invokes=33 time(total, min, max, avg) = 59.312 0.004 9.082 1.797
2019-09-13 14:53:51,808 subfeaturehandler INFO Exit: SubFeatureHandler
2019-09-13 14:53:51,808 component INFO SubFeatureHandler invokes=33 time(total, min, max, avg) = 5.280 0.001 5.212 0.160
2019-09-13 14:53:51,809 subfeaturehandler INFO Exit: SubFeatureHandler
2019-09-13 14:53:51,809 component INFO SubFeatureHandler invokes=33 time(total, min, max, avg) = 0.039 0.001 0.003 0.001
2019-09-13 14:53:51,809 gfspreparationfilter INFO Exit: GFS preparation filter
2019-09-13 14:53:51,810 component INFO GfsPreparationFilter invokes=32 time(total, min, max, avg) = 94.830 0.090 22.033 2.963
2019-09-13 14:53:51,810 component INFO Ogr2OgrExecOutput invokes=32 time(total, min, max, avg) = 141.180 0.121 31.823 4.412
Traceback (most recent call last):
  File "../../externals/stetl/stetl/main.py", line 147, in <module>
    main()
  File "../../externals/stetl/stetl/main.py", line 138, in main
    etl.run()
  File "/mnt/d/repo/NLExtract/externals/stetl/stetl/etl.py", line 159, in run
    chain.run()
  File "/mnt/d/repo/NLExtract/externals/stetl/stetl/chain.py", line 174, in run
    packet = self.first_comp.process(packet)
  File "/mnt/d/repo/NLExtract/externals/stetl/stetl/component.py", line 218, in process
    packet = self.next.process(packet)
  File "/mnt/d/repo/NLExtract/externals/stetl/stetl/component.py", line 218, in process
    packet = self.next.process(packet)
  File "/mnt/d/repo/NLExtract/externals/stetl/stetl/component.py", line 218, in process
    packet = self.next.process(packet)
  File "/mnt/d/repo/NLExtract/externals/stetl/stetl/component.py", line 204, in process
    packet = self.invoke(packet)
  File "/mnt/d/repo/NLExtract/bgt/etl/stetlbgt/subfeaturehandler.py", line 146, in invoke
    xf.flush()
  File "src/lxml/serializer.pxi", line 925, in lxml.etree.xmlfile.__exit__
  File "src/lxml/serializer.pxi", line 1263, in lxml.etree._IncrementalFileWriter._close
  File "src/lxml/serializer.pxi", line 1269, in lxml.etree._IncrementalFileWriter._handle_error
  File "src/lxml/serializer.pxi", line 199, in lxml.etree._raiseSerialisationError
lxml.etree.SerialisationError: unknown error -2029986190

Waar komt het bestand bgt_148.zip vandaan? Is dat een deel van het landelijke bestand? Zou je een link kunnen posten? En gebruik je Windows of Linux? En welke Python-versie? Je moet nog Python 2.7 gebruiken. We zijn er nog niet aan toegekomen NLExtract te porten naar Python 3. Stetl is al wel omgezet.

Het lijkt erop dat deze fout met encoding/decoding van een karakterstring te maken heeft. Zelf ben ik deze fout nog nooit tegengekomen, terwijl ik wel regelmatig heel Nederland verwerk. Wel gebruik ik altijd een Docker-image met NLExtract voor de verwerking van de BGT. Verder is het ook bijzonder dat het bij een pand gebeurt, waarbij ‘vreemde’ karakterstrings hooguit in een nummeraanduiding voorkomen.

Ik gebruik het base image van stetl die python3 gebruikt. Ik heb de python code aangepast om te werken met python3.

Het bestand komt uit de zip file (32x32 km gebied) die gedownload wordt vanuit: https://downloads.pdok.nl/service/extract.zip?extractname=bgt&extractset=citygml&excludedtypes=plaatsbepalingspunt&history=true&tiles=%7B%22layers%22%3A%5B%7B%22aggregateLevel%22%3A4%2C%22codes%22%3A%5B${block}%5D%7D%5D%7D&enddate=${today}

Toevallig staat jouw naam bij de commit die deze lijn heeft aangemaakt ;P. Ik zou graag python3 willen gebruiken. En daarvoor moet ik dus ook even dit probleem oplossen. Ik denk inderdaad ook dat het iets te maken heeft met de encoding die onder water plaatsvindt. In python3 is er een verschil tussen binary en text mode. Misschien dat daardoor speciale karakters niet goed worden gecodeerd.

Hoi William, leuk om je gisteren op de OpenGeo dag even gesproken te hebben. Ik had nog geen link gelegd met deze thread op het Geoforum :wink: Zoals uitgelegd staat migratie naar Python 3 ook bij mij en Just op de lijst i.v.m. de aflopende ondersteuning van Python 2.7, maar we zitten helaas beide erg krap in de tijd. Hopelijk vind je zelf de oplossing, of iemand anders die NLExtract gebruikt met Python 3. Alle hulp is welkom!

Ik liep zelf ook tegen het lxml serialization issue aan bij de verwerking van heel Nederland. De oorzaak blijkt in libxml te zitten. De teruggegeven waarde van xmlOutputBufferClose, de functie die wordt gebruikt om het tijdelijke bestand wordt weggeschreven, is de grootte van het bestand. Echter, het datatype, een int, is in C een signed 32 bit waarde, dus bij een bestand groter dan 2,1 GB (2^31) wordt het als een foutcode geinterpreteerd, want de waarde wordt naar een negatieve waarde gecast. DIt is een klassieke integer overflow fout. En bij groter dan 4 GB weer als een succesvolle schrijfactie, etc. Vandaar dat ik het issue niet eerder met de volledige dump kon reproduceren. Maar aangezien de BGT steeds groeit, was het een kwestie van tijd voordat dit issue de kop op zou steken.

Ik heb besloten in NLExtract hiervoor een workaround te gebruiken. Libxml wordt overal gebruikt en lxml ook op veel plekken, dus op een fix daar hoef ik niet te rekenen. Temeer omdat heel veel bestaande software hier geen rekening mee houdt. Meer info: https://gitter.im/nlextract/NLExtract?at=5df7657255d93923001d3b4d

De fix zit nu in de master van NLExtract. Ik ben hem aan het testen op de volledige dump, maar bij een kleiner extract (ook 32x32 km) waarbij dit issue eerst optrad, gaat het nu wel goed.