5

I am trying to use the Dutch BGT Api via https://api.pdok.nl/lv/bgt/download/v1_0/ui/ with the following code:

# Native
import requests
from requests.structures import CaseInsensitiveDict
import json
import time
from zipfile import ZipFile
from io import BytesIO

# Third Party
import pandas as pd
import geopandas as gpd

# %% Function to request the download link through the BGT API
def request_bgt_download_url(base_url, featurelist, fileformat, geofilter):
    api_url = F"{base_url}/lv/bgt/download/v1_0/delta/custom"
    
    #  Headers
    headers = CaseInsensitiveDict()
    headers["accept"] = "application/json"
    headers["Content-Type"] = "application/json"
    
    features = json.dumps(featurelist)
    data = f'{{"featuretypes": {features}, "format": "{fileformat}", "geofilter": "{geofilter}"}}'

    # Request
    response = requests.post(api_url, headers=headers, data=data)
    
    return response.json()['_links']['status']['href']

# %% Get the download zip URL from the download url requested with: request_bgt_download_url
def request_bgt_zip_url(base_url, download_url):
    api_url = F"{base_url}{download_url}"
    
    response = requests.get(api_url)

    print(response.json())
    while response.json()['status'] != 'COMPLETED':
        response = requests.get(api_url)
        print(response.json()['progress'])
        time.sleep(1)
    
    print(response.json())
    return response.json()['_links']['download']['href']

# %% Main
base_url = "https://api.pdok.nl"
featurelist = ["bak","begroeidterreindeel","bord","buurt","functioneelgebied",
               "gebouwinstallatie","installatie","kast","kunstwerkdeel",
               "mast","onbegroeidterreindeel","ondersteunendwaterdeel",
               "ondersteunendwegdeel","ongeclassificeerdobject","openbareruimte",
               "openbareruimtelabel","overbruggingsdeel","overigbouwwerk","overigescheiding",
               "paal","pand","plaatsbepalingspunt","put","scheiding","sensor","spoor",
               "stadsdeel","straatmeubilair","tunneldeel","vegetatieobject","waterdeel",
               "waterinrichtingselement","waterschap","wegdeel","weginrichtingselement",
               "wijk"]
fileformat = "citygml"
geofilter = 'POLYGON((211417.92 475752.4800000001,212390.64000000004 475896.12,212916.48000000004 475818.84,212879.52000000005 475360.2,212950.08000000002 475203.12,212839.2 475065.36,212819.04 474981.36,212819.04 474877.2,212772 474857.04,212792.16 474769.68,212832.48 474705.84,212889.6 474695.76,213010.56000000003 474685.68,213044.16 474611.76,213030.72 474450.48,212637.6 474423.6,212708.16 473956.56,211122.24000000002 473849.04,210453.6 473896.08,210315.84000000003 473970,211417.92 475752.4800000001))'

# Get the ZIP URL
download_url = request_bgt_download_url(base_url, featurelist, fileformat, geofilter)
zip_url = request_bgt_zip_url(base_url, download_url)

# Request the ZIP URL and unpack it in python
zip_response = requests.get(f"{base_url}{zip_url}")
zipfile = ZipFile(BytesIO(zip_response.content))
files = [zipfile.open(file_name) for file_name in zipfile.namelist()]

# Read the xml files with Geopandas
gdf = gpd.read_file(files[4])

The problem is that I get an error with certain XML files, because of the CurvePolygons present in the XML:

Traceback (most recent call last):

  File "<ipython-input-71-beceeaf42900>", line 1, in <module>
    gdf = gpd.read_file(files[4])

  File "C:\ProgramData\Anaconda3\envs\gis\lib\site-packages\geopandas\io\file.py", line 197, in _read_file
    columns = list(features.schema["properties"])

  File "C:\ProgramData\Anaconda3\envs\gis\lib\site-packages\fiona\collection.py", line 200, in schema
    self._schema = self.session.get_schema()

  File "fiona/ogrext.pyx", line 661, in fiona.ogrext.Session.get_schema

  File "fiona/_geometry.pyx", line 80, in fiona._geometry.normalize_geometry_type_code

