Skip to content

Commit

Permalink
for roads add all intersecting boundaries to address list
Browse files Browse the repository at this point in the history
When roads cross boundaries, both administrative entities should
be added to the address list, so that both entities can be used
for searching. Also allows in a second step to better sort out
addresses of POIs on such roads.

Fixes osm-search#121.
  • Loading branch information
lonvia committed Mar 18, 2017
1 parent ecee382 commit b3186d0
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 7 deletions.
7 changes: 6 additions & 1 deletion sql/functions.sql
Expand Up @@ -1679,7 +1679,12 @@ BEGIN
-- added ourself as address already
address_havelevel[NEW.rank_address] := true;
-- RAISE WARNING ' getNearFeatures(%,''%'',%,''%'')',NEW.partition, place_centroid, search_maxrank, isin_tokens;
FOR location IN SELECT * from getNearFeatures(NEW.partition, place_centroid, search_maxrank, isin_tokens) LOOP
FOR location IN
SELECT * from getNearFeatures(NEW.partition,
CASE WHEN NEW.rank_search >= 26 THEN NEW.geometry
ELSE place_centroid END,
search_maxrank, isin_tokens)
LOOP

--RAISE WARNING ' AREA: %',location;

Expand Down
10 changes: 5 additions & 5 deletions sql/partition-functions.src.sql
@@ -1,19 +1,19 @@
create or replace function getNearFeatures(in_partition INTEGER, point GEOMETRY, maxrank INTEGER, isin_tokens INT[]) RETURNS setof nearfeaturecentr AS $$
create or replace function getNearFeatures(in_partition INTEGER, feature GEOMETRY, maxrank INTEGER, isin_tokens INT[]) RETURNS setof nearfeaturecentr AS $$
DECLARE
r nearfeaturecentr%rowtype;
BEGIN

-- start
IF in_partition = -partition- THEN
FOR r IN
SELECT place_id, keywords, rank_address, rank_search, min(ST_Distance(point, centroid)) as distance, isguess, centroid FROM (
SELECT * FROM location_area_large_-partition- WHERE ST_Contains(geometry, point) and rank_search < maxrank
SELECT place_id, keywords, rank_address, rank_search, min(ST_Distance(feature, centroid)) as distance, isguess, centroid FROM (
SELECT * FROM location_area_large_-partition- WHERE ST_Intersects(geometry, feature) and rank_search < maxrank
UNION ALL
SELECT * FROM location_area_country WHERE ST_Contains(geometry, point) and rank_search < maxrank
SELECT * FROM location_area_country WHERE ST_Intersects(geometry, feature) and rank_search < maxrank
) as location_area
GROUP BY place_id, keywords, rank_address, rank_search, isguess, centroid
ORDER BY rank_address, isin_tokens && keywords desc, isguess asc,
ST_Distance(point, centroid) *
ST_Distance(feature, centroid) *
CASE
WHEN rank_address = 16 AND rank_search = 15 THEN 0.2 -- capital city
WHEN rank_address = 16 AND rank_search = 16 THEN 0.25 -- city
Expand Down
22 changes: 22 additions & 0 deletions test/bdd/db/import/addressing.feature
@@ -0,0 +1,22 @@
@DB
Feature: Address computation
Tests for filling of place_addressline

# github #121
Scenario: Roads crossing boundaries should contain both states
Given the grid
| 1 | | | 2 | | 3 |
| | 7 | | 8 | | |
| 4 | | | 5 | | 6 |
And the named places
| osm | class | type | geometry |
| W1 | highway | road | 7, 8 |
And the named places
| osm | class | type | admin | geometry |
| W10 | boundary | administrative | 5 | (1, 2, 5, 4, 1) |
| W11 | boundary | administrative | 5 | (2, 3, 6, 5, 2) |
When importing
Then place_addressline contains
| object | address | cached_rank_address |
| W1 | W10 | 10 |
| W1 | W11 | 10 |
31 changes: 30 additions & 1 deletion test/bdd/steps/db_ops.py
Expand Up @@ -93,6 +93,12 @@ def __init__(self, oid):
self.oid = m.group('id')
self.cls = m.group('cls')

def __str__(self):
if self.cls is None:
return self.typ + self.oid

return '%s%d:%s' % (self.typ, self.oid, self.cls)

def table_select(self):
""" Return where clause and parameter list to select the object
from a Nominatim table.
Expand All @@ -109,7 +115,9 @@ def table_select(self):
def get_place_id(self, cur):
where, params = self.table_select()
cur.execute("SELECT place_id FROM placex WHERE %s" % where, params)
eq_(1, cur.rowcount, "Expected exactly 1 entry in placex found %s" % cur.rowcount)
eq_(1, cur.rowcount,
"Expected exactly 1 entry in placex for %s found %s"
% (str(self), cur.rowcount))

return cur.fetchone()[0]

Expand Down Expand Up @@ -386,6 +394,27 @@ def check_search_name_contents(context):

context.db.commit()

@then("place_addressline contains")
def check_place_addressline(context):
cur = context.db.cursor(cursor_factory=psycopg2.extras.DictCursor)

for row in context.table:
pid = NominatimID(row['object']).get_place_id(cur)
apid = NominatimID(row['address']).get_place_id(cur)
cur.execute(""" SELECT * FROM place_addressline
WHERE place_id = %s AND address_place_id = %s""",
(pid, apid))
assert_less(0, cur.rowcount,
"No rows found for place %s and address %s"
% (row['object'], row['address']))

for res in cur:
for h in row.headings:
if h not in ('address', 'object'):
assert_db_column(res, h, row[h], context)

context.db.commit()

@then("(?P<oid>\w+) expands to(?P<neg> no)? interpolation")
def check_location_property_osmline(context, oid, neg):
cur = context.db.cursor(cursor_factory=psycopg2.extras.DictCursor)
Expand Down

0 comments on commit b3186d0

Please sign in to comment.