diff --git a/settings/address-levels.json b/settings/address-levels.json index f245c227..406b3548 100644 --- a/settings/address-levels.json +++ b/settings/address-levels.json @@ -64,7 +64,15 @@ "peak" : [18, 0], "volcano" : [18, 0], "mountain_range" : [18, 0], - "sea" : [4, 0] + "sea" : [4, 0], + "tree" : 30, + "spring" : 30, + "cave_entrance" : 30, + "geyser" : 30, + "hot_spring" : 30, + "rock" : 30, + "stone" : 30, + "" : [22, 0] }, "waterway" : { "river" : [19, 0], diff --git a/sql/functions/placex_triggers.sql b/sql/functions/placex_triggers.sql index 1e2aac4c..6848140a 100644 --- a/sql/functions/placex_triggers.sql +++ b/sql/functions/placex_triggers.sql @@ -509,6 +509,8 @@ DECLARE addr_street TEXT; addr_place TEXT; + max_rank SMALLINT; + name_vector INTEGER[]; nameaddress_vector INTEGER[]; addr_nameaddress_vector INTEGER[]; @@ -906,14 +908,19 @@ BEGIN --DEBUG: RAISE WARNING 'Country names updated'; END IF; - SELECT * FROM insert_addresslines(NEW.place_id, NEW.partition, - CASE WHEN NEW.rank_address = 0 THEN NEW.rank_search - WHEN NEW.rank_address > 25 THEN 25::smallint - ELSE NEW.rank_address END, + IF NEW.rank_address = 0 THEN + max_rank := geometry_to_rank(NEW.rank_search, NEW.geometry, NEW.country_code); + ELSEIF NEW.rank_address > 25 THEN + max_rank := 25; + ELSE + max_rank = NEW.rank_address; + END IF; + + SELECT * FROM insert_addresslines(NEW.place_id, NEW.partition, max_rank, NEW.address, - CASE WHEN NEW.rank_search >= 26 - AND NEW.rank_search < 30 - THEN NEW.geometry ELSE NEW.centroid END) + CASE WHEN (NEW.rank_address = 0 or + NEW.rank_search between 26 and 29) + THEN NEW.geometry ELSE NEW.centroid END) INTO NEW.parent_place_id, NEW.postcode, nameaddress_vector; --DEBUG: RAISE WARNING 'RETURN insert_addresslines: %, %, %', NEW.parent_place_id, NEW.postcode, nameaddress_vector; diff --git a/sql/functions/ranking.sql b/sql/functions/ranking.sql index 0c8f4c49..a84269fe 100644 --- a/sql/functions/ranking.sql +++ b/sql/functions/ranking.sql @@ -55,6 +55,53 @@ END; $$ LANGUAGE plpgsql IMMUTABLE; +-- Compute a base address rank from the extent of the given geometry. +-- +-- This is all simple guess work. We don't need particularly good estimates +-- here. This just avoids to have very high ranked address parts in features +-- that span very large areas (or vice versa). +CREATE OR REPLACE FUNCTION geometry_to_rank(search_rank SMALLINT, geometry GEOMETRY, country_code TEXT) + RETURNS SMALLINT + AS $$ +DECLARE + area FLOAT; +BEGIN + IF ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon') THEN + area := ST_Area(geometry); + ELSIF ST_GeometryType(geometry) in ('ST_LineString','ST_MultiLineString') THEN + area := (ST_Length(geometry)^2) * 0.1; + ELSE + RETURN search_rank; + END IF; + + -- adjust for the fact that countries come in different sizes + IF country_code IN ('ca', 'au', 'ru') THEN + area := area / 5; + ELSIF country_code IN ('br', 'kz', 'cn', 'us', 'ne', 'gb', 'za', 'sa', 'id', 'eh', 'ml', 'tm') THEN + area := area / 3; + ELSIF country_code IN ('bo', 'ar', 'sd', 'mn', 'in', 'et', 'cd', 'mz', 'ly', 'cl', 'zm') THEN + area := area / 2; + END IF; + + IF area > 1 THEN + RETURN 7; + ELSIF area > 0.1 THEN + RETURN 9; + ELSIF area > 0.01 THEN + RETURN 13; + ELSIF area > 0.001 THEN + RETURN 17; + ELSIF area > 0.0001 THEN + RETURN 19; + ELSIF area > 0.000005 THEN + RETURN 21; + END IF; + + RETURN 23; +END; +$$ +LANGUAGE plpgsql IMMUTABLE; + -- Guess a ranking for postcodes from country and postcode format. CREATE OR REPLACE FUNCTION get_postcode_rank(country_code VARCHAR(2), postcode TEXT, diff --git a/test/bdd/db/import/placex.feature b/test/bdd/db/import/placex.feature index 1a62638d..a9e81c44 100644 --- a/test/bdd/db/import/placex.feature +++ b/test/bdd/db/import/placex.feature @@ -216,13 +216,13 @@ Feature: Import into placex | object | rank_search | rank_address | | N2 | 18 | 0 | | N4 | 18 | 0 | - | N5 | 30 | 30 | + | N5 | 22 | 0 | | W2 | 18 | 0 | | R3 | 18 | 0 | - | R4 | 30 | 30 | + | R4 | 22 | 0 | | R5 | 4 | 0 | | R6 | 4 | 0 | - | W3 | 30 | 30 | + | W3 | 22 | 0 | Scenario: boundary ways for countries and states are ignored Given the named places diff --git a/test/bdd/db/update/simple.feature b/test/bdd/db/update/simple.feature index 0ae0ac4a..ccaacad0 100644 --- a/test/bdd/db/update/simple.feature +++ b/test/bdd/db/update/simple.feature @@ -35,7 +35,7 @@ Feature: Update of simple objects When importing Then placex contains | object | rank_address | - | R1 | 30 | + | R1 | 0 | | R2 | 26 | | W1 | 30 | When marking for delete R1,R2,W1