UnsupportedGeometryTypeError: 10

TypeError 10 refers to (https://github.com/Toblerity/Fiona/blob/master/fiona/_geometry.pyx):

# Unsupported types.
    #8: 'CircularString',
    #9: 'CompoundCurve',
    #10: 'CurvePolygon',
    #11: 'MultiCurve',
    #12: 'MultiSurface',
    #13: 'Curve',
    #14: 'Surface',
    #15: 'PolyhedralSurface',
    #16: 'TIN',
    #17: 'Triangle'

Is there a way to read the CurvePolygons fom the XML files and make them into normal Polygons so they will fit into a Geopandas GeoDataFrame?

1
  • 3
    Simplest way maybe: from osgeo import gdal; gdal.VectorTranslate(inputfile, outputfile, options='-nlt CONVERT_TO_LINEAR'), if you want to try it. Jun 12, 2022 at 20:16

1 Answer 1

1

Thanks Gabriel De Luca for your comment it pushed me into the right direction.

from osgeo import ogr

# I saved the zipfile first to a local directory and uzipped it
zipfile.extractall(r"C:\MapWithData")

# OGR was used to read the xml files from the directory
ds = driver_cloud.Open(r"C:\MapWithData\bgt_begroeidterreindeel.xml")
dataLayer = ds.GetLayer(0)

# You can then loop over the features from the dataLayer and alter the Geometry
# For now I selected the last feature
num_features = dataLayer.GetFeatureCount()
last_feature = dataLayer.GetFeature(num_features - 1)

# From https://gis.stackexchange.com/questions/256123/how-to-convert-curved-features-into-geojson
polygon_geometry = ogr.CreateGeometryFromWkt(last_feature.GetGeometryRef().ExportToWkt()).GetLinearGeometry()
last_feature.SetGeometryDirectly(polygon_geometry)

# write the feature to geojson
geojson_out = last_feature.ExportToJson()

print(geojson_out)
'{"type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[212368.186, 475094.89], [212368.152, 475095.028], [212363.707, 475094.019], [212363.6498651207, 475094.0053874058], [212363.5937045143, 475093.9881919697], [212363.53874261674, 475093.96748241776], [212363.48519905654, 475093.94334150845], [212363.43328781423, 475093.91586570436], [212363.3832163438, 475093.88516482705], [212363.33518473068, 475093.8513615355], [212363.28938493883, 475093.814590956], [212363.246, 475093.775], [212363.20546198025, 475093.7330512827], [212363.16766718827, 475093.68861503154], [212363.1327679306, 475093.6418703496], [212363.10090482977, 475093.5930055379], [212363.0722062811, 475093.5422175675], [212363.0467879325, 475093.48971104616], [212363.02475221452, 475093.4356976002], [212363.00618793067, 475093.38039486104], [212362.99116987042, 475093.3240256831], [212362.979758562, 475093.26681722456], [212362.972, 475093.209], [212363.327, 475091.812], [212367.455, 475091.408], [212368.966, 475091.713], [212368.778, 475092.479], [212368.186, 475094.89]]]}, "properties": {"gml_id": "b5451a320-90d2-2d5d-2aae-71af9df6d5de", "creationDate": "2015-02-26", "LV-publicatiedatum": "2016-12-09T07:48:11", "relatieveHoogteligging": 0, "inOnderzoek": false, "eindRegistratie": null, "tijdstipRegistratie": "2016-12-09T07:22:29.000", "namespace": "NL.IMGeo", "lokaalID": "G0150.d1e9c2997cec4060b406057e58461b8d", "bronhouder": "G0150", "bgt-status": "bestaand", "plus-status": "geenWaarde", "class": "groenvoorziening", "begroeidTerreindeelOpTalud": false, "kruinlijnBegroeidTerreindeel": null, "plus-fysiekVoorkomen": "gras- en kruidachtigen", "terminationDate": null}, "id": 23645}'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.