Merge branch 'interpolations'

This commit is contained in:
Sarah Hoffmann
2016-06-04 23:29:11 +02:00
27 changed files with 2030 additions and 1593 deletions

View File

@@ -431,11 +431,8 @@
if (30 >= $this->iMinAddressRank && 30 <= $this->iMaxAddressRank) if (30 >= $this->iMinAddressRank && 30 <= $this->iMaxAddressRank)
{ {
if (CONST_Use_US_Tiger_Data) //only Tiger housenumbers and interpolation lines need to be interpolated, because they are saved as lines
{ // with start- and endnumber, the common osm housenumbers are usually saved as points
//query also location_property_tiger and location_property_aux
//Tiger search only if a housenumber was searched and if it was found (i.e. aPlaceIDs[placeID] = housenumber != -1) (realized through a join)
//only Tiger housenumbers need to be interpolated, because they are saved as lines with start- and endnumber, the common osm housenumbers are usually saved as points
$sHousenumbers = ""; $sHousenumbers = "";
$i = 0; $i = 0;
$length = count($aPlaceIDs); $length = count($aPlaceIDs);
@@ -446,9 +443,11 @@
if($i<$length) if($i<$length)
$sHousenumbers .= ", "; $sHousenumbers .= ", ";
} }
if (CONST_Use_US_Tiger_Data)
$sSQL .= "union "; {
$sSQL .= "select 'T' as osm_type, place_id as osm_id, 'place' as class, 'house' as type, null as admin_level, 30 as rank_search, 30 as rank_address, min(place_id) as place_id, min(parent_place_id) as parent_place_id, 'us' as country_code"; //Tiger search only if a housenumber was searched and if it was found (i.e. aPlaceIDs[placeID] = housenumber != -1) (realized through a join)
$sSQL .= " union";
$sSQL .= " select 'T' as osm_type, place_id as osm_id, 'place' as class, 'house' as type, null as admin_level, 30 as rank_search, 30 as rank_address, min(place_id) as place_id, min(parent_place_id) as parent_place_id, 'us' as country_code";
$sSQL .= ", get_address_by_language(place_id, housenumber_for_place, $sLanguagePrefArraySQL) as langaddress "; $sSQL .= ", get_address_by_language(place_id, housenumber_for_place, $sLanguagePrefArraySQL) as langaddress ";
$sSQL .= ", null as placename"; $sSQL .= ", null as placename";
$sSQL .= ", null as ref"; $sSQL .= ", null as ref";
@@ -460,13 +459,37 @@
$sSQL .= ", null as extra_place "; $sSQL .= ", null as extra_place ";
$sSQL .= " from (select place_id"; $sSQL .= " from (select place_id";
//interpolate the Tiger housenumbers here //interpolate the Tiger housenumbers here
$sSQL .= ", ST_LineInterpolatePoint(linegeo, (housenumber_for_place-startnumber::float)/(endnumber-startnumber)::float) as centroid, parent_place_id, housenumber_for_place "; $sSQL .= ", ST_LineInterpolatePoint(linegeo, (housenumber_for_place-startnumber::float)/(endnumber-startnumber)::float) as centroid, parent_place_id, housenumber_for_place";
$sSQL .= "from (location_property_tiger "; $sSQL .= " from (location_property_tiger ";
$sSQL .= " join (values ".$sHousenumbers.") as housenumbers(place_id, housenumber_for_place) using(place_id)) "; $sSQL .= " join (values ".$sHousenumbers.") as housenumbers(place_id, housenumber_for_place) using(place_id)) ";
$sSQL .= " where housenumber_for_place>=0 and 30 between $this->iMinAddressRank and $this->iMaxAddressRank) as blub"; //postgres wants an alias here $sSQL .= " where housenumber_for_place>=0 and 30 between $this->iMinAddressRank and $this->iMaxAddressRank) as blub"; //postgres wants an alias here
$sSQL .= " group by place_id, housenumber_for_place"; //is this group by really needed?, place_id + housenumber (in combination) are unique $sSQL .= " group by place_id, housenumber_for_place"; //is this group by really needed?, place_id + housenumber (in combination) are unique
if (!$this->bDeDupe) $sSQL .= ", place_id "; if (!$this->bDeDupe) $sSQL .= ", place_id ";
} }
// osmline
// interpolation line search only if a housenumber was searched and if it was found (i.e. aPlaceIDs[placeID] = housenumber != -1) (realized through a join)
$sSQL .= " union ";
$sSQL .= "select 'W' as osm_type, place_id as osm_id, 'place' as class, 'house' as type, null as admin_level, 30 as rank_search, 30 as rank_address, min(place_id) as place_id, min(parent_place_id) as parent_place_id, calculated_country_code as country_code, ";
$sSQL .= "get_address_by_language(place_id, housenumber_for_place, $sLanguagePrefArraySQL) as langaddress, ";
$sSQL .= "null as placename, ";
$sSQL .= "null as ref, ";
if ($this->bIncludeExtraTags) $sSQL .= "null as extra, ";
if ($this->bIncludeNameDetails) $sSQL .= "null as names, ";
$sSQL .= " avg(st_x(centroid)) as lon, avg(st_y(centroid)) as lat,";
$sSQL .= $sImportanceSQL."-0.1 as importance, "; // slightly smaller than the importance for normal houses with rank 30, which is 0
$sSQL .= " (select max(p.importance*(p.rank_address+2)) from place_addressline s, placex p";
$sSQL .= " where s.place_id = min(blub.parent_place_id) and p.place_id = s.address_place_id and s.isaddress and p.importance is not null) as addressimportance,";
$sSQL .= " null as extra_place ";
$sSQL .= " from (select place_id, calculated_country_code ";
//interpolate the housenumbers here
$sSQL .= ", CASE WHEN startnumber != endnumber THEN ST_LineInterpolatePoint(linegeo, (housenumber_for_place-startnumber::float)/(endnumber-startnumber)::float) ";
$sSQL .= " ELSE ST_LineInterpolatePoint(linegeo, 0.5) END as centroid";
$sSQL .= ", parent_place_id, housenumber_for_place ";
$sSQL .= " from (location_property_osmline ";
$sSQL .= " join (values ".$sHousenumbers.") as housenumbers(place_id, housenumber_for_place) using(place_id)) ";
$sSQL .= " where housenumber_for_place>=0 and 30 between $this->iMinAddressRank and $this->iMaxAddressRank) as blub"; //postgres wants an alias here
$sSQL .= " group by place_id, housenumber_for_place, calculated_country_code "; //is this group by really needed?, place_id + housenumber (in combination) are unique
if (!$this->bDeDupe) $sSQL .= ", place_id ";
if (CONST_Use_Aux_Location_data) if (CONST_Use_Aux_Location_data)
{ {
@@ -1307,7 +1330,13 @@
if ($aSearch['sHouseNumber'] && sizeof($aSearch['aAddress'])) if ($aSearch['sHouseNumber'] && sizeof($aSearch['aAddress']))
{ {
$sHouseNumberRegex = '\\\\m'.$aSearch['sHouseNumber'].'\\\\M'; $sHouseNumberRegex = '\\\\m'.$aSearch['sHouseNumber'].'\\\\M';
$aOrder[] = "exists(select place_id from placex where parent_place_id = search_name.place_id and transliteration(housenumber) ~* E'".$sHouseNumberRegex."' limit 1) desc"; $aOrder[] = "";
$aOrder[0] = " (exists(select place_id from placex where parent_place_id = search_name.place_id";
$aOrder[0] .= " and transliteration(housenumber) ~* E'".$sHouseNumberRegex."' limit 1) ";
// also housenumbers from interpolation lines table are needed
$aOrder[0] .= " or exists(select place_id from location_property_osmline where parent_place_id = search_name.place_id";
$aOrder[0] .= " and ".intval($aSearch['sHouseNumber']).">=startnumber and ".intval($aSearch['sHouseNumber'])."<=endnumber limit 1))";
$aOrder[0] .= " desc";
} }
// TODO: filter out the pointless search terms (2 letter name tokens and less) // TODO: filter out the pointless search terms (2 letter name tokens and less)
@@ -1422,10 +1451,11 @@
//now search for housenumber, if housenumber provided //now search for housenumber, if housenumber provided
if ($aSearch['sHouseNumber'] && sizeof($aPlaceIDs)) if ($aSearch['sHouseNumber'] && sizeof($aPlaceIDs))
{ {
$searchedHousenumber = intval($aSearch['sHouseNumber']);
$aRoadPlaceIDs = $aPlaceIDs; $aRoadPlaceIDs = $aPlaceIDs;
$sPlaceIDs = join(',',$aPlaceIDs); $sPlaceIDs = join(',',$aPlaceIDs);
// Now they are indexed look for a house attached to a street we found // Now they are indexed, look for a house attached to a street we found
$sHouseNumberRegex = '\\\\m'.$aSearch['sHouseNumber'].'\\\\M'; $sHouseNumberRegex = '\\\\m'.$aSearch['sHouseNumber'].'\\\\M';
$sSQL = "select place_id from placex where parent_place_id in (".$sPlaceIDs.") and transliteration(housenumber) ~* E'".$sHouseNumberRegex."'"; $sSQL = "select place_id from placex where parent_place_id in (".$sPlaceIDs.") and transliteration(housenumber) ~* E'".$sHouseNumberRegex."'";
if (sizeof($this->aExcludePlaceIDs)) if (sizeof($this->aExcludePlaceIDs))
@@ -1436,20 +1466,43 @@
if (CONST_Debug) var_dump($sSQL); if (CONST_Debug) var_dump($sSQL);
$aPlaceIDs = $this->oDB->getCol($sSQL); $aPlaceIDs = $this->oDB->getCol($sSQL);
// if nothing found, search in the interpolation line table
if(!sizeof($aPlaceIDs))
{
// do we need to use transliteration and the regex for housenumbers???
//new query for lines, not housenumbers anymore
if($searchedHousenumber%2 == 0){
//if housenumber is even, look for housenumber in streets with interpolationtype even or all
$sSQL = "select distinct place_id from location_property_osmline where parent_place_id in (".$sPlaceIDs.") and (interpolationtype='even' or interpolationtype='all') and ".$searchedHousenumber.">=startnumber and ".$searchedHousenumber."<=endnumber";
}else{
//look for housenumber in streets with interpolationtype odd or all
$sSQL = "select distinct place_id from location_property_osmline where parent_place_id in (".$sPlaceIDs.") and (interpolationtype='odd' or interpolationtype='all') and ".$searchedHousenumber.">=startnumber and ".$searchedHousenumber."<=endnumber";
}
if (sizeof($this->aExcludePlaceIDs))
{
$sSQL .= " and parent_place_id not in (".join(',', $this->aExcludePlaceIDs).")";
}
//$sSQL .= " limit $this->iLimit";
if (CONST_Debug) var_dump($sSQL);
//get place IDs
$aPlaceIDs = $this->oDB->getCol($sSQL, 0);
}
// If nothing found try the aux fallback table // If nothing found try the aux fallback table
if (CONST_Use_Aux_Location_data && !sizeof($aPlaceIDs)) if (CONST_Use_Aux_Location_data && !sizeof($aPlaceIDs))
{ {
$sSQL = "select place_id from location_property_aux where parent_place_id in (".$sPlaceIDs.") and housenumber = '".pg_escape_string($aSearch['sHouseNumber'])."'"; $sSQL = "select place_id from location_property_aux where parent_place_id in (".$sPlaceIDs.") and housenumber = '".pg_escape_string($aSearch['sHouseNumber'])."'";
if (sizeof($this->aExcludePlaceIDs)) if (sizeof($this->aExcludePlaceIDs))
{ {
$sSQL .= " and place_id not in (".join(',',$this->aExcludePlaceIDs).")"; $sSQL .= " and parent_place_id not in (".join(',',$this->aExcludePlaceIDs).")";
} }
//$sSQL .= " limit $this->iLimit"; //$sSQL .= " limit $this->iLimit";
if (CONST_Debug) var_dump($sSQL); if (CONST_Debug) var_dump($sSQL);
$aPlaceIDs = $this->oDB->getCol($sSQL); $aPlaceIDs = $this->oDB->getCol($sSQL);
} }
//if nothing was found in placex or location_property_aux, then search in Tiger data for this housenumber(location_property_tiger) //if nothing was found in placex or location_property_aux, then search in Tiger data for this housenumber(location_property_tiger)
$searchedHousenumber = intval($aSearch['sHouseNumber']);
if (CONST_Use_US_Tiger_Data && !sizeof($aPlaceIDs)) if (CONST_Use_US_Tiger_Data && !sizeof($aPlaceIDs))
{ {
//new query for lines, not housenumbers anymore //new query for lines, not housenumbers anymore
@@ -1618,6 +1671,7 @@
{ {
// Need to verify passes rank limits before dropping out of the loop (yuk!) // Need to verify passes rank limits before dropping out of the loop (yuk!)
// reduces the number of place ids, like a filter // reduces the number of place ids, like a filter
// rank_address is 30 for interpolated housenumbers
$sSQL = "select place_id from placex where place_id in (".join(',',array_keys($aResultPlaceIDs)).") "; $sSQL = "select place_id from placex where place_id in (".join(',',array_keys($aResultPlaceIDs)).") ";
$sSQL .= "and (placex.rank_address between $this->iMinAddressRank and $this->iMaxAddressRank "; $sSQL .= "and (placex.rank_address between $this->iMinAddressRank and $this->iMaxAddressRank ";
if (14 >= $this->iMinAddressRank && 14 <= $this->iMaxAddressRank) $sSQL .= " OR (extratags->'place') = 'city'"; if (14 >= $this->iMinAddressRank && 14 <= $this->iMaxAddressRank) $sSQL .= " OR (extratags->'place') = 'city'";
@@ -1628,7 +1682,8 @@
$sSQL .= "and (30 between $this->iMinAddressRank and $this->iMaxAddressRank "; $sSQL .= "and (30 between $this->iMinAddressRank and $this->iMaxAddressRank ";
if ($this->aAddressRankList) $sSQL .= " OR 30 in (".join(',',$this->aAddressRankList).")"; if ($this->aAddressRankList) $sSQL .= " OR 30 in (".join(',',$this->aAddressRankList).")";
} }
$sSQL .= ")"; $sSQL .= ") UNION select place_id from location_property_osmline where place_id in (".join(',',array_keys($aResultPlaceIDs)).")";
$sSQL .= " and (30 between $this->iMinAddressRank and $this->iMaxAddressRank)";
if (CONST_Debug) var_dump($sSQL); if (CONST_Debug) var_dump($sSQL);
$aFilteredPlaceIDs = $this->oDB->getCol($sSQL); $aFilteredPlaceIDs = $this->oDB->getCol($sSQL);
$tempIDs = array(); $tempIDs = array();

View File

@@ -111,7 +111,7 @@
{ {
$this->setOSMID($details['osm_type'], $details['osm_id']); $this->setOSMID($details['osm_type'], $details['osm_id']);
} }
if (isset($details['fraction'])) $this->fTigerFraction = $details['fraction']; if (isset($details['fraction'])) $this->fInterpolFraction = $details['fraction'];
return $this->lookup(); return $this->lookup();
} }
@@ -134,12 +134,33 @@
if ($this->bNameDetails) $sSQL .= " null as names,"; if ($this->bNameDetails) $sSQL .= " null as names,";
$sSQL .= " ST_X(point) as lon, ST_Y(point) as lat from (select *, ST_LineInterpolatePoint(linegeo, (housenumber-startnumber::float)/(endnumber-startnumber)::float) as point from "; $sSQL .= " ST_X(point) as lon, ST_Y(point) as lat from (select *, ST_LineInterpolatePoint(linegeo, (housenumber-startnumber::float)/(endnumber-startnumber)::float) as point from ";
$sSQL .= " (select *, "; $sSQL .= " (select *, ";
$sSQL .= " CASE WHEN interpolationtype='odd' THEN floor((".$this->fTigerFraction."*(endnumber-startnumber)+startnumber)/2)::int*2+1"; $sSQL .= " CASE WHEN interpolationtype='odd' THEN floor((".$this->fInterpolFraction."*(endnumber-startnumber)+startnumber)/2)::int*2+1";
$sSQL .= " WHEN interpolationtype='even' THEN ((".$this->fTigerFraction."*(endnumber-startnumber)+startnumber+1)/2)::int*2"; $sSQL .= " WHEN interpolationtype='even' THEN ((".$this->fInterpolFraction."*(endnumber-startnumber)+startnumber)/2)::int*2";
$sSQL .= " WHEN interpolationtype='all' THEN (".$this->fTigerFraction."*(endnumber-startnumber)+startnumber)::int"; $sSQL .= " WHEN interpolationtype='all' THEN (".$this->fInterpolFraction."*(endnumber-startnumber)+startnumber)::int";
$sSQL .= " END as housenumber"; $sSQL .= " END as housenumber";
$sSQL .= " from location_property_tiger where place_id = ".(int)$this->iPlaceID.") as blub1) as blub2"; $sSQL .= " from location_property_tiger where place_id = ".(int)$this->iPlaceID.") as blub1) as blub2";
} }
else if ($this->sType == 'interpolation')
{
$sSQL = "select place_id, partition, 'W' as osm_type, osm_id, 'place' as class, 'house' as type, null admin_level, housenumber, null as street, null as isin, postcode,";
$sSQL .= " calculated_country_code as country_code, parent_place_id, null as linked_place_id, 30 as rank_address, 30 as rank_search,";
$sSQL .= " (0.75-(30::float/40)) as importance, null as indexed_status, null as indexed_date, null as wikipedia, calculated_country_code, ";
$sSQL .= " get_address_by_language(place_id, housenumber, $sLanguagePrefArraySQL) as langaddress,";
$sSQL .= " null as placename,";
$sSQL .= " null as ref,";
if ($this->bExtraTags) $sSQL .= " null as extra,";
if ($this->bNameDetails) $sSQL .= " null as names,";
$sSQL .= " ST_X(point) as lon, ST_Y(point) as lat from (select *, ST_LineInterpolatePoint(linegeo, (housenumber-startnumber::float)/(endnumber-startnumber)::float) as point from ";
$sSQL .= " (select *, ";
$sSQL .= " CASE WHEN interpolationtype='odd' THEN floor((".$this->fInterpolFraction."*(endnumber-startnumber)+startnumber)/2)::int*2+1";
$sSQL .= " WHEN interpolationtype='even' THEN ((".$this->fInterpolFraction."*(endnumber-startnumber)+startnumber)/2)::int*2";
$sSQL .= " WHEN interpolationtype='all' THEN (".$this->fInterpolFraction."*(endnumber-startnumber)+startnumber)::int";
$sSQL .= " END as housenumber";
$sSQL .= " from location_property_osmline where place_id = ".(int)$this->iPlaceID.") as blub1) as blub2";
// testcase: interpolationtype=odd, startnumber=1000, endnumber=1006, fInterpolFraction=1 => housenumber=1007 => error in st_lineinterpolatepoint
// but this will never happen, because if the searched point is that close to the endnumber, the endnumber house will be directly taken from placex (in ReverseGeocode.php line 220)
// and not interpolated
}
else else
{ {
$sSQL = "select placex.place_id, partition, osm_type, osm_id, class, type, admin_level, housenumber, street, isin, postcode, country_code, parent_place_id, linked_place_id, rank_address, rank_search, "; $sSQL = "select placex.place_id, partition, osm_type, osm_id, class, type, admin_level, housenumber, street, isin, postcode, country_code, parent_place_id, linked_place_id, rank_address, rank_search, ";
@@ -166,7 +187,7 @@
if ($this->bAddressDetails) if ($this->bAddressDetails)
{ {
if(CONST_Use_US_Tiger_Data && $this->sType == 'tiger') // to get addressdetails for tiger data, the housenumber is needed if(CONST_Use_US_Tiger_Data && $this->sType == 'tiger' || $this->sType == 'interpolation') // to get addressdetails for tiger data, the housenumber is needed
$aAddress = $this->getAddressNames($aPlace['housenumber']); $aAddress = $this->getAddressNames($aPlace['housenumber']);
else else
$aAddress = $this->getAddressNames(); $aAddress = $this->getAddressNames();

View File

@@ -121,6 +121,7 @@
$fMaxAreaDistance = 1; $fMaxAreaDistance = 1;
$bIsInUnitedStates = false; $bIsInUnitedStates = false;
$bPlaceIsTiger = false; $bPlaceIsTiger = false;
$bPlaceIsLine = false;
while(!$iPlaceID && $fSearchDiam < $fMaxAreaDistance) while(!$iPlaceID && $fSearchDiam < $fMaxAreaDistance)
{ {
$fSearchDiam = $fSearchDiam * 2; $fSearchDiam = $fSearchDiam * 2;
@@ -156,6 +157,77 @@
$iParentPlaceID = $aPlace['parent_place_id']; $iParentPlaceID = $aPlace['parent_place_id'];
$bIsInUnitedStates = ($aPlace['calculated_country_code'] == 'us'); $bIsInUnitedStates = ($aPlace['calculated_country_code'] == 'us');
} }
// if a street or house was found, look in interpolation lines table
if ($iMaxRank_orig >= 28 && $aPlace && $aPlace['rank_search'] >= 26)
{
// if a house was found, search the interpolation line that is at least as close as the house
$sSQL = 'SELECT place_id, parent_place_id, 30 as rank_search, ST_line_locate_point(linegeo,'.$sPointSQL.') as fraction';
$sSQL .= ' FROM location_property_osmline';
$sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', linegeo, '.$fSearchDiam.')';
$sSQL .= ' and indexed_status = 0 ';
$sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', linegeo) ASC limit 1';
if (CONST_Debug)
{
$sSQL = preg_replace('/limit 1/', 'limit 100', $sSQL);
var_dump($sSQL);
$aAllHouses = $this->oDB->getAll($sSQL);
foreach($aAllHouses as $i)
{
echo $i['housenumber'] . ' | ' . $i['distance'] * 1000 . ' | ' . $i['lat'] . ' | ' . $i['lon']. ' | '. "<br>\n";
}
}
$aPlaceLine = $this->oDB->getRow($sSQL);
if (PEAR::IsError($aPlaceLine))
{
failInternalError("Could not determine closest housenumber on an osm interpolation line.", $sSQL, $aPlaceLine);
}
if ($aPlaceLine)
{
if (CONST_Debug) var_dump('found housenumber in interpolation lines table', $aPlaceLine);
if ($aPlace['rank_search'] == 30)
{
// if a house was already found in placex, we have to find out,
// if the placex house or the interpolated house are closer to the searched point
// distance between point and placex house
$sSQL = 'SELECT ST_distance('.$sPointSQL.', house.geometry) as distance FROM placex as house WHERE house.place_id='.$iPlaceID;
$aDistancePlacex = $this->oDB->getRow($sSQL);
if (PEAR::IsError($aDistancePlacex))
{
failInternalError("Could not determine distance between searched point and placex house.", $sSQL, $aDistancePlacex);
}
$fDistancePlacex = $aDistancePlacex['distance'];
// distance between point and interpolated house (fraction on interpolation line)
$sSQL = 'SELECT ST_distance('.$sPointSQL.', ST_LineInterpolatePoint(linegeo, '.$aPlaceLine['fraction'].')) as distance';
$sSQL .= ' FROM location_property_osmline WHERE place_id = '.$aPlaceLine['place_id'];
$aDistanceInterpolation = $this->oDB->getRow($sSQL);
if (PEAR::IsError($aDistanceInterpolation))
{
failInternalError("Could not determine distance between searched point and interpolated house.", $sSQL, $aDistanceInterpolation);
}
$fDistanceInterpolation = $aDistanceInterpolation['distance'];
if ($fDistanceInterpolation < $fDistancePlacex)
{
// interpolation is closer to point than placex house
$bPlaceIsLine = true;
$aPlace = $aPlaceLine;
$iPlaceID = $aPlaceLine['place_id'];
$iParentPlaceID = $aPlaceLine['parent_place_id']; // the street
$fFraction = $aPlaceLine['fraction'];
}
// else: nothing to do, take placex house from above
}
else
{
$bPlaceIsLine = true;
$aPlace = $aPlaceLine;
$iPlaceID = $aPlaceLine['place_id'];
$iParentPlaceID = $aPlaceLine['parent_place_id']; // the street
$fFraction = $aPlaceLine['fraction'];
}
}
}
// Only street found? If it's in the US we can check TIGER data for nearest housenumber // Only street found? If it's in the US we can check TIGER data for nearest housenumber
if (CONST_Use_US_Tiger_Data && $bIsInUnitedStates && $iMaxRank_orig >= 28 && $iPlaceID && ($aPlace['rank_search'] == 26 || $aPlace['rank_search'] == 27 )) if (CONST_Use_US_Tiger_Data && $bIsInUnitedStates && $iMaxRank_orig >= 28 && $iPlaceID && ($aPlace['rank_search'] == 26 || $aPlace['rank_search'] == 27 ))
@@ -180,25 +252,25 @@
} }
$aPlaceTiger = $this->oDB->getRow($sSQL); $aPlaceTiger = $this->oDB->getRow($sSQL);
if (PEAR::IsError($aPlace)) if (PEAR::IsError($aPlaceTiger))
{ {
failInternalError("Could not determine closest Tiger place.", $sSQL, $aPlaceTiger); failInternalError("Could not determine closest Tiger place.", $sSQL, $aPlaceTiger);
} }
if ($aPlaceTiger) if ($aPlaceTiger)
{ {
if (CONST_Debug) var_dump('found Tiger place', $aPlaceTiger); if (CONST_Debug) var_dump('found Tiger housenumber', $aPlaceTiger);
$bPlaceIsTiger = true; $bPlaceIsTiger = true;
$aPlace = $aPlaceTiger; $aPlace = $aPlaceTiger;
$iPlaceID = $aPlaceTiger['place_id']; $iPlaceID = $aPlaceTiger['place_id'];
$iParentPlaceID = $aPlaceTiger['parent_place_id']; // the street $iParentPlaceID = $aPlaceTiger['parent_place_id']; // the street
$iFraction = $aPlaceTiger['fraction']; $fFraction = $aPlaceTiger['fraction'];
} }
} }
// The point we found might be too small - use the address to find what it is a child of // The point we found might be too small - use the address to find what it is a child of
if ($iPlaceID && $iMaxRank < 28) if ($iPlaceID && $iMaxRank < 28)
{ {
if ($aPlace['rank_search'] > 28 && $iParentPlaceID && !$bPlaceIsTiger) if (($aPlace['rank_search'] > 28 || $bPlaceIsTiger || $bPlaceIsLine) && $iParentPlaceID)
{ {
$iPlaceID = $iParentPlaceID; $iPlaceID = $iParentPlaceID;
} }
@@ -217,10 +289,9 @@
$iPlaceID = $aPlace['place_id']; $iPlaceID = $aPlace['place_id'];
} }
} }
return array('place_id' => $iPlaceID, return array('place_id' => $iPlaceID,
'type' => $bPlaceIsTiger ? 'tiger' : 'osm', 'type' => $bPlaceIsTiger ? 'tiger' : $bPlaceIsLine ? 'interpolation' : 'osm',
'fraction' => $bPlaceIsTiger ? $iFraction : -1); 'fraction' => ($bPlaceIsTiger || $bPlaceIsLine) ? $fFraction : -1);
} }
} }

