Skip to content

Commit

Permalink
Merge pull request #3554 from lonvia/postcode-bbox
Browse files Browse the repository at this point in the history
Improve bounding boxes for postcodes
  • Loading branch information
lonvia authored Sep 30, 2024
2 parents b2dc01a + 5160a1d commit 6299afc
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 16 deletions.
2 changes: 2 additions & 0 deletions src/nominatim_api/search/db_searches.py
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,8 @@ async def lookup(self, conn: SearchConnection,

for prow in await conn.execute(placex_sql, _details_to_bind_params(details)):
result = nres.create_from_placex_row(prow, nres.SearchResult)
if result is not None:
result.bbox = Bbox.from_wkb(prow.bbox)
break
else:
result = nres.create_from_postcode_row(row, nres.SearchResult)
Expand Down
5 changes: 5 additions & 0 deletions src/nominatim_api/v1/classtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ def bbox_from_result(result: Union[ReverseResult, SearchResult]) -> Bbox:
around the centroid according to dimensions derived from the
search rank.
"""
if result.category == ('place', 'postcode') and result.bbox is None:
return Bbox.from_point(result.centroid,
0.05 - 0.012 * (result.rank_search - 21))

if (result.osm_object and result.osm_object[0] == 'N') or result.bbox is None:

extent = NODE_EXTENT.get(result.category, 0.00005)
return Bbox.from_point(result.centroid, extent)

Expand Down
38 changes: 22 additions & 16 deletions src/nominatim_db/clicmd/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import logging
import json
import sys
import pprint
from functools import reduce

import nominatim_api as napi
Expand Down Expand Up @@ -113,24 +114,29 @@ def _list_formats(formatter: napi.FormatDispatcher, rtype: Type[Any]) -> int:
for fmt in formatter.list_formats(rtype):
print(fmt)
print('debug')
print('raw')

return 0


def _print_output(formatter: napi.FormatDispatcher, result: Any,
fmt: str, options: Mapping[str, Any]) -> None:
output = formatter.format_result(result, fmt, options)
if formatter.get_content_type(fmt) == CONTENT_JSON:
# reformat the result, so it is pretty-printed
try:
json.dump(json.loads(output), sys.stdout, indent=4, ensure_ascii=False)
except json.decoder.JSONDecodeError as err:
# Catch the error here, so that data can be debugged,
# when people are developping custom result formatters.
LOG.fatal("Parsing json failed: %s\nUnformatted output:\n%s", err, output)

if fmt == 'raw':
pprint.pprint(result)
else:
sys.stdout.write(output)
sys.stdout.write('\n')
output = formatter.format_result(result, fmt, options)
if formatter.get_content_type(fmt) == CONTENT_JSON:
# reformat the result, so it is pretty-printed
try:
json.dump(json.loads(output), sys.stdout, indent=4, ensure_ascii=False)
except json.decoder.JSONDecodeError as err:
# Catch the error here, so that data can be debugged,
# when people are developping custom result formatters.
LOG.fatal("Parsing json failed: %s\nUnformatted output:\n%s", err, output)
else:
sys.stdout.write(output)
sys.stdout.write('\n')


class APISearch:
Expand Down Expand Up @@ -174,7 +180,7 @@ def run(self, args: NominatimArgs) -> int:
if args.list_formats:
return _list_formats(formatter, napi.SearchResults)

if args.format == 'debug':
if args.format in ('debug', 'raw'):
loglib.set_log_output('text')
elif not formatter.supports_format(napi.SearchResults, args.format):
raise UsageError(f"Unsupported format '{args.format}'. "
Expand Down Expand Up @@ -254,7 +260,7 @@ def run(self, args: NominatimArgs) -> int:
if args.list_formats:
return _list_formats(formatter, napi.ReverseResults)

if args.format == 'debug':
if args.format in ('debug', 'raw'):
loglib.set_log_output('text')
elif not formatter.supports_format(napi.ReverseResults, args.format):
raise UsageError(f"Unsupported format '{args.format}'. "
Expand Down Expand Up @@ -320,7 +326,7 @@ def run(self, args: NominatimArgs) -> int:
if args.list_formats:
return _list_formats(formatter, napi.ReverseResults)

if args.format == 'debug':
if args.format in ('debug', 'raw'):
loglib.set_log_output('text')
elif not formatter.supports_format(napi.ReverseResults, args.format):
raise UsageError(f"Unsupported format '{args.format}'. "
Expand Down Expand Up @@ -402,7 +408,7 @@ def run(self, args: NominatimArgs) -> int:
if args.list_formats:
return _list_formats(formatter, napi.DetailedResult)

if args.format == 'debug':
if args.format in ('debug', 'raw'):
loglib.set_log_output('text')
elif not formatter.supports_format(napi.DetailedResult, args.format):
raise UsageError(f"Unsupported format '{args.format}'. "
Expand Down Expand Up @@ -473,7 +479,7 @@ def run(self, args: NominatimArgs) -> int:
if args.list_formats:
return _list_formats(formatter, napi.StatusResult)

if args.format == 'debug':
if args.format in ('debug', 'raw'):
loglib.set_log_output('text')
elif not formatter.supports_format(napi.StatusResult, args.format):
raise UsageError(f"Unsupported format '{args.format}'. "
Expand Down
13 changes: 13 additions & 0 deletions test/python/api/search/test_search_postcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,19 @@ def test_postcode_with_country(apiobj, frontend):
assert results[0].place_id == 101


def test_postcode_area(apiobj, frontend):
apiobj.add_postcode(place_id=100, country_code='ch', postcode='12345')
apiobj.add_placex(place_id=200, country_code='ch', postcode='12345',
osm_type='R', osm_id=34, class_='boundary', type='postal_code',
geometry='POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))')

results = run_search(apiobj, frontend, 0.3, ['12345'], [0.0])

assert len(results) == 1
assert results[0].place_id == 200
assert results[0].bbox.area == 1


class TestPostcodeSearchWithAddress:

@pytest.fixture(autouse=True)
Expand Down

0 comments on commit 6299afc

Please sign in to comment.