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