Convertir archivos KML para usar con la biblioteca Python Shapely

8

Estoy tratando de obtener un archivo KML ( wijken.kml ) en Shapely . El archivo KML se valida con el esquema XML adecuado, por lo que supongo que la entrada es correcta.

Rutas que he probado:

1) Convertir a formato WKT o WKB, y leer con funciones incorporadas

Conversión:

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

En bien proporcionado:

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

Lo que da (lo mismo para wkt()):

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

Como no proporciona más información, y el código de Python envuelve otras bibliotecas (C?), No sé qué tiene de malo el formato. El archivo CSV contiene varias columnas, tal vez algo está mal allí, pero no he encontrado un ejemplo WKT en línea comparable para probar.

2) Convertir a GeoJSON y usar la asShapefunción Buildly en Buildly

ogr2ogr2 -f GeoJSON wijken.json wijken.kml

En bien proporcionado:

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

Lo que da:

ValueError: Unknown geometry type: featurecollection

Este error es el mismo para un ejemplo mínimo y válido de GeoJSON. Mirando el código Shapley, el problema es que los tipos básicos de GeoJSON como "Feature" y "FeatureCollection" no son reconocidos. No está claro qué ruta tomar para llegar de las características de GeoJSON a las características que Shapely entiende.

3) Leer en KML con fastkml , que devuelve objetos Shapely

Esto funciona, pero parece perder las propiedades / valores ExtendedData en el KML (o al menos no lo pasa a los objetos Shapely).

Siento que me falta algo, no puede ser tan difícil ingresar datos en Shapely. ¿Alguien puede señalarme hacia la solución más robusta / funcional?

mhermans
fuente

Respuestas:

8

Trata bien con objetos geométricos, no con características o colecciones de características. Consulte el manual sobre forma () .

Su código (con JSON) podría 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
fuente
1

Para obtener algunas líneas y polígonos en forma, utilicé My Maps en maps.google.com, lo exporté como KML y luego usé esta pequeña función:

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

PD: No veo una manera de agregar un comentario a la respuesta de Sean, pero me pregunto por qué no mencionó Keytree, que encontré a través de otra pregunta similar: ¿Cómo puedo saber si un lat Lon dado está en un anillo lineal KML? utilizando bien proporcionado?

TomGoBravo
fuente