protected $aLangPrefOrder = array();
protected $bIncludeAddressDetails = false;
+ protected $bIncludeExtraTags = false;
+ protected $bIncludeNameDetails = false;
protected $bIncludePolygonAsPoints = false;
protected $bIncludePolygonAsText = false;
protected $aExcludePlaceIDs = array();
protected $bDeDupe = true;
- protected $bReverseInPlan = false;
+ protected $bReverseInPlan = true;
protected $iLimit = 20;
protected $iFinalLimit = 10;
return $this->bIncludeAddressDetails;
}
+ function getIncludeExtraTags()
+ {
+ return $this->bIncludeExtraTags;
+ }
+
+ function getIncludeNameDetails()
+ {
+ return $this->bIncludeNameDetails;
+ }
+
function setIncludePolygonAsPoints($b = true)
{
$this->bIncludePolygonAsPoints = $b;
function loadParamArray($aParams)
{
if (isset($aParams['addressdetails'])) $this->bIncludeAddressDetails = (bool)$aParams['addressdetails'];
+ if ((float) CONST_Postgresql_Version > 9.2)
+ {
+ if (isset($aParams['extratags'])) $this->bIncludeExtraTags = (bool)$aParams['extratags'];
+ if (isset($aParams['namedetails'])) $this->bIncludeNameDetails = (bool)$aParams['namedetails'];
+ }
if (isset($aParams['bounded'])) $this->bBoundedSearch = (bool)$aParams['bounded'];
if (isset($aParams['dedupe'])) $this->bDeDupe = (bool)$aParams['dedupe'];
$sSQL .= "get_address_by_language(place_id, $sLanguagePrefArraySQL) as langaddress,";
$sSQL .= "get_name_by_language(name, $sLanguagePrefArraySQL) as placename,";
$sSQL .= "get_name_by_language(name, ARRAY['ref']) as ref,";
+ if ($this->bIncludeExtraTags) $sSQL .= "hstore_to_json(extratags)::text as extra,";
+ if ($this->bIncludeNameDetails) $sSQL .= "hstore_to_json(name)::text as names,";
$sSQL .= "avg(ST_X(centroid)) as lon,avg(ST_Y(centroid)) as lat, ";
$sSQL .= $sImportanceSQL."coalesce(importance,0.75-(rank_search::float/40)) as importance, ";
$sSQL .= "(select max(p.importance*(p.rank_address+2)) from place_addressline s, placex p where s.place_id = min(CASE WHEN placex.rank_search < 28 THEN placex.place_id ELSE placex.parent_place_id END) and p.place_id = s.address_place_id and s.isaddress and p.importance is not null) as addressimportance, ";
$sSQL .= ",langaddress ";
$sSQL .= ",placename ";
$sSQL .= ",ref ";
+ if ($this->bIncludeExtraTags) $sSQL .= ",extratags";
+ if ($this->bIncludeNameDetails) $sSQL .= ",name";
$sSQL .= ",extratags->'place' ";
if (30 >= $this->iMinAddressRank && 30 <= $this->iMaxAddressRank)
$sSQL .= "get_address_by_language(place_id, $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."-1.15 as importance, ";
$sSQL .= "(select max(p.importance*(p.rank_address+2)) from place_addressline s, placex p where s.place_id = min(location_property_tiger.parent_place_id) and p.place_id = s.address_place_id and s.isaddress and p.importance is not null) as addressimportance, ";
$sSQL .= "and 30 between $this->iMinAddressRank and $this->iMaxAddressRank ";
$sSQL .= "group by place_id";
if (!$this->bDeDupe) $sSQL .= ",place_id ";
+ /*
$sSQL .= " union ";
$sSQL .= "select 'L' 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, $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."-1.10 as importance, ";
$sSQL .= "(select max(p.importance*(p.rank_address+2)) from place_addressline s, placex p where s.place_id = min(location_property_aux.parent_place_id) and p.place_id = s.address_place_id and s.isaddress and p.importance is not null) as addressimportance, ";
$sSQL .= "group by place_id";
if (!$this->bDeDupe) $sSQL .= ",place_id";
$sSQL .= ",get_address_by_language(place_id, $sLanguagePrefArraySQL) ";
+ */
}
$sSQL .= " order by importance desc";
// TODO: filter out the pointless search terms (2 letter name tokens and less)
// they might be right - but they are just too darned expensive to run
if (sizeof($aSearch['aName'])) $aTerms[] = "name_vector @> ARRAY[".join($aSearch['aName'],",")."]";
- if (sizeof($aSearch['aNameNonSearch'])) $aTerms[] = "array_cat(name_vector,ARRAY[]::integer[]) @> ARRAY[".join($aSearch['aNameNonSearch'],",")."]";
+ //if (sizeof($aSearch['aNameNonSearch'])) $aTerms[] = "array_cat(name_vector,ARRAY[]::integer[]) @> ARRAY[".join($aSearch['aNameNonSearch'],",")."]";
if (sizeof($aSearch['aAddress']) && $aSearch['aName'] != $aSearch['aAddress'])
{
// For infrequent name terms disable index usage for address
sizeof($aSearch['aName']) == 1 &&
$aWordFrequencyScores[$aSearch['aName'][reset($aSearch['aName'])]] < CONST_Search_NameOnlySearchFrequencyThreshold)
{
- $aTerms[] = "array_cat(nameaddress_vector,ARRAY[]::integer[]) @> ARRAY[".join(array_merge($aSearch['aAddress'],$aSearch['aAddressNonSearch']),",")."]";
+ //$aTerms[] = "array_cat(nameaddress_vector,ARRAY[]::integer[]) @> ARRAY[".join(array_merge($aSearch['aAddress'],$aSearch['aAddressNonSearch']),",")."]";
+ $aTerms[] = "array_cat(nameaddress_vector,ARRAY[]::integer[]) @> ARRAY[".join($aSearch['aAddress'],",")."]";
}
else
{
$aTerms[] = "nameaddress_vector @> ARRAY[".join($aSearch['aAddress'],",")."]";
- if (sizeof($aSearch['aAddressNonSearch'])) $aTerms[] = "array_cat(nameaddress_vector,ARRAY[]::integer[]) @> ARRAY[".join($aSearch['aAddressNonSearch'],",")."]";
+ //if (sizeof($aSearch['aAddressNonSearch'])) $aTerms[] = "array_cat(nameaddress_vector,ARRAY[]::integer[]) @> ARRAY[".join($aSearch['aAddressNonSearch'],",")."]";
}
}
if ($aSearch['sCountryCode']) $aTerms[] = "country_code = '".pg_escape_string($aSearch['sCountryCode'])."'";
$aPlaceIDs = $this->oDB->getCol($sSQL);
// If not try the aux fallback table
+ /*
if (!sizeof($aPlaceIDs))
{
$sSQL = "select place_id from location_property_aux where parent_place_id in (".$sPlaceIDs.") and housenumber = '".pg_escape_string($aSearch['sHouseNumber'])."'";
if (CONST_Debug) var_dump($sSQL);
$aPlaceIDs = $this->oDB->getCol($sSQL);
}
+ */
if (!sizeof($aPlaceIDs))
{
foreach($aSearchResults as $iResNum => $aResult)
{
+ // Default
+ $fDiameter = 0.0001;
+
+ if (isset($aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'])
+ && $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'])
+ {
+ $fDiameter = $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'];
+ }
+ elseif (isset($aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'])
+ && $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'])
+ {
+ $fDiameter = $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'];
+ }
+ $fRadius = $fDiameter / 2;
+
if (CONST_Search_AreaPolygons)
{
// Get the bounding box and outline polygon
{
preg_match_all('/(-?[0-9.]+) (-?[0-9.]+)/',$aMatch[1],$aPolyPoints,PREG_SET_ORDER);
}
+ /*
elseif (preg_match('#MULTIPOLYGON\\(\\(\\(([- 0-9.,]+)#',$aPointPolygon['astext'],$aMatch))
{
preg_match_all('/(-?[0-9.]+) (-?[0-9.]+)/',$aMatch[1],$aPolyPoints,PREG_SET_ORDER);
}
+ */
elseif (preg_match('#POINT\\((-?[0-9.]+) (-?[0-9.]+)\\)#',$aPointPolygon['astext'],$aMatch))
{
- $fRadius = 0.01;
- $iSteps = ($fRadius * 40000)^2;
+ $iSteps = max(8, min(100, ($fRadius * 40000)^2));
$fStepSize = (2*pi())/$iSteps;
$aPolyPoints = array();
for($f = 0; $f < 2*pi(); $f += $fStepSize)
{
$aPolyPoints[] = array('',$aMatch[1]+($fRadius*sin($f)),$aMatch[2]+($fRadius*cos($f)));
}
- $aPointPolygon['minlat'] = $aPointPolygon['minlat'] - $fRadius;
- $aPointPolygon['maxlat'] = $aPointPolygon['maxlat'] + $fRadius;
- $aPointPolygon['minlon'] = $aPointPolygon['minlon'] - $fRadius;
- $aPointPolygon['maxlon'] = $aPointPolygon['maxlon'] + $fRadius;
}
}
$aResult['aPolyPoints'][] = array($aPoint[1], $aPoint[2]);
}
}
- $aResult['aBoundingBox'] = array($aPointPolygon['minlat'],$aPointPolygon['maxlat'],$aPointPolygon['minlon'],$aPointPolygon['maxlon']);
+
+ if (abs($aPointPolygon['minlat'] - $aPointPolygon['maxlat']) < 0.0000001)
+ {
+ $aPointPolygon['minlat'] = $aPointPolygon['minlat'] - $fRadius;
+ $aPointPolygon['maxlat'] = $aPointPolygon['maxlat'] + $fRadius;
+ }
+ if (abs($aPointPolygon['minlon'] - $aPointPolygon['maxlon']) < 0.0000001)
+ {
+ $aPointPolygon['minlon'] = $aPointPolygon['minlon'] - $fRadius;
+ $aPointPolygon['maxlon'] = $aPointPolygon['maxlon'] + $fRadius;
+ }
+ $aResult['aBoundingBox'] = array((string)$aPointPolygon['minlat'],(string)$aPointPolygon['maxlat'],(string)$aPointPolygon['minlon'],(string)$aPointPolygon['maxlon']);
}
}
if (!isset($aResult['aBoundingBox']))
{
- // Default
- $fDiameter = 0.0001;
-
- if (isset($aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'])
- && $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defdiameter'])
- {
- $fDiameter = $aClassType[$aResult['class'].':'.$aResult['type'].':'.$aResult['admin_level']]['defzoom'];
- }
- elseif (isset($aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'])
- && $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'])
- {
- $fDiameter = $aClassType[$aResult['class'].':'.$aResult['type']]['defdiameter'];
- }
- $fRadius = $fDiameter / 2;
-
$iSteps = max(8,min(100,$fRadius * 3.14 * 100000));
$fStepSize = (2*pi())/$iSteps;
- $aPolyPoints = array();
- for($f = 0; $f < 2*pi(); $f += $fStepSize)
- {
- $aPolyPoints[] = array('',$aResult['lon']+($fRadius*sin($f)),$aResult['lat']+($fRadius*cos($f)));
- }
$aPointPolygon['minlat'] = $aResult['lat'] - $fRadius;
$aPointPolygon['maxlat'] = $aResult['lat'] + $fRadius;
$aPointPolygon['minlon'] = $aResult['lon'] - $fRadius;
// Output data suitable for display (points and a bounding box)
if ($this->bIncludePolygonAsPoints)
{
+ $aPolyPoints = array();
+ for($f = 0; $f < 2*pi(); $f += $fStepSize)
+ {
+ $aPolyPoints[] = array('',$aResult['lon']+($fRadius*sin($f)),$aResult['lat']+($fRadius*cos($f)));
+ }
$aResult['aPolyPoints'] = array();
foreach($aPolyPoints as $aPoint)
{
}
}
+ if ($this->bIncludeExtraTags)
+ {
+ if ($aResult['extra'])
+ {
+ $aResult['sExtraTags'] = json_decode($aResult['extra']);
+ }
+ else
+ {
+ $aResult['sExtraTags'] = array();
+ }
+ }
+
+ if ($this->bIncludeNameDetails)
+ {
+ if ($aResult['names'])
+ {
+ $aResult['sNameDetails'] = json_decode($aResult['names']);
+ }
+ else
+ {
+ $aResult['sNameDetails'] = array();
+ }
+ }
+
// Adjust importance for the number of exact string matches in the result
$aResult['importance'] = max(0.001,$aResult['importance']);
$iCountWords = 0;
if (isset($aClassType[$aResult['class'].':'.$aResult['type']]['importance'])
&& $aClassType[$aResult['class'].':'.$aResult['type']]['importance'])
{
- $aResult['foundorder'] = $aResult['foundorder'] + 0.000001 * $aClassType[$aResult['class'].':'.$aResult['type']]['importance'];
+ $aResult['foundorder'] += 0.0001 * $aClassType[$aResult['class'].':'.$aResult['type']]['importance'];
}
else
{
- $aResult['foundorder'] = $aResult['foundorder'] + 0.001;
+ $aResult['foundorder'] += 0.01;
}
+ if (CONST_Debug) { var_dump($aResult); }
$aSearchResults[$iResNum] = $aResult;
}
uasort($aSearchResults, 'byImportance');