Komplexní příklad přístupu k datům RÚIAN

Tato kapitola prezentuje příklad použití knihovny GDAL pro čtení online dat z Registru územní identifikace, adres a nemovitostí (RÚIAN) dostupných v rámci Veřejného dálkové přístupu.

Pro zadanou obec (řádek 8) skript vypíše informace o parcelách (parcelní číslo, výměru uloženou v atributech a vypočtenou z geometrie). Parcely, u kterých je rozdíl výměr větší než tolerance (řádek 5), uloží do nové vrstvy ve formátu Esri Shapefile do aktuálního adresáře (řádek 27).

 1import datetime
 2from osgeo import ogr, osr
 3
 4# tolerance ve vymere
 5tol = 100
 6
 7# kod zajmove obce
 8obec = 505528
 9
10# posledni datum v mesici (k tomuto dni jsou publikovana stavova data)
11today = datetime.date.today()
12if today.month == 12:
13    day = today.replace(day=31)
14day = (today.replace(month=today.month, day=1) - datetime.timedelta(days=1))
15datum = day.strftime("%Y%m%d")
16
17# URL souboru VDP
18url='https://vdp.cuzk.cz/vymenny_format/soucasna/{}_OB_{}_UKSH.xml.zip'.format(datum, obec)
19
20# otevrit vstupni datasource (RUIAN)
21ds = ogr.Open('/vsizip/vsicurl/' + url)
22# nacist vrstvu parcel
23layer = ds.GetLayerByName('Parcely')
24
25# vytvorit vystupni datasource (Shapefile - parcely)
26driver = ogr.GetDriverByName("ESRI Shapefile")
27dso = driver.CreateDataSource("parcely.shp")
28srs = osr.SpatialReference()
29srs.ImportFromEPSG(5514)
30olayer = dso.CreateLayer("parcely", srs, ogr.wkbPolygon)
31
32# definovat atributovou tabulku vystupniho Shapefile
33field_name = ogr.FieldDefn("cislo", ogr.OFTString)
34field_name.SetWidth(255)
35olayer.CreateField(field_name)
36olayer.CreateField(ogr.FieldDefn("vymera", ogr.OFTReal))
37olayer.CreateField(ogr.FieldDefn("rozdil", ogr.OFTReal))
38
39# pocet parcel
40count = layer.GetFeatureCount()
41
42# pocet parcel nad toleranci
43count_dif = 0
44
45# sekvencne cist parcely
46layer.ResetReading()
47while True:
48    feat = layer.GetNextFeature()
49    if feat is None:
50        break
51		
52    # nacist zajmove atributy
53    kc = feat.GetField('KmenoveCislo')
54    pod = feat.GetField('PododdeleniCisla')
55    vym = feat.GetField('VymeraParcely')
56	
57    # prvek ma vice geometrickych reprezentaci, zajima nas hranice parcel
58    geom = feat.GetGeomFieldRef('OriginalniHranice')
59	
60    # na zakladne geometrie spocitat vymeru
61    vym2 = geom.GetArea()
62	
63    # vypocitat rozdil mezi vymerou z atributove tabulky a geometrie
64    dif = abs(vym - vym2)
65
66    # oznaceni parcely
67    pc = str(kc)
68    if pod:
69        pc += '/' + str(pod)
70	
71    # vytisknout report pro kazdou parcelu
72    print ('{0}: {1} {2:.1f} {3:.1f}'.format(pc, vym, vym2, dif))
73	
74    if dif < tol:
75        continue
76	
77    # parcely, u kterych je rozdil vymer vetsi nez 100m2, ulozime
78    # do vystupniho shapefile
79    ofeature = ogr.Feature(olayer.GetLayerDefn())
80    ofeature.SetField("cislo", pc)
81    ofeature.SetField("vymera", vym)
82    ofeature.SetField("rozdil", dif)
83    ofeature.SetGeometry(geom)
84    olayer.CreateFeature(ofeature)
85    
86    count_dif += 1
87    
88    # dealokovat pamet
89    ofeature = None
90    
91# vytisknout zaverecnou statistiku
92print ('-' * 80)
93print ('Pocet parcel: {}'.format(count))
94print ('Pocet parcel nad toleranci: {}'.format(count_dif))
95
96# zavrit datove zdroje
97ds.Destroy()
98dso.Destroy()

Poznámka

Skript ke stažení zde.

Tip

Pro efektivní práci s daty RÚIAN existuje speciální knihovna GDAL-VFR a její konzolové nastroje.

Pro srovnání ještě stejný skript za použití knihoven Fiona a Shapely

 1import datetime
 2import fiona
 3from shapely.geometry import shape
 4
 5# tolerance ve vymere
 6tol = 100
 7
 8# kod zajmove obce
 9obec = 505528
10
11# posledni datum v mesici (k tomuto dni jsou publikovana stavova data)
12today = datetime.date.today()
13if today.month == 12:
14    day = today.replace(day=31)
15day = (today.replace(month=today.month, day=1) - datetime.timedelta(days=1))
16datum = day.strftime("%Y%m%d")
17
18# URL souboru VDP
19url = 'https://vdp.cuzk.cz/vymenny_format/soucasna/{}_OB_{}_UKSH.xml.zip'.format(datum, obec)
20
21# Fiona nepodporuje zdroje s vice geometriemi, proto data nejprve predzpracujeme
22# pomoci knihovny GDAL
23from osgeo import gdal
24parcely_poly = "/tmp/parcely.gml"
25gdal.VectorTranslate(parcely_poly, '/vsizip/vsicurl/' + url, format="GML",
26                     SQLStatement="select OriginalniHranice,* from parcely")
27# with fiona.open('/vsizip/vsicurl/' + url, layer='Parcely') as ds:
28with fiona.open(parcely_poly, layer='Parcely') as ds:
29    schema = {
30            "geometry": "Polygon",
31            "properties": {
32                "cislo":  "str:25",
33                "vymera": "float",
34                "rozdil": "float"
35                }
36            }
37    with fiona.open("parcely.shp", 'w', driver="ESRI Shapefile", crs="epsg:5514", schema=schema) as dso:
38        count = 0
39        count_dif = 0
40
41        for f in ds:
42            count += 1
43            
44            cislo = f["properties"]["KmenoveCislo"]
45            if f["properties"]["PododdeleniCisla"]:
46                cislo  = "{}/{}".format(cislo, f["properties"]["PododdeleniCisla"])
47
48            vym = float(f["properties"]["VymeraParcely"])
49            vym2 = shape(f["geometry"]).area
50            dif = abs(vym - vym2)
51            if dif < tol:
52                continue
53
54            dso.write({
55                "type": "Feature",
56                "properties": {
57                    "cislo": cislo,
58                    "vymera": f["properties"]["VymeraParcely"],
59                    "rozdil": vym - vym2
60                },
61                "geometry": f["geometry"]
62            })
63
64            count_dif += 1
65
66        print("-"*80)
67        print("Počet parcel: {}".format(count))
68        print("Počet parcel nad tolerancí: {}".format(count_dif))