2

I'm a GIS basic/novice user.

I have some LinearRings in a KML file that give the areas for a bunch of different regions. And then I (will) have some lat lons that I want to test to see if they're in any of the (about 8) different regions that I have LinearRings for. I want to use python and shapely looks like it's a good fit, but it doesn't deal with kml data at all.

Is there a standard way to do things like load KML that I can then import into shapely?

PolyGeo
  • 65,136
  • 29
  • 109
  • 338
Paul Huff
  • 23
  • 1
  • 3
  • Although I realize this is an old post would you care to help me out? Working with Python3 the code needed to change a bit for it to work e.g. line 1 : from urllib.request import urlopen But after all changes the output seems to be strange: <filter object at 0x0000000003948D30> Let me state i've changed nothing further then to make the original code work. Thank you Maurice – MauriceP Aug 06 '15 at 13:01
  • If you have a new question about python please ask a new question. – Mapperz Aug 06 '15 at 13:42
  • This does not really answer the question. If you have a different question, you can ask it by clicking Ask Question. You can also add a bounty to draw more attention to this question once you have enough reputation. – Brad Nesom Aug 06 '15 at 15:03

1 Answers1

2

Both Keytree and FastKML parse KML placemarks into GeoJSON-ish objects that are easy to use with Shapely. Here's an example of using Keytree:

from urllib import urlopen
from xml.etree import ElementTree

import keytree
from shapely.geometry import Point, shape

# Parse the KML doc
doc = urlopen("http://pleiades.stoa.org/places/638753/kml").read()
tree = ElementTree.fromstring(doc)
kmlns = tree.tag.split('}')[0][1:]

# Find all Polygon elements anywhere in the doc
elems = tree.findall(".//{%s}Polygon" % kmlns)

# Here's our point of interest
p = Point(28.722144580890763, 37.707799701548467)

# Filter polygon elements using this lambda (anonymous function)
# keytree.geometry() makes a GeoJSON-like geometry object from an
# element and shape() makes a Shapely object of that.
hits = filter(
    lambda e: shape(keytree.geometry(e)).contains(p),
    elems )

print hits
# Output:  [<Element {http://www.opengis.net/kml/2.2}Polygon at ...>]

Once you've found the elements that contain the point, you can use the xml module's etree API to inspect them further.

sgillies
  • 9,056
  • 1
  • 33
  • 41
  • I was wrestling with this all afternoon today, but then I finally figured out that keytree.geometry() is pulling things in as lon,lat not lat,lon. when I switched my code so that I was encoding points like so: p = Point(lon, lat) then it finally worked for me. Thanks, so much, Sean! – Paul Huff Sep 09 '12 at 02:31