5 Basic usage is checking whether a point is inside an area.
6 Supports GoogleEarth KML coordinates.
7 FIXME: It should works using polar coordinated, but now works in 2D.
10 from __future__ import division
12 __all__ = [ 'Area', 'load_area_from_kml_polygon', 'list_areas' ]
17 AREA_DIR = u'/var/lib/ais/areas/'
21 That class defines an area (on the Earth)
22 It provides testing whether a point is inside or not
24 def __init__(self, points=()):
29 def addpoint(self, point):
33 self.points.append(point)
34 # min/max doesn't work around the change date line...
35 #if len(self.points)==1:
39 #if point[0] < self.min[0]:
40 # self.min = (point[0], self.min[1])
41 #elif point[0] > self.max[0]:
42 # self.max = (point[0], self.max[1])
43 #if point[1] < self.min[1]:
44 # self.min = (self.min[0], point[1])
45 #elif point[1] > self.max[1]:
46 # self.max = (self.max[0], point[1])
51 From clockwise to counter-clockwise
52 Or from counter-clockwise to clockwise
58 Area library self-test:
59 We only support counter-clockwise and convex areas.
61 for point in self.points:
62 if not self.contains(point):
66 def contains(self, point):
68 Tests whether a point is in self.
72 # first test the bounding box
73 #if point[0] < self.min[0] \
74 # or point[0] > self.max[0] \
75 # or point[1] < self.min[1] \
76 # or point[1] > self.max[1] :
78 for i in range(len(self.points)):
81 p2 = self.points[(i+1)%len(self.points)]
91 def load_area_from_kml_polygon(filename, reverse=False):
93 Loads a kml file into an Area structure.
94 The kml must contains exacly one set of <coordinates>.
95 The first and last points must be the same.
96 It must also be counter-clockwise and convex.
97 Actually, it may be clockwise, but then you need reverse=True.
99 kml = open(filename).read()
100 coordinates_lines = re.findall('<coordinates>(.*)</coordinates>', kml, re.IGNORECASE|re.DOTALL)
101 assert len(coordinates_lines) == 1, \
102 'There should be exactly one set of <coordinates> %s' % filename
103 coordinates = coordinates_lines[0].replace('\n', ' ').replace('\r', ' ').replace('\t', ' ')
104 coordinates = [ xyz for xyz in coordinates.split(' ') if xyz ]
105 assert coordinates[0] == coordinates[-1], \
106 'First and last coordinates of %s should be the same: %s, %s' % \
107 (filename, coordinates[0], coordinates[-1])
108 assert len(coordinates)>3, 'polygon should have 3 edges minimum'
111 for xyz in coordinates[:-1]:
112 x, y, z = xyz.split(',')
113 area.addpoint((float(y), float(x)))
116 assert area.check(), 'Polygon should be counter-clockwise and convex.'
122 return a list of areas as tupples:
123 [(nicename, fullpath), ...]
126 for filename in os.listdir(AREA_DIR):
127 if not filename.endswith(u'.kml'):
128 continue # ignore non-kml files
129 results.append((filename[:-4], AREA_DIR+filename))
132 if __name__ == '__main__':
134 pelagos = load_area_from_kml_polygon('/var/lib/ais/areas/pelagos.kml')
135 # counter clock-wise : Positive
138 # (45.3612930132714, 10.01843703552244),
150 if pelagos.contains(p):