]> git.openstreetmap.org Git - nominatim.git/commitdiff
Adds code to merge place polygon and points using:
authorBrian Quinion <openstreetmap@brian.quinion.co.uk>
Sun, 1 Apr 2012 00:40:50 +0000 (01:40 +0100)
committerBrian Quinion <openstreetmap@brian.quinion.co.uk>
Sun, 1 Apr 2012 00:40:50 +0000 (01:40 +0100)
  label relation member
  admin_center, admin_centre relation member (with same name)
  exact name, search_rank and location match

Adding this requires a new column and index:
  SELECT AddGeometryColumn('placex', 'centroid', 4326, 'GEOMETRY', 2);
  CREATE INDEX idx_placex_linked_place_id ON placex USING BTREE (linked_place_id);

lib/template/search-html.php
settings/settings.php
sql/functions.sql
sql/tables.sql
website/search.php

index 09b7021f314458b9774213c5017555997175ef48..f66ee705fcf1b2baa584fbbc29cd22eb349341d6 100644 (file)
@@ -208,7 +208,7 @@ form{
                        map.panTo(lonLat, <?php echo $iZoom ?>);
                }
 
-               function panToLatLonZoom(lat,lon, zoom) {
+               function panToLatLonZoom(lat, lon, zoom) {
                        var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
                        if (zoom != map.getZoom())
                                map.setCenter(lonLat, zoom);
@@ -220,6 +220,8 @@ form{
                        var proj_EPSG4326 = new OpenLayers.Projection("EPSG:4326");
                        var proj_map = map.getProjectionObject();
                         map.zoomToExtent(new OpenLayers.Bounds(minlon,minlat,maxlon,maxlat).transform(proj_EPSG4326, proj_map));
+                       var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
+                       map.panTo(lonLat, <?php echo $iZoom ?>);
 
                         var pointList = [];
                         var style = {
index 66d7bed625e8b8fc61913d9ccc96c4bb0d88448d..30739f433a4163d01960b6f567ef031ca6614824 100644 (file)
@@ -27,6 +27,7 @@
        @define('CONST_Default_Zoom', 2);
 
        @define('CONST_Search_AreaPolygons_Enabled', true);
+       @define('CONST_Search_AreaPolygons', true);
 
        @define('CONST_Suggestions_Enabled', false);
 
index 7e9f957b8e750dcd858e7e4be347105675844687..1baecfc0096f6bea7d1ab52417e7fc7939039040 100644 (file)
@@ -1189,6 +1189,9 @@ DECLARE
   location RECORD;
   way RECORD;
   relation RECORD;
+  relation_members TEXT[];
+  relMember RECORD;
+  linkedplacex RECORD;
   search_diameter FLOAT;
   search_prevdiameter FLOAT;
   search_maxrank INTEGER;
@@ -1240,6 +1243,7 @@ BEGIN
       DELETE FROM place_boundingbox where place_id = NEW.place_id;
       result := deleteRoad(NEW.partition, NEW.place_id);
       result := deleteLocationArea(NEW.partition, NEW.place_id);
+      UPDATE placex set linked_place_id = null where linked_place_id = NEW.place_id;
     END IF;
 
     -- reclaculate country and partition (should probably have a country_code and calculated_country_code as seperate fields)
@@ -1257,6 +1261,7 @@ BEGIN
     -- Speed up searches - just use the centroid of the feature
     -- cheaper but less acurate
     place_centroid := ST_Centroid(NEW.geometry);
+    NEW.centroid := null;
 
     -- Thought this wasn't needed but when we add new languages to the country_name table
     -- we need to update the existing names
@@ -1452,6 +1457,93 @@ BEGIN
 
 -- RAISE WARNING '  INDEXING: %',NEW;
 
+    IF NEW.osm_type = 'R' AND NEW.rank_search < 26 THEN
+
+      -- see if we have any special relation members
+      select members from planet_osm_rels where id = NEW.osm_id INTO relation_members;
+
+      FOR relMember IN select get_osm_rel_members(relation_members,ARRAY['label']) as member LOOP
+
+        select * from placex where osm_type = upper(substring(relMember.member,1,1)) 
+          and osm_id = substring(relMember.member,2,10000)::integer order by rank_search desc limit 1 into linkedPlacex;
+
+        -- If we don't already have one use this as the centre point of the geometry
+        IF NEW.centroid IS NULL THEN
+          NEW.centroid := coalesce(linkedPlacex.centroid,st_centroid(linkedPlacex.geometry));
+        END IF;
+
+        -- merge in the label name, re-init word vector
+        NEW.name := linkedPlacex.name || NEW.name;
+        name_vector := make_keywords(NEW.name);
+
+        -- merge in extra tags
+        NEW.extratags := linkedPlacex.extratags || NEW.extratags;
+
+        -- mark the linked place (excludes from search results)
+        UPDATE placex set linked_place_id = NEW.place_id where place_id = linkedPlacex.place_id;
+        DELETE from search_name where place_id = linkedPlacex.place_id;
+
+      END LOOP;
+
+      FOR relMember IN select get_osm_rel_members(relation_members,ARRAY['admin_center','admin_centre']) as member LOOP
+
+        select * from placex where osm_type = upper(substring(relMember.member,1,1)) 
+          and osm_id = substring(relMember.member,2,10000)::integer order by rank_search desc limit 1 into linkedPlacex;
+
+        IF NEW.name->'name' = linkedPlacex.name->'name' THEN
+          -- If we don't already have one use this as the centre point of the geometry
+          IF NEW.centroid IS NULL THEN
+            NEW.centroid := coalesce(linkedPlacex.centroid,st_centroid(linkedPlacex.geometry));
+          END IF;
+
+          -- merge in the name, re-init word vector
+          NEW.name := linkedPlacex.name || NEW.name;
+          name_vector := make_keywords(NEW.name);
+
+          -- merge in extra tags
+          NEW.extratags := linkedPlacex.extratags || NEW.extratags;
+
+          -- mark the linked place (excludes from search results)
+          UPDATE placex set linked_place_id = NEW.place_id where place_id = linkedPlacex.place_id;
+          DELETE from search_name where place_id = linkedPlacex.place_id;
+        END IF;
+
+      END LOOP;
+
+      -- not found one yet? how about doing a name search
+      IF NEW.centroid IS NULL THEN
+        FOR linkedPlacex IN select placex.* from search_name join placex using (place_id) WHERE
+          search_name.name_vector @> ARRAY[getorcreate_name_id(make_standard_name(NEW.name->'name'))] 
+          AND search_name.search_rank = NEW.rank_search
+          AND search_name.place_id != NEW.place_id
+          AND osm_type = 'N'
+          AND NEW.name->'name' = placex.name->'name'
+          AND st_contains(NEW.geometry, placex.geometry)
+        LOOP
+          -- If we don't already have one use this as the centre point of the geometry
+          IF NEW.centroid IS NULL THEN
+            NEW.centroid := coalesce(linkedPlacex.centroid,st_centroid(linkedPlacex.geometry));
+          END IF;
+
+          -- merge in the name, re-init word vector
+          NEW.name := linkedPlacex.name || NEW.name;
+          name_vector := make_keywords(NEW.name);
+
+          -- merge in extra tags
+          NEW.extratags := linkedPlacex.extratags || NEW.extratags;
+
+          -- mark the linked place (excludes from search results)
+          UPDATE placex set linked_place_id = NEW.place_id where place_id = linkedPlacex.place_id;
+          DELETE from search_name where place_id = linkedPlacex.place_id;
+        END LOOP;
+      END IF;
+
+      IF NEW.centroid IS NOT NULL THEN
+        place_centroid := NEW.centroid
+      END IF;
+
+    END IF;
+
     NEW.parent_place_id = 0;
     parent_place_id_rank = 0;
 
@@ -1576,6 +1668,11 @@ BEGIN
 --      INSERT INTO search_name values (NEW.place_id, NEW.rank_search, NEW.rank_search, 0, NEW.country_code, name_vector, nameaddress_vector, place_centroid);
     END IF;
 
+    -- If we've not managed to pick up a better one - default centroid
+    IF NEW.centroid IS NULL THEN
+      NEW.centroid := place_centroid;
+    END IF;
+
   END IF;
 
   RETURN NEW;
@@ -1590,6 +1687,9 @@ DECLARE
   classtable TEXT;
 BEGIN
 
+  update placex set linked_place_id = null where linked_place_id = OLD.place_id;
+  update placex set indexed_status = 2 where linked_place_id = OLD.place_id and indexed_status = 0;
+
   IF OLD.rank_address < 30 THEN
 
     -- mark everything linked to this place for re-indexing
@@ -2545,3 +2645,40 @@ BEGIN
 END;
 $$
 LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION get_osm_rel_members(members TEXT[], member TEXT) RETURNS TEXT[]
+  AS $$
+DECLARE
+  result TEXT[];
+  i INTEGER;
+BEGIN
+
+  FOR i IN 1..ARRAY_UPPER(members,1) BY 2 LOOP
+    IF members[i+1] = member THEN
+      result := result || members[i];
+    END IF;
+  END LOOP;
+
+  return result;
+END;
+$$
+LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION get_osm_rel_members(members TEXT[], memberLabels TEXT[]) RETURNS SETOF TEXT
+  AS $$
+DECLARE
+  i INTEGER;
+BEGIN
+
+  FOR i IN 1..ARRAY_UPPER(members,1) BY 2 LOOP
+    IF members[i+1] = ANY(memberLabels) THEN
+      RETURN NEXT members[i];
+    END IF;
+  END LOOP;
+
+  RETURN;
+END;
+$$
+LANGUAGE plpgsql;
+
+
index 795b927747a99b9ef04418dd48bdd33c0321f2a5..a3e50953dcd1be607a84c4dcdcf246d863826e5c 100644 (file)
@@ -215,6 +215,7 @@ SELECT AddGeometryColumn('placex', 'geometry', 4326, 'GEOMETRY', 2);
 SELECT AddGeometryColumn('placex', 'centroid', 4326, 'GEOMETRY', 2);
 CREATE UNIQUE INDEX idx_place_id ON placex USING BTREE (place_id);
 CREATE INDEX idx_placex_osmid ON placex USING BTREE (osm_type, osm_id);
+CREATE INDEX idx_placex_linked_place_id ON placex USING BTREE (linked_place_id);
 CREATE INDEX idx_placex_rank_search ON placex USING BTREE (rank_search, geometry_sector);
 CREATE INDEX idx_placex_geometry ON placex USING GIST (geometry);
 
index ae2c39635eed0b1d188ef1c29aeb61db07872e92..c00c4cfd3ac33389306ea0723830b4f420757f16 100755 (executable)
        }
        foreach($aSearchResults as $iResNum => $aResult)
        {
-               if (CONST_Search_AreaPolygons || true)
+               if (CONST_Search_AreaPolygons)
                {
                        // Get the bounding box and outline polygon
                        $sSQL = "select place_id,numfeatures,area,outline,";
                        $sSQL .= "ST_AsText(outline) as outlinestring from get_place_boundingbox_quick(".$aResult['place_id'].")";
 
                        $sSQL = "select place_id,0 as numfeatures,st_area(geometry) as area,";
+                       $sSQL .= "ST_Y(centroid) as centrelat,ST_X(centroid) as centrelon,";
                        $sSQL .= "ST_Y(ST_PointN(ExteriorRing(ST_Box2D(geometry)),4)) as minlat,ST_Y(ST_PointN(ExteriorRing(ST_Box2D(geometry)),2)) as maxlat,";
                        $sSQL .= "ST_X(ST_PointN(ExteriorRing(ST_Box2D(geometry)),1)) as minlon,ST_X(ST_PointN(ExteriorRing(ST_Box2D(geometry)),3)) as maxlon,";
                        $sSQL .= "ST_AsText(geometry) as outlinestring from placex where place_id = ".$aResult['place_id'].' and st_geometrytype(ST_Box2D(geometry)) = \'ST_Polygon\'';
                        }
                        if ($aPointPolygon['place_id'])
                        {
+                               if ($aPointPolygon['centrelon'] !== null && $aPointPolygon['centrelat'] !== null ) {
+                                       $aResult['lat'] = $aPointPolygon['centrelat'];
+                                       $aResult['lon'] = $aPointPolygon['centrelon'];
+                               }
                                // Translate geometary string to point array
                                if (preg_match('#POLYGON\\(\\(([- 0-9.,]+)#',$aPointPolygon['outlinestring'],$aMatch))
                                {