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 geometry 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' coordinates 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)