Fiumi FVG

From OpenStreetMap Wiki
Jump to navigation Jump to search

In questa pagina viene dettagliato il processo di importazione dei dati dal layer "Corsi d'acqua" che si può scaricare dal sito della Regione FVG

anteprima del layer


Autorizzazione

L'uso di questi dati in OSM è stato autorizzato ufficialmente dalla regione, richiesta e autorizzazione possono essere trovati qui

Da fare

  • Controllare cosa c'è già nel DB
  • Convertire i dati i WGS84 usando i parametri medi già utilizzati
  • Decidere quale campo usare com nome
  • Decidere quali altri campi importare
  • Aggiustare le way in modo che le intersezioni condividano un nodo
  • Verificare che la direzione delle way sia diretta verso valle purtroppo questo è stato fatto al 70%, senza usare algoritmi davvero complessi non si può fare di più
  • Convertire tutti i dati in formato OSM
  • Fare l'upload Upload concluso il 7/3/2010

Chi si è occupato del lavoro

Stefano Salvador: elaborazione dati e upload

gnotul: correzione errori e nodi duplicati dopo l'upload

Proposta Tag

Una pagina da tenere d'occhio è sicuramente questa WikiProject_Rivers

I dati fanno parte del Catalogo Regionale del Sistema Cartografico del FVG, molte informazioni sono tratte dalla CTRN ma vengono fatti continui aggiornamenti da altre basi dati. Per questo motivo il prefisso 'it:fvg:ctrn' stavolta viene sostituito da 'it:fvg:regional_catalog'. I campi riportati nella colonna valore si riferiscono alla tabella riportata nella sezione "Dati originali"

# Tag Valore
1 name Se [NOME] è valorizzato allora [Natura Nome], altrimenti [Nome_Foreste] o, se anche questo è vuoto, [Nome_consorzio]. In alcuni casi bisogna prendere [Nome_1] invece di [Nome]
2 waterway Da valorizzare in base al campo [Natura], [Caratteristica] o [Classe], da studiare come. Sotto riporto una possibille classificazione in base al campo [Natura].
3 man_made waterway se e solo se [Tipologia]=Artificiale
4 it:fvg:regional_catalog:corsi_acqua:codice_fvg [Codice_FVG] da usare come identificativo in caso di aggiornamenti
5 it:fvg:regional_catalog:corsi_acqua:nome [Nome] se valorizzato
6 it:fvg:regional_catalog:corsi_acqua:natura [Natura] se valorizzato
7 it:fvg:regional_catalog:corsi_acqua:caratteristica [Caratteristica]
8 it:fvg:regional_catalog:corsi_acqua:nome_foreste [Nome_Foreste] se valorizzato
9 it:fvg:regional_catalog:corsi_acqua:nome_consorzio [Nome_Consorzio] se valorizzato
10 it:fvg:regional_catalog:corsi_acqua:nome_1 [Nome_1] se valorizzato
11 it:fvg:regional_catalog:corsi_acqua:nome_2 [Nome_2] se valorizzato
12 it:fvg:regional_catalog:corsi_acqua:nome_3 [Nome_3] se valorizzato
13 it:fvg:regional_catalog:corsi_acqua:note [Note] se valorizzato
14 it:fvg:regional_catalog:corsi_acqua:bacino [Bacino] se valorizzato (per i canali artificiali non è definito il bacino)
15 it:fvg:regional_catalog:corsi_acqua:sottobacino [Sottobacino] se valorizzato

Il bacino e il sottobacino potrebbero essere importati anche come in altri due modi:

  • is_in:dreinage_basin=?
  • definendo le aree dei bacini idrografici

il primo approccio ha il problema che il tag non esiste e andrebbe perlomeno proposto, il secondo approccio sarebbe quello più corretto e il catalogo regionale ha anche i dati relativi, però non so se OSM è il posto giusto dove mettere questi dati. Per ora lascierei il tag come in tabella e ci riserviamo la decisione per aggiornamenti successivi.

Campo natura Quantità Lunghezza media (Km) Valore waterway
Canale 1227 1.6 canal
Fiume 40 27.5 river
Ramo 3 0.8 ?
Rio 1412 2.2 stream
Roggia 271 3.7 stream
Scolo 100 2.9 drain
Torrente 278 7.4 ?
<Vuoto> 4126 0.7 stream

Dati originali

