Conversion de fichiers KML pour une utilisation avec la bibliothèque Python Shapely

8

J'essaye d'obtenir un fichier KML ( wijken.kml ) dans Shapely . Le fichier KML est validé par rapport au schéma XML approprié, donc je suppose que l'entrée est correcte.

Itinéraires que j'ai essayés:

1) Conversion au format WKT ou WKB et lecture avec les fonctions intégrées

Conversion:

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

En forme:

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

Ce qui donne (pareil pour wkt()):

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

Comme il ne fournit aucune autre information et que le code Python enveloppe d'autres bibliothèques (C?), Je ne sais pas ce qui ne va pas avec le format. Le fichier CSV contient plusieurs colonnes, peut-être que quelque chose ne va pas, mais je n'ai pas trouvé d'exemple WKT en ligne comparable à tester.

2) Conversion en GeoJSON et en utilisant la construction dans galbé asShapefonction

ogr2ogr2 -f GeoJSON wijken.json wijken.kml

En forme:

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

Qui donne:

ValueError: Unknown geometry type: featurecollection

Cette erreur est la même pour un exemple GeoJSON minimal et valide. En regardant le code Shapley, le problème est que les types GeoJSON de base tels que "Feature" et "FeatureCollection" ne sont pas reconnus. La route à suivre pour passer des fonctionnalités GeoJSON aux fonctionnalités comprises par Shapely n'est pas claire.

3) Lire en KML avec fastkml , qui renvoie des objets Shapely

Cela fonctionne, mais il semble perdre les propriétés / valeurs ExtendedData dans le KML (ou du moins ne pas les transmettre aux objets Shapely).

Je sens que je manque quelque chose, il ne peut pas être si difficile d'entrer des données dans Shapely. Quelqu'un peut-il m'orienter vers la solution la plus robuste / la plus fonctionnelle?

Hermans
la source

Réponses:

9

Traite avec forme des objets géométriques, et non des objets ou des collections d'objets. Voir le manuel sur la forme () .

Votre code (avec JSON) pourrait être:

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
la source
1

Pour obtenir des lignes et des polygones bien formés, j'ai utilisé Mes cartes sur maps.google.com, je l'ai exporté au format KML, puis j'ai utilisé cette petite fonction:

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: Je ne vois pas de moyen d'ajouter un commentaire à la réponse de Sean, mais je me demande pourquoi il n'a pas mentionné Keytree, que j'ai trouvé via une autre question similaire: comment savoir si un lat lon donné est dans un anneau linéaire KML utiliser galbée?

TomGoBravo
la source