Convertendo arquivos KML para uso com a biblioteca Python Shapely

8

Estou tentando obter um arquivo KML ( wijken.kml ) no Shapely . O arquivo KML é validado contra o esquema XML adequado, então acho que a entrada está correta.

Rotas que tentei:

1) Convertendo para o formato WKT ou WKB e lendo com funções incorporadas

Conversão:

ogr2ogr -f CSV wijken.csv wijken.kml -lco GEOMETRY=AS_WKT
ogr2ogr -f SQLite wijken.wkb wijken.kml

Em bem torneado:

from shapely import wkt, wkb
f = open('../kml/wijken.wkb')
wkb.load(f) 

O que fornece (o mesmo para wkt()):

ReadingError: Could not create geometry because of errors while reading input.

Como ele não fornece mais informações, e o código Python envolve outras bibliotecas (C?), Não sei o que há de errado com o formato. O arquivo CSV contém várias colunas, talvez algo esteja errado por lá, mas não encontrei um exemplo WKT on-line comparável para testar.

2) Convertendo para GeoJSON e usando a construção na asShapefunção Shapely

ogr2ogr2 -f GeoJSON wijken.json wijken.kml

Em Shapely:

import json
from shapely.geometry import asShape
f = open('wijken.json', 'r')
js = json.load(f)
f.close()
asShape(js)

Que dá:

ValueError: Unknown geometry type: featurecollection

Este erro é o mesmo para um exemplo GeoJSON mínimo e válido. Observando o código de Shapley, o problema é que tipos básicos de GeoJSON, como "Feature" e "FeatureCollection", não são reconhecidos. Não está claro qual rota seguir para ir dos recursos GeoJSON aos recursos que Shapely entende.

3) Leia em KML com fastkml , que retorna objetos Shapely

Isso funciona, mas parece perder os valores de properties / ExtendedData no KML (ou pelo menos não o passa para os objetos Shapely).

Sinto que estou perdendo alguma coisa, não pode ser tão difícil inserir dados no Shapely. Alguém pode me indicar a solução mais robusta / funcional?

mhermans
fonte

Respostas:

8

Shapely lida com objetos geométricos, não recursos ou coleções de recursos. Veja o manual em shape () .

Seu código (com JSON) pode ser:

import json
from shapely.geometry import shape
f = open('wijken.json', 'r')
js = json.load(f)
f.close()

for f in js['features']:    
    s = shape(f['geometry'])
    ...
sgillies
fonte
1

Para obter algumas linhas e polígonos em forma, usei o My Maps em maps.google.com, exportei-o como KML e depois usei esta pequena função:

def ExtractPoints(kml):
  rv = {}
  ns = "{http://earth.google.com/kml/2.2}"
  tree = ElementTree()
  tree.parse(kml)
  for placemark in tree.findall(".//" + ns + "Placemark"):
    name = placemark.findtext(ns + "name")
    print "Found %s" % name
    coordinates_text = placemark.findtext(ns + "LineString/" + ns + "coordinates")
    coordinates = []
    for point_text in coordinates_text.split():
      floats = point_text.split(",")
      coordinates.append((float(floats[0]), float(floats[1])))
    if coordinates[0] == coordinates[-1]:
      rv[name] = Polygon(coordinates)
    else:
      rv[name] = LineString(coordinates)
  return rv

PS: Não vejo uma maneira de adicionar um comentário à resposta de Sean, mas me pergunto por que ele não mencionou Keytree, o que encontrei por meio de outra pergunta semelhante: Como descobrir se uma determinada latitude está em um anel linear KML usando bem torneado?

TomGoBravo
fonte