]> git.openstreetmap.org Git - nominatim.git/blobdiff - sql/functions/utils.sql
use computed centroid for location_area_large
[nominatim.git] / sql / functions / utils.sql
index 6697ff971953a32972521d825a79016e25681f45..0a49eef52fc16ee1068642e73ac337880e2d1ed1 100644 (file)
@@ -272,21 +272,27 @@ END;
 $$
 LANGUAGE plpgsql;
 
-CREATE OR REPLACE FUNCTION near_feature_rank_distance(rank_search INTEGER)
-  RETURNS FLOAT
+-- Create a bounding box with an extent computed from the radius (in meters)
+-- which in turn is derived from the given search rank.
+CREATE OR REPLACE FUNCTION place_node_fuzzy_area(geom GEOMETRY, rank_search INTEGER)
+  RETURNS GEOMETRY
   AS $$
+DECLARE
+  radius FLOAT := 500;
 BEGIN
   IF rank_search <= 16 THEN -- city
-    RETURN 7500;
+    radius := 15000;
   ELSIF rank_search <= 18 THEN -- town
-    RETURN 4000;
+    radius := 4000;
   ELSIF rank_search <= 19 THEN -- village
-    RETURN 2000;
+    radius := 2000;
   ELSIF rank_search  <= 20 THEN -- hamlet
-    RETURN 1000;
+    radius := 1000;
   END IF;
 
-  RETURN 500;
+  RETURN ST_Envelope(ST_Collect(
+                     ST_Project(geom, radius, 0.785398)::geometry,
+                     ST_Project(geom, radius, 3.9269908)::geometry));
 END;
 $$
 LANGUAGE plpgsql IMMUTABLE;
@@ -295,13 +301,12 @@ LANGUAGE plpgsql IMMUTABLE;
 CREATE OR REPLACE FUNCTION add_location(place_id BIGINT, country_code varchar(2),
                                         partition INTEGER, keywords INTEGER[],
                                         rank_search INTEGER, rank_address INTEGER,
-                                        in_postcode TEXT, geometry GEOMETRY)
+                                        in_postcode TEXT, geometry GEOMETRY,
+                                        centroid GEOMETRY)
   RETURNS BOOLEAN
   AS $$
 DECLARE
   locationid INTEGER;
-  centroid GEOMETRY;
-  radius FLOAT;
   secgeo GEOMETRY;
   postcode TEXT;
 BEGIN
@@ -314,21 +319,13 @@ BEGIN
   END IF;
 
   IF ST_GeometryType(geometry) in ('ST_Polygon','ST_MultiPolygon') THEN
-    centroid := ST_Centroid(geometry);
-
     FOR secgeo IN select split_geometry(geometry) AS geom LOOP
       PERFORM insertLocationAreaLarge(partition, place_id, country_code, keywords, rank_search, rank_address, false, postcode, centroid, secgeo);
     END LOOP;
 
   ELSEIF ST_GeometryType(geometry) = 'ST_Point' THEN
-    radius := near_feature_rank_distance(rank_search);
-    --DEBUG: RAISE WARNING 'adding % radius %', place_id, radius;
-
-    -- Create a bounding box with an extent computed from the radius (in meters).
-    secgeo := ST_Envelope(ST_Collect(
-                            ST_Project(geometry, radius, 0.785398)::geometry,
-                            ST_Project(geometry, radius, 3.9269908)::geometry));
-    PERFORM insertLocationAreaLarge(partition, place_id, country_code, keywords, rank_search, rank_address, true, postcode, geometry, secgeo);
+    secgeo := place_node_fuzzy_area(geometry, rank_search);
+    PERFORM insertLocationAreaLarge(partition, place_id, country_code, keywords, rank_search, rank_address, true, postcode, centroid, secgeo);
 
   END IF;
 
@@ -470,14 +467,20 @@ DECLARE
   rank SMALLINT;
 BEGIN
   UPDATE placex SET indexed_status = 2 WHERE place_id = placeid;
-  SELECT geometry, rank_search FROM placex WHERE place_id = placeid INTO placegeom, rank;
+
+  SELECT geometry, rank_address INTO placegeom, rank
+    FROM placex WHERE place_id = placeid;
+
   IF placegeom IS NOT NULL AND ST_IsValid(placegeom) THEN
-    IF ST_GeometryType(placegeom) in ('ST_Polygon','ST_MultiPolygon') THEN
-      FOR geom IN select split_geometry(placegeom) FROM placex WHERE place_id = placeid LOOP
-        update placex set indexed_status = 2 where (st_covers(geom, placex.geometry) OR ST_Intersects(geom, placex.geometry)) 
-        AND rank_search > rank and indexed_status = 0 and ST_geometrytype(placex.geometry) = 'ST_Point' and (rank_search < 28 or name is not null or (rank >= 16 and address ? 'place'));
-        update placex set indexed_status = 2 where (st_covers(geom, placex.geometry) OR ST_Intersects(geom, placex.geometry)) 
-        AND rank_search > rank and indexed_status = 0 and ST_geometrytype(placex.geometry) != 'ST_Point' and (rank_search < 28 or name is not null or (rank >= 16 and address ? 'place'));
+    IF ST_GeometryType(placegeom) in ('ST_Polygon','ST_MultiPolygon')
+       AND rank > 0
+    THEN
+      FOR geom IN SELECT split_geometry(placegeom) LOOP
+        UPDATE placex SET indexed_status = 2
+         WHERE ST_Intersects(geom, placex.geometry)
+               and indexed_status = 0
+               and ((rank_address = 0 and rank_search > rank) or rank_address > rank)
+               and (rank_search < 28 or name is not null or (rank >= 16 and address ? 'place'));
       END LOOP;
     ELSE
         diameter := update_place_diameter(rank);