Skip to content

Commit

Permalink
Merge pull request #3608 from lonvia/reverse-fallback-country
Browse files Browse the repository at this point in the history
Fall back to using the OSM grid country table when no countries are found in the OSM data
  • Loading branch information
lonvia authored Dec 12, 2024
2 parents 494640c + 416e70b commit 0862671
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 8 deletions.
36 changes: 31 additions & 5 deletions src/nominatim_api/reverse.py
Original file line number Diff line number Diff line change
Expand Up @@ -478,14 +478,15 @@ async def lookup_country_codes(self) -> List[str]:
log().var_dump('Country codes', ccodes)
return ccodes

async def lookup_country(self, ccodes: List[str]) -> Optional[SaRow]:
async def lookup_country(self, ccodes: List[str]) -> Tuple[Optional[SaRow], RowFunc]:
""" Lookup the country for the current search.
"""
row_func = nres.create_from_placex_row
if not ccodes:
ccodes = await self.lookup_country_codes()

if not ccodes:
return None
return None, row_func

t = self.conn.t.placex
if self.max_rank > 4:
Expand Down Expand Up @@ -537,7 +538,32 @@ def _country_base_query() -> SaSelect:

address_row = (await self.conn.execute(sql, self.bind_params)).one_or_none()

return address_row
if address_row is None:
# finally fall back to country table
t = self.conn.t.country_name
tgrid = self.conn.t.country_grid

sql = sa.select(tgrid.c.country_code,
tgrid.c.geometry.ST_Centroid().ST_Collect().ST_Centroid()
.label('centroid'),
tgrid.c.geometry.ST_Collect().ST_Expand(0).label('bbox'))\
.where(tgrid.c.country_code.in_(ccodes))\
.group_by(tgrid.c.country_code)

sub = sql.subquery('grid')
sql = sa.select(t.c.country_code,
t.c.name.merge(t.c.derived_name).label('name'),
sub.c.centroid, sub.c.bbox)\
.join(sub, t.c.country_code == sub.c.country_code)\
.order_by(t.c.country_code)\
.limit(1)

sql = self._add_geometry_columns(sql, sub.c.centroid)

address_row = (await self.conn.execute(sql, self.bind_params)).one_or_none()
row_func = nres.create_from_country_row

return address_row, row_func

async def lookup(self, coord: AnyPoint) -> Optional[nres.ReverseResult]:
""" Look up a single coordinate. Returns the place information,
Expand Down Expand Up @@ -566,12 +592,12 @@ async def lookup(self, coord: AnyPoint) -> Optional[nres.ReverseResult]:
if self.max_rank > 4:
row = await self.lookup_area()
if row is None and self.layer_enabled(DataLayer.ADDRESS):
row = await self.lookup_country(ccodes)
row, row_func = await self.lookup_country(ccodes)

result = row_func(row, nres.ReverseResult)
if result is not None:
assert row is not None
result.distance = row.distance
result.distance = getattr(row, 'distance', 0)
if hasattr(row, 'bbox'):
result.bbox = Bbox.from_wkb(row.bbox)
await nres.add_result_details(self.conn, [result], self.params)
Expand Down
10 changes: 7 additions & 3 deletions test/bdd/api/reverse/queries.feature
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@ Feature: Reverse geocoding
Examples:
| lat | lon |
| 0.0 | 0.0 |
| -34.830 | -56.105 |
| 45.174 | -103.072 |
| 21.156 | -12.2744 |
| 91.3 | 0.4 |
| -700 | 0.4 |
| 0.2 | 324.44 |
| 0.2 | -180.4 |


Scenario: Unknown countries fall back to default country grid
When sending v1/reverse at 45.174,-103.072
Then results contain
| category | type | display_name |
| place | country | United States |


@Tiger
Scenario: TIGER house number
When sending v1/reverse at 32.4752389363,-86.4810198619
Expand Down

0 comments on commit 0862671

Please sign in to comment.