I dati originali vengono distribuiti in vari formati direttamente dal sito della regione, lo shapefile può essere scaricato da qui. I metadati invece sono raggiungibili tramite il consultatore ricercando "acqua", il layer in oggetto è il primo della ricerca (purtroppo non sembra esserci il modo di linkare direttamente la pagina con i metadati).

Riporto qua sotto gli attributi del layer:

Name Data type Description
Nome Text è la denominazione del corpo idrico, attribuita tenuto conto delle diverse denominazioni rilevate dalle cartografie e delle fonti consultate
Classe Integer number
Nome_RD Text denominazione riportata nel corrispondente elenco delle Acque Pubbliche emanato in attuazione del R.D. 1775/1933 (per i soli corsi d’acqua ivi iscritti). Tale attributo ha valore puramente indicativo
Nome_Foreste Text denominazione attribuita dalla Direzione centrale delle risorse agricole, naturali, forestali e montagna
Nome_1 Text altre eventuali denominazioni riscontrate da altre fonti, inclusi, in alcuni casi, abitanti della zona (nome toponomastico, dialettale, storico…)
Codice_PT Integer number codice attribuito dalla quarta circolare esplicativa della L.R. 19/11/1991, n. 52 che identifica i corsi d’acqua sottoposti a vincolo paesaggistico
Codice_Foreste Integer number codice attribuito dalla Direzione centrale delle risorse agricole, naturali, forestali e montagna
Tipologia Text definisce se si tratta di corso d’acqua prevalentemente naturale o artificiale
Codice_RD Text codice attribuito negli elenchi delle Acque Pubbliche in attuazione del Regio Decreto n. 1775/1933 (per i soli corsi d’acqua ivi iscritti). Al riguardo di tale attributo, valgono le considerazioni sopra espresse con riferimento al nome_RD
Portata_Nulla Boolean campo sì/no; indica se si tratta di corpo idrico che ha portata nulla per più di 120 giorni l'anno, in un anno idrologico medio (in riferimento al Decreto del Ministero dell’Ambiente del 19 agosto 2003). Tale campo non risulta ancora compilato per mancanza di esaustive informazioni sull’andamento idrologico dei corpi idrici
Bacino Text è la denominazione del bacino idrografico principale entro il quale ricade il corso d’acqua. Da notare che per i corpi idrici di tipo "vettore", che attraversano i bacini a scolo nullo (Magredi Occidentali, Magredi Centrali, Magredi Orientali, Lavie Occidentali, Lavie Orientali), il campo bacino viene lasciato vuoto.
Sottobacino Text è la denominazione del bacino idrografico del secondo ordine
Codice_SINA_bacino Text è il codice identificativo del bacino di appartenenza così come richiesto nel Decreto del Ministero dell’Ambiente del 19 agosto 2003. Tale codice è stata adottato ed ufficializzato con delibera di Giunta n. 3349 dd. 23 dicembre 2005
Regione Text Tale campo indica se il corpo idrico ricade nella Regione Friuli Venezia Giulia, nello stato della Slovenia o nella Regione del Veneto
Ordine Text alle aste principali scolanti a mare è stato attribuito ordine pari a 1; ai corpi idrici (naturali e/o artificiali affluenti in aste di ordine 1 è stato attribuito ordine pari a 2 e così via; ai corpi idrici cui non è stato possibile attribuire un bacino scolante in quanto aventi la funzione di mero trasferimento di portate da un corpo idrico di prelievo a un altro corpo idrico ricettore (denominati corpi idrici vettori) e a tutti i canali artificiali a scolo meccanico è stato assegnato un ordine pari a 0; a tutti i corpi idrici che si innestano in altrettanti corpi idrici di ordine 0 è stato assegnato un ordine pari a 0
Natura Text definisce se si tratta di corso d’acqua superficiale, di risorgiva, o vettore, nel caso si tratti di canale che deriva l'acqua da un bacino per rilasciarla in un altro (è opportuno precisare che tali corsi non hanno bacino scolante)
Nome_2 Text altre eventuali denominazioni riscontrate da altre fonti, inclusi, in alcuni casi, abitanti della zona (nome toponomastico, dialettale, storico…)
Nome_3 Text altre eventuali denominazioni riscontrate da altre fonti, inclusi, in alcuni casi, abitanti della zona (nome toponomastico, dialettale, storico…)
Codice_FVG Text codice attribuito dalla Direzione centrale ambiente e lavori pubblici in base al Decreto Ministeriale del 19/08/2003 come meglio illustrato nel capitolo precedente. Tale codifica è stata adottata ed ufficializzata con delibera di Giunta n. 3349 dd. 23 dicembre 2005.Il codice prevede 7 caratteri: due lettere che identificano l’asta principale ricettrice; due cifre che identificano l’ordine dell'asta (crescente a partire dalla foce); numero progressivo di tre cifre attribuito in base alla lunghezza dell’asta (ordine decrescente)
ID Real number
NOTE Real number
LUNGHEZZA Real number
Caratteristica Text
Nome_Consorzio Text
Nome_CTR Text denominazione così come riportata nella Carta tecnica regionale numerica 1:5000

Processo di importazione

I dati originali presentavano una serie di imprecisioni che sono state corrette prima dell'importazione, quasi tutte in automatico tramite script. Sotto li riporto tutti, spero che i commenti siano comprensibili.

Lo strumento utilizzato per tutte le elaborazioni è stato PostGIS, quello che è stato fatto viene riassunto nello script più sotto.

L'intera operazione (download dati originali, trasformazioni e correzioni) è stata eseguita con il seguente script:

#!/bin/sh

# scarica il layer
echo "scarico il layer dal sito della regione"
wget http://www.irdat.regione.fvg.it/MetadatiWS/download/Idraulica/Shape/S_CorsiAcqua.zip -O S_CorsiAcqua.zip

# decomprimo tutto
echo "unzip ..."
unzip S_CorsiAcqua.zip

# riproietta il file originale
echo "riproietto il layer da Gauss-Boaga a WGS84"
ogr2ogr -t_srs EPSG:4326 -s_srs "+proj=tmerc +lat_0=0 +lon_0=15 +k=0.999600 +x_0=2520000 +y_0=0 +ellps=intl +units=m +towgs84=-128.6633,-30.2694,-6.12,-1.05572,-2.6951,-2.28808,-16.9352" CORSIACQUA_WGS84.shp CORSIACQUA.shp

# crea database e tabella sul db
echo "importo i dati in PostGIS per la rielaborazione"
createdb -T template_postgis fvg -U postgres
shp2pgsql -s 4326 -i -I -c -W "LATIN1" CORSIACQUA_WGS84.shp public.corsi > corsi.sql
psql -U postgres  fvg < corsi.sql

# aggiusta il layer prima della conversione in formato OSM
echo "rielaborazione PostGIS ..."
psql -U postgres fvg < modify.sql

# ferma un attimo lo script per aggiustare a mano i nomi che contengono S.
read

# esporta in formato OSM
echo "esporta OSM ..."
ruby corsi2.osm.rb

# esegui l'upload
echo "upload su OSM"
svn co http://svn.openstreetmap.org/applications/utils/import/bulk_upload_06/
patch bulbulk_upload_06/bulk_upload.py bu_source.diff # aggiungi il tag source al changeset
python bulk_upload.py -i corsi.osm -u *** -p ***

questo è script SQL usato per le correzioni:

-- abbiamo 797 corsi d'acqua spezzettati, cerchiamo di fare il possibile per riunirli
UPDATE corsi SET the_geom=ST_Force_4D(ST_Multi(ST_LineMerge(the_geom))) WHERE ST_NumGeometries(the_geom) > 1;
-- adesso ne restano 141 (110 con 2 pezzi e 31 con 3 pezzi)
-- sono tutti con problemi di snap, cerchiamo di metterne a posto qualcun'altro
UPDATE corsi SET the_geom= 
  ST_Force_4D(ST_Multi(ST_LineMerge(ST_Union(
    ST_SetPoint(ST_GeometryN(the_geom,1), 0, ST_EndPoint(ST_GeometryN(the_geom,2))),
    ST_GeometryN(the_geom,2)
  ))))
WHERE
  ST_NumGeometries(the_geom) = 2 AND
  ST_Intersects(
    ST_Buffer(ST_StartPoint(ST_GeometryN(the_geom,1)), 0.0002),
    ST_EndPoint(ST_GeometryN(the_geom,2))
  )

UPDATE corsi SET the_geom= 
  ST_Force_4D(ST_Multi(ST_LineMerge(ST_Union(
    ST_SetPoint(ST_GeometryN(the_geom,1), 0, ST_StartPoint(ST_GeometryN(the_geom,2))),
    ST_GeometryN(the_geom,2)
  ))))
WHERE
  ST_NumGeometries(the_geom) = 2 AND
  ST_Intersects(
    ST_Buffer(ST_StartPoint(ST_GeometryN(the_geom,1)), 0.0002),
    ST_StartPoint(ST_GeometryN(the_geom,2))
  )

UPDATE corsi SET the_geom= 
  ST_Force_4D(ST_Multi(ST_LineMerge(ST_Union(
    ST_SetPoint(ST_GeometryN(the_geom,1), ST_NumPoints(ST_GeometryN(the_geom,1))-1, ST_StartPoint(ST_GeometryN(the_geom,2))),
    ST_GeometryN(the_geom,2)
  ))))
WHERE
  ST_NumGeometries(the_geom) = 2 AND
  ST_Intersects(
    ST_Buffer(ST_EndPoint(ST_GeometryN(the_geom,1)), 0.0002),
    ST_StartPoint(ST_GeometryN(the_geom,2))
  )


UPDATE corsi SET the_geom= 
  ST_Force_4D(ST_Multi(ST_LineMerge(ST_Union(
    ST_SetPoint(ST_GeometryN(the_geom,1), ST_NumPoints(ST_GeometryN(the_geom,1))-1, ST_EndPoint(ST_GeometryN(the_geom,2))),
    ST_GeometryN(the_geom,2)
  ))))
WHERE
  ST_NumGeometries(the_geom) = 2 AND
  ST_Intersects(
    ST_Buffer(ST_EndPoint(ST_GeometryN(the_geom,1)), 0.0002),
    ST_EndPoint(ST_GeometryN(the_geom,2))
  )

-- adesso ne restano 36 (5 hanno 2 pezzi, 31 hanno 3 pezzi)
-- alcune hanno pezzi proprio piccoli

UPDATE corsi SET the_geom=ST_Multi(ST_GeometryN(the_geom, 1))
WHERE ST_NumGeometries(the_geom) > 1
AND ST_Contains(ST_Buffer(ST_GeometryN(the_geom, 1), 0.0006), the_geom)

SELECT count(*) FROM corsi
UPDATE corsi SET the_geom=ST_Multi(ST_GeometryN(the_geom, 2))
WHERE ST_NumGeometries(the_geom) > 1
AND ST_Contains(ST_Buffer(ST_GeometryN(the_geom, 2), 0.0006), the_geom)

UPDATE corsi SET the_geom=ST_Multi(ST_GeometryN(the_geom, 3))
WHERE ST_NumGeometries(the_geom) > 1
AND ST_Contains(ST_Buffer(ST_GeometryN(the_geom, 3), 0.0006), the_geom)

UPDATE corsi SET the_geom=
ST_Force_4D(ST_Multi(ST_LineMerge(ST_Union(ST_GeometryN(the_geom, 2), ST_GeometryN(the_geom, 3)))))
WHERE ST_NumGeometries(the_geom) = 3
AND ST_Length(ST_GeometryN(the_geom, 1)) < 0.0006

UPDATE corsi SET the_geom=
ST_Force_4D(ST_Multi(ST_LineMerge(ST_Union(ST_GeometryN(the_geom, 1), ST_GeometryN(the_geom, 3)))))
WHERE ST_NumGeometries(the_geom) = 3
AND ST_Length(ST_GeometryN(the_geom, 2)) < 0.0006

UPDATE corsi SET the_geom=
ST_Force_4D(ST_Multi(ST_LineMerge(ST_Union(ST_GeometryN(the_geom, 1), ST_GeometryN(the_geom, 2))))) 
WHERE ST_NumGeometries(the_geom) = 3
AND ST_Length(ST_GeometryN(the_geom, 3)) < 0.0006

--- adesso ne restano 7 (2 da 2 pezzi e 5 da 3 pezzi) ... questi sono da aggiustare uno a uno :-(

-- gid: 817 - ha due problemi di snap
UPDATE corsi SET the_geom=
ST_Force_4D(ST_Multi(ST_LineMerge(ST_Union(Array[
  ST_GeometryN(the_geom, 1),
  ST_AddPoint(ST_GeometryN(the_geom, 2), ST_StartPoint(ST_GeometryN(the_geom, 1))),
  ST_SetPoint(ST_GeometryN(the_geom, 3), ST_NumPoints(ST_GeometryN(the_geom, 3)) - 1, ST_StartPoint(ST_GeometryN(the_geom, 2)))
]))))
WHERE gid = 817
-- gid: 1769 - è giusto così: è un canale con 2 rami.
-- gid: 5891 - è giusto così: è un canale con 2 rami.
-- gid: 6410 - è giusto così: è un canale con 2 rami.
-- gid: 6532 - ha geometrie in più
UPDATE corsi SET the_geom=
ST_Force_4D(ST_Multi(ST_LineMerge(ST_Union(
  ST_GeometryN(the_geom, 1),
  ST_GeometryN(the_geom, 2)
))))
WHERE gid = 6532
-- gid: 6699 - è giusto così: è un canale con 2 rami.
-- gid: 7379: la geometria 1 è un errore
UPDATE corsi SET the_geom=ST_Multi(ST_GeometryN(the_geom, 2)) WHERE gid = 7379

-- tenta di dirigere i corsi d'acqua verso valle
-- praticamente gira tutte le way che si intersecano all'inizio invece che alla fine
-- restano fuori da questo controllo i fiumi principali (circa 40) che non si intesecano nè all'inizio nè alla fine
-- e i canali che collegano due corsi d'acqua (che hanno l'intersezione sia all'inizio che alla fine)

UPDATE corsi SET the_geom=ST_Reverse(the_geom)
WHERE gid IN
(SELECT a.gid FROM corsi a
LEFT OUTER JOIN corsi b ON ST_Intersects(ST_StartPoint(a.the_geom), b.the_geom) AND a.gid <> b.gid
LEFT OUTER JOIN corsi c ON ST_Intersects(ST_EndPoint(a.the_geom), c.the_geom) AND a.gid <> c.gid
WHERE NOT b.gid IS NULL AND c.gid IS NULL);

-- aggiungi un punto ad ogni intersezione
-- questo serve per costruire delle way connesse
DROP FUNCTION add_intersection(varchar, varchar);
CREATE OR REPLACE FUNCTION add_intersection(varchar, varchar) RETURNS VOID AS $$
  DECLARE
     tab ALIAS FOR $1;
     col ALIAS FOR $2;
     sqry TEXT;
     uqry TEXT;
     g RECORD;
     c INTEGER;
     l GEOMETRY;
     p1 GEOMETRY;
     p2 GEOMETRY;
     p GEOMETRY;
     pt TEXT;
     i INTEGER;
  BEGIN
    sqry:= 'SELECT a.id AS id, a.'|| col ||' AS g1, b.'|| col ||' AS g2 FROM '|| tab ||' a INNER JOIN '|| tab ||' b on ST_Intersects(a.'|| col ||', b.'|| col ||') WHERE GeometryType(ST_Intersection(a.'|| col ||', b.'|| col ||')) = ''POINT''';
    FOR g IN EXECUTE sqry LOOP
      SELECT ST_NumPoints(g.g1) INTO c;
      FOR i IN 1..(c-1) LOOP
        SELECT ST_PointN(g.g1, i) INTO p1;
        SELECT ST_PointN(g.g1, i+1) INTO p2;
        SELECT ST_MakeLine(p1, p2) INTO l;
        IF ST_Intersects(l, g.g2) THEN
          SELECT ST_Intersection(l, g.g2) INTO p;
          IF NOT (ST_Equals(p, p1) OR ST_Equals(p, p2)) THEN
            BEGIN
              SELECT ST_AsEWKT(ST_AddPoint(g.g1, p, i)) INTO pt;
              uqry:= 'UPDATE ' || tab || ' SET '|| col || '=ST_GeomFromEWKT(''' || pt || ''') WHERE id=' || g.id;
              EXECUTE uqry;
            EXCEPTION
              WHEN OTHERS THEN
                RAISE NOTICE 'error ...';
            END;
          END IF;
        END IF;
      END LOOP;
    END LOOP;
    
  END;
$$ LANGUAGE plpgsql;

SELECT add_intersection('corsi', 'the_geom');

questo è script Ruby usato per trasformare i dati da PostGIS a OSM:

require 'rubygems'

gem 'activerecord'
require 'active_record'

require 'pathname'
$: << "."
$: << "./spatial_adapter/lib/"

ActiveRecord::Base.establish_connection(
  :adapter => 'postgresql',
  :host => 'localhost',
  :username => 'postgres',
  :password => 'postgres',
  :database => 'fvg'
)

require 'spatial_adapter/init.rb'

class Corsi < ActiveRecord::Base
  set_table_name 'corsi'
  set_primary_key :gid
end

require 'xml'
require 'net/http'


class Util

  def add_tags(node, hash)
    hash.each do |k, v|
      tag = XML::Node.new('tag')
      tag.attributes["k"] = k.to_s
      tag.attributes["v"] = v.to_s
      node << tag
    end
  end

  def add_attributes(node, hash)
    hash.each do |k, v|
      node.attributes[k] = v.to_s
    end
  end

  def prepare_doc
    doc = XML::Document.new()
    doc.root = XML::Node.new('osm')
    doc.root.attributes["version"] = '0.6'
    doc.root.attributes["generator"] = 'custom ruby script'
    return doc, doc.root
  end

  def add_node(name, parent, attributes = nil, tags=nil)
    node = XML::Node.new(name)
    parent << node
    add_attributes(node, attributes) unless attributes.nil? || attributes.empty?
    add_tags(node, tags) unless tags.nil? || tags.empty?
    return node
  end

  def next_id()
    if(@id.nil?)
      @id = -1
    else
      @id = @id - 1
    end
    return @id
  end

  def add_elements(num, outfile, doc, node)
    outfile.add_elements(num)
    if(outfile.elements > 25000)
      outfile.close(doc)
      outfile = OutFile.new(ARGV[0])
      doc, node = prepare_doc
    end
    return outfile, doc, node
  end
end

class OutFile

  def initialize(folder, name)
    @file = File.new(File.join(folder, name), 'w')
  end

  def close(doc)
    @file.write(doc.to_s)
    @file.close
  end

end

util = Util.new

outfile = OutFile.new(".", "corsi.osm")
doc, base_node = util.prepare_doc

#corsi = Corsi.find(:all, :conditions => ['gid=?', 7379])
corsi = Corsi.find(:all, :order => 'gid')

# estrae tutti i nodi
nodes = {}
corsi.each do |c|

  print c.gid
  STDOUT.flush
  c.the_geom.geometries.each do |g|
    n_ids = []
    g.points.each do |p|
      print "."
      STDOUT.flush
      n_key = "#{p.x}_#{p.y}"
      if(nodes.has_key?(n_key))
        n_ids << nodes[n_key] unless n_ids.include?(nodes[n_key])
      else
        node = util.add_node(
          'node', 
          base_node,
          {'lat' => p.y, 'lon' => p.x, 'id' => util.next_id}
        )
        nodes[n_key] = node.attributes['id']
        n_ids << node.attributes['id'] unless n_ids.include?(node.attributes['id'])
      end
    end
    
    tags = {}
    tags["waterway"] = if(c.natura == "Canale")
      "canal"
    elsif(c.natura == "Fiume")
      "river"
    elsif(c.natura == "Scolo" || c.caratteris == "Scolo_meccanico")
      "drain"
    else
      "stream"
    end
    
    if(c.natura && c.nome)
      tags["name"] = "#{c.natura} #{c.nome}"
    elsif(c.nome_fores)
      tags["name"] = c.nome_fores
    elsif(c.nome_conso)
      tags["name"] = c.nome_conso
    elsif(c.nome_1)
      tags["name"] = c.nome_1
    end
    
    tags["man_made"] = "waterway" if c.tipologia=='Artificiale'
    tags["it:fvg:regional_catalog:corsi_acqua:codice_fvg"] = c.codice_fvg
    tags["it:fvg:regional_catalog:corsi_acqua:nome"] = c.nome if c.nome
    tags["it:fvg:regional_catalog:corsi_acqua:natura"] = c.natura if c.natura
    tags["it:fvg:regional_catalog:corsi_acqua:caratteristica"] = c.caratteris if c.caratteris
    tags["it:fvg:regional_catalog:corsi_acqua:nome_foreste"] = c.nome_fores if c.nome_fores
    tags["it:fvg:regional_catalog:corsi_acqua:nome_consorzio"] = c.nome_conso if c.nome_conso
    tags["it:fvg:regional_catalog:corsi_acqua:nome_1"] = c.nome_1 if c.nome_1
    tags["it:fvg:regional_catalog:corsi_acqua:nome_2"] = c.nome_2 if c.nome_2
    tags["it:fvg:regional_catalog:corsi_acqua:nome_3"] = c.nome_3 if c.nome_3
    tags["it:fvg:regional_catalog:corsi_acqua:note"] = c.note if c.note
    tags["it:fvg:regional_catalog:corsi_acqua:bacino"] = c.bacino if c.bacino
    tags["it:fvg:regional_catalog:corsi_acqua:sottobacino"] = c.sottobacin if c.sottobacin
      
    way = util.add_node(
      'way',
      base_node,
      {"id" => util.next_id},
      tags
    )
    n_ids.each do |n_id|
      nd = util.add_node('nd', way, {"ref" => n_id})
    end
  
  end

  print "done\n"
  STDOUT.flush
end

outfile.close(doc)