Skip to main content

UAT, România (linie, geometrie simplificată)

Cod set de date

ro_admin_lau_simplified_polygon

Limite administrative - UAT, România (linie)

Abordare practică

Datele au fost obținute prin simplificarea geometriei stratului Limite administrative - UAT, România (linie). Procesarea s-a făcut folosind un script (Bash - mediu *nix) ce este rulat după fiecare actualizare a datelor de la ANCPI. Scriptul utilizează mai multe biblioteci open source și utilitare de sistem: mapshaper, GDAL, curl, zip. Scriptul rezultat este prezentat în secțiunea Script ETL și accesibil pentru descărcare pe pagina GitHub a geo-spatial.org.

Prelucrarea datelor

Simplificarea geometriei

S-a făcut folosind biblioteca mapshaper cu următoarele setări:

  • Algoritm: Visvalingam / weighted area;
  • Factor de simplificare: 3%;

Inserarea geometriei UAT Bălan

Simplificarea independentă a stratului de tip poligon și a celui de tip linie a dus la mici diferențe între aceste două seturi de date. 99.9% din vertexi sunt identici, cu excepția câtorva situații. Cea mai importantă fiind cea a UAT Bălan, care apare în setul de date de tip poligon, dar care nu se mai regăsește în setul de date de tip linie (figura de mai jos). S-a optat pentru a insera manual această entitate. Alternativa ar fi fost convertirea versiunii cu geometrie poligon în linie și obținerea programatică a atributelor specifice setului de date de tip linie (numele UAT-urile ce împart o limită, codul lor SIRUTA, etc.). Diferența notabilă este însă dată de faptul că datele de tip linie de la ANCPI conțin un atribut ceva mai greu de obținut prin scripturi ce folosesc în special GDAL/Shapely și anume legalStat, care ne indică dacă limita de UAT a fost agreeată sau nu oficial între cele două UAT-uri ce o împart. De acceea, pentru a nu complica fluxul de lucru, a fost inserată această entitate printr-o comandă de tip SQL.

Exemplu: situația geometriei UAT Bălan (albastru: geometria originală; roșu: geometria simplificată de tip polygon)
Exemplu: situația geometriei UAT Bălan (albastru: geometria originală; roșu: geometria simplificată de tip polygon).
Notă

Algoritmul de simplicare a păstrat intrarea pentru UAT Bălan în tabela de atribute, doar geometria asociată este nulă. Identificarea geometriilor nule se poate face cu o comandă de genul:

ogrinfo ro_admin_lau_simplified_line.gpkg -dialect SQLite -sql "SELECT id, * FROM ro_admin_lau_simplified_line WHERE geometry IS NULL OR ST_IsEmpty(geometry)=1"

Conversia în formate de fișier populare

Datele au foct convertite în formatele de fișier utilizate de geo-spatial.org pentru distribuirea de date vectoriale: GeoPackage, Shapefile, Geoparquet, FlatGeobuf, GeoJSON, TopoJSON, KML. Detalii despre motivația alegerii acestor formate și beneficiile fiecăruia sunt prezentate în ghidul cu privire la date. De asemenea, pentru nevoi interne, datele au fost încărcate în baza de date PostgreSQL/PostGIS.

Publicarea datelor

Datele au fost documentate în Catalogul geo-spatial.org și puse la dispoziție pentru download/access prin protocolul HTTP și prin intermediul serviciilor standardizate OGC. Pentru mai multe detalii accesați Catalogul și/sau secțiunea Descărcare.

Diagrama fluxului de lucru

Deschide diagrama într-o pagină separată

Script ETL

ro_admin_lau_simplified_line.sh
#!/usr/bin/zsh

##############################################################################################################
#🛠 Publicare/actualizare UAT, România (linie, geometrie simplificată)
##############################################################################################################

#🎛 configurații

#🕹 activare mediu Anaconda cu bibliotecile necesare pentru procesare
source /home/ubuntu/anaconda3/etc/profile.d/conda.sh
conda activate geo

#🚏 definire căi date
lau_data_path="/storage/volumes/geoserver-1-storage/administrative_boundaries/lau"

#⚙️ PostGIS
pg_host="localhost"
pg_port=5432
pg_user="user"
pg_db="geospatial"
pg_pass="pass"
pg_schema="romania"

#⚙️ GeoServer
gs_url="http://localhost:8080/geoserver"
gs_user="user"
gs_pass="pass"
gs_workspace="administrative-boundaries"
gs_store="administrative-boundaries"
gs_layer_title="Limite administrative - UAT, România (linie, geometrie simplificată)"
gs_layer_abstract="Set de date care conține limitele unităților administrativ-teritoriale (UAT) din România, în format vectorial de tip linie, procesat de comunitatea geo-spatial.org pe baza datelor publice furnizate de Agenția Națională de Cadastru și Publicitate Imobiliară. Geometria originală a fost simplificată pentru scenariile în care este nevoie de o afișare rapidă a datelor sau reprezentarea la scări mici (ex: aplicații cartografice web)."
gs_layer_keywords=("România" "UAT" "limite administrative" "vector" "linie" "geometrie simplificată")
gs_layer_metadata_link="https://services.geo-spatial.org/geonetwork/srv/eng/catalog.search#/metadata/16e2798e-c024-4c46-9e6e-de2c1212d41a"
gs_layer_style="administrative-boundaries:ro_admin_lau_simplified_line"

