mirror of
https://github.com/osm-search/Nominatim.git
synced 2024-12-23 04:53:09 +03:00
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:
parent
80cf5df1cd
commit
041b3edf89
@ -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 = {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user