1 from pathlib import Path
5 """ Provides functions to create geometries from scenes and data grids.
9 defpath = Path(__file__) / '..' / '..' / '..' / 'scenes' / 'data'
10 self.scene_path = os.environ.get('SCENE_PATH', defpath.resolve())
14 def parse_geometry(self, geom, scene):
15 """ Create a WKT SQL term for the given geometry.
16 The function understands the following formats:
19 Geometry from a scene. If the scene is omitted, use the
28 <P> may either be a coordinate of the form '<x> <y>' or a single
29 number. In the latter case it must refer to a point in
30 a previously defined grid.
32 if geom.find(':') >= 0:
33 return "ST_SetSRID({}, 4326)".format(self.get_scene_geometry(scene, geom))
35 if geom.find(',') < 0:
36 out = "POINT({})".format(self.mk_wkt_point(geom))
37 elif geom.find('(') < 0:
38 out = "LINESTRING({})".format(self.mk_wkt_points(geom))
40 out = "POLYGON(({}))".format(self.mk_wkt_points(geom.strip('() ')))
42 return "ST_SetSRID('{}'::geometry, 4326)".format(out)
44 def mk_wkt_point(self, point):
45 """ Parse a point description.
46 The point may either consist of 'x y' cooordinates or a number
47 that refers to a grid setup.
50 if geom.find(' ') >= 0:
54 pt = self.grid_node(int(geom))
56 assert False, "Scenario error: Point '{}' is not a number".format(geom)
58 assert pt is not None, "Scenario error: Point '{}' not found in grid".format(geom)
59 return "{} {}".format(*pt)
61 def mk_wkt_points(self, geom):
62 """ Parse a list of points.
63 The list must be a comma-separated list of points. Points
64 in coordinate and grid format may be mixed.
66 return ','.join([self.mk_wkt_point(x) for x in geom.split(',')])
68 def get_scene_geometry(self, default_scene, name):
69 """ Load the geometry from a scene.
72 for obj in name.split('+'):
74 if oname.startswith(':'):
75 assert default_scene is not None, "Scenario error: You need to set a scene"
76 defscene = self.load_scene(default_scene)
77 wkt = defscene[oname[1:]]
79 scene, obj = oname.split(':', 2)
80 scene_geoms = self.load_scene(scene)
81 wkt = scene_geoms[obj]
83 geoms.append("'{}'::geometry".format(wkt))
88 return 'ST_LineMerge(ST_Collect(ARRAY[{}]))'.format(','.join(geoms))
90 def load_scene(self, name):
91 """ Load a scene from a file.
93 if name in self.scene_cache:
94 return self.scene_cache[name]
97 with open(Path(self.scene_path) / "{}.wkt".format(name), 'r') as fd:
100 obj, wkt = line.split('|', 2)
101 scene[obj.strip()] = wkt.strip()
102 self.scene_cache[name] = scene
106 def set_grid(self, lines, grid_step):
107 """ Replace the grid with one from the given lines.
115 self.grid[int(pt_id)] = (x, y)
119 def grid_node(self, nodeid):
120 """ Get the coordinates for the given grid node.
122 return self.grid.get(nodeid)