1 # SPDX-License-Identifier: GPL-2.0-only
3 # This file is part of Nominatim. (https://nominatim.org)
5 # Copyright (C) 2022 by the Nominatim developer community.
6 # For a full list of authors see the git log.
7 from pathlib import Path
10 from steps.geometry_alias import ALIASES
12 class GeometryFactory:
13 """ Provides functions to create geometries from coordinates and data grids.
19 def parse_geometry(self, geom):
20 """ Create a WKT SQL term for the given geometry.
21 The function understands the following formats:
23 country:<country code>
24 Point geoemtry guaranteed to be in the given country
32 <P> may either be a coordinate of the form '<x> <y>' or a single
33 number. In the latter case it must refer to a point in
34 a previously defined grid.
36 if geom.startswith('country:'):
37 ccode = geom[8:].upper()
38 assert ccode in ALIASES, "Geometry error: unknown country " + ccode
39 return "ST_SetSRID('POINT({} {})'::geometry, 4326)".format(*ALIASES[ccode])
41 if geom.find(',') < 0:
42 out = "POINT({})".format(self.mk_wkt_point(geom))
43 elif geom.find('(') < 0:
44 out = "LINESTRING({})".format(self.mk_wkt_points(geom))
46 out = "POLYGON(({}))".format(self.mk_wkt_points(geom.strip('() ')))
48 return "ST_SetSRID('{}'::geometry, 4326)".format(out)
51 def mk_wkt_point(self, point):
52 """ Parse a point description.
53 The point may either consist of 'x y' cooordinates or a number
54 that refers to a grid setup.
57 if geom.find(' ') >= 0:
61 pt = self.grid_node(int(geom))
63 assert False, "Scenario error: Point '{}' is not a number".format(geom)
65 assert pt is not None, "Scenario error: Point '{}' not found in grid".format(geom)
66 return "{} {}".format(*pt)
69 def mk_wkt_points(self, geom):
70 """ Parse a list of points.
71 The list must be a comma-separated list of points. Points
72 in coordinate and grid format may be mixed.
74 return ','.join([self.mk_wkt_point(x) for x in geom.split(',')])
77 def set_grid(self, lines, grid_step, origin=(0.0, 0.0)):
78 """ Replace the grid with one from the given lines.
86 self.grid[int(pt_id)] = (x, y)
91 def grid_node(self, nodeid):
92 """ Get the coordinates for the given grid node.
94 return self.grid.get(nodeid)