#⚙️ Date
layer_name="ro_admin_lau_simplified_line"

echo "
🛠 Procesare UAT, România (linie, geometrie simplificată)
"

#💾 creare versiune GeoJSON prin simplificarea stratului original
echo "💾 creare versiune GeoJSON"
if [ -f ${lau_data_path}/${layer_name}.geojson ]; then
rm ${lau_data_path}/${layer_name}.geojson
fi
mapshaper -i ${lau_data_path}/ro_admin_lau_line.geojson -simplify 3% keep-shapes -o ${lau_data_path}/${layer_name}.geojson

#💾 creare versiune GeoPackage
echo "💾 creare versiune GeoPackage"
if [ -f ${lau_data_path}/${layer_name}.gpkg ]; then
rm ${lau_data_path}/${layer_name}.gpkg
fi
ogr2ogr -of GPKG -s_srs EPSG:4326 -t_srs EPSG:3844 -nln ${layer_name}_int ${lau_data_path}/${layer_name}_int.gpkg ${lau_data_path}/${layer_name}.geojson

ogr2ogr -of GPKG -lco FID=id -nln ${layer_name} -dialect sqlite -sql "SELECT geom AS geometry, * FROM ${layer_name}_int" ${lau_data_path}/${layer_name}.gpkg ${lau_data_path}/${layer_name}_int.gpkg

#💾 inserare UAT Bălan
ogrinfo ${lau_data_path}/${layer_name}.gpkg \
-dialect SQLite \
-sql "UPDATE ${layer_name}
SET geometry = ST_GeomFromText('LINESTRING(560837.2707372273 575700.7060779982,
561079.9577371818 574279.4160781316,
561567.9327369902 573205.0090782174,
562075.8707367636 572528.0920782610,
562229.2947366540 572899.1570782135,
561568.4367369558 573798.3030781478,
561256.2697370579 574868.2040780619,
560837.2707372273 575700.7060779982)', 3844)
WHERE id = 5007"

#💾 creare versiune Esri Shapefile
echo "💾 creare versiune Esri Shapefile"
if [ -f ${lau_data_path}/${layer_name}.zip ]; then
rm ${lau_data_path}/${layer_name}.zip
fi
ogr2ogr -lco ENCODING=UTF-8 -nln ${layer_name} -dialect sqlite -sql "SELECT a.id AS id, * FROM ${layer_name} AS a" ${lau_data_path}/${layer_name}.shp ${lau_data_path}/${layer_name}.gpkg

#📦 arhivare versiune shp
echo "📦 arhivare versiune shp"
zip -j ${lau_data_path}/${layer_name}.zip ${lau_data_path}/${layer_name}.dbf ${lau_data_path}/${layer_name}.shp ${lau_data_path}/${layer_name}.prj ${lau_data_path}/${layer_name}.shx ${lau_data_path}/${layer_name}.cpg

#💾 creare versiune FlatGeobuf
echo "💾 creare versiune FlatGeobuf"
if [ -f ${lau_data_path}/${layer_name}.fgb ]; then
rm ${lau_data_path}/${layer_name}.fgb
fi
ogr2ogr -of FlatGeobuf -nlt MULTILINESTRING -nln ${layer_name} -dialect sqlite -sql "SELECT a.id AS id, * FROM ${layer_name} AS a WHERE a.geometry IS NOT NULL" ${lau_data_path}/${layer_name}.fgb ${lau_data_path}/${layer_name}.gpkg

#💾 creare versiune GeoParquet
echo "💾 creare versiune GeoParquet"
if [ -f ${lau_data_path}/${layer_name}.parquet ]; then
rm ${lau_data_path}/${layer_name}.parquet
fi
ogr2ogr -of Parquet -nlt MULTILINESTRING ${lau_data_path}/${layer_name}.parquet ${lau_data_path}/${layer_name}.gpkg

#💾 creare versiune KML
echo "💾 creare versiune KML"
if [ -f ${lau_data_path}/${layer_name}.kml ]; then
rm ${lau_data_path}/${layer_name}.kml
fi
ogr2ogr -of KML -t_srs EPSG:4326 -dsco NameField=name ${lau_data_path}/${layer_name}.kml ${lau_data_path}/${layer_name}.gpkg