View File

@@ -12,7 +12,8 @@
{ {
if (isset($aPlace['place_id'])) $aFilteredPlaces['place_id'] = $aPlace['place_id']; if (isset($aPlace['place_id'])) $aFilteredPlaces['place_id'] = $aPlace['place_id'];
$aFilteredPlaces['licence'] = "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright"; $aFilteredPlaces['licence'] = "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright";
$sOSMType = ($aPlace['osm_type'] == 'N'?'node':($aPlace['osm_type'] == 'W'?'way':($aPlace['osm_type'] == 'R'?'relation':''))); $sOSMType = ($aPlace['osm_type'] == 'N'?'node':($aPlace['osm_type'] == 'W'?'way':($aPlace['osm_type'] == 'R'?'relation':
($aPlace['osm_type'] == 'T'?'tiger':($aPlace['osm_type'] == 'I'?'interpolation':'')))));
if ($sOSMType) if ($sOSMType)
{ {
$aFilteredPlaces['osm_type'] = $sOSMType; $aFilteredPlaces['osm_type'] = $sOSMType;

View File

@@ -12,7 +12,8 @@
{ {
if ($aPlace['place_id']) $aFilteredPlaces['place_id'] = $aPlace['place_id']; if ($aPlace['place_id']) $aFilteredPlaces['place_id'] = $aPlace['place_id'];
$aFilteredPlaces['licence'] = "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright"; $aFilteredPlaces['licence'] = "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright";
$sOSMType = ($aPlace['osm_type'] == 'N'?'node':($aPlace['osm_type'] == 'W'?'way':($aPlace['osm_type'] == 'R'?'relation':''))); $sOSMType = ($aPlace['osm_type'] == 'N'?'node':($aPlace['osm_type'] == 'W'?'way':($aPlace['osm_type'] == 'R'?'relation':
($aPlace['osm_type'] == 'T'?'tiger':($aPlace['osm_type'] == 'I'?'interpolation':'')))));
if ($sOSMType) if ($sOSMType)
{ {
$aFilteredPlaces['osm_type'] = $sOSMType; $aFilteredPlaces['osm_type'] = $sOSMType;

View File

@@ -22,7 +22,8 @@
{ {
echo "<result"; echo "<result";
if ($aPlace['place_id']) echo ' place_id="'.$aPlace['place_id'].'"'; if ($aPlace['place_id']) echo ' place_id="'.$aPlace['place_id'].'"';
$sOSMType = ($aPlace['osm_type'] == 'N'?'node':($aPlace['osm_type'] == 'W'?'way':($aPlace['osm_type'] == 'R'?'relation':''))); $sOSMType = ($aPlace['osm_type'] == 'N'?'node':($aPlace['osm_type'] == 'W'?'way':($aPlace['osm_type'] == 'R'?'relation':
($aPlace['osm_type'] == 'T'?'tiger':($aPlace['osm_type'] == 'I'?'interpolation':'')))));
if ($sOSMType) echo ' osm_type="'.$sOSMType.'"'.' osm_id="'.$aPlace['osm_id'].'"'; if ($sOSMType) echo ' osm_type="'.$sOSMType.'"'.' osm_id="'.$aPlace['osm_id'].'"';
if ($aPlace['ref']) echo ' ref="'.htmlspecialchars($aPlace['ref']).'"'; if ($aPlace['ref']) echo ' ref="'.htmlspecialchars($aPlace['ref']).'"';
if (isset($aPlace['lat'])) echo ' lat="'.htmlspecialchars($aPlace['lat']).'"'; if (isset($aPlace['lat'])) echo ' lat="'.htmlspecialchars($aPlace['lat']).'"';

View File

@@ -9,7 +9,8 @@
'licence'=>"Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright", 'licence'=>"Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
); );
$sOSMType = ($aPointDetails['osm_type'] == 'N'?'node':($aPointDetails['osm_type'] == 'W'?'way':($aPointDetails['osm_type'] == 'R'?'relation':($aPointDetails['osm_type'] == 'T'?'tiger':'')))); $sOSMType = ($aPointDetails['osm_type'] == 'N'?'node':($aPointDetails['osm_type'] == 'W'?'way':($aPointDetails['osm_type'] == 'R'?
'relation':($aPointDetails['osm_type'] == 'T'?'tiger':($aPointDetails['osm_type'] == 'I'?'interpolation':'')))));
if ($sOSMType) if ($sOSMType)
{ {
$aPlace['osm_type'] = $sOSMType; $aPlace['osm_type'] = $sOSMType;

View File

@@ -7,7 +7,7 @@
'licence'=>"Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright", 'licence'=>"Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
); );
$sOSMType = ($aPointDetails['osm_type'] == 'N'?'node':($aPointDetails['osm_type'] == 'W'?'way':($aPointDetails['osm_type'] == 'R'?'relation':($aPointDetails['osm_type'] == 'T'?'tiger':'')))); $sOSMType = ($aPointDetails['osm_type'] == 'N'?'node':($aPointDetails['osm_type'] == 'W'?'way':($aPointDetails['osm_type'] == 'R'?'relation':($aPointDetails['osm_type'] == 'T'?'tiger':($aPointDetails['osm_type'] == 'I'?'interpolation':'')))));
if ($sOSMType) if ($sOSMType)
{ {
$aPlace['osm_type'] = $sOSMType; $aPlace['osm_type'] = $sOSMType;

View File

@@ -25,7 +25,8 @@
foreach($aSearchResults as $iResNum => $aResult) foreach($aSearchResults as $iResNum => $aResult)
{ {
echo "<place place_id='".$aResult['place_id']."'"; echo "<place place_id='".$aResult['place_id']."'";
$sOSMType = ($aResult['osm_type'] == 'N'?'node':($aResult['osm_type'] == 'W'?'way':($aResult['osm_type'] == 'R'?'relation':($aResult['osm_type'] == 'T'?'tiger':'')))); $sOSMType = ($aResult['osm_type'] == 'N'?'node':($aResult['osm_type'] == 'W'?'way':($aResult['osm_type'] == 'R'?'relation':
($aResult['osm_type'] == 'T'?'tiger':($aResult['osm_type'] == 'I'?'interpolation':'')))));
if ($sOSMType) if ($sOSMType)
{ {
echo " osm_type='$sOSMType'"; echo " osm_type='$sOSMType'";

View File

@@ -1,4 +1,6 @@
/* /*
* triggers indexing (reparenting etc.) through setting resetting indexed_status: update placex/osmline set indexed_status = 0 where indexed_status > 0
* triggers placex_update and osmline_update
*/ */
#include <stdio.h> #include <stdio.h>
@@ -19,24 +21,21 @@
extern int verbose; extern int verbose;
void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile) void run_indexing(int rank, int interpolation, PGconn *conn, int num_threads,
struct index_thread_data * thread_data, const char *structuredoutputfile)
{ {
struct index_thread_data * thread_data;
pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
int tuples, count, sleepcount; int tuples, count, sleepcount;
pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
time_t rankStartTime; time_t rankStartTime;
int rankTotalTuples; int rankTotalTuples;
int rankCountTuples; int rankCountTuples;
float rankPerSecond; float rankPerSecond;
PGconn *conn;
PGresult * res;
PGresult * resSectors; PGresult * resSectors;
PGresult * resPlaces; PGresult * resPlaces;
PGresult * resNULL; PGresult * resNULL;
int rank;
int i; int i;
int iSector; int iSector;
int iResult; int iResult;
@@ -51,93 +50,6 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
xmlTextWriterPtr writer; xmlTextWriterPtr writer;
pthread_mutex_t writer_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t writer_mutex = PTHREAD_MUTEX_INITIALIZER;
Oid pg_prepare_params[2];
conn = PQconnectdb(conninfo);
if (PQstatus(conn) != CONNECTION_OK)
{
fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
pg_prepare_params[0] = PG_OID_INT4;
res = PQprepare(conn, "index_sectors",
"select geometry_sector,count(*) from placex where rank_search = $1 and indexed_status > 0 group by geometry_sector order by geometry_sector",
1, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_sectors: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
pg_prepare_params[0] = PG_OID_INT4;
res = PQprepare(conn, "index_nosectors",
"select 0::integer,count(*) from placex where rank_search = $1 and indexed_status > 0",
1, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_sectors: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
pg_prepare_params[0] = PG_OID_INT4;
pg_prepare_params[1] = PG_OID_INT4;
res = PQprepare(conn, "index_sector_places",
"select place_id from placex where rank_search = $1 and geometry_sector = $2 and indexed_status > 0",
2, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_sector_places: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
pg_prepare_params[0] = PG_OID_INT4;
res = PQprepare(conn, "index_nosector_places",
"select place_id from placex where rank_search = $1 and indexed_status > 0 order by geometry_sector",
1, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_nosector_places: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
// Build the data for each thread
thread_data = (struct index_thread_data *)malloc(sizeof(struct index_thread_data)*num_threads);
for (i = 0; i < num_threads; i++)
{
thread_data[i].conn = PQconnectdb(conninfo);
if (PQstatus(thread_data[i].conn) != CONNECTION_OK)
{
fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(thread_data[i].conn));
exit(EXIT_FAILURE);
}
pg_prepare_params[0] = PG_OID_INT8;
res = PQprepare(thread_data[i].conn, "index_placex",
"update placex set indexed_status = 0 where place_id = $1",
1, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_placex: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
/*res = PQexec(thread_data[i].conn, "set enable_seqscan = false");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed disabling sequential scan: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);*/
nominatim_exportCreatePreparedQueries(thread_data[i].conn);
}
// Create the output file // Create the output file
writer = NULL; writer = NULL;
if (structuredoutputfile) if (structuredoutputfile)
@@ -145,11 +57,15 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
writer = nominatim_exportXMLStart(structuredoutputfile); writer = nominatim_exportXMLStart(structuredoutputfile);
} }
fprintf(stderr, "Starting indexing rank (%i to %i) using %i threads\n", rank_min, rank_max, num_threads); if (interpolation)
{
for (rank = rank_min; rank <= rank_max; rank++) fprintf(stderr, "Starting interpolation lines (location_property_osmline)\n");
}
else
{ {
fprintf(stderr, "Starting rank %d\n", rank); fprintf(stderr, "Starting rank %d\n", rank);
}
rankCountTuples = 0; rankCountTuples = 0;
rankPerSecond = 0; rankPerSecond = 0;
@@ -157,11 +73,15 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
paramValues[0] = (char *)&paramRank; paramValues[0] = (char *)&paramRank;
paramLengths[0] = sizeof(paramRank); paramLengths[0] = sizeof(paramRank);
paramFormats[0] = 1; paramFormats[0] = 1;
// if (rank < 16)
// resSectors = PQexecPrepared(conn, "index_nosectors", 1, paramValues, paramLengths, paramFormats, 1);
// else
resSectors = PQexecPrepared(conn, "index_sectors", 1, paramValues, paramLengths, paramFormats, 1);
if (interpolation)
{
resSectors = PQexecPrepared(conn, "index_sectors_osmline", 0, NULL, 0, NULL, 1);
}
else
{
resSectors = PQexecPrepared(conn, "index_sectors", 1, paramValues, paramLengths, paramFormats, 1);
}
if (PQresultStatus(resSectors) != PGRES_TUPLES_OK) if (PQresultStatus(resSectors) != PGRES_TUPLES_OK)
{ {
fprintf(stderr, "index_sectors: SELECT failed: %s", PQerrorMessage(conn)); fprintf(stderr, "index_sectors: SELECT failed: %s", PQerrorMessage(conn));
@@ -220,21 +140,42 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
// Get all the place_id's for this sector // Get all the place_id's for this sector
paramRank = PGint32(rank); paramRank = PGint32(rank);
paramValues[0] = (char *)&paramRank;
paramLengths[0] = sizeof(paramRank);
paramFormats[0] = 1;
paramSector = PGint32(sector); paramSector = PGint32(sector);
paramValues[1] = (char *)&paramSector;
paramLengths[1] = sizeof(paramSector);
paramFormats[1] = 1;
if (rankTotalTuples-rankCountTuples < num_threads*1000) if (rankTotalTuples-rankCountTuples < num_threads*1000)
{ {
iResult = PQsendQueryPrepared(conn, "index_nosector_places", 1, paramValues, paramLengths, paramFormats, 1); // no sectors
if (interpolation)
{
iResult = PQsendQueryPrepared(conn, "index_nosector_places_osmline", 0, NULL, 0, NULL, 1);
} }
else else
{ {
paramValues[0] = (char *)&paramRank;
paramLengths[0] = sizeof(paramRank);
paramFormats[0] = 1;
iResult = PQsendQueryPrepared(conn, "index_nosector_places", 1, paramValues, paramLengths, paramFormats, 1);
}
}
else
{
if (interpolation)
{
iResult = PQsendQueryPrepared(conn, "index_sector_places_osmline", 1, paramValues, paramLengths, paramFormats, 1);
paramValues[0] = (char *)&paramSector;
paramLengths[0] = sizeof(paramSector);
paramFormats[0] = 1;
}
else
{
paramValues[0] = (char *)&paramRank;
paramLengths[0] = sizeof(paramRank);
paramFormats[0] = 1;
paramValues[1] = (char *)&paramSector;
paramLengths[1] = sizeof(paramSector);
paramFormats[1] = 1;
iResult = PQsendQueryPrepared(conn, "index_sector_places", 2, paramValues, paramLengths, paramFormats, 1); iResult = PQsendQueryPrepared(conn, "index_sector_places", 2, paramValues, paramLengths, paramFormats, 1);
} }
}
if (!iResult) if (!iResult)
{ {
fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn)); fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn));
@@ -242,7 +183,6 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (iSector > 0) if (iSector > 0)
{ {
count = 0; count = 0;
@@ -260,6 +200,14 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
thread_data[i].count_mutex = &count_mutex; thread_data[i].count_mutex = &count_mutex;
thread_data[i].writer = writer; thread_data[i].writer = writer;
thread_data[i].writer_mutex = &writer_mutex; thread_data[i].writer_mutex = &writer_mutex;
if (interpolation)
{
thread_data[i].table = 0; // use interpolations table
}
else
{
thread_data[i].table = 1; // use placex table
}
pthread_create(&thread_data[i].thread, NULL, &nominatim_indexThread, (void *)&thread_data[i]); pthread_create(&thread_data[i].thread, NULL, &nominatim_indexThread, (void *)&thread_data[i]);
} }
@@ -273,7 +221,15 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
if (sleepcount++ > 500) if (sleepcount++ > 500)
{ {
rankPerSecond = ((float)rankCountTuples + (float)count) / MAX(difftime(time(0), rankStartTime),1); rankPerSecond = ((float)rankCountTuples + (float)count) / MAX(difftime(time(0), rankStartTime),1);
if(interpolation)
{
fprintf(stderr, " Done %i in %i @ %f per second - Interpolation lines ETA (seconds): %f\n", (rankCountTuples + count), (int)(difftime(time(0), rankStartTime)), rankPerSecond, ((float)(rankTotalTuples - (rankCountTuples + count)))/rankPerSecond);
}
else
{
fprintf(stderr, " Done %i in %i @ %f per second - Rank %i ETA (seconds): %f\n", (rankCountTuples + count), (int)(difftime(time(0), rankStartTime)), rankPerSecond, rank, ((float)(rankTotalTuples - (rankCountTuples + count)))/rankPerSecond); fprintf(stderr, " Done %i in %i @ %f per second - Rank %i ETA (seconds): %f\n", (rankCountTuples + count), (int)(difftime(time(0), rankStartTime)), rankPerSecond, rank, ((float)(rankTotalTuples - (rankCountTuples + count)))/rankPerSecond);
}
sleepcount = 0; sleepcount = 0;
} }
} }
@@ -299,16 +255,167 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
} }
} }
// Finished rank // Finished rank
fprintf(stderr, "\r Done %i in %i @ %f per second - FINISHED \n\n", rankCountTuples, (int)(difftime(time(0), rankStartTime)), rankPerSecond); fprintf(stderr, "\r Done %i in %i @ %f per second - FINISHED\n\n", rankCountTuples, (int)(difftime(time(0), rankStartTime)), rankPerSecond);
PQclear(resSectors); PQclear(resSectors);
} }
if (writer) void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile)
{
struct index_thread_data * thread_data;
PGconn *conn;
PGresult * res;
int rank;
int i;
xmlTextWriterPtr writer;
pthread_mutex_t writer_mutex = PTHREAD_MUTEX_INITIALIZER;
Oid pg_prepare_params[2];
conn = PQconnectdb(conninfo);
if (PQstatus(conn) != CONNECTION_OK)
{ {
nominatim_exportXMLEnd(writer); fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
} }
pg_prepare_params[0] = PG_OID_INT4;
res = PQprepare(conn, "index_sectors",
"select geometry_sector,count(*) from placex where rank_search = $1 and indexed_status > 0 group by geometry_sector order by geometry_sector",
1, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_sectors: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
res = PQprepare(conn, "index_sectors_osmline",
"select geometry_sector,count(*) from location_property_osmline where indexed_status > 0 group by geometry_sector order by geometry_sector",
0, NULL);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_sectors: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
pg_prepare_params[0] = PG_OID_INT4;
res = PQprepare(conn, "index_nosectors",
"select 0::integer,count(*) from placex where rank_search = $1 and indexed_status > 0",
1, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_sectors: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
pg_prepare_params[0] = PG_OID_INT4;
pg_prepare_params[1] = PG_OID_INT4;
res = PQprepare(conn, "index_sector_places",
"select place_id from placex where rank_search = $1 and geometry_sector = $2 and indexed_status > 0",
2, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_sector_places: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
pg_prepare_params[0] = PG_OID_INT4;
res = PQprepare(conn, "index_nosector_places",
"select place_id from placex where rank_search = $1 and indexed_status > 0 order by geometry_sector",
1, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_nosector_places: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
pg_prepare_params[0] = PG_OID_INT4;
res = PQprepare(conn, "index_sector_places_osmline",
"select place_id from location_property_osmline where geometry_sector = $1 and indexed_status > 0",
1, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_sector_places: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
res = PQprepare(conn, "index_nosector_places_osmline",
"select place_id from location_property_osmline where indexed_status > 0 order by geometry_sector",
0, NULL);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_nosector_places: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
// Build the data for each thread
thread_data = (struct index_thread_data *)malloc(sizeof(struct index_thread_data)*num_threads);
for (i = 0; i < num_threads; i++)
{
thread_data[i].conn = PQconnectdb(conninfo);
if (PQstatus(thread_data[i].conn) != CONNECTION_OK)
{
fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(thread_data[i].conn));
exit(EXIT_FAILURE);
}
pg_prepare_params[0] = PG_OID_INT8;
res = PQprepare(thread_data[i].conn, "index_placex",
"update placex set indexed_status = 0 where place_id = $1",
1, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_placex: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
pg_prepare_params[0] = PG_OID_INT8;
res = PQprepare(thread_data[i].conn, "index_osmline",
"update location_property_osmline set indexed_status = 0 where place_id = $1",
1, pg_prepare_params);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed preparing index_osmline: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);
/*res = PQexec(thread_data[i].conn, "set enable_seqscan = false");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Failed disabling sequential scan: %s\n", PQerrorMessage(conn));
exit(EXIT_FAILURE);
}
PQclear(res);*/
nominatim_exportCreatePreparedQueries(thread_data[i].conn);
}
fprintf(stderr, "Starting indexing rank (%i to %i) using %i threads\n", rank_min, rank_max, num_threads);
for (rank = rank_min; rank <= rank_max; rank++)
{
// OSMLINE: do reindexing (=> reparenting) for interpolation lines at rank 30, but before all other objects of rank 30
// reason: houses (rank 30) depend on the updated interpolation line, when reparenting (see placex_update in functions.sql)
if (rank == 30)
{
run_indexing(rank, 1, conn, num_threads, thread_data, structuredoutputfile);
}
run_indexing(rank, 0, conn, num_threads, thread_data, structuredoutputfile);
}
// Close all connections // Close all connections
for (i = 0; i < num_threads; i++) for (i = 0; i < num_threads; i++)
{ {
@@ -330,6 +437,9 @@ void *nominatim_indexThread(void * thread_data_in)
uint64_t paramPlaceID; uint64_t paramPlaceID;
uint64_t place_id; uint64_t place_id;
time_t updateStartTime; time_t updateStartTime;
uint table;
table = (uint)(thread_data->table);
while (1) while (1)
{ {
@@ -361,20 +471,41 @@ void *nominatim_indexThread(void * thread_data_in)
paramValues[0] = (char *)&paramPlaceID; paramValues[0] = (char *)&paramPlaceID;
paramLengths[0] = sizeof(paramPlaceID); paramLengths[0] = sizeof(paramPlaceID);
paramFormats[0] = 1; paramFormats[0] = 1;
if (table == 1) // table=1 for placex
{
res = PQexecPrepared(thread_data->conn, "index_placex", 1, paramValues, paramLengths, paramFormats, 1); res = PQexecPrepared(thread_data->conn, "index_placex", 1, paramValues, paramLengths, paramFormats, 1);
}
else // table=0 for osmline
{
res = PQexecPrepared(thread_data->conn, "index_osmline", 1, paramValues, paramLengths, paramFormats, 1);
}
if (PQresultStatus(res) == PGRES_COMMAND_OK) if (PQresultStatus(res) == PGRES_COMMAND_OK)
done = 1; done = 1;
else else
{ {
if (!strncmp(PQerrorMessage(thread_data->conn), "ERROR: deadlock detected", 25)) if (!strncmp(PQerrorMessage(thread_data->conn), "ERROR: deadlock detected", 25))
{
if (table == 1)
{ {
fprintf(stderr, "index_placex: UPDATE failed - deadlock, retrying (%ld)\n", place_id); fprintf(stderr, "index_placex: UPDATE failed - deadlock, retrying (%ld)\n", place_id);
}
else
{
fprintf(stderr, "index_osmline: UPDATE failed - deadlock, retrying (%ld)\n", place_id);
}
PQclear(res); PQclear(res);
sleep(rand() % 10); sleep(rand() % 10);
} }
else else
{
if (table == 1)
{ {
fprintf(stderr, "index_placex: UPDATE failed: %s", PQerrorMessage(thread_data->conn)); fprintf(stderr, "index_placex: UPDATE failed: %s", PQerrorMessage(thread_data->conn));
}
else
{
fprintf(stderr, "index_osmline: UPDATE failed: %s", PQerrorMessage(thread_data->conn));
}
PQclear(res); PQclear(res);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@@ -14,6 +14,7 @@ struct index_thread_data
pthread_mutex_t * count_mutex; pthread_mutex_t * count_mutex;
xmlTextWriterPtr writer; xmlTextWriterPtr writer;
pthread_mutex_t * writer_mutex; pthread_mutex_t * writer_mutex;
uint table;
}; };
void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile); void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile);
void *nominatim_indexThread(void * thread_data_in); void *nominatim_indexThread(void * thread_data_in);

View File

@@ -579,8 +579,7 @@ $$
LANGUAGE plpgsql; LANGUAGE plpgsql;
-- find the parent road of the cut road parts
-- find the parant road of an interpolation
CREATE OR REPLACE FUNCTION get_interpolation_parent(wayid BIGINT, street TEXT, place TEXT, CREATE OR REPLACE FUNCTION get_interpolation_parent(wayid BIGINT, street TEXT, place TEXT,
partition INTEGER, centroid GEOMETRY, geom GEOMETRY) partition INTEGER, centroid GEOMETRY, geom GEOMETRY)
RETURNS BIGINT AS $$ RETURNS BIGINT AS $$
@@ -647,11 +646,12 @@ END;
$$ $$
LANGUAGE plpgsql; LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION create_interpolation(wayid BIGINT, interpolationtype TEXT,
parent_id BIGINT, partition INTEGER, CREATE OR REPLACE FUNCTION insert_osmline(wayid BIGINT, interpolationtype TEXT,
country_code TEXT, geometry_sector INTEGER, street TEXT, addr_place TEXT,
defpostalcode TEXT, geom GEOMETRY) RETURNS INTEGER defpostalcode TEXT, country_code TEXT,
AS $$ geom GEOMETRY)
RETURNS INTEGER AS $$
DECLARE DECLARE
newpoints INTEGER; newpoints INTEGER;
@@ -661,26 +661,24 @@ DECLARE
nextnode RECORD; nextnode RECORD;
startnumber INTEGER; startnumber INTEGER;
endnumber INTEGER; endnumber INTEGER;
stepsize INTEGER;
orginalstartnumber INTEGER;
originalnumberrange INTEGER;
housenum INTEGER; housenum INTEGER;
linegeo GEOMETRY; linegeo GEOMETRY;
splitline GEOMETRY; splitline GEOMETRY;
sectiongeo GEOMETRY; sectiongeo GEOMETRY;
pointgeo GEOMETRY; pointgeo GEOMETRY;
place_centroid GEOMETRY;
calculated_country_code VARCHAR(2);
partition INTEGER;
geometry_sector INTEGER;
BEGIN BEGIN
delete from placex where osm_type = 'W' and osm_id = wayid place_centroid := ST_PointOnSurface(geom);
and class = 'place' and type = 'address'; calculated_country_code := lower(get_country_code(place_centroid));
partition := get_partition(calculated_country_code);
geometry_sector := geometry_sector(partition, place_centroid);
IF interpolationtype = 'odd' OR interpolationtype = 'even' THEN IF interpolationtype != 'odd' AND interpolationtype != 'even' AND interpolationtype!='all' THEN
stepsize := 2; -- other interpolation types than odd/even/all (e.g. numeric ones) are not supported
ELSEIF interpolationtype = 'all' THEN
stepsize := 1;
ELSEIF interpolationtype ~ '^\d+$' THEN
stepsize := interpolationtype::INTEGER;
ELSE
RETURN 0; RETURN 0;
END IF; END IF;
@@ -692,19 +690,14 @@ BEGIN
linegeo := geom; linegeo := geom;
startnumber := NULL; startnumber := NULL;
newpoints := 0;
FOR nodeidpos in 1..array_upper(waynodes, 1) LOOP FOR nodeidpos in 1..array_upper(waynodes, 1) LOOP
-- If there is a place of a type other than place/house, use that because select * from place where osm_type = 'N' and osm_id = waynodes[nodeidpos]::BIGINT
-- it is guaranteed to be the original node. For place/house types use the and housenumber is not NULL limit 1 INTO nextnode;
-- one with the smallest id because the original node was created first. --RAISE NOTICE 'Nextnode.place_id: %s', nextnode.place_id;
-- Ignore all nodes marked for deletion. (Might happen when the type changes.) IF nextnode.osm_id IS NOT NULL THEN
select * from placex where osm_type = 'N' and osm_id = waynodes[nodeidpos]::BIGINT --RAISE NOTICE 'place_id is not null';
and indexed_status < 100 and housenumber is not NULL
order by (type = 'address'),place_id limit 1 INTO nextnode;
IF nextnode.place_id IS NOT NULL THEN
IF nodeidpos > 1 and nodeidpos < array_upper(waynodes, 1) THEN IF nodeidpos > 1 and nodeidpos < array_upper(waynodes, 1) THEN
-- Make sure that the point is actually on the line. That might -- Make sure that the point is actually on the line. That might
-- be a bit paranoid but ensures that the algorithm still works -- be a bit paranoid but ensures that the algorithm still works
@@ -718,7 +711,7 @@ BEGIN
endnumber := substring(nextnode.housenumber,'[0-9]+')::integer; endnumber := substring(nextnode.housenumber,'[0-9]+')::integer;
IF startnumber IS NOT NULL AND endnumber IS NOT NULL IF startnumber IS NOT NULL AND endnumber IS NOT NULL
AND @(startnumber - endnumber) < 1000 AND startnumber != endnumber AND startnumber != endnumber
AND ST_GeometryType(sectiongeo) = 'ST_LineString' THEN AND ST_GeometryType(sectiongeo) = 'ST_LineString' THEN
IF (startnumber > endnumber) THEN IF (startnumber > endnumber) THEN
@@ -727,44 +720,20 @@ BEGIN
startnumber := housenum; startnumber := housenum;
sectiongeo := ST_Reverse(sectiongeo); sectiongeo := ST_Reverse(sectiongeo);
END IF; END IF;
orginalstartnumber := startnumber;
originalnumberrange := endnumber - startnumber;
startnumber := startnumber + stepsize; insert into location_property_osmline
-- correct for odd/even values (sectiongeo, nextval('seq_place'), partition, wayid, NULL,
IF (interpolationtype = 'odd' AND startnumber%2 = 0) startnumber, endnumber, interpolationtype,
OR (interpolationtype = 'even' AND startnumber%2 = 1) THEN coalesce(street, prevnode.street, nextnode.street),
startnumber := startnumber - 1; coalesce(addr_place, prevnode.addr_place, nextnode.addr_place),
END IF; coalesce(defpostalcode, prevnode.postcode, nextnode.postcode),
endnumber := endnumber - 1; calculated_country_code, geometry_sector, 2, now());
-- keep for compatibility with previous versions
delete from placex where osm_type = 'N' and osm_id = prevnode.osm_id
and place_id != prevnode.place_id and class = 'place'
and type = 'house';
FOR housenum IN startnumber..endnumber BY stepsize LOOP
pointgeo := ST_LineInterpolatePoint(sectiongeo, (housenum::float-orginalstartnumber::float)/originalnumberrange::float);
insert into placex (place_id, partition, osm_type, osm_id,
class, type, admin_level, housenumber,
postcode,
country_code, parent_place_id, rank_address, rank_search,
indexed_status, indexed_date, geometry_sector,
calculated_country_code, centroid, geometry)
values (nextval('seq_place'), partition, 'W', wayid,
'place', 'address', prevnode.admin_level, housenum,
coalesce(prevnode.postcode, defpostalcode),
prevnode.country_code, parent_id, 30, 30,
0, now(), geometry_sector, country_code,
pointgeo, pointgeo);
newpoints := newpoints + 1;
--RAISE WARNING 'interpolation number % % ',prevnode.place_id,housenum;
END LOOP;
END IF; END IF;
-- early break if we are out of line string, -- early break if we are out of line string,
-- might happen when a line string loops back on itself -- might happen when a line string loops back on itself
IF ST_GeometryType(linegeo) != 'ST_LineString' THEN IF ST_GeometryType(linegeo) != 'ST_LineString' THEN
RETURN newpoints; RETURN 0;
END IF; END IF;
startnumber := substring(nextnode.housenumber,'[0-9]+')::integer; startnumber := substring(nextnode.housenumber,'[0-9]+')::integer;
@@ -772,13 +741,12 @@ BEGIN
END IF; END IF;
END LOOP; END LOOP;
--RAISE WARNING 'interpolation points % ',newpoints; RETURN 1;
RETURN newpoints;
END; END;
$$ $$
LANGUAGE plpgsql; LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION placex_insert() RETURNS TRIGGER CREATE OR REPLACE FUNCTION placex_insert() RETURNS TRIGGER
AS $$ AS $$
DECLARE DECLARE
@@ -789,10 +757,11 @@ DECLARE
default_language VARCHAR(10); default_language VARCHAR(10);
diameter FLOAT; diameter FLOAT;
classtable TEXT; classtable TEXT;
line RECORD;
BEGIN BEGIN
--DEBUG: RAISE WARNING '% %',NEW.osm_type,NEW.osm_id; --DEBUG: RAISE WARNING '% %',NEW.osm_type,NEW.osm_id;
-- ignore interpolated addresses -- ignore interpolated addresses, not necessary anymore, cause interpolated addresses are now in location_property_osmline
IF NEW.class = 'place' and NEW.type = 'address' THEN IF NEW.class = 'place' and NEW.type = 'address' THEN
RETURN NEW; RETURN NEW;
END IF; END IF;
@@ -1065,6 +1034,8 @@ BEGIN
IF NEW.rank_search >= 26 THEN IF NEW.rank_search >= 26 THEN
-- roads may cause reparenting for >27 rank places -- roads may cause reparenting for >27 rank places
update placex set indexed_status = 2 where indexed_status = 0 and rank_search > NEW.rank_search and ST_DWithin(placex.geometry, NEW.geometry, diameter); update placex set indexed_status = 2 where indexed_status = 0 and rank_search > NEW.rank_search and ST_DWithin(placex.geometry, NEW.geometry, diameter);
-- reparenting also for OSM Interpolation Lines (and for Tiger?)
update location_property_osmline set indexed_status = 2 where indexed_status = 0 and ST_DWithin(location_property_osmline.linegeo, NEW.geometry, diameter);
ELSEIF NEW.rank_search >= 16 THEN ELSEIF NEW.rank_search >= 16 THEN
-- up to rank 16, street-less addresses may need reparenting -- up to rank 16, street-less addresses may need reparenting
update placex set indexed_status = 2 where indexed_status = 0 and rank_search > NEW.rank_search and ST_DWithin(placex.geometry, NEW.geometry, diameter) and (rank_search < 28 or name is not null or addr_place is not null); update placex set indexed_status = 2 where indexed_status = 0 and rank_search > NEW.rank_search and ST_DWithin(placex.geometry, NEW.geometry, diameter) and (rank_search < 28 or name is not null or addr_place is not null);
@@ -1093,6 +1064,35 @@ END;
$$ $$
LANGUAGE plpgsql; LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION osmline_update() RETURNS
TRIGGER
AS $$
DECLARE
place_centroid GEOMETRY;
BEGIN
-- deferred delete
IF OLD.indexed_status = 100 THEN
delete from location_property_osmline where place_id = OLD.place_id;
RETURN NULL;
END IF;
IF NEW.indexed_status != 0 OR OLD.indexed_status = 0 THEN
RETURN NEW;
END IF;
-- do the reparenting: (finally here, because ALL places in placex, that are needed for reparenting, need to be up to date)
-- (the osm interpolationline in location_property_osmline was marked for reparenting in placex_insert/placex_delete with index_status = 1 or 2 (1 inset, 2 delete)
-- => index.c: sets index_status back to 0
-- => triggers this function)
place_centroid := ST_PointOnSurface(NEW.linegeo);
-- marking descendants for reparenting is not needed, because there are actually no descendants for interpolation lines
NEW.parent_place_id = get_interpolation_parent(NEW.osm_id, NEW.street, NEW.addr_place,
NEW.partition, place_centroid, NEW.linegeo);
return NEW;
END;
$$
LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION placex_update() RETURNS CREATE OR REPLACE FUNCTION placex_update() RETURNS
TRIGGER TRIGGER
AS $$ AS $$
@@ -1137,7 +1137,6 @@ DECLARE
result BOOLEAN; result BOOLEAN;
BEGIN BEGIN
-- deferred delete -- deferred delete
IF OLD.indexed_status = 100 THEN IF OLD.indexed_status = 100 THEN
--DEBUG: RAISE WARNING 'placex_update_delete % %',NEW.osm_type,NEW.osm_id; --DEBUG: RAISE WARNING 'placex_update_delete % %',NEW.osm_type,NEW.osm_id;
@@ -1164,9 +1163,6 @@ BEGIN
RETURN NEW; RETURN NEW;
END IF; END IF;
-- TODO: this test is now redundant?
IF OLD.indexed_status != 0 THEN
NEW.indexed_date = now(); NEW.indexed_date = now();
result := deleteSearchName(NEW.partition, NEW.place_id); result := deleteSearchName(NEW.partition, NEW.place_id);
@@ -1175,6 +1171,7 @@ BEGIN
result := deleteLocationArea(NEW.partition, NEW.place_id, NEW.rank_search); result := deleteLocationArea(NEW.partition, NEW.place_id, NEW.rank_search);
UPDATE placex set linked_place_id = null, indexed_status = 2 UPDATE placex set linked_place_id = null, indexed_status = 2
where linked_place_id = NEW.place_id; where linked_place_id = NEW.place_id;
-- update not necessary for osmline, cause linked_place_id does not exist
IF NEW.linked_place_id is not null THEN IF NEW.linked_place_id is not null THEN
RETURN NEW; RETURN NEW;
@@ -1206,19 +1203,6 @@ BEGIN
END IF; END IF;
NEW.partition := get_partition(NEW.calculated_country_code); NEW.partition := get_partition(NEW.calculated_country_code);
END IF; END IF;
NEW.geometry_sector := geometry_sector(NEW.partition, place_centroid);
-- interpolations
IF NEW.class = 'place' AND NEW.type = 'houses'THEN
IF NEW.osm_type = 'W' and ST_GeometryType(NEW.geometry) = 'ST_LineString' THEN
NEW.parent_place_id := get_interpolation_parent(NEW.osm_id, NEW.street, NEW.addr_place,
NEW.partition, place_centroid, NEW.geometry);
i := create_interpolation(NEW.osm_id, NEW.housenumber, NEW.parent_place_id,
NEW.partition, NEW.calculated_country_code,
NEW.geometry_sector, NEW.postcode, NEW.geometry);
END IF;
RETURN NEW;
END IF;
-- waterway ways are linked when they are part of a relation and have the same class/type -- waterway ways are linked when they are part of a relation and have the same class/type
IF NEW.osm_type = 'R' and NEW.class = 'waterway' THEN IF NEW.osm_type = 'R' and NEW.class = 'waterway' THEN
@@ -1274,6 +1258,7 @@ BEGIN
--RAISE WARNING 'before low level% %', NEW.place_id, NEW.rank_search; --RAISE WARNING 'before low level% %', NEW.place_id, NEW.rank_search;
-- ---------------------------------------------------------------------------
-- For low level elements we inherit from our parent road -- For low level elements we inherit from our parent road
IF (NEW.rank_search > 27 OR (NEW.type = 'postcode' AND NEW.rank_search = 25)) THEN IF (NEW.rank_search > 27 OR (NEW.type = 'postcode' AND NEW.rank_search = 25)) THEN
@@ -1338,43 +1323,30 @@ BEGIN
END IF; END IF;
END IF; END IF;
-- Is this node part of an interpolation?
IF NEW.parent_place_id IS NULL AND NEW.osm_type = 'N' THEN
FOR location IN
SELECT q.parent_place_id FROM location_property_osmline q, planet_osm_ways x
WHERE q.linegeo && NEW.geometry and x.id = q.osm_id and NEW.osm_id = any(x.nodes)
LIMIT 1
LOOP
NEW.parent_place_id := location.parent_place_id;
END LOOP;
END IF;
-- Is this node part of a way?
IF NEW.parent_place_id IS NULL AND NEW.osm_type = 'N' THEN IF NEW.parent_place_id IS NULL AND NEW.osm_type = 'N' THEN
--RAISE WARNING 'x1'; FOR location IN select p.place_id, p.osm_id, p.parent_place_id, p.rank_search, p.street, p.addr_place from placex p, planet_osm_ways w
-- Is this node part of a way? where p.osm_type = 'W' and p.rank_search >= 26 and p.geometry && NEW.geometry and w.id = p.osm_id and NEW.osm_id = any(w.nodes)
FOR location IN select p.* from placex p, planet_osm_ways w
where p.osm_type = 'W' and p.rank_search >= 26
and p.geometry && NEW.geometry and p.osm_id = w.id and NEW.osm_id = any(w.nodes)
LOOP LOOP
--RAISE WARNING '%', location;
-- Way IS a road then we are on it - that must be our road -- Way IS a road then we are on it - that must be our road
IF location.rank_search = 26 AND NEW.parent_place_id IS NULL THEN IF location.rank_search < 28 AND NEW.parent_place_id IS NULL THEN
--RAISE WARNING 'node in way that is a street %',location; --RAISE WARNING 'node in way that is a street %',location;
NEW.parent_place_id := location.place_id; NEW.parent_place_id := location.place_id;
END IF; END IF;
-- If this way is a street interpolation line then it is probably as good as we are going to get
IF NEW.parent_place_id IS NULL AND location.class = 'place' and location.type='houses' THEN
NEW.parent_place_id := location.parent_place_id;
END IF;
-- Is the WAY part of a relation
IF NEW.parent_place_id IS NULL THEN
FOR relation IN select * from planet_osm_rels where parts @> ARRAY[location.osm_id] and members @> ARRAY['w'||location.osm_id]
LOOP
-- At the moment we only process one type of relation - associatedStreet
IF relation.tags @> ARRAY['associatedStreet'] AND array_upper(relation.members, 1) IS NOT NULL THEN
FOR i IN 1..array_upper(relation.members, 1) BY 2 LOOP
IF NEW.parent_place_id IS NULL AND relation.members[i+1] = 'street' THEN
--RAISE WARNING 'node in way that is in a relation %',relation;
SELECT place_id from placex where osm_type='W' and osm_id = substring(relation.members[i],2,200)::bigint
and rank_search = 26 and name is not null INTO NEW.parent_place_id;
END IF;
END LOOP;
END IF;
END LOOP;
END IF;
-- If the way mentions a street or place address, try that for parenting. -- If the way mentions a street or place address, try that for parenting.
IF NEW.parent_place_id IS NULL AND location.street IS NOT NULL THEN IF NEW.parent_place_id IS NULL AND location.street IS NOT NULL THEN
address_street_word_ids := get_name_ids(make_standard_name(location.street)); address_street_word_ids := get_name_ids(make_standard_name(location.street));
@@ -1394,6 +1366,23 @@ BEGIN
END IF; END IF;
END IF; END IF;
-- Is the WAY part of a relation
IF NEW.parent_place_id IS NULL THEN
FOR relation IN select * from planet_osm_rels where parts @> ARRAY[location.osm_id] and members @> ARRAY['w'||location.osm_id]
LOOP
-- At the moment we only process one type of relation - associatedStreet
IF relation.tags @> ARRAY['associatedStreet'] AND array_upper(relation.members, 1) IS NOT NULL THEN
FOR i IN 1..array_upper(relation.members, 1) BY 2 LOOP
IF NEW.parent_place_id IS NULL AND relation.members[i+1] = 'street' THEN
--RAISE WARNING 'node in way that is in a relation %',relation;
SELECT place_id from placex where osm_type='W' and osm_id = substring(relation.members[i],2,200)::bigint
and rank_search = 26 and name is not null INTO NEW.parent_place_id;
END IF;
END LOOP;
END IF;
END LOOP;
END IF;
END LOOP; END LOOP;
END IF; END IF;
@@ -1464,6 +1453,9 @@ BEGIN
-- RAISE WARNING ' INDEXING Started:'; -- RAISE WARNING ' INDEXING Started:';
-- RAISE WARNING ' INDEXING: %',NEW; -- RAISE WARNING ' INDEXING: %',NEW;
-- ---------------------------------------------------------------------------
-- Full indexing
IF NEW.osm_type = 'R' AND NEW.rank_search < 26 THEN IF NEW.osm_type = 'R' AND NEW.rank_search < 26 THEN
-- see if we have any special relation members -- see if we have any special relation members
@@ -1611,6 +1603,7 @@ BEGIN
NEW.parent_place_id = 0; NEW.parent_place_id = 0;
parent_place_id_rank = 0; parent_place_id_rank = 0;
-- convert isin to array of tokenids -- convert isin to array of tokenids
isin_tokens := '{}'::int[]; isin_tokens := '{}'::int[];
IF NEW.isin IS NOT NULL THEN IF NEW.isin IS NOT NULL THEN
@@ -1741,7 +1734,7 @@ BEGIN
FOR location IN SELECT * from getNearestNamedFeature(NEW.partition, place_centroid, search_maxrank, isin_tokens[i]) LOOP FOR location IN SELECT * from getNearestNamedFeature(NEW.partition, place_centroid, search_maxrank, isin_tokens[i]) LOOP
--RAISE WARNING ' ISIN: %',location; --RAISE WARNING ' ISIN: %',location;
IF location.rank_search > 4 THEN IF location.rank_search > 4 THEN
nameaddress_vector := array_merge(nameaddress_vector, location.keywords::integer[]); nameaddress_vector := array_merge(nameaddress_vector, location.keywords::integer[]);
@@ -1805,8 +1798,6 @@ BEGIN
NEW.centroid := place_centroid; NEW.centroid := place_centroid;
END IF; END IF;
END IF;
RETURN NEW; RETURN NEW;
END; END;
$$ $$
@@ -1841,6 +1832,8 @@ BEGIN
--DEBUG: RAISE WARNING 'placex_delete:06 % %',OLD.osm_type,OLD.osm_id; --DEBUG: RAISE WARNING 'placex_delete:06 % %',OLD.osm_type,OLD.osm_id;
update placex set indexed_status = 2 where parent_place_id = OLD.place_id and indexed_status = 0; update placex set indexed_status = 2 where parent_place_id = OLD.place_id and indexed_status = 0;
--DEBUG: RAISE WARNING 'placex_delete:07 % %',OLD.osm_type,OLD.osm_id; --DEBUG: RAISE WARNING 'placex_delete:07 % %',OLD.osm_type,OLD.osm_id;
-- reparenting also for OSM Interpolation Lines (and for Tiger?)
update location_property_osmline set indexed_status = 2 where indexed_status = 0 and parent_place_id = OLD.place_id;
END IF; END IF;
@@ -1898,8 +1891,8 @@ BEGIN
UPDATE placex set indexed_status = 100 where osm_type = OLD.osm_type and osm_id = OLD.osm_id and class = OLD.class and type = OLD.type; UPDATE placex set indexed_status = 100 where osm_type = OLD.osm_type and osm_id = OLD.osm_id and class = OLD.class and type = OLD.type;
-- interpolations are special -- interpolations are special
IF OLD.class = 'place' and OLD.type = 'houses' THEN IF OLD.osm_type='W' and OLD.class = 'place' and OLD.type = 'houses' THEN
UPDATE placex set indexed_status = 100 where osm_type = OLD.osm_type and osm_id = OLD.osm_id and class = 'place' and type = 'address'; UPDATE location_property_osmline set indexed_status = 100 where osm_id = OLD.osm_id; -- osm_id = wayid (=old.osm_id)
END IF; END IF;
RETURN OLD; RETURN OLD;
@@ -1914,6 +1907,7 @@ DECLARE
i INTEGER; i INTEGER;
existing RECORD; existing RECORD;
existingplacex RECORD; existingplacex RECORD;
existingline RECORD;
existinggeometry GEOMETRY; existinggeometry GEOMETRY;
existingplace_id BIGINT; existingplace_id BIGINT;
result BOOLEAN; result BOOLEAN;
@@ -1922,12 +1916,7 @@ BEGIN
--DEBUG: RAISE WARNING '-----------------------------------------------------------------------------------'; --DEBUG: RAISE WARNING '-----------------------------------------------------------------------------------';
--DEBUG: RAISE WARNING 'place_insert: % % % % %',NEW.osm_type,NEW.osm_id,NEW.class,NEW.type,st_area(NEW.geometry); --DEBUG: RAISE WARNING 'place_insert: % % % % %',NEW.osm_type,NEW.osm_id,NEW.class,NEW.type,st_area(NEW.geometry);
-- filter wrong tupels
IF FALSE and NEW.osm_type = 'R' THEN
select * from placex where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type INTO existingplacex;
--DEBUG: RAISE WARNING '%', existingplacex;
END IF;
IF ST_IsEmpty(NEW.geometry) OR NOT ST_IsValid(NEW.geometry) OR ST_X(ST_Centroid(NEW.geometry))::text in ('NaN','Infinity','-Infinity') OR ST_Y(ST_Centroid(NEW.geometry))::text in ('NaN','Infinity','-Infinity') THEN IF ST_IsEmpty(NEW.geometry) OR NOT ST_IsValid(NEW.geometry) OR ST_X(ST_Centroid(NEW.geometry))::text in ('NaN','Infinity','-Infinity') OR ST_Y(ST_Centroid(NEW.geometry))::text in ('NaN','Infinity','-Infinity') THEN
INSERT INTO import_polygon_error values (NEW.osm_type, NEW.osm_id, NEW.class, NEW.type, NEW.name, NEW.country_code, INSERT INTO import_polygon_error values (NEW.osm_type, NEW.osm_id, NEW.class, NEW.type, NEW.name, NEW.country_code,
now(), ST_IsValidReason(NEW.geometry), null, NEW.geometry); now(), ST_IsValidReason(NEW.geometry), null, NEW.geometry);
@@ -1935,6 +1924,68 @@ BEGIN
RETURN null; RETURN null;
END IF; END IF;
-- decide, whether it is an osm interpolation line => insert_osmline, or else just insert into placex
IF NEW.class='place' and NEW.type='houses' and NEW.osm_type='W' and ST_GeometryType(NEW.geometry) = 'ST_LineString' THEN
-- Have we already done this place?
select * from place where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type INTO existing;
-- Get the existing place_id
select * from location_property_osmline where osm_id = NEW.osm_id INTO existingline;
-- Handle a place changing type by removing the old data (this trigger is executed BEFORE INSERT of the NEW tupel)
IF existing.osm_type IS NULL THEN
DELETE FROM place where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class;
END IF;
DELETE from import_polygon_error where osm_type = NEW.osm_type and osm_id = NEW.osm_id;
DELETE from import_polygon_delete where osm_type = NEW.osm_type and osm_id = NEW.osm_id;
-- update method for interpolation lines: delete all old interpolation lines with same osm_id (update on place) and insert the new one(s) (they can be split up, if they have > 2 nodes)
IF existingline.osm_id IS NOT NULL THEN
delete from location_property_osmline where osm_id = NEW.osm_id;
END IF;
-- for interpolations invalidate all nodes on the line
update placex p set indexed_status = 2
from planet_osm_ways w
where w.id = NEW.osm_id and p.osm_type = 'N' and p.osm_id = any(w.nodes);
-- insert new line into location_property_osmline, use function insert_osmline
IF existing.osm_type IS NULL THEN
i = insert_osmline(NEW.osm_id, NEW.housenumber, NEW.street, NEW.addr_place, NEW.postcode, NEW.country_code, NEW.geometry);
return NEW;
END IF;
IF coalesce(existing.housenumber, '') != coalesce(NEW.housenumber, '')
OR coalesce(existing.street, '') != coalesce(NEW.street, '')
OR coalesce(existing.addr_place, '') != coalesce(NEW.addr_place, '')
OR coalesce(existing.isin, '') != coalesce(NEW.isin, '')
OR coalesce(existing.postcode, '') != coalesce(NEW.postcode, '')
OR coalesce(existing.country_code, '') != coalesce(NEW.country_code, '')
OR existing.geometry::text != NEW.geometry::text
THEN
update place set
name = NEW.name,
housenumber = NEW.housenumber,
street = NEW.street,
addr_place = NEW.addr_place,
isin = NEW.isin,
postcode = NEW.postcode,
country_code = NEW.country_code,
extratags = NEW.extratags,
admin_level = NEW.admin_level,
geometry = NEW.geometry
where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type;
i = insert_osmline(NEW.osm_id, NEW.housenumber, NEW.street, NEW.addr_place, NEW.postcode, NEW.country_code, NEW.geometry);
END IF;
RETURN NULL;
ELSE -- insert to placex
-- Patch in additional country names -- Patch in additional country names
IF NEW.admin_level = 2 AND NEW.type = 'administrative' AND NEW.country_code is not null THEN IF NEW.admin_level = 2 AND NEW.type = 'administrative' AND NEW.country_code is not null THEN
select coalesce(country_name.name || NEW.name,NEW.name) from country_name where country_name.country_code = lower(NEW.country_code) INTO NEW.name; select coalesce(country_name.name || NEW.name,NEW.name) from country_name where country_name.country_code = lower(NEW.country_code) INTO NEW.name;
@@ -2095,6 +2146,7 @@ BEGIN
geometry = NEW.geometry geometry = NEW.geometry
where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type; where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type;
IF NEW.class in ('place','boundary') AND NEW.type in ('postcode','postal_code') THEN IF NEW.class in ('place','boundary') AND NEW.type in ('postcode','postal_code') THEN
IF NEW.postcode IS NULL THEN IF NEW.postcode IS NULL THEN
-- postcode was deleted, no longer retain in placex -- postcode was deleted, no longer retain in placex
@@ -2120,15 +2172,18 @@ BEGIN
geometry = NEW.geometry geometry = NEW.geometry
where place_id = existingplacex.place_id; where place_id = existingplacex.place_id;
-- if a node(=>house), which is part of a interpolation line, changes (e.g. the street attribute) => mark this line for reparenting
-- (already here, because interpolation lines are reindexed before nodes, so in the second call it would be too late)
IF NEW.osm_type='N' and NEW.class='place' and NEW.type='house' THEN
-- Is this node part of an interpolation line? search for it in location_property_osmline and mark the interpolation line for reparenting
update location_property_osmline p set indexed_status = 2 from planet_osm_ways w where p.linegeo && NEW.geometry and p.osm_id = w.id and NEW.osm_id = any(w.nodes);
END IF; END IF;
-- for interpolations invalidate all nodes on the line
IF NEW.class = 'place' and NEW.type = 'houses' and NEW.osm_type = 'W' THEN
update placex p set indexed_status = 2 from planet_osm_ways w where w.id = NEW.osm_id and p.osm_type = 'N' and p.osm_id = any(w.nodes);
END IF; END IF;
-- Abort the add (we modified the existing place instead) -- Abort the add (we modified the existing place instead)
RETURN NULL; RETURN NULL;
END IF;
END; END;
$$ LANGUAGE plpgsql; $$ LANGUAGE plpgsql;
@@ -2242,7 +2297,7 @@ create type addressline as (
CREATE OR REPLACE FUNCTION get_addressdata(in_place_id BIGINT, in_housenumber INTEGER) RETURNS setof addressline CREATE OR REPLACE FUNCTION get_addressdata(in_place_id BIGINT, in_housenumber INTEGER) RETURNS setof addressline
AS $$ AS $$
DECLARE DECLARE
for_place_id BIGINT;--parent_place_id for_place_id BIGINT;
result TEXT[]; result TEXT[];
search TEXT[]; search TEXT[];
found INTEGER; found INTEGER;
@@ -2258,14 +2313,24 @@ DECLARE
countryname HSTORE; countryname HSTORE;
hadcountry BOOLEAN; hadcountry BOOLEAN;
BEGIN BEGIN
--first query tiger data -- first query osmline (interpolation lines)
select parent_place_id, calculated_country_code, 30, postcode, null, 'place', 'house' from location_property_osmline
WHERE place_id = in_place_id AND in_housenumber>=startnumber AND in_housenumber <= endnumber
INTO for_place_id,searchcountrycode, searchrankaddress, searchpostcode, searchhousename, searchclass, searchtype;
IF for_place_id IS NOT NULL THEN
searchhousenumber = in_housenumber::text;
END IF;
--then query tiger data
-- %NOTIGERDATA% IF 0 THEN -- %NOTIGERDATA% IF 0 THEN
IF for_place_id IS NULL THEN
select parent_place_id,'us', 30, postcode, null, 'place', 'house' from location_property_tiger select parent_place_id,'us', 30, postcode, null, 'place', 'house' from location_property_tiger
WHERE place_id = in_place_id AND in_housenumber>=startnumber AND in_housenumber <= endnumber WHERE place_id = in_place_id AND in_housenumber>=startnumber AND in_housenumber <= endnumber
INTO for_place_id,searchcountrycode, searchrankaddress, searchpostcode, searchhousename, searchclass, searchtype; INTO for_place_id,searchcountrycode, searchrankaddress, searchpostcode, searchhousename, searchclass, searchtype;
IF for_place_id IS NOT NULL THEN IF for_place_id IS NOT NULL THEN
searchhousenumber = in_housenumber::text; searchhousenumber = in_housenumber::text;
END IF; END IF;
END IF;
-- %NOTIGERDATA% END IF; -- %NOTIGERDATA% END IF;
-- %NOAUXDATA% IF 0 THEN -- %NOAUXDATA% IF 0 THEN

View File

@@ -17,6 +17,8 @@ CREATE INDEX idx_placex_parent_place_id ON placex USING BTREE (parent_place_id)
CREATE INDEX idx_placex_reverse_geometry ON placex USING gist (geometry) {ts:search-index} where rank_search != 28 and (name is not null or housenumber is not null) and class not in ('waterway','railway','tunnel','bridge','man_made'); CREATE INDEX idx_placex_reverse_geometry ON placex USING gist (geometry) {ts:search-index} where rank_search != 28 and (name is not null or housenumber is not null) and class not in ('waterway','railway','tunnel','bridge','man_made');
CREATE INDEX idx_location_area_country_place_id ON location_area_country USING BTREE (place_id) {ts:address-index}; CREATE INDEX idx_location_area_country_place_id ON location_area_country USING BTREE (place_id) {ts:address-index};
CREATE INDEX idx_osmline_parent_place_id ON location_property_osmline USING BTREE (parent_place_id) {ts:search-index};
CREATE INDEX idx_search_name_country_centroid ON search_name_country USING GIST (centroid) {ts:address-index}; CREATE INDEX idx_search_name_country_centroid ON search_name_country USING GIST (centroid) {ts:address-index};
DROP INDEX IF EXISTS place_id_idx; DROP INDEX IF EXISTS place_id_idx;

View File

@@ -75,6 +75,37 @@ CREATE TABLE location_property (
); );
SELECT AddGeometryColumn('location_property', 'centroid', 4326, 'POINT', 2); SELECT AddGeometryColumn('location_property', 'centroid', 4326, 'POINT', 2);
CREATE TABLE location_property_aux () INHERITS (location_property);
CREATE INDEX idx_location_property_aux_place_id ON location_property_aux USING BTREE (place_id);
CREATE INDEX idx_location_property_aux_parent_place_id ON location_property_aux USING BTREE (parent_place_id);
CREATE INDEX idx_location_property_aux_housenumber_parent_place_id ON location_property_aux USING BTREE (parent_place_id, housenumber);
GRANT SELECT ON location_property_aux TO "{www-user}";
CREATE TABLE location_property_tiger (linegeo GEOMETRY, place_id BIGINT, partition INTEGER, parent_place_id BIGINT, startnumber INTEGER, endnumber INTEGER, interpolationtype TEXT, postcode TEXT);
GRANT SELECT ON location_property_tiger TO "{www-user}";
drop table if exists location_property_osmline;
CREATE TABLE location_property_osmline (
linegeo GEOMETRY,
place_id BIGINT NOT NULL,
partition INTEGER,
osm_id BIGINT,
parent_place_id BIGINT,
startnumber INTEGER,
endnumber INTEGER,
interpolationtype TEXT,
street TEXT,
addr_place TEXT,
postcode TEXT,
calculated_country_code VARCHAR(2),
geometry_sector INTEGER,
indexed_status INTEGER,
indexed_date TIMESTAMP){ts:search-data};
CREATE UNIQUE INDEX idx_osmline_place_id ON location_property_osmline USING BTREE (place_id) {ts:search-index};
CREATE INDEX idx_osmline_geometry_sector ON location_property_osmline USING BTREE (geometry_sector) {ts:address-index};
CREATE INDEX idx_osmline_linegeo ON location_property_osmline USING GIST (linegeo) {ts:search-index};
GRANT SELECT ON location_property_osmline TO "{www-user}";
drop table IF EXISTS search_name; drop table IF EXISTS search_name;
CREATE TABLE search_name ( CREATE TABLE search_name (
place_id BIGINT, place_id BIGINT,
@@ -133,13 +164,15 @@ GRANT SELECT ON planet_osm_ways to "{www-user}" ;
GRANT SELECT ON planet_osm_rels to "{www-user}" ; GRANT SELECT ON planet_osm_rels to "{www-user}" ;
GRANT SELECT on location_area to "{www-user}" ; GRANT SELECT on location_area to "{www-user}" ;
-- insert creates the location tagbles, creates location indexes if indexed == true -- insert creates the location tables, creates location indexes if indexed == true
CREATE TRIGGER placex_before_insert BEFORE INSERT ON placex CREATE TRIGGER placex_before_insert BEFORE INSERT ON placex
FOR EACH ROW EXECUTE PROCEDURE placex_insert(); FOR EACH ROW EXECUTE PROCEDURE placex_insert();
-- update insert creates the location tables -- update insert creates the location tables
CREATE TRIGGER placex_before_update BEFORE UPDATE ON placex CREATE TRIGGER placex_before_update BEFORE UPDATE ON placex
FOR EACH ROW EXECUTE PROCEDURE placex_update(); FOR EACH ROW EXECUTE PROCEDURE placex_update();
CREATE TRIGGER osmline_before_update BEFORE UPDATE ON location_property_osmline
FOR EACH ROW EXECUTE PROCEDURE osmline_update();
-- diff update triggers -- diff update triggers
CREATE TRIGGER placex_before_delete AFTER DELETE ON placex CREATE TRIGGER placex_before_delete AFTER DELETE ON placex

View File

@@ -19,6 +19,9 @@ Feature: Reverse geocoding
When looking up coordinates 53.9788769,13.0830313 When looking up coordinates 53.9788769,13.0830313
And results contain valid boundingboxes And results contain valid boundingboxes
Scenario: Reverse geocoding for odd interpolated housenumber
Scenario: Reverse geocoding for even interpolated housenumber
@Tiger @Tiger
Scenario: TIGER house number Scenario: TIGER house number

View File

@@ -2,41 +2,23 @@
Feature: Import of address interpolations Feature: Import of address interpolations
Tests that interpolated addresses are added correctly Tests that interpolated addresses are added correctly
Scenario: Simple even two point interpolation Scenario: Simple even interpolation line with two points
Given the place nodes Given the place nodes
| osm_id | class | type | housenumber | geometry | osm_id | osm_type | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1 | 1 | N | place | house | 2 | 1 1
| 2 | place | house | 6 | 1 1.001 | 2 | N | place | house | 6 | 1 1.001
And the place ways And the place ways
| osm_id | class | type | housenumber | geometry | osm_id | osm_type | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1, 1 1.001 | 1 | W | place | houses | even | 1 1, 1 1.001
And the ways And the ways
| id | nodes | id | nodes
| 1 | 1,2 | 1 | 1,2
When importing When importing
Then way 1 expands to housenumbers Then way 1 expands to lines
| housenumber | centroid | startnumber | endnumber | geometry
| 4 | 1,1.0005 | 2 | 6 | 1 1, 1 1.001
Scenario: Simple even two point interpolation with zero beginning Scenario: Backwards even two point interpolation line
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 0 | 1 1
| 2 | place | house | 8 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1, 1 1.001
And the ways
| id | nodes
| 1 | 1,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 2 | 1,1.00025
| 4 | 1,1.0005
| 6 | 1,1.00075
Scenario: Backwards even two point interpolation
Given the place nodes Given the place nodes
| osm_id | class | type | housenumber | geometry | osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1 | 1 | place | house | 2 | 1 1
@@ -48,77 +30,9 @@ Feature: Import of address interpolations
| id | nodes | id | nodes
| 1 | 2,1 | 1 | 2,1
When importing When importing
Then way 1 expands to housenumbers Then way 1 expands to lines
| housenumber | centroid | startnumber | endnumber | geometry
| 4 | 1,1.0005 | 2 | 6 | 1 1, 1 1.001
Scenario: Even two point interpolation with odd beginning
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 11 | 1 1
| 2 | place | house | 16 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1, 1 1.001
And the ways
| id | nodes
| 1 | 1,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 12 | 1,1.0002
| 14 | 1,1.0006
Scenario: Even two point interpolation with odd end
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 10 | 1 1
| 2 | place | house | 15 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1, 1 1.001
And the ways
| id | nodes
| 1 | 1,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 12 | 1,1.0004
| 14 | 1,1.0008
Scenario: Reverse even two point interpolation with odd beginning
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 11 | 1 1
| 2 | place | house | 16 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1.001, 1 1
And the ways
| id | nodes
| 1 | 2,1
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 12 | 1,1.0002
| 14 | 1,1.0006
Scenario: Reverse even two point interpolation with odd end
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 10 | 1 1
| 2 | place | house | 15 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | 1 1.001, 1 1
And the ways
| id | nodes
| 1 | 2,1
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 12 | 1,1.0004
| 14 | 1,1.0008
Scenario: Simple odd two point interpolation Scenario: Simple odd two point interpolation
Given the place nodes Given the place nodes
@@ -132,29 +46,9 @@ Feature: Import of address interpolations
| id | nodes | id | nodes
| 1 | 1,2 | 1 | 1,2
When importing When importing
Then way 1 expands to housenumbers Then way 1 expands to lines
| housenumber | centroid | startnumber | endnumber | geometry
| 3 | 1,1.0002 | 1 | 11 | 1 1, 1 1.001
| 5 | 1,1.0004
| 7 | 1,1.0006
| 9 | 1,1.0008
Scenario: Odd two point interpolation with even beginning
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1
| 2 | place | house | 7 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | odd | 1 1, 1 1.001
And the ways
| id | nodes
| 1 | 1,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 3 | 1,1.0002
| 5 | 1,1.0006
Scenario: Simple all two point interpolation Scenario: Simple all two point interpolation
Given the place nodes Given the place nodes
@@ -168,27 +62,11 @@ Feature: Import of address interpolations
| id | nodes | id | nodes
| 1 | 1,2 | 1 | 1,2
When importing When importing
Then way 1 expands to housenumbers Then way 1 expands to lines
| housenumber | centroid | startnumber | endnumber | geometry
| 2 | 1,1.0005 | 1 | 3 | 1 1, 1 1.001
Scenario: Simple numbered two point interpolation Scenario: Even two point interpolation line with intermediate empty node
Given the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 3 | 1 1
| 2 | place | house | 9 | 1 1.001
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | 3 | 1 1, 1 1.001
And the ways
| id | nodes
| 1 | 1,2
When importing
Then way 1 expands to housenumbers
| housenumber | centroid
| 6 | 1,1.0005
Scenario: Even two point interpolation with intermediate empty node
Given the place nodes Given the place nodes
| osm_id | class | type | housenumber | geometry | osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1 | 1 | place | house | 2 | 1 1
@@ -200,14 +78,11 @@ Feature: Import of address interpolations
| id | nodes | id | nodes
| 1 | 1,3,2 | 1 | 1,3,2
When importing When importing
Then way 1 expands to housenumbers Then way 1 expands to lines
| housenumber | centroid | startnumber | endnumber | geometry
| 4 | 1,1.0005 | 2 | 10 | 1 1, 1 1.001, 1.001 1.001
| 6 | 1,1.001
| 8 | 1.0005,1.001
Scenario: Even two point interpolation line with intermediate duplicated empty node
Scenario: Even two point interpolation with intermediate duplicated empty node
Given the place nodes Given the place nodes
| osm_id | class | type | housenumber | geometry | osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1 | 1 | place | house | 2 | 1 1
@@ -219,13 +94,11 @@ Feature: Import of address interpolations
| id | nodes | id | nodes
| 1 | 1,3,3,2 | 1 | 1,3,3,2
When importing When importing
Then way 1 expands to housenumbers Then way 1 expands to lines
| housenumber | centroid | startnumber | endnumber | geometry
| 4 | 1,1.0005 | 2 | 10 | 1 1, 1 1.001, 1.001 1.001
| 6 | 1,1.001
| 8 | 1.0005,1.001
Scenario: Simple even three point interpolation Scenario: Simple even three point interpolation line
Given the place nodes Given the place nodes
| osm_id | class | type | housenumber | geometry | osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1 | 1 | place | house | 2 | 1 1
@@ -238,14 +111,12 @@ Feature: Import of address interpolations
| id | nodes | id | nodes
| 1 | 1,3,2 | 1 | 1,3,2
When importing When importing
Then way 1 expands to housenumbers Then way 1 expands to lines
| housenumber | centroid | startnumber | endnumber | geometry
| 4 | 1,1.00025 | 2 | 10 | 1 1, 1 1.001
| 6 | 1,1.0005 | 10 | 14 | 1 1.001, 1.001 1.001
| 8 | 1,1.00075
| 12 | 1.0005,1.001
Scenario: Simple even four point interpolation Scenario: Simple even four point interpolation line
Given the place nodes Given the place nodes
| osm_id | class | type | housenumber | geometry | osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1 | 1 | place | house | 2 | 1 1
@@ -259,15 +130,13 @@ Feature: Import of address interpolations
| id | nodes | id | nodes
| 1 | 1,3,2,4 | 1 | 1,3,2,4
When importing When importing
Then way 1 expands to housenumbers Then way 1 expands to lines
| housenumber | centroid | startnumber | endnumber | geometry
| 4 | 1,1.00025 | 2 | 10 | 1 1, 1 1.001
| 6 | 1,1.0005 | 10 | 14 | 1 1.001, 1.001 1.001
| 8 | 1,1.00075 | 14 | 18 | 1.001 1.001, 1.001 1.002
| 12 | 1.0005,1.001
| 16 | 1.001,1.0015
Scenario: Reverse simple even three point interpolation Scenario: Reverse simple even three point interpolation line
Given the place nodes Given the place nodes
| osm_id | class | type | housenumber | geometry | osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1 | 1 | place | house | 2 | 1 1
@@ -280,14 +149,12 @@ Feature: Import of address interpolations
| id | nodes | id | nodes
| 1 | 2,3,1 | 1 | 2,3,1
When importing When importing
Then way 1 expands to housenumbers Then way 1 expands to lines
| housenumber | centroid | startnumber | endnumber | geometry
| 4 | 1,1.00025 | 2 | 10 | 1 1, 1 1.001
| 6 | 1,1.0005 | 10 | 14 | 1 1.001, 1.001 1.001
| 8 | 1,1.00075
| 12 | 1.0005,1.001
Scenario: Even three point interpolation with odd center point Scenario: Even three point interpolation line with odd center point
Given the place nodes Given the place nodes
| osm_id | class | type | housenumber | geometry | osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 1 1 | 1 | place | house | 2 | 1 1
@@ -300,12 +167,12 @@ Feature: Import of address interpolations
| id | nodes | id | nodes
| 1 | 1,3,2 | 1 | 1,3,2
When importing When importing
Then way 1 expands to housenumbers Then way 1 expands to lines
| housenumber | centroid | startnumber | endnumber | geometry
| 4 | 1,1.0004 | 2 | 7 | 1 1, 1 1.001
| 6 | 1,1.0008 | 7 | 8 | 1 1.001, 1.001 1.001
Scenario: Interpolation on self-intersecting way Scenario: Interpolation line with self-intersecting way
Given the place nodes Given the place nodes
| osm_id | class | type | housenumber | geometry | osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 0 0 | 1 | place | house | 2 | 0 0
@@ -318,12 +185,13 @@ Feature: Import of address interpolations
| id | nodes | id | nodes
| 1 | 1,2,3,2 | 1 | 1,2,3,2
When importing When importing
Then way 1 expands to housenumbers Then way 1 expands to lines
| housenumber | centroid | startnumber | endnumber | geometry
| 4 | 0,0.0005 | 2 | 6 | 0 0, 0 0.001
| 8 | 0,0.0015 | 6 | 10 | 0 0.001, 0 0.002
| 6 | 10 | 0 0.001, 0 0.002
Scenario: Interpolation on self-intersecting way II Scenario: Interpolation line with self-intersecting way II
Given the place nodes Given the place nodes
| osm_id | class | type | housenumber | geometry | osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | 0 0 | 1 | place | house | 2 | 0 0
@@ -335,9 +203,9 @@ Feature: Import of address interpolations
| id | nodes | id | nodes
| 1 | 1,2,3,2 | 1 | 1,2,3,2
When importing When importing
Then way 1 expands to housenumbers Then way 1 expands to lines
| housenumber | centroid | startnumber | endnumber | geometry
| 4 | 0,0.0005 | 2 | 6 | 0 0, 0 0.001
Scenario: addr:street on interpolation way Scenario: addr:street on interpolation way
@@ -367,10 +235,10 @@ Feature: Import of address interpolations
| N2 | W2 | N2 | W2
| N3 | W3 | N3 | W3
| N4 | W3 | N4 | W3
| W10 | W2 Then table location_property_osmline contains
| W11 | W3 | object | parent_place_id | startnumber | endnumber
And way 10 expands exactly to housenumbers 4 | W10 | W2 | 2 | 6
And way 11 expands exactly to housenumbers 14 | W11 | W3 | 12 | 16
Scenario: addr:street on housenumber way Scenario: addr:street on housenumber way
Given the scene parallel-road Given the scene parallel-road
@@ -399,10 +267,10 @@ Feature: Import of address interpolations
| N2 | W2 | N2 | W2
| N3 | W3 | N3 | W3
| N4 | W3 | N4 | W3
| W10 | W2 And table location_property_osmline contains
| W11 | W3 | object | parent_place_id | startnumber | endnumber
And way 10 expands exactly to housenumbers 4 | W10 | W2 | 2 | 6
And way 11 expands exactly to housenumbers 14 | W11 | W3 | 12 | 16
Scenario: Geometry of points and way don't match (github #253) Scenario: Geometry of points and way don't match (github #253)
Given the place nodes Given the place nodes
@@ -417,10 +285,10 @@ Feature: Import of address interpolations
| id | nodes | id | nodes
| 1 | 1,2,3 | 1 | 1,2,3
When importing When importing
Then way 1 expands to housenumbers Then way 1 expands to lines
| housenumber | centroid | startnumber | endnumber | geometry
| 4 | 144.963016723312,-37.7629464422819+-0.000005 | 2 | 6 | 144.9629794 -37.7630755, 144.9630541 -37.7628174
| 8 | 144.9631440856,-37.762223694978+-0.000005 | 6 | 10 | 144.9630541 -37.7628174, 144.9632341 -37.76163
Scenario: Place with missing address information Scenario: Place with missing address information
Given the place nodes Given the place nodes
@@ -435,7 +303,6 @@ Feature: Import of address interpolations
| id | nodes | id | nodes
| 1 | 1,2,3 | 1 | 1,2,3
When importing When importing
Then way 1 expands to housenumbers Then way 1 expands to lines
| housenumber | centroid | startnumber | endnumber | geometry
| 25 | 0.0001,0.0002 | 23 | 29 | 0.0001 0.0001, 0.0001 0.0002, 0.0001 0.0004
| 27 | 0.0001,0.0003

View File

@@ -23,19 +23,20 @@ Feature: Update of address interpolations
| object | parent_place_id | object | parent_place_id
| N1 | W2 | N1 | W2
| N2 | W2 | N2 | W2
| W10 | W2 And table location_property_osmline contains
And way 10 expands exactly to housenumbers 4 | object | parent_place_id | startnumber | endnumber
| W10 | W2 | 2 | 6
When updating place ways When updating place ways
| osm_id | class | type | housenumber | street | geometry | osm_id | class | type | housenumber | street | geometry
| 10 | place | houses | even | Cloud Street | :w-middle | 10 | place | houses | even | Cloud Street | :w-middle
Then way 10 expands exactly to housenumbers 4 Then table placex contains
And table placex contains
| object | parent_place_id | object | parent_place_id
| N1 | W3 | N1 | W3
| N2 | W3 | N2 | W3
| W10 | W3 And table location_property_osmline contains
| object | parent_place_id | startnumber | endnumber
| W10 | W3 | 2 | 6
@Fail
Scenario: addr:street added to housenumbers Scenario: addr:street added to housenumbers
Given the scene parallel-road Given the scene parallel-road
And the place nodes And the place nodes
@@ -57,18 +58,20 @@ Feature: Update of address interpolations
| object | parent_place_id | object | parent_place_id
| N1 | W2 | N1 | W2
| N2 | W2 | N2 | W2
| W10 | W2 And table location_property_osmline contains
And way 10 expands exactly to housenumbers 4 | object | parent_place_id | startnumber | endnumber
| W10 | W2 | 2 | 6
When updating place nodes When updating place nodes
| osm_id | class | type | street | housenumber | geometry | osm_id | class | type | street | housenumber | geometry
| 1 | place | house | Cloud Street| 2 | :n-middle-w | 1 | place | house | Cloud Street| 2 | :n-middle-w
| 2 | place | house | Cloud Street| 6 | :n-middle-e | 2 | place | house | Cloud Street| 6 | :n-middle-e
Then way 10 expands exactly to housenumbers 4 Then table placex contains
And table placex contains
| object | parent_place_id | object | parent_place_id
| N1 | W3 | N1 | W3
| N2 | W3 | N2 | W3
| W10 | W3 And table location_property_osmline contains
| object | parent_place_id | startnumber | endnumber
| W10 | W3 | 2 | 6
Scenario: interpolation tag removed Scenario: interpolation tag removed
@@ -92,10 +95,11 @@ Feature: Update of address interpolations
| object | parent_place_id | object | parent_place_id
| N1 | W2 | N1 | W2
| N2 | W2 | N2 | W2
| W10 | W2 And table location_property_osmline contains
And way 10 expands exactly to housenumbers 4 | object | parent_place_id | startnumber | endnumber
| W10 | W2 | 2 | 6
When marking for delete W10 When marking for delete W10
Then way 10 expands to no housenumbers Then table location_property_osmline has no entry for W10
And table placex contains And table placex contains
| object | parent_place_id | object | parent_place_id
| N1 | W2 | N1 | W2
@@ -122,17 +126,19 @@ Feature: Update of address interpolations
| object | parent_place_id | object | parent_place_id
| N1 | W2 | N1 | W2
| N2 | W2 | N2 | W2
| W10 | W2 And table location_property_osmline contains
And way 10 expands exactly to housenumbers 4 | object | parent_place_id | startnumber | endnumber
| W10 | W2 | 2 | 6
When updating place ways When updating place ways
| osm_id | class | type | name | geometry | osm_id | class | type | name | geometry
| 3 | highway | unclassified | 'name' : 'Cloud Street' | :w-south | 3 | highway | unclassified | 'name' : 'Cloud Street' | :w-south
Then way 10 expands exactly to housenumbers 4 Then table placex contains
And table placex contains
| object | parent_place_id | object | parent_place_id
| N1 | W3 | N1 | W3
| N2 | W3 | N2 | W3
| W10 | W3 And table location_property_osmline contains
| object | parent_place_id | startnumber | endnumber
| W10 | W3 | 2 | 6
Scenario: referenced road deleted Scenario: referenced road deleted
@@ -156,12 +162,97 @@ Feature: Update of address interpolations
| object | parent_place_id | object | parent_place_id
| N1 | W3 | N1 | W3
| N2 | W3 | N2 | W3
| W10 | W3 And table location_property_osmline contains
And way 10 expands exactly to housenumbers 4 | object | parent_place_id | startnumber | endnumber
| W10 | W3 | 2 | 6
When marking for delete W3 When marking for delete W3
Then way 10 expands exactly to housenumbers 4 Then table placex contains
And table placex contains
| object | parent_place_id | object | parent_place_id
| N1 | W2 | N1 | W2
| N2 | W2 | N2 | W2
| W10 | W2 And table location_property_osmline contains
| object | parent_place_id | startnumber | endnumber
| W10 | W2 | 2 | 6
Scenario: building becomes interpolation
Given the scene building-with-parallel-streets
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 3 | :w-building
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | unclassified | 'name' : 'Cloud Street' | :w-south
When importing
Then table placex contains
| object | parent_place_id
| W1 | W2
When updating place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | :n-north-w
| 2 | place | house | 6 | :n-north-e
And the ways
| id | nodes
| 1 | 1,100,101,102,2
And updating place ways
| osm_id | class | type | housenumber | street | geometry
| 1 | place | houses | even | Cloud Street| :w-north
Then table placex has no entry for W1
And table location_property_osmline contains
| object | parent_place_id | startnumber | endnumber
| W1 | W2 | 2 | 6
Scenario: interpolation becomes building
Given the scene building-with-parallel-streets
And the place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | :n-north-w
| 2 | place | house | 6 | :n-north-e
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | unclassified | 'name' : 'Cloud Street' | :w-south
And the ways
| id | nodes
| 1 | 1,100,101,102,2
And the place ways
| osm_id | class | type | housenumber | street | geometry
| 1 | place | houses | even | Cloud Street| :w-north
When importing
Then table placex has no entry for W1
And table location_property_osmline contains
| object | parent_place_id | startnumber | endnumber
| W1 | W2 | 2 | 6
When updating place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 3 | :w-building
Then table placex contains
| object | parent_place_id
| W1 | W2
Scenario: housenumbers added to interpolation
Given the scene building-with-parallel-streets
And the place ways
| osm_id | class | type | name | geometry
| 2 | highway | unclassified | 'name' : 'Cloud Street' | :w-south
And the ways
| id | nodes
| 1 | 1,100,101,102,2
And the place ways
| osm_id | class | type | housenumber | geometry
| 1 | place | houses | even | :w-north
When importing
Then table location_property_osmline has no entry for W1
When updating place nodes
| osm_id | class | type | housenumber | geometry
| 1 | place | house | 2 | :n-north-w
| 2 | place | house | 6 | :n-north-e
And updating place ways
| osm_id | class | type | housenumber | street | geometry
| 1 | place | houses | even | Cloud Street| :w-north
Then table location_property_osmline contains
| object | parent_place_id | startnumber | endnumber
| W1 | W2 | 2 | 6

View File

@@ -24,3 +24,4 @@ osm2wkt: osm2wkt.cc
$(CXX) $(CXXFLAGS) $(CXXFLAGS_WARNINGS) -o $@ $< $(LDFLAGS) $(LIB_IO) $(CXX) $(CXXFLAGS) $(CXXFLAGS_WARNINGS) -o $@ $< $(LDFLAGS) $(LIB_IO)
scenarios: osm2wkt scenarios: osm2wkt
./make_scenes.sh

View File

@@ -1,4 +1,4 @@
#/bin/bash -e #!/bin/bash -e
# #
# Regenerates wkts for scenarios. # Regenerates wkts for scenarios.
# #
@@ -11,10 +11,10 @@ if [ ! -d "$datadir" ]; then
fi fi
echo "Using datadir $datadir" echo "Using datadir $datadir"
pushd $datadir cd $datadir
# remove old wkts # remove old wkts
rm $datadir/*.wkt rm -f $datadir/*.wkt
# create wkts from SQL scripts # create wkts from SQL scripts
for fl in *.sql; do for fl in *.sql; do
@@ -27,5 +27,3 @@ for fl in *.osm; do
echo "Processing $fl.." echo "Processing $fl.."
../bin/osm2wkt $fl ../bin/osm2wkt $fl
done done
popd

View File

@@ -92,10 +92,6 @@ int main(int argc, char* argv[]) {
reader2.close(); reader2.close();
export_handler.close(); export_handler.close();
std::cerr << "Pass 2 done\n"; std::cerr << "Pass 2 done\n";
google::protobuf::ShutdownProtobufLibrary();
} }

View File

@@ -0,0 +1,7 @@
n-south-w | POINT(1.0031633 2.001023)
n-south-e | POINT(1.0043359 2.0010068)
n-north-w | POINT(1.0031511 2.0012655)
n-north-e | POINT(1.0043238 2.0012493)
w-south | LINESTRING(1.0031633 2.001023,1.0036943 2.0010149,1.0040717 2.0010203,1.0043359 2.0010068)
w-north | LINESTRING(1.0031511 2.0012655,1.0036822 2.0012574,1.0040596 2.0012628,1.0043238 2.0012493)
w-building | LINESTRING(1.0036157 2.0011891,1.0036166 2.0010787,1.0038457 2.0010805,1.0038448 2.001191,1.0036157 2.0011891)

View File

@@ -56,7 +56,7 @@
cz | POINT(16.3209805488586 49.5069274902344) cz | POINT(16.3209805488586 49.5069274902344)
de | POINT(9.30716800689697 50.2128944396973) de | POINT(9.30716800689697 50.2128944396973)
dj | POINT(42.969040422876 11.41542855) dj | POINT(42.969040422876 11.41542855)
dk | POINT(9.18490123748779 55.5634002685547) dk | POINT(9.18490123748779 55.9891662597656)
dm | POINT(-61.0035801928854 15.6547055) dm | POINT(-61.0035801928854 15.6547055)
do | POINT(-69.6285591125488 18.5884169089722) do | POINT(-69.6285591125488 18.5884169089722)
dz | POINT(4.24749487638474 25.797215461731) dz | POINT(4.24749487638474 25.797215461731)
@@ -69,7 +69,7 @@
et | POINT(38.6169757843018 7.71399855613708) et | POINT(38.6169757843018 7.71399855613708)
fi | POINT(26.8979873657227 63.5619449615479) fi | POINT(26.8979873657227 63.5619449615479)
fj | POINT(177.918533325195 -17.7423753738403) fj | POINT(177.918533325195 -17.7423753738403)
fk | POINT(-60.0855102539062 -51.6555919647217) fk | POINT(-58.9904479980469 -51.3450936007813)
fm | POINT(151.9535889125 8.5045) fm | POINT(151.9535889125 8.5045)
fo | POINT(-6.60483694084778 62.10000995) fo | POINT(-6.60483694084778 62.10000995)
fr | POINT(0.284105718135834 47.5104522705078) fr | POINT(0.284105718135834 47.5104522705078)
@@ -105,7 +105,7 @@
in | POINT(88.6762087020508 27.86155515) in | POINT(88.6762087020508 27.86155515)
io | POINT(71.4274391359073 -6.14349685) io | POINT(71.4274391359073 -6.14349685)
iq | POINT(42.5810985565186 34.2610359191895) iq | POINT(42.5810985565186 34.2610359191895)
ir | POINT(51.268892288208 34.1931705474854) ir | POINT(56.0935573577881 30.4675178527832)
is | POINT(-17.5178508758545 64.7168769836426) is | POINT(-17.5178508758545 64.7168769836426)
it | POINT(10.4263944625854 44.8790493011475) it | POINT(10.4263944625854 44.8790493011475)
je | POINT(-2.19261599848299 49.1245833) je | POINT(-2.19261599848299 49.1245833)
@@ -156,7 +156,7 @@
mw | POINT(33.9572296142578 -12.2821822166443) mw | POINT(33.9572296142578 -12.2821822166443)
mx | POINT(-105.892219543457 25.8682699203491) mx | POINT(-105.892219543457 25.8682699203491)
my | POINT(112.711540222168 2.10098683834076) my | POINT(112.711540222168 2.10098683834076)
mz | POINT(37.5868968963623 -15.5801844596863) mz | POINT(37.5868968963623 -13.7268223762512)
na | POINT(16.6856970787048 -21.4657220840454) na | POINT(16.6856970787048 -21.4657220840454)
nc | POINT(164.953224182129 -20.3888988494873) nc | POINT(164.953224182129 -20.3888988494873)
ne | POINT(10.060417175293 19.0827360153198) ne | POINT(10.060417175293 19.0827360153198)
@@ -204,7 +204,7 @@
sm | POINT(12.4606268797657 43.9427969) sm | POINT(12.4606268797657 43.9427969)
sn | POINT(-15.3711128234863 14.9947791099548) sn | POINT(-15.3711128234863 14.9947791099548)
so | POINT(46.9338359832764 9.34094429016113) so | POINT(46.9338359832764 9.34094429016113)
sr | POINT(-56.4855213165283 4.5773549079895) sr | POINT(-55.4286479949951 4.5698549747467)
ss | POINT(28.1357345581055 8.50933408737183) ss | POINT(28.1357345581055 8.50933408737183)
st | POINT(6.61025854583333 0.2215) st | POINT(6.61025854583333 0.2215)
sv | POINT(-89.3666543301004 13.4307287) sv | POINT(-89.3666543301004 13.4307287)

View File

@@ -1,347 +1,399 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<osm version='0.6' upload='false' generator='JOSM'> <osm version='0.6' upload='false' generator='JOSM'>
<node id='-197' action='modify' visible='true' lat='2.0006515863' lon='1.0057464449'> <node id='-11' action='modify' visible='true' lat='2.0006515863' lon='1.0057464449'>
<tag k='name' v='split-road' /> <tag k='name' v='split-road' />
</node> </node>
<node id='-195' action='modify' visible='true' lat='2.00053508276' lon='1.00574909433' /> <node id='-13' action='modify' visible='true' lat='2.00053508276' lon='1.00574909433' />
<node id='-193' action='modify' visible='true' lat='2.00054302619' lon='1.00589746199' /> <node id='-15' action='modify' visible='true' lat='2.00054302619' lon='1.00589746199' />
<node id='-191' action='modify' visible='true' lat='2.00054302619' lon='1.0060511285' /> <node id='-17' action='modify' visible='true' lat='2.00054302619' lon='1.0060511285' />
<node id='-189' action='modify' visible='true' lat='2.00053243496' lon='1.00613061118' /> <node id='-19' action='modify' visible='true' lat='2.00053243496' lon='1.00613061118' />
<node id='-187' action='modify' visible='true' lat='2.00052449153' lon='1.00551064629' /> <node id='-21' action='modify' visible='true' lat='2.00052449153' lon='1.00551064629' />
<node id='-185' action='modify' visible='true' lat='2.00056685646' lon='1.00560867493' /> <node id='-23' action='modify' visible='true' lat='2.00056685646' lon='1.00560867493' />
<node id='-183' action='modify' visible='true' lat='2.00056156084' lon='1.00568550818' /> <node id='-25' action='modify' visible='true' lat='2.00056156084' lon='1.00568550818' />
<node id='-181' action='modify' visible='true' lat='2.00050066126' lon='1.00573584721' /> <node id='-27' action='modify' visible='true' lat='2.00050066126' lon='1.00573584721' />
<node id='-179' action='modify' visible='true' lat='2.00050595688' lon='1.0059107091' /> <node id='-29' action='modify' visible='true' lat='2.00050595688' lon='1.0059107091' />
<node id='-177' action='modify' visible='true' lat='2.00051125249' lon='1.00605377792' /> <node id='-31' action='modify' visible='true' lat='2.00051125249' lon='1.00605377792' />
<node id='-175' action='modify' visible='true' lat='2.00049536565' lon='1.00613591002' /> <node id='-33' action='modify' visible='true' lat='2.00049536565' lon='1.00613591002' />
<node id='-173' action='modify' visible='true' lat='2.0005139003' lon='1.00628427769' /> <node id='-35' action='modify' visible='true' lat='2.0005139003' lon='1.00628427769' />
<node id='-171' action='modify' visible='true' lat='2.00047153538' lon='1.00637170863' /> <node id='-37' action='modify' visible='true' lat='2.00047153538' lon='1.00637170863' />
<node id='-169' action='modify' visible='true' lat='2.00029678005' lon='1.00635846152' /> <node id='-39' action='modify' visible='true' lat='2.00029678005' lon='1.00635846152' />
<node id='-167' action='modify' visible='true' lat='2.00026235854' lon='1.00628162826' /> <node id='-41' action='modify' visible='true' lat='2.00026235854' lon='1.00628162826' />
<node id='-165' action='modify' visible='true' lat='2.00033914498' lon='1.00619949616' /> <node id='-43' action='modify' visible='true' lat='2.00033914498' lon='1.00619949616' />
<node id='-163' action='modify' visible='true' lat='2.00035767963' lon='1.00610411695' /> <node id='-45' action='modify' visible='true' lat='2.00035767963' lon='1.00610411695' />
<node id='-161' action='modify' visible='true' lat='2.00034973621' lon='1.00600343889' /> <node id='-47' action='modify' visible='true' lat='2.00034973621' lon='1.00600343889' />
<node id='-159' action='modify' visible='true' lat='2.00032590594' lon='1.0058868643' /> <node id='-49' action='modify' visible='true' lat='2.00032590594' lon='1.0058868643' />
<node id='-157' action='modify' visible='true' lat='2.0002808932' lon='1.00579413451' /> <node id='-51' action='modify' visible='true' lat='2.0002808932' lon='1.00579413451' />
<node id='-155' action='modify' visible='true' lat='2.00027824539' lon='1.00563516915' /> <node id='-53' action='modify' visible='true' lat='2.00027824539' lon='1.00563516915' />
<node id='-153' action='modify' visible='true' lat='2.00036032744' lon='1.00547090495' /> <node id='-55' action='modify' visible='true' lat='2.00036032744' lon='1.00547090495' />
<node id='-151' action='modify' visible='true' lat='2.00072654218' lon='1.00470543134'> <node id='-57' action='modify' visible='true' lat='2.00072654218' lon='1.00470543134'>
<tag k='name' v='points-on-road' /> <tag k='name' v='points-on-road' />
</node> </node>
<node id='-149' action='modify' visible='true' lat='2.00051552538' lon='1.00492201384' /> <node id='-59' action='modify' visible='true' lat='2.00051552538' lon='1.00492201384' />
<node id='-147' action='modify' visible='true' lat='2.00051552538' lon='1.00492201384'> <node id='-61' action='modify' visible='true' lat='2.00051552538' lon='1.00492201384'>
<tag k='test:id' v='n-N-unglued' /> <tag k='test:id' v='n-N-unglued' />
<tag k='test:section' v='points-on-roads' /> <tag k='test:section' v='points-on-roads' />
</node> </node>
<node id='-145' action='modify' visible='true' lat='2.00029485534' lon='1.00462587591'> <node id='-63' action='modify' visible='true' lat='2.00029485534' lon='1.00462587591'>
<tag k='test:id' v='n-S-unglued' /> <tag k='test:id' v='n-S-unglued' />
<tag k='test:section' v='points-on-roads' /> <tag k='test:section' v='points-on-roads' />
</node> </node>
<node id='-143' action='modify' visible='true' lat='2.00029485534' lon='1.00462587591' /> <node id='-65' action='modify' visible='true' lat='2.00029485534' lon='1.00462587591' />
<node id='-141' action='modify' visible='true' lat='2.00061177404' lon='1.00506613814'> <node id='-67' action='modify' visible='true' lat='2.00061177404' lon='1.00506613814'>
<tag k='test:id' v='n-NE' /> <tag k='test:id' v='n-NE' />
<tag k='test:section' v='points-on-roads' /> <tag k='test:section' v='points-on-roads' />
</node> </node>
<node id='-139' action='modify' visible='true' lat='2.00033485479' lon='1.00513387079'> <node id='-69' action='modify' visible='true' lat='2.00033485479' lon='1.00513387079'>
<tag k='test:id' v='n-SE' /> <tag k='test:id' v='n-SE' />
<tag k='test:section' v='points-on-roads' /> <tag k='test:section' v='points-on-roads' />
</node> </node>
<node id='-137' action='modify' visible='true' lat='2.00062408156' lon='1.00531551745' /> <node id='-71' action='modify' visible='true' lat='2.00062408156' lon='1.00531551745' />
<node id='-135' action='modify' visible='true' lat='2.00040869993' lon='1.00475826245'> <node id='-73' action='modify' visible='true' lat='2.00040869993' lon='1.00475826245'>
<tag k='test:id' v='n-NW' /> <tag k='test:id' v='n-NW' />
<tag k='test:section' v='points-on-roads' /> <tag k='test:section' v='points-on-roads' />
</node> </node>
<node id='-133' action='modify' visible='true' lat='2.00038408489' lon='1.00462587591' /> <node id='-75' action='modify' visible='true' lat='2.00038408489' lon='1.00462587591' />
<node id='-131' action='modify' visible='true' lat='2.00043023809' lon='1.00449964688' /> <node id='-77' action='modify' visible='true' lat='2.00043023809' lon='1.00449964688' />
<node id='-129' action='modify' visible='true' lat='2.00036870048' lon='1.00532783248' /> <node id='-79' action='modify' visible='true' lat='2.00036870048' lon='1.00532783248' />
<node id='-127' action='modify' visible='true' lat='2.00026408654' lon='1.00493683035' /> <node id='-81' action='modify' visible='true' lat='2.00026408654' lon='1.00493683035' />
<node id='-125' action='modify' visible='true' lat='2.00029177846' lon='1.00482599511' /> <node id='-83' action='modify' visible='true' lat='2.00029177846' lon='1.00482599511' />
<node id='-123' action='modify' visible='true' lat='2.00035639296' lon='1.00472747489'> <node id='-85' action='modify' visible='true' lat='2.00035639296' lon='1.00472747489'>
<tag k='test:id' v='n-SW' /> <tag k='test:id' v='n-SW' />
<tag k='test:section' v='points-on-roads' /> <tag k='test:section' v='points-on-roads' />
</node> </node>
<node id='-121' action='modify' visible='true' lat='2.00022408708' lon='1.00452427693' /> <node id='-87' action='modify' visible='true' lat='2.00022408708' lon='1.00452427693' />
<node id='-119' action='modify' visible='true' lat='2.00071561841' lon='1.00183227343'> <node id='-89' action='modify' visible='true' lat='2.00071561841' lon='1.00183227343'>
<tag k='name' v='road-with-alley' /> <tag k='name' v='road-with-alley' />
</node> </node>
<node id='-117' action='modify' visible='true' lat='2.00072864414' lon='1.00046699629'> <node id='-91' action='modify' visible='true' lat='2.00072864414' lon='1.00046699629'>
<tag k='name' v='roads-with-pois' /> <tag k='name' v='roads-with-pois' />
</node> </node>
<node id='-115' action='modify' visible='true' lat='2.00035415446' lon='1.00244811443'> <node id='-93' action='modify' visible='true' lat='2.00035415446' lon='1.00244811443'>
<tag k='test:id' v='n-main-east' /> <tag k='test:id' v='n-main-east' />
<tag k='test:section' v='road-with-alley' /> <tag k='test:section' v='road-with-alley' />
</node> </node>
<node id='-113' action='modify' visible='true' lat='2.00026623078' lon='1.00155204948'> <node id='-95' action='modify' visible='true' lat='2.00026623078' lon='1.00155204948'>
<tag k='test:id' v='n-main-west' /> <tag k='test:id' v='n-main-west' />
<tag k='test:section' v='road-with-alley' /> <tag k='test:section' v='road-with-alley' />
</node> </node>
<node id='-111' action='modify' visible='true' lat='2.00054628396' lon='1.00192350914'> <node id='-97' action='modify' visible='true' lat='2.00054628396' lon='1.00192350914'>
<tag k='test:id' v='n-alley' /> <tag k='test:id' v='n-alley' />
<tag k='test:section' v='road-with-alley' /> <tag k='test:section' v='road-with-alley' />
</node> </node>
<node id='-109' action='modify' visible='true' lat='2.00035415446' lon='1.00192350914'> <node id='-99' action='modify' visible='true' lat='2.00035415446' lon='1.00192350914'>
<tag k='test:id' v='n-corner' /> <tag k='test:id' v='n-corner' />
<tag k='test:section' v='road-with-alley' /> <tag k='test:section' v='road-with-alley' />
</node> </node>
<node id='-107' action='modify' visible='true' lat='2.00057559185' lon='1.00195935173' /> <node id='-101' action='modify' visible='true' lat='2.00057559185' lon='1.00195935173' />
<node id='-105' action='modify' visible='true' lat='2.00029879511' lon='1.00260777692' /> <node id='-103' action='modify' visible='true' lat='2.00029879511' lon='1.00260777692' />
<node id='-103' action='modify' visible='true' lat='2.00031182084' lon='1.0023699124' /> <node id='-105' action='modify' visible='true' lat='2.00031182084' lon='1.0023699124' />
<node id='-101' action='modify' visible='true' lat='2.00031507727' lon='1.00212553105' /> <node id='-107' action='modify' visible='true' lat='2.00031507727' lon='1.00212553105' />
<node id='-99' action='modify' visible='true' lat='2.00030856441' lon='1.00195935173' /> <node id='-109' action='modify' visible='true' lat='2.00030856441' lon='1.00195935173' />
<node id='-97' action='modify' visible='true' lat='2.00030530797' lon='1.00167586937' /> <node id='-111' action='modify' visible='true' lat='2.00030530797' lon='1.00167586937' />
<node id='-95' action='modify' visible='true' lat='2.00031182084' lon='1.00134351073' /> <node id='-113' action='modify' visible='true' lat='2.00031182084' lon='1.00134351073' />
<node id='-93' action='modify' visible='true' lat='2.00040546963' lon='1.00011736285'> <node id='-115' action='modify' visible='true' lat='2.00040546963' lon='1.00011736285'>
<tag k='test:section' v='roads-with-pois' /> <tag k='test:section' v='roads-with-pois' />
</node> </node>
<node id='-91' action='modify' visible='true' lat='2.00039759893' lon='1.00042975784'> <node id='-117' action='modify' visible='true' lat='2.00039759893' lon='1.00042975784'>
<tag k='test:section' v='roads-with-pois' /> <tag k='test:section' v='roads-with-pois' />
</node> </node>
<node id='-89' action='modify' visible='true' lat='2.000457941' lon='1.00066077263'> <node id='-119' action='modify' visible='true' lat='2.000457941' lon='1.00066077263'>
<tag k='test:section' v='roads-with-pois' /> <tag k='test:section' v='roads-with-pois' />
</node> </node>
<node id='-87' action='modify' visible='true' lat='2.00054189517' lon='1.00106242333'> <node id='-121' action='modify' visible='true' lat='2.00054189517' lon='1.00106242333'>
<tag k='test:section' v='roads-with-pois' /> <tag k='test:section' v='roads-with-pois' />
</node> </node>
<node id='-85' action='modify' visible='true' lat='2.00019033703' lon='1.00013836419'> <node id='-123' action='modify' visible='true' lat='2.00019033703' lon='1.00013836419'>
<tag k='test:section' v='roads-with-pois' /> <tag k='test:section' v='roads-with-pois' />
</node> </node>
<node id='-83' action='modify' visible='true' lat='2.00019820773' lon='1.00072115149'> <node id='-125' action='modify' visible='true' lat='2.00019820773' lon='1.00072115149'>
<tag k='test:section' v='roads-with-pois' /> <tag k='test:section' v='roads-with-pois' />
</node> </node>
<node id='-81' action='modify' visible='true' lat='2.00021919628' lon='1.00106767367'> <node id='-127' action='modify' visible='true' lat='2.00021919628' lon='1.00106767367'>
<tag k='test:section' v='roads-with-pois' /> <tag k='test:section' v='roads-with-pois' />
</node> </node>
<node id='-79' action='modify' visible='true' lat='2.00033988043' lon='1.00039038032'> <node id='-129' action='modify' visible='true' lat='2.00033988043' lon='1.00039038032'>
<tag k='test:id' v='p-N2' /> <tag k='test:id' v='p-N2' />
<tag k='test:section' v='roads-with-pois' /> <tag k='test:section' v='roads-with-pois' />
</node> </node>
<node id='-77' action='modify' visible='true' lat='2.0002926562' lon='1.0008104072'> <node id='-131' action='modify' visible='true' lat='2.0002926562' lon='1.0008104072'>
<tag k='test:id' v='p-S1' /> <tag k='test:id' v='p-S1' />
<tag k='test:section' v='roads-with-pois' /> <tag k='test:section' v='roads-with-pois' />
</node> </node>
<node id='-75' action='modify' visible='true' lat='2.00052877733' lon='1.0005321394'> <node id='-133' action='modify' visible='true' lat='2.00052877733' lon='1.0005321394'>
<tag k='test:id' v='p-N1' /> <tag k='test:id' v='p-N1' />
<tag k='test:section' v='roads-with-pois' /> <tag k='test:section' v='roads-with-pois' />
</node> </node>
<node id='-73' action='modify' visible='true' lat='2.00010638283' lon='1.00063977128'> <node id='-135' action='modify' visible='true' lat='2.00010638283' lon='1.00063977128'>
<tag k='test:id' v='p-S2' /> <tag k='test:id' v='p-S2' />
<tag k='test:section' v='roads-with-pois' /> <tag k='test:section' v='roads-with-pois' />
</node> </node>
<node id='-71' action='modify' visible='true' lat='2.00072116924' lon='1.00358286582'> <node id='-137' action='modify' visible='true' lat='2.00072116924' lon='1.00358286582'>
<tag k='name' v='building-on-street-corner' /> <tag k='name' v='building-on-street-corner' />
</node> </node>
<node id='-69' action='modify' visible='true' lat='2.00023163534' lon='1.00317592051' /> <node id='-139' action='modify' visible='true' lat='2.00023163534' lon='1.00317592051' />
<node id='-67' action='modify' visible='true' lat='2.00022108767' lon='1.00403607904' /> <node id='-141' action='modify' visible='true' lat='2.00022108767' lon='1.00403607904' />
<node id='-65' action='modify' visible='true' lat='2.0002263615' lon='1.00427354612' /> <node id='-143' action='modify' visible='true' lat='2.0002263615' lon='1.00427354612' />
<node id='-63' action='modify' visible='true' lat='2.00010506339' lon='1.00404135609' /> <node id='-145' action='modify' visible='true' lat='2.00010506339' lon='1.00404135609' />
<node id='-61' action='modify' visible='true' lat='2.00063772026' lon='1.00403639915' /> <node id='-147' action='modify' visible='true' lat='2.00063772026' lon='1.00403639915' />
<node id='-59' action='modify' visible='true' lat='2.00043885695' lon='1.0039042871' /> <node id='-149' action='modify' visible='true' lat='2.00043885695' lon='1.0039042871' />
<node id='-57' action='modify' visible='true' lat='2.00043855477' lon='1.00400225362' /> <node id='-151' action='modify' visible='true' lat='2.00043855477' lon='1.00400225362' />
<node id='-55' action='modify' visible='true' lat='2.0002343878' lon='1.00400162309' /> <node id='-153' action='modify' visible='true' lat='2.0002343878' lon='1.00400162309' />
<node id='-53' action='modify' visible='true' lat='2.00023468998' lon='1.00390365657' /> <node id='-155' action='modify' visible='true' lat='2.00023468998' lon='1.00390365657' />
<node id='-51' action='modify' visible='true' lat='2.00032403886' lon='1.00400189996'> <node id='-157' action='modify' visible='true' lat='2.00032403886' lon='1.00400189996'>
<tag k='test:id' v='n-edge-NS' /> <tag k='test:id' v='n-edge-NS' />
<tag k='test:section' v='building-on-street-corner' /> <tag k='test:section' v='building-on-street-corner' />
</node> </node>
<node id='-49' action='modify' visible='true' lat='2.00035479802' lon='1.00393848586'> <node id='-159' action='modify' visible='true' lat='2.00035479802' lon='1.00393848586'>
<tag k='test:id' v='n-inner' /> <tag k='test:id' v='n-inner' />
<tag k='test:section' v='building-on-street-corner' /> <tag k='test:section' v='building-on-street-corner' />
</node> </node>
<node id='-47' action='modify' visible='true' lat='2.00046760515' lon='1.00394781445'> <node id='-161' action='modify' visible='true' lat='2.00046760515' lon='1.00394781445'>
<tag k='test:id' v='n-outer' /> <tag k='test:id' v='n-outer' />
<tag k='test:section' v='building-on-street-corner' /> <tag k='test:section' v='building-on-street-corner' />
</node> </node>
<node id='-45' action='modify' visible='true' lat='2.00023451637' lon='1.00395994156'> <node id='-163' action='modify' visible='true' lat='2.00023451637' lon='1.00395994156'>
<tag k='test:id' v='n-edge-WE' /> <tag k='test:id' v='n-edge-WE' />
<tag k='test:section' v='building-on-street-corner' /> <tag k='test:section' v='building-on-street-corner' />
</node> </node>
<node id='-43' action='modify' visible='true' lat='2.0001892102' lon='1.00653236169' /> <node id='-165' action='modify' visible='true' lat='2.0001892102' lon='1.00653236169' />
<node id='-41' action='modify' visible='true' lat='2.00027856164' lon='1.00667595302' /> <node id='-167' action='modify' visible='true' lat='2.00027856164' lon='1.00667595302' />
<node id='-39' action='modify' visible='true' lat='2.00027856164' lon='1.00681954435' /> <node id='-169' action='modify' visible='true' lat='2.00027856164' lon='1.00681954435' />
<node id='-37' action='modify' visible='true' lat='2.00025148545' lon='1.00691707809' /> <node id='-171' action='modify' visible='true' lat='2.00025148545' lon='1.00691707809' />
<node id='-35' action='modify' visible='true' lat='2.0001892102' lon='1.00704170453' /> <node id='-173' action='modify' visible='true' lat='2.0001892102' lon='1.00704170453' />
<node id='-33' action='modify' visible='true' lat='2.00017296448' lon='1.00724219054' /> <node id='-175' action='modify' visible='true' lat='2.00017296448' lon='1.00724219054' />
<node id='-31' action='modify' visible='true' lat='2.00062243814' lon='1.00685396461'> <node id='-177' action='modify' visible='true' lat='2.00062243814' lon='1.00685396461'>
<tag k='name' v='parallel-road' /> <tag k='name' v='parallel-road' />
</node> </node>
<node id='-29' action='modify' visible='true' lat='2.00033813812' lon='1.00653156143'> <node id='-179' action='modify' visible='true' lat='2.00033813812' lon='1.00653156143'>
<tag k='test:id' v='n-middle-w' /> <tag k='test:id' v='n-middle-w' />
<tag k='test:section' v='parallel-road' /> <tag k='test:section' v='parallel-road' />
</node> </node>
<node id='-27' action='modify' visible='true' lat='2.00042478194' lon='1.00668598984' /> <node id='-181' action='modify' visible='true' lat='2.00042478194' lon='1.00668598984' />
<node id='-25' action='modify' visible='true' lat='2.00041665908' lon='1.00690002221' /> <node id='-183' action='modify' visible='true' lat='2.00041665908' lon='1.00690002221' />
<node id='-23' action='modify' visible='true' lat='2.00034084574' lon='1.00723597174'> <node id='-185' action='modify' visible='true' lat='2.00034084574' lon='1.00723597174'>
<tag k='test:id' v='n-middle-e' /> <tag k='test:id' v='n-middle-e' />
<tag k='test:section' v='parallel-road' /> <tag k='test:section' v='parallel-road' />
</node> </node>
<node id='-21' action='modify' visible='true' lat='2.00041801289' lon='1.00653968924' /> <node id='-187' action='modify' visible='true' lat='2.00041801289' lon='1.00653968924' />
<node id='-19' action='modify' visible='true' lat='2.00050736432' lon='1.00668328057' /> <node id='-189' action='modify' visible='true' lat='2.00050736432' lon='1.00668328057' />
<node id='-17' action='modify' visible='true' lat='2.00050736432' lon='1.00682687191' /> <node id='-191' action='modify' visible='true' lat='2.00050736432' lon='1.00682687191' />
<node id='-15' action='modify' visible='true' lat='2.00048028813' lon='1.00692440564' /> <node id='-193' action='modify' visible='true' lat='2.00048028813' lon='1.00692440564' />
<node id='-13' action='modify' visible='true' lat='2.00041801289' lon='1.00704903208' /> <node id='-195' action='modify' visible='true' lat='2.00041801289' lon='1.00704903208' />
<node id='-11' action='modify' visible='true' lat='2.00040176717' lon='1.00724951809' /> <node id='-197' action='modify' visible='true' lat='2.00040176717' lon='1.00724951809' />
<node id='-199' action='modify' visible='true' lat='2.00102300625' lon='1.00316327416'>
<tag k='test:id' v='n-south-w' />
<tag k='test:section' v='building-with-parallel-streets' />
</node>
<node id='-201' action='modify' visible='true' lat='2.00101492424' lon='1.00369431688' />
<node id='-203' action='modify' visible='true' lat='2.00102031225' lon='1.00407170765' />
<node id='-205' action='modify' visible='true' lat='2.00100684223' lon='1.00433588118'>
<tag k='test:id' v='n-south-e' />
<tag k='test:section' v='building-with-parallel-streets' />
</node>
<node id='-207' action='modify' visible='true' lat='2.00148637497' lon='1.00362153438'>
<tag k='name' v='building-with-parallel-streets' />
</node>
<node id='-209' action='modify' visible='true' lat='2.00126546664' lon='1.00315114374'>
<tag k='test:id' v='n-north-w' />
<tag k='test:section' v='building-with-parallel-streets' />
</node>
<node id='-211' action='modify' visible='true' lat='2.00125738463' lon='1.00368218646' />
<node id='-213' action='modify' visible='true' lat='2.00126277264' lon='1.00405957723' />
<node id='-215' action='modify' visible='true' lat='2.00124930262' lon='1.00432375077'>
<tag k='test:id' v='n-north-e' />
<tag k='test:section' v='building-with-parallel-streets' />
</node>
<node id='-217' action='modify' visible='true' lat='2.00118914388' lon='1.00361572227' />
<node id='-219' action='modify' visible='true' lat='2.0010786539' lon='1.00361659971' />
<node id='-221' action='modify' visible='true' lat='2.001080471' lon='1.003845694' />
<node id='-223' action='modify' visible='true' lat='2.00119096098' lon='1.00384481656' />
<node id='100000' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='2.0' lon='1.0' /> <node id='100000' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='2.0' lon='1.0' />
<node id='100001' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='3.0' lon='1.0' /> <node id='100001' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='3.0' lon='1.0' />
<node id='100002' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='3.0' lon='2.0' /> <node id='100002' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='3.0' lon='2.0' />
<node id='100003' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='2.0' lon='2.0' /> <node id='100003' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1' lat='2.0' lon='2.0' />
<way id='-237' action='modify' visible='true'> <way id='-229' action='modify' visible='true'>
<nd ref='-183' /> <nd ref='-25' />
<nd ref='-185' /> <nd ref='-23' />
<nd ref='-187' /> <nd ref='-21' />
<tag k='test:id' v='w-5' /> <tag k='test:id' v='w-5' />
<tag k='test:section' v='split-road' /> <tag k='test:section' v='split-road' />
</way> </way>
<way id='-235' action='modify' visible='true'> <way id='-231' action='modify' visible='true'>
<nd ref='-173' /> <nd ref='-35' />
<nd ref='-175' /> <nd ref='-33' />
<nd ref='-177' /> <nd ref='-31' />
<nd ref='-179' /> <nd ref='-29' />
<nd ref='-181' /> <nd ref='-27' />
<nd ref='-183' /> <nd ref='-25' />
<tag k='test:id' v='w-4a' /> <tag k='test:id' v='w-4a' />
<tag k='test:section' v='split-road' /> <tag k='test:section' v='split-road' />
</way> </way>
<way id='-233' action='modify' visible='true'> <way id='-233' action='modify' visible='true'>
<nd ref='-165' />
<nd ref='-167' />
<nd ref='-169' />
<nd ref='-171' />
<nd ref='-173' />
<tag k='test:id' v='w-3' />
<tag k='test:section' v='split-road' />
</way>
<way id='-231' action='modify' visible='true'>
<nd ref='-157' />
<nd ref='-159' />
<nd ref='-161' />
<nd ref='-163' />
<nd ref='-165' />
<tag k='test:id' v='w-2' />
<tag k='test:section' v='split-road' />
</way>
<way id='-229' action='modify' visible='true'>
<nd ref='-173' />
<nd ref='-189' />
<nd ref='-191' />
<nd ref='-193' />
<nd ref='-195' />
<nd ref='-183' />
<tag k='test:id' v='w-4b' />
<tag k='test:section' v='split-road' />
</way>
<way id='-227' action='modify' visible='true'>
<nd ref='-153' />
<nd ref='-155' />
<nd ref='-157' />
<tag k='test:id' v='w-1' />
<tag k='test:section' v='split-road' />
</way>
<way id='-225' action='modify' visible='true'>
<nd ref='-131' />
<nd ref='-133' />
<nd ref='-135' />
<nd ref='-149' />
<nd ref='-141' />
<nd ref='-137' />
<tag k='test:id' v='w-north' />
<tag k='test:section' v='points-on-roads' />
</way>
<way id='-223' action='modify' visible='true'>
<nd ref='-121' />
<nd ref='-143' />
<nd ref='-123' />
<nd ref='-125' />
<nd ref='-127' />
<nd ref='-139' />
<nd ref='-129' />
<tag k='test:id' v='w-south' />
<tag k='test:section' v='points-on-roads' />
</way>
<way id='-221' action='modify' visible='true'>
<nd ref='-99' />
<nd ref='-107' />
<tag k='test:id' v='w-alley' />
<tag k='test:section' v='road-with-alley' />
</way>
<way id='-219' action='modify' visible='true'>
<nd ref='-95' />
<nd ref='-97' />
<nd ref='-99' />
<nd ref='-101' />
<nd ref='-103' />
<nd ref='-105' />
<tag k='test:id' v='w-main' />
<tag k='test:section' v='road-with-alley' />
</way>
<way id='-217' action='modify' visible='true'>
<nd ref='-93' />
<nd ref='-91' />
<nd ref='-89' />
<nd ref='-87' />
<tag k='test:id' v='w-north' />
<tag k='test:section' v='roads-with-pois' />
</way>
<way id='-215' action='modify' visible='true'>
<nd ref='-85' />
<nd ref='-83' />
<nd ref='-81' />
<tag k='test:id' v='w-south' />
<tag k='test:section' v='roads-with-pois' />
</way>
<way id='-213' action='modify' visible='true'>
<nd ref='-69' />
<nd ref='-67' />
<nd ref='-65' />
<tag k='test:id' v='w-WE' />
<tag k='test:section' v='building-on-street-corner' />
</way>
<way id='-211' action='modify' visible='true'>
<nd ref='-63' />
<nd ref='-67' />
<nd ref='-61' />
<tag k='test:id' v='w-NS' />
<tag k='test:section' v='building-on-street-corner' />
</way>
<way id='-209' action='modify' visible='true'>
<nd ref='-59' />
<nd ref='-57' />
<nd ref='-51' />
<nd ref='-55' />
<nd ref='-45' />
<nd ref='-53' />
<nd ref='-59' />
<tag k='area' v='yes' />
<tag k='test:id' v='w-building' />
<tag k='test:section' v='building-on-street-corner' />
</way>
<way id='-207' action='modify' visible='true'>
<nd ref='-43' /> <nd ref='-43' />
<nd ref='-41' /> <nd ref='-41' />
<nd ref='-39' /> <nd ref='-39' />
<nd ref='-37' /> <nd ref='-37' />
<nd ref='-35' /> <nd ref='-35' />
<nd ref='-33' /> <tag k='test:id' v='w-3' />
<tag k='test:id' v='w-south' /> <tag k='test:section' v='split-road' />
<tag k='test:section' v='parallel-road' />
</way> </way>
<way id='-205' action='modify' visible='true'> <way id='-235' action='modify' visible='true'>
<nd ref='-29' /> <nd ref='-51' />
<nd ref='-27' /> <nd ref='-49' />
<nd ref='-25' /> <nd ref='-47' />
<nd ref='-23' /> <nd ref='-45' />
<tag k='test:id' v='w-middle' /> <nd ref='-43' />
<tag k='test:section' v='parallel-road' /> <tag k='test:id' v='w-2' />
<tag k='test:section' v='split-road' />
</way> </way>
<way id='-203' action='modify' visible='true'> <way id='-237' action='modify' visible='true'>
<nd ref='-21' /> <nd ref='-35' />
<nd ref='-19' /> <nd ref='-19' />
<nd ref='-17' /> <nd ref='-17' />
<nd ref='-15' /> <nd ref='-15' />
<nd ref='-13' /> <nd ref='-13' />
<nd ref='-11' /> <nd ref='-25' />
<tag k='test:id' v='w-4b' />
<tag k='test:section' v='split-road' />
</way>
<way id='-239' action='modify' visible='true'>
<nd ref='-55' />
<nd ref='-53' />
<nd ref='-51' />
<tag k='test:id' v='w-1' />
<tag k='test:section' v='split-road' />
</way>
<way id='-241' action='modify' visible='true'>
<nd ref='-77' />
<nd ref='-75' />
<nd ref='-73' />
<nd ref='-59' />
<nd ref='-67' />
<nd ref='-71' />
<tag k='test:id' v='w-north' />
<tag k='test:section' v='points-on-roads' />
</way>
<way id='-243' action='modify' visible='true'>
<nd ref='-87' />
<nd ref='-65' />
<nd ref='-85' />
<nd ref='-83' />
<nd ref='-81' />
<nd ref='-69' />
<nd ref='-79' />
<tag k='test:id' v='w-south' />
<tag k='test:section' v='points-on-roads' />
</way>
<way id='-245' action='modify' visible='true'>
<nd ref='-109' />
<nd ref='-101' />
<tag k='test:id' v='w-alley' />
<tag k='test:section' v='road-with-alley' />
</way>
<way id='-247' action='modify' visible='true'>
<nd ref='-113' />
<nd ref='-111' />
<nd ref='-109' />
<nd ref='-107' />
<nd ref='-105' />
<nd ref='-103' />
<tag k='test:id' v='w-main' />
<tag k='test:section' v='road-with-alley' />
</way>
<way id='-249' action='modify' visible='true'>
<nd ref='-115' />
<nd ref='-117' />
<nd ref='-119' />
<nd ref='-121' />
<tag k='test:id' v='w-north' />
<tag k='test:section' v='roads-with-pois' />
</way>
<way id='-251' action='modify' visible='true'>
<nd ref='-123' />
<nd ref='-125' />
<nd ref='-127' />
<tag k='test:id' v='w-south' />
<tag k='test:section' v='roads-with-pois' />
</way>
<way id='-253' action='modify' visible='true'>
<nd ref='-139' />
<nd ref='-141' />
<nd ref='-143' />
<tag k='test:id' v='w-WE' />
<tag k='test:section' v='building-on-street-corner' />
</way>
<way id='-255' action='modify' visible='true'>
<nd ref='-145' />
<nd ref='-141' />
<nd ref='-147' />
<tag k='test:id' v='w-NS' />
<tag k='test:section' v='building-on-street-corner' />
</way>
<way id='-257' action='modify' visible='true'>
<nd ref='-149' />
<nd ref='-151' />
<nd ref='-157' />
<nd ref='-153' />
<nd ref='-163' />
<nd ref='-155' />
<nd ref='-149' />
<tag k='area' v='yes' />
<tag k='test:id' v='w-building' />
<tag k='test:section' v='building-on-street-corner' />
</way>
<way id='-259' action='modify' visible='true'>
<nd ref='-165' />
<nd ref='-167' />
<nd ref='-169' />
<nd ref='-171' />
<nd ref='-173' />
<nd ref='-175' />
<tag k='test:id' v='w-south' />
<tag k='test:section' v='parallel-road' />
</way>
<way id='-261' action='modify' visible='true'>
<nd ref='-179' />
<nd ref='-181' />
<nd ref='-183' />
<nd ref='-185' />
<tag k='test:id' v='w-middle' />
<tag k='test:section' v='parallel-road' />
</way>
<way id='-263' action='modify' visible='true'>
<nd ref='-187' />
<nd ref='-189' />
<nd ref='-191' />
<nd ref='-193' />
<nd ref='-195' />
<nd ref='-197' />
<tag k='test:id' v='w-north' /> <tag k='test:id' v='w-north' />
<tag k='test:section' v='parallel-road' /> <tag k='test:section' v='parallel-road' />
</way> </way>
<way id='-265' action='modify' visible='true'>
<nd ref='-199' />
<nd ref='-201' />
<nd ref='-203' />
<nd ref='-205' />
<tag k='test:id' v='w-south' />
<tag k='test:section' v='building-with-parallel-streets' />
</way>
<way id='-267' action='modify' visible='true'>
<nd ref='-209' />
<nd ref='-211' />
<nd ref='-213' />
<nd ref='-215' />
<tag k='test:id' v='w-north' />
<tag k='test:section' v='building-with-parallel-streets' />
</way>
<way id='-269' action='modify' visible='true'>
<nd ref='-217' />
<nd ref='-219' />
<nd ref='-221' />
<nd ref='-223' />
<nd ref='-217' />
<tag k='test:id' v='w-building' />
<tag k='test:section' v='building-with-parallel-streets' />
</way>
<way id='100000' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1'> <way id='100000' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' visible='true' version='1' changeset='1'>
<nd ref='100000' /> <nd ref='100000' />
<nd ref='100001' /> <nd ref='100001' />

View File

@@ -35,6 +35,7 @@ def check_placex_names(step, osmtyp, osmid):
@step(u'table ([a-z_]+) contains$') @step(u'table ([a-z_]+) contains$')
def check_placex_content(step, tablename): def check_placex_content(step, tablename):
""" check that the given lines are in the given table """ check that the given lines are in the given table
@@ -49,12 +50,21 @@ def check_placex_content(step, tablename):
q = 'SELECT *' q = 'SELECT *'
if tablename == 'placex': if tablename == 'placex':
q = q + ", ST_X(centroid) as clat, ST_Y(centroid) as clon" q = q + ", ST_X(centroid) as clat, ST_Y(centroid) as clon"
if tablename == 'location_property_osmline':
q = q + ' FROM %s where osm_id = %%s' % (tablename,)
else:
q = q + ", ST_GeometryType(geometry) as geometrytype" q = q + ", ST_GeometryType(geometry) as geometrytype"
q = q + ' FROM %s where osm_type = %%s and osm_id = %%s' % (tablename,) q = q + ' FROM %s where osm_type = %%s and osm_id = %%s' % (tablename,)
if cls is None: if cls is None:
if tablename == 'location_property_osmline':
params = (osmid,)
else:
params = (osmtype, osmid) params = (osmtype, osmid)
else: else:
q = q + ' and class = %s' q = q + ' and class = %s'
if tablename == 'location_property_osmline':
params = (osmid, cls)
else:
params = (osmtype, osmid, cls) params = (osmtype, osmid, cls)
cur.execute(q, params) cur.execute(q, params)
assert(cur.rowcount > 0) assert(cur.rowcount > 0)
@@ -92,6 +102,18 @@ def check_placex_missing(step, tablename, osmtyp, osmid, placeclass):
cur.close() cur.close()
world.conn.commit() world.conn.commit()
@step(u'table location_property_osmline has no entry for W(\d+)?')
def check_osmline_missing(step, osmid):
cur = world.conn.cursor()
try:
q = 'SELECT count(*) FROM location_property_osmline where osm_id = %s' % (osmid, )
cur.execute(q)
numres = cur.fetchone()[0]
assert_equals (numres, 0)
finally:
cur.close()
world.conn.commit()
@step(u'search_name table contains$') @step(u'search_name table contains$')
def check_search_name_content(step): def check_search_name_content(step):
cur = world.conn.cursor(cursor_factory=psycopg2.extras.DictCursor) cur = world.conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
@@ -118,27 +140,26 @@ def check_search_name_content(step):
else: else:
raise Exception("Cannot handle field %s in search_name table" % (k, )) raise Exception("Cannot handle field %s in search_name table" % (k, ))
@step(u'way (\d+) expands to housenumbers') @step(u'way (\d+) expands to lines')
def check_interpolated_housenumbers(step, nodeid): def check_interpolation_lines(step, wayid):
"""Check that the exact set of housenumbers has been entered in """Check that the correct interpolation line has been entered in
placex for the given source node. Expected are two columns: location_property_osmline for the given source line/nodes.
housenumber and centroid Expected are three columns:
startnumber, endnumber and linegeo
""" """
numbers = {} lines = []
for line in step.hashes: for line in step.hashes:
assert line["housenumber"] not in numbers lines.append((line["startnumber"], line["endnumber"], line["geometry"]))
numbers[line["housenumber"]] = line["centroid"]
cur = world.conn.cursor(cursor_factory=psycopg2.extras.DictCursor) cur = world.conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
cur.execute("""SELECT DISTINCT housenumber, cur.execute("""SELECT startnumber::text, endnumber::text, st_astext(linegeo) as geometry
ST_X(centroid) as clat, ST_Y(centroid) as clon FROM location_property_osmline WHERE osm_id = %s""",
FROM placex WHERE osm_type = 'W' and osm_id = %s (int(wayid),))
and class = 'place' and type = 'address'""", assert_equals(len(lines), cur.rowcount)
(int(nodeid),))
assert_equals(len(numbers), cur.rowcount)
for r in cur: for r in cur:
assert_in(r["housenumber"], numbers) linegeo = str(str(r["geometry"].split('(')[1]).split(')')[0]).replace(',', ', ')
world.match_geometry((r['clat'], r['clon']), numbers[r["housenumber"]]) exp = (r["startnumber"], r["endnumber"], linegeo)
del numbers[r["housenumber"]] assert_in(exp, lines)
lines.remove(exp)
@step(u'way (\d+) expands exactly to housenumbers ([0-9,]*)') @step(u'way (\d+) expands exactly to housenumbers ([0-9,]*)')
def check_interpolated_housenumber_list(step, nodeid, numberlist): def check_interpolated_housenumber_list(step, nodeid, numberlist):

View File

@@ -23,6 +23,7 @@ import os
import subprocess import subprocess
import random import random
import base64 import base64
import sys
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
@@ -143,8 +144,8 @@ def import_set_scene(step, scene):
@step(u'the (named )?place (node|way|area)s') @step(u'the (named )?place (node|way|area)s')
def import_place_table_nodes(step, named, osmtype): def import_place_table_nodes(step, named, osmtype):
"""Insert a list of nodes into the placex table. """Insert a list of nodes into the place table.
Expects a table where columns are named in the same way as placex. Expects a table where columns are named in the same way as place.
""" """
cur = world.conn.cursor() cur = world.conn.cursor()
cur.execute('ALTER TABLE place DISABLE TRIGGER place_before_insert') cur.execute('ALTER TABLE place DISABLE TRIGGER place_before_insert')
@@ -214,18 +215,19 @@ def import_database(step):
""" Runs the actual indexing. """ """ Runs the actual indexing. """
world.run_nominatim_script('setup', 'create-functions', 'create-partition-functions') world.run_nominatim_script('setup', 'create-functions', 'create-partition-functions')
cur = world.conn.cursor() cur = world.conn.cursor()
#world.db_dump_table('place')
cur.execute("""insert into placex (osm_type, osm_id, class, type, name, admin_level, cur.execute("""insert into placex (osm_type, osm_id, class, type, name, admin_level,
housenumber, street, addr_place, isin, postcode, country_code, extratags, housenumber, street, addr_place, isin, postcode, country_code, extratags,
geometry) select * from place""") geometry) select * from place where not (class='place' and type='houses' and osm_type='W')""")
cur.execute("""select insert_osmline (osm_id, housenumber, street, addr_place, postcode, country_code, geometry) from place where class='place' and type='houses' and osm_type='W'""")
world.conn.commit() world.conn.commit()
world.run_nominatim_script('setup', 'index', 'index-noanalyse') world.run_nominatim_script('setup', 'index', 'index-noanalyse')
#world.db_dump_table('placex') #world.db_dump_table('placex')
#world.db_dump_table('location_property_osmline')
@step(u'updating place (node|way|area)s') @step(u'updating place (node|way|area)s')
def update_place_table_nodes(step, osmtype): def update_place_table_nodes(step, osmtype):
""" Replace a geometry in place by reinsertion and reindex database. """ Replace a geometry in place by reinsertion and reindex database."""
"""
world.run_nominatim_script('setup', 'create-functions', 'create-partition-functions', 'enable-diff-updates') world.run_nominatim_script('setup', 'create-functions', 'create-partition-functions', 'enable-diff-updates')
if osmtype == 'node': if osmtype == 'node':
_insert_place_table_nodes(step.hashes, False) _insert_place_table_nodes(step.hashes, False)

View File

@@ -123,16 +123,19 @@ def match_geometry(coord, matchstring):
logger.debug("Distances expected: %f, got: %f" % (expdist, dist)) logger.debug("Distances expected: %f, got: %f" % (expdist, dist))
assert dist <= expdist, "Geometry too far away, expected: %f, got: %f" % (expdist, dist) assert dist <= expdist, "Geometry too far away, expected: %f, got: %f" % (expdist, dist)
@world.absorb
def print_statement(element):
print '\n\n\n'+str(element)+'\n\n\n'
@world.absorb @world.absorb
def db_dump_table(table): def db_dump_table(table):
cur = world.conn.cursor() cur = world.conn.cursor()
cur.execute('SELECT * FROM %s' % table) cur.execute('SELECT * FROM %s' % table)
print '<<<<<<< BEGIN OF TABLE DUMP %s' % table print '\n\n\n<<<<<<< BEGIN OF TABLE DUMP %s' % table
for res in cur: for res in cur:
print res print res
print '<<<<<<< END OF TABLE DUMP %s' % table print '<<<<<<< END OF TABLE DUMP %s\n\n\n' % table
@world.absorb @world.absorb
def db_drop_database(name): def db_drop_database(name):

View File

@@ -353,6 +353,8 @@
echo '.'; echo '.';
if (!pg_query($oDB->connection, 'TRUNCATE placex')) fail(pg_last_error($oDB->connection)); if (!pg_query($oDB->connection, 'TRUNCATE placex')) fail(pg_last_error($oDB->connection));
echo '.'; echo '.';
if (!pg_query($oDB->connection, 'TRUNCATE location_property_osmline')) fail(pg_last_error($oDB->connection));
echo '.';
if (!pg_query($oDB->connection, 'TRUNCATE place_addressline')) fail(pg_last_error($oDB->connection)); if (!pg_query($oDB->connection, 'TRUNCATE place_addressline')) fail(pg_last_error($oDB->connection));
echo '.'; echo '.';
if (!pg_query($oDB->connection, 'TRUNCATE place_boundingbox')) fail(pg_last_error($oDB->connection)); if (!pg_query($oDB->connection, 'TRUNCATE place_boundingbox')) fail(pg_last_error($oDB->connection));
@@ -394,20 +396,30 @@
echo "Load Data\n"; echo "Load Data\n";
$aDBInstances = array(); $aDBInstances = array();
for($i = 0; $i < $iInstances; $i++) $iLoadThreads = max(1, $iInstances - 1);
for($i = 0; $i < $iLoadThreads; $i++)
{ {
$aDBInstances[$i] =& getDB(true); $aDBInstances[$i] =& getDB(true);
$sSQL = 'insert into placex (osm_type, osm_id, class, type, name, admin_level, '; $sSQL = 'insert into placex (osm_type, osm_id, class, type, name, admin_level, ';
$sSQL .= 'housenumber, street, addr_place, isin, postcode, country_code, extratags, '; $sSQL .= 'housenumber, street, addr_place, isin, postcode, country_code, extratags, ';
$sSQL .= 'geometry) select * from place where osm_id % '.$iInstances.' = '.$i; $sSQL .= 'geometry) select * from place where osm_id % '.$iLoadThreads.' = '.$i;
$sSQL .= " and not (class='place' and type='houses' and osm_type='W' and ST_GeometryType(geometry) = 'ST_LineString')";
if ($aCMDResult['verbose']) echo "$sSQL\n"; if ($aCMDResult['verbose']) echo "$sSQL\n";
if (!pg_send_query($aDBInstances[$i]->connection, $sSQL)) fail(pg_last_error($oDB->connection)); if (!pg_send_query($aDBInstances[$i]->connection, $sSQL)) fail(pg_last_error($oDB->connection));
} }
// last thread for interpolation lines
$aDBInstances[$iLoadThreads] =& getDB(true);
$sSQL = 'select insert_osmline (osm_id, housenumber, street, addr_place, postcode, country_code, ';
$sSQL .= 'geometry) from place where ';
$sSQL .= "class='place' and type='houses' and osm_type='W' and ST_GeometryType(geometry) = 'ST_LineString'";
if ($aCMDResult['verbose']) echo "$sSQL\n";
if (!pg_send_query($aDBInstances[$i]->connection, $sSQL)) fail(pg_last_error($oDB->connection));
$bAnyBusy = true; $bAnyBusy = true;
while($bAnyBusy) while($bAnyBusy)
{ {
$bAnyBusy = false; $bAnyBusy = false;
for($i = 0; $i < $iInstances; $i++) for($i = 0; $i <= $iLoadThreads; $i++)
{ {
if (pg_connection_busy($aDBInstances[$i]->connection)) $bAnyBusy = true; if (pg_connection_busy($aDBInstances[$i]->connection)) $bAnyBusy = true;
} }