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))