Adicionando campo com nome de arquivo ao mesclar arquivos shapefiles com ogr2ogr?

14

Estou mesclando alguns shapefiles e tive alguns problemas ao fazê-lo no QGIS, por isso estou usando ogr2ogr diretamente. Estou fazendo isso (em um lote):

ogr2ogr -overwrite %destination% %n1%
ogr2ogr -update -append %destination% %n2% -nln all_new
ogr2ogr -update -append %destination% %n3% -nln all_new
ogr2ogr -update -append %destination% %n4% -nln all_new

Funciona bem, mas agora preciso ter no shapefile resultante, um campo com os nomes dos shapefiles originais que mesclei. Não parece muito difícil, mas não estou conseguindo fazer isso.

Alguém pode ajudar? Obrigado!

vascobnunes
fonte

Respostas:

14

Com scripts pequenos, seria possível. Com algo como a seguir, você deve poder adicionar uma coluna a um shapefile em todos os shapefiles em uma pasta e mesclá-los ao arquivo merged.shp

for %f in (*.shp) do (
  ogrinfo %f -sql "ALTER TABLE %f ADD COLUMN filename character(15)"
  ogrinfo %f -sql "UPDATE TABLE %f filename = '%f'"
  ogr2ogr -update -append merged.shp %f -f esri shapefile -nln merge 
)

edit: O mesmo que um script Bash, com algumas alterações para fazê-lo funcionar:

for f in *.shp
do 
  base=${f%.shp}
  ogrinfo $f -sql "ALTER TABLE $base ADD COLUMN filename character(15)"
  ogrinfo $f -dialect SQLite -sql "UPDATE $base SET filename = '$base'"
  ogr2ogr -update -append merged.shp $f
done
JaakL
fonte
Esta solução só funcionaria se todas as suas camadas / shapefiles tivessem o mesmo nome, por exemplo, "CHEMIN", correto? Estou procurando uma solução para arquivos de script com diferentes nomes de camadas.
oeon 29/11
Correto, se você substituir CHEMIN por% f, ele deverá funcionar com qualquer nome, pois na tabela shapefile o nome é o nome da camada. Eu editei a resposta. Eu não tenho janelas para testá-lo realmente #
JaakL 1/12
9

Eu usaria a opção -sql e importaria o shapefile da seguinte maneira:

ogr2ogr -update -append %destination% %n2% -sql 'SELECT "%n2%" as SHAPE_ORIG, field1, field2, ... FROM %n2%'
capooti
fonte
Paolo - Estou lutando para que isso funcione. Isso só pode ser feito com ogr2ogr e não com ogrinfo? Eu afixei a gdal-dev também, com meus exemplos lists.osgeo.org/pipermail/gdal-dev/2012-November/034849.html não pode fazê-lo no Windows ou Bash ..
oeon
Joe, a única linha ogrinfo falha ou está falhando apenas no contexto do script (dentro do loop)?
Capooti
Paolo - vou adicionar a resposta que funcionou para mim, abaixo. Obrigado por me acompanhar, gentil senhor! :)
oeon 01/12/12
7

existem algumas maneiras de mesclar arquivos de forma.

  • se você deseja mesclar camadas como uma camada, pode usar as ferramentas MMqgis para mesclar ...

mmqgis

  • Se você deseja mesclar todos os arquivos de forma em uma pasta, pode usar o código simples DARREN COPE aqui.

mkdir merged
for %f in (*.shp) do (
if not exist merged\merged.shp (
ogr2ogr -f esri shapefile merged\merged.shp %f) else (
ogr2ogr -f esri shapefile -update -append merged\merged.shp %f -nln Merged )
)
  • Além disso, você pode usar a ferramenta gratuita GeoMerge para mesclar muitos arquivos, mas não se esqueça de considerar o tamanho do arquivo para trabalhar com ele.

e adicionar atributo ao shapefile @dango directon é bom. você pode usar layer.CreateField (field_name) para criar uma nova coluna que é preenchida a partir de

import os
shapeFileName = os.path.splitext("your_shape_file_path")[0]

espero que ajude você ...

Aragão
fonte
5

vascobnunes, eis como eu consegui esse problema usando um script Python para encadear várias instruções ogr2ogr juntas. Você pode facilmente convertê-lo em um script em lote, basicamente apenas concatenar as instruções ogr2ogr ( cmd) e executá-las chamando os.system(cmd), passando o comando ogr2ogr que eu concatenou.

A arma secreta é ( como demonstrado pelo capooti ) aplicando OGR_SQL para impor o nome do arquivo como um valor constante do conjunto de dados de origem que você está anexando ao resultado da mesclagem.

No meu exemplo, a -sqlflag lida com isso, no código é assim:

-sql "SELECT \'' + filename + '\' AS filename, * FROM ' + filenameNoExt + '"'

Mas isso é confuso para ler porque eu preciso aplicar aspas simples e aspas duplas na concatenação resultante. Para fazer isso, preciso escapar das aspas simples (ou seja, \ ') para usá-las "de verdade". Portanto, para facilitar a leitura, ajuda a vê-lo sem variáveis ​​e seqüências de escape. Se você fingir que o nome do arquivo era "roads1" para uma iteração específica, a concatenação resultante ficaria assim na sentença ogr2ogr:

-sql "SELECT 'roads1.shp' AS filename, * FROM roads1"

Esse script .py é uma amálgama de três truques que eu roubei de matt wilkie (um clone vazio de um shapefile), j03lar50n (adicionando uma coluna a um shapefile usando ogrinfo e ogr_sql) e capooti (usando ogr_sql para impor um valor fixo da coluna em todos os registros em um shapefile). Então, aqui está o script completo:


# merge_shps.py
import os    

path = "D:/GIS/01_tutorials/ND_Roads/extracted"  # path to your folder of .shp files
merge = "merge_filename"                         # this will be the name of your merged result

directory = os.listdir(path)

count = 0
for filename in directory:
    if ".SHP" in filename.upper() and not ".XML" in filename.upper():

        # On the first pass, create a clone and add the filename column.
        if count == 0:
            # Make a clone (matt wilkie)..
            cmd = 'ogr2ogr ' + path + '/' + merge + '.shp ' + path + '/' + filename + ' -where "FID < 0"'
            os.system(cmd)

            # Add the field (j03lar50n)..
            cmd = 'ogrinfo ' + path + '/' + merge + '.shp -sql "ALTER TABLE ' + merge + ' ADD COLUMN filename character(50)"'
            os.system(cmd)

        # Now populate the data (capooti)..
        print "Merging: " + str(filename)

        # You'll need the filename without the .shp extension for the OGR_SQL..
        filenameNoExt = filename.replace(".shp","")

        cmd = 'ogr2ogr -f "esri shapefile" -update -append ' + \
                path + '/' + merge + '.shp ' + \
                path + '/' + filename + \
                ' -sql "SELECT \'' + filename + '\' AS filename, * FROM ' + filenameNoExt + '"'

        # Uncomment this line to spit the ogr2ogr sentence to the terminal..
        #print "\n" + cmd + "\n"

        os.system(cmd)

        count += 1
elrobis
fonte
4

Adicione coluna com o nome do arquivo de origem da pasta shapefiles. Requer GDAL 1.10dev, minha tentativa de descartar a extensão .shp não está funcionando - mas, no geral, funciona. - Eu imagino que poderia ser adicionado às linhas que se fundem com o OGR.

for f in *.shp;

do

name=${f%.shp}

/Users/you/gdal_src/bin/ogrinfo $f -sql "ALTER TABLE $name ADD COLUMN filename character(21)"
/Users/you/gdal_src/bin/ogrinfo $f -dialect SQLite -sql "UPDATE $name SET filename = '$f'"
done;
oeon
fonte
+1 para a especificação de dialeto. Eu estava recebendo erros na resposta superior devido ao OGR SQL não fazer atualizações.
user15741
3

Oi, talvez este link ajude. Ele mostra como adicionar um campo a um shapefile usando as ligações pydal gdal.

dango
fonte
2

Dentro do QGIS, você pode adicionar o plug-in Merge Shapefile. Existe uma opção para "Adicionar coluna com nome de arquivo"insira a descrição da imagem aqui

Ryan Garnett
fonte
Eu recebo um TypeError: objeto do tipo 'NoneType' não tem len ()
Hannes Ledegen
0

Uma versão ligeiramente modificada da resposta do JaaKL. Observe que o -append foo.shp e -nln foo precisam corresponder. Além disso, observe o uso do dialeto SQLite (o GDAL aparentemente não aceita a palavra-chave 'Update', portanto o dialeto SQLite deve ser usado instaed) e a ausência da palavra-chave 'TABLE' após a palavra 'UPDATE' (não necessário ou aceito pelo SQLite).

for %%f in (*.shp) do (
  if not "%%f" == "merge.shp" (
    ogrinfo %%f -sql "ALTER TABLE %%~nf ADD COLUMN fname character(15)"
    ogrinfo %%f -dialect SQLite -sql "UPDATE %%~nf SET fname = '%%~nf'"
    ogr2ogr -update -append merge.shp %%f -f "ESRI SHAPEFILE" -nln merge 
  )
)

fonte
0

Um pouco tarde para a discussão, mas agora também há ogrmerge

ogrmerge.py -single -o merged.shp *.shp -src_layer_field_content {DS_BASENAME}
t Livro
fonte