Better parsing of kml <coordinates> that now can span on several lines.
authorJean-Michel Nirgal Vourgère <jmv@nirgal.com>
Sun, 17 Apr 2011 08:06:27 +0000 (08:06 +0000)
committerJean-Michel Nirgal Vourgère <jmv@nirgal.com>
Sun, 17 Apr 2011 08:06:27 +0000 (08:06 +0000)
bin/area.py

index 97ba9009f21fbf8791793c03a2301256a53e0649..b0d8fbaf8cc8a0b0c43c613b7e577242edc56934 100644 (file)
@@ -3,7 +3,7 @@
 """
 Library for areas.
 Basic usage is checking whether a point is inside an area.
-Supports GoogleEarth KML polylines.
+Supports GoogleEarth KML coordinates.
 FIXME: It should works using polar coordinated, but now works in 2D.
 """
 
@@ -11,6 +11,8 @@ from __future__ import division
 
 __all__ = [ 'Area', 'load_area_from_kml_polygon' ]
 
+import re
+
 class Area:
     """
     That class defines an area (on the Earth)
@@ -86,19 +88,16 @@ class Area:
 def load_area_from_kml_polygon(filename, reverse=False):
     """
     Loads a kml file into an Area structure.
-    The kml must contains exacly 1 polyline structure.
+    The kml must contains exacly one set of <coordinates>.
     The first and last points must be the same.
     It must also be counter-clockwise and convex.
     Actually, it may be clockwise, but then you need reverse=True.
-
-    FIXME: This makes a lot of assumption about the way GoogleEarth output the
-    XML file.
     """
-    kmlfile = open(filename)
-    coordinates_lines = [ line for line in kmlfile.readlines() if '</coordinates>' in line ]
+    kml = open(filename).read()
+    coordinates_lines = re.findall('<coordinates>(.*)</coordinates>', kml, re.IGNORECASE|re.DOTALL)
     assert len(coordinates_lines) == 1, \
-        'There should be exactly one line with coordinates in %s' % filename
-    coordinates = coordinates_lines[0].replace('</coordinates>', '').replace('\n', '').replace('\r', '').replace('\t', '')
+        'There should be exactly one set of <coordinates> %s' % filename
+    coordinates = coordinates_lines[0].replace('\n', ' ').replace('\r', ' ').replace('\t', ' ')
     coordinates = [ xyz for xyz in coordinates.split(' ') if xyz ]
     assert coordinates[0] == coordinates[-1], \
         'First and last coordinates of %s should be the same: %s, %s' % \
@@ -106,7 +105,7 @@ def load_area_from_kml_polygon(filename, reverse=False):
     assert len(coordinates)>3, 'polygon should have 3 edges minimum'
     
     area = Area()
-    for xyz in coordinates[0:-1]:
+    for xyz in coordinates[:-1]:
         x, y, z = xyz.split(',')
         area.addpoint((float(y), float(x)))
     if reverse:
@@ -114,26 +113,25 @@ def load_area_from_kml_polygon(filename, reverse=False):
     assert area.check(), 'Polygon should be counter-clockwise and convex.'
     return area
 
-
-#if __name__ == '__main__':
-# counter clock-wise : Positive
-#pelagos = Area([
-#    (42.91, 12.5),
-#    (45.3612930132714, 10.01843703552244),
-#    (43.6,5.5),
-#    (40.57,8.6)
-#    ])
-#for p in [
-#    (42,9),
-#    (41,5),
-#    (40,12),
-#    (45,13),
-#    (45,7),
-#    ]:
-#    print "testing", p
-#    if pelagos.contains(p):
-#        print "inside"
-#    else:
-#        print"outside"
-
+if __name__ == '__main__':
+    # counter clock-wise : Positive
+    pelagos = load_area_from_kml_polygon_2('/var/lib/ais/areas/pelagos.kml')
+    #pelagos = Area([
+    #    (42.91, 12.5),
+    #    (45.3612930132714, 10.01843703552244),
+    #    (43.6,5.5),
+    #    (40.57,8.6)
+    #    ])
+    for p in [
+        (42,9),
+        (41,5),
+        (40,12),
+        (45,13),
+        (45,7),
+        ]:
+        print "testing", p
+        if pelagos.contains(p):
+            print "inside"
+        else:
+            print"outside"