#💾 creare versiune TopoJSON
echo "💾 creare versiune TopoJSON"
if [ -f ${lau_data_path}/${layer_name}.topojson ]; then
rm ${lau_data_path}/${layer_name}.topojson
fi
mapshaper -i ${lau_data_path}/${layer_name}.geojson -o format=topojson ${lau_data_path}/${layer_name}.topojson

#💾 actualizarea setului de date în baza de date PostGIS
echo "💾 actualizarea setului de date în baza de date PostGIS"
ogr2ogr -of PostgreSQL PG:"host=${pg_host} port=${pg_port} user=${pg_user} dbname=${pg_db} password=${pg_pass}" -lco schema=${pg_schema} -lco GEOMETRY_NAME=geom -lco overwrite=yes ${lau_data_path}/${layer_name}.gpkg ${layer_name} -skipfailures -overwrite

#🖇 indexare date PostGIS
psql -h ${pg_host} -p ${pg_port} -U ${pg_user} -d ${pg_db} -c "
CREATE INDEX ${layer_name}_geom_idx ON romania.${layer_name} USING GIST (geom);
CLUSTER romania.${layer_name} USING ${layer_name}_geom_idx;"

#💾 publicarea/actualizarea serviciilor de date
echo "💾 publicarea/actualizarea serviciilor de date"

#❌ ștergere strat existent (dacă există)
echo "🔍 Verificare dacă există stratul."
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -u $gs_user:$gs_pass \
"${gs_url}/rest/layers/${gs_workspace}:${layer_name}.xml")

if [ "$HTTP_STATUS" == "200" ]; then
echo "⚠️ Stratul există. Se șterge."
curl -s -u $gs_user:$gs_pass -XDELETE \
"${gs_url}/rest/layers/${gs_workspace}:${layer_name}?recurse=true"
echo "🗑️ Stratul a fost șters."
else
echo "✅ Nu există strat cu acest nume."
fi

#💾 creare strat
echo "➕ Creare strat ${layer_name}"
curl -s -u $gs_user:$gs_pass -XPOST -H "Content-type: text/xml" \
-d "<featureType>
<name>${layer_name}</name>
<nativeName>${layer_name}</nativeName>
<title>${gs_layer_title}</title>
<abstract>${gs_layer_abstract}</abstract>
</featureType>" \
"${gs_url}/rest/workspaces/${gs_workspace}/datastores/${gs_store}/featuretypes"

#💾 adăugare detalii suplimentare (keywords și metadata link)
echo "📝 Actualizare metadate"
keywords_xml=""
for keyword in "${gs_layer_keywords[@]}"; do
keywords_xml+="<string>${keyword}</string>"
done

curl -s -u $gs_user:$gs_pass -XPUT -H "Content-type: text/xml" \
-d "<featureType>
<keywords>
${keywords_xml}
</keywords>
<metadataLinks>
<metadataLink>
<type>text/xml</type>
<metadataType>ISO19115:2003</metadataType>
<content>${gs_layer_metadata_link}</content>
</metadataLink>
</metadataLinks>
</featureType>" \
"${gs_url}/rest/workspaces/${gs_workspace}/datastores/${gs_store}/featuretypes/${layer_name}"

#💾 Setare stil implicit
echo "🎨 Setare stil implicit + atașare stil suplimentar..."
curl -s -u $gs_user:$gs_pass -XPUT -H "Content-type: text/xml" \
-d "<layer>
<defaultStyle>
<name>${gs_layer_style##*:}</name>
</defaultStyle>
</layer>" \
"${gs_url}/rest/layers/${gs_workspace}:${layer_name}"

echo "✅ Stratul ${layer_name} a fost adăugat și configurat cu succes în GeoServer."

#🗑️ Ștergere fișiere intermediare
echo "🗑️ Ștergere fișiere Shapefile"
rm ${lau_data_path}/${layer_name}.dbf ${lau_data_path}/${layer_name}.shp ${lau_data_path}/${layer_name}.prj ${lau_data_path}/${layer_name}.shx ${lau_data_path}/${layer_name}.cpg

Script accesibil și pe GitHub.

Simbolizare SLD

Simbolizare SLD implicită

ro_admin_lau_simplified_polygon_labels.sld
<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:se="http://www.opengis.net/se" version="1.1.0">
<NamedLayer>
<se:Name>Frontiera de stat</se:Name>
<UserStyle>
<se:Name>Frontiera de stat</se:Name>
<se:FeatureTypeStyle>
<se:Rule>
<se:Name>Frontiera</se:Name>
<se:LineSymbolizer>
<se:Stroke>
<se:SvgParameter name="stroke">#000000</se:SvgParameter>
<se:SvgParameter name="stroke-width">2</se:SvgParameter>
<se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter>
<se:SvgParameter name="stroke-linecap">square</se:SvgParameter>
</se:Stroke>
</se:LineSymbolizer>
</se:Rule>
</se:FeatureTypeStyle>
</UserStyle>
</NamedLayer>
</StyledLayerDescriptor>

Fișier accesibil și pe GitHub.