Adds code to merge place polygon and points using:

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);
This commit is contained in:
Brian Quinion 2012-04-01 01:40:50 +01:00
parent 80cf5df1cd
commit 041b3edf89
5 changed files with 148 additions and 2 deletions

View 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 = {

View 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);

View 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;

View 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);

View File

@ -1139,7 +1139,7 @@
}
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,";
@ -1148,6 +1148,7 @@
$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\'';
@ -1158,6 +1159,10 @@
}
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))
{