OpenGastroMap/Installation/features.php

From OpenStreetMap Wiki
Jump to: navigation, search
To use this file, please do not copy the contents of this page directly, but take the Wiki source instead. Otherwise, HTML codes are not provided correctly.
<?php
/*
    Map layers for OpenStreetMap 'smoking' tag, online editing of tags
    Copyright (C) 2010 Stephan Knauss, stephankn@toolserver.org
    several changes: Markus Weber

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

	parameter f
    m - return no smoking tag
    n - return nonsmoking
    p - return isolated
    s - return smoking
    x - return all symbols for n, p, s
    c - return cuisine
    w - return wheelchair
    i - return internet access
    a - return details

    parameter t (for f==m,n,p,s,x)
    g - "getraenkegepraegte Gaststaetten", i.e. only: bar, pub, nightclub
    s - "speisegepraegte Gaststaetten", i.e. only: restaurant, cafe, fast_food, food_court
*/

//header('Content-Type: text/plain; charset=utf-8');

$bbox= $_GET['bbox'];
if (!isset($bbox)) {
echo "not defined bbox\n";
// we should exit here, but for test purposes we need t go on
$bbox='10.5, 49.0, 11.5, 50.0';
}
$box=explode(',', $bbox);
$bounds= pg_escape_string($box[0].' '.$box[1].','.$box[2].' '.$box[3]);

$fpar= 'a';
if(isset($_GET['f'])) {
  $fpar= $_GET['f'];
  if(!in_array($fpar,array('n','s','m','p','x','c','w','i','a'))) $fpar= 'a';
  }

$tpar= $_GET['t'];

$resolution= 0;
if(isset($_GET['resolution']) && is_numeric($_GET['resolution']))
  $resolution= $_GET['resolution'];

if($resolution>156543.0339 || $resolution<0.5971642833709717)
   $resolution= 0;

$zoom= 0;
if(isset($_GET['zoom']) && is_numeric($_GET['zoom']))
  $zoom= $_GET['zoom'];
if($zoom>18 || $zoom<0)
  $zoom = 0;


$cluster= '';
if($resolution>0) {  // enable clustering if needed
  if($zoom>=17 || in_array($fpar,array('c','w','i','a'))) {
    // no clustering on Z17 and Z18, no clustering for detail layers at all
//      $cluster= ', st_astext(way) as cluster';
//      $cluster= ", st_astext(st_makepoint(round(st_x(way)/1)*1,round(st_y(way)/1)*1)) as cluster";
    $cluster= ", st_astext(st_makepoint(round(st_x(way)),round(st_y(way)))) as cluster";
    }
  else {
    // calculate clustering value. resolution is per pixel, so multiply by size of icon, take overlap factor into account
    $clvalue= 32*$resolution*0.9;
    $cluster= ", st_astext(st_makepoint(round(st_x(way)/$clvalue)*$clvalue,round(st_y(way)/$clvalue)*$clvalue)) as cluster";
    }
  }

if($tpar=='g')
  $amenityQuery= "(amenity in ('bar','pub','nightclub') and disused is null)";
else if($tpar=='s')
  $amenityQuery= "(amenity in ('restaurant','cafe','fast_food','food_court') and disused is null)";
else
  $amenityQuery= "(amenity in ('bar','pub','restaurant','cafe','fast_food','food_court','nightclub') and disused is null)";

// concerning database(s), please note:
// we may have several data bases which are being used alternately every other day;
// that makes it possible to build-up one database content by using osm2pgsql
// while serving requests using the other data base at the same time;
// so we will access the database gis0 at even days and gis1 at odd;

// first, calculate which day we have - even or odd;
// assume that, starting at 16:00 UT, we want the next day's database
// because at this time the generation process for the new data
// should have been completed;
$dbnum= time() + 28800;  // 8*3600 means: at 16:00 UT
$dbnum= $dbnum / 86400 % 2;

// connect to the appropriate database
//$dbconn= pg_pconnect('dbname=gis'.' user=gisuser');
$dbconn= pg_connect('dbname=gis'.$dbnum.' user=gisuser');
if (!$dbconn) {  // could not connect to this day's database
  // try to connect to the other day's data base
  $dbconn= pg_connect('dbname=gis'.(1-$dbnum).' user=gisuser');
  if (!$dbconn) {  // could not connect to the other day's database
    // try to connect to a commonly usable database as a fallback strategy
    $dbconn= pg_connect('dbname=gis user=gisuser');
    if (!$dbconn) {  // could not connect either
      echo "Error connecting. Please report to @TODO .\n";
      exit;
      }
    }
  }

// create header for output
if($fpar=='a')
   echo "lon\tlat\tosmid\tosmtype\tname\tamenity\tsmoking\tsmoking_hours\tsmoking_outside\tcuisine\tcuisine_icon\twheelchair\tinternet_access\twebsite\ticonSize\ticonOffset\ticon\n";
else
   echo "lon\tlat\ticonSize\ticonOffset\ticon\n";

if($fpar=='x')
  $farray= array('n','p','s');
else if($fpar=='m')
  $farray= array('m');
else
  $farray= array($fpar);


// main loop, integrating each layer in case of $fpar=='x'
foreach($farray as $ftype) {

// Generate Filter
$column= "";
switch($ftype) {
case m: // missing attributes
  $filter= "($amenityQuery AND smoking is null AND \"smoking:outside\" is null)"; break;
case n: // non-smoking
  $filter= "(smoking='no' AND $amenityQuery)"; break;
case s: // smoking
  $filter= "(smoking is not null AND $amenityQuery AND smoking<>'no' AND smoking<>'isolated')";
  break;
case p: // isolated
  $filter= "(smoking='isolated' AND $amenityQuery )"; break;
case c: // cuisine
  $filter= "($amenityQuery)";
  $column= "cuisine";
  break;
case w:
  $filter= "(wheelchair is not null AND $amenityQuery)";
  $column= "wheelchair";
  break;
case i:
  $filter= "(internet_access is not null AND $amenityQuery)";
  $column= "internet_access";
  break;
case a: // return details
default:
  $filter= "($amenityQuery)";
  }

// query strategy: first try to reduce data utilizing indexes where available. Validated with ANALYZE EXPLAIN

// RESULT IS REQUIRED AS POINT, OSM_ID, NAME, OSMTYPE, COUNT !!!
if($ftype=='a') {
  $query= 'SELECT st_astext(st_centroid(st_collect(way))) as point, min(osm_id) as osm_id, min(name) as name, min(osmtype) as osmtype, count(*), min(amenity) as amenity, min(smoking) as smoking, min(smoking_hours) as smoking_hours, min("smoking:outside") as smoking_outside, min(cuisine) as cuisine, min(wheelchair) as wheelchair, min(internet_access) as internet_access, min(website) as website'.$cluster.' FROM (';
  $query.= ' SELECT way, osm_id, name, amenity, \'n\' as osmtype, smoking, smoking_hours, "smoking:outside", cuisine, wheelchair, internet_access, website FROM planet_osm_point ';
  $query.= " WHERE (way && SetSRID('BOX3D($bounds)'::box3d,900913)) AND $filter";
  $query.= ' UNION ALL';
  $query.= ' SELECT st_centroid(way) AS way, osm_id, name, amenity, \'w\' as osmtype, smoking, smoking_hours, "smoking:outside", cuisine, wheelchair, internet_access, website FROM planet_osm_polygon ';
  $query.= " WHERE (way && SetSRID('BOX3D($bounds)'::box3d,900913)) AND $filter";
  $query.= ') AS t GROUP by cluster LIMIT 500;';
//   $query .= ') AS t LIMIT 500;';
  }
else {
  $query= 'SELECT point, osm_id, name';
  if($column!="") $query.= ', '.$column;
  $query.= ', count FROM ( SELECT st_astext(st_centroid(st_collect(way))) AS point, min(osm_id) AS osm_id, min(name) AS name';
  if($column!="") $query.= ', min('.$column.') AS '.$column;
  $query.= ', count(*)'.$cluster.', min(way) as pos FROM (';
  $query.= ' SELECT st_centroid(way) AS way, osm_id, name';
  if($column!="") $query.= ', '.$column;
  $query.= ' FROM planet_osm_polygon ';
  $query.= " WHERE (way && SetSRID('BOX3D($bounds)'::box3d,900913)) AND $filter ";
  $query.= ' UNION ALL';
  $query.= ' SELECT way, osm_id, name';
  if($column!="") $query.= ', '.$column;
  $query.= ' FROM planet_osm_point ';
  $query.= " WHERE (way && SetSRID('BOX3D($bounds)'::box3d,900913)) AND $filter ";
  $query.= ' ) AS t GROUP BY cluster ';
  $query.= ") AS t2 WHERE pos && SetSRID('BOX3D($bounds)'::box3d,900913) LIMIT 500;";
  }
// echo "$query\n";

$result= pg_query($dbconn,$query);
if(!$result) {
  echo "An error occurred:".pg_last_error()."\n";
  echo $query;
  exit;
  }

// output the data for every marker
while($row= pg_fetch_array($result)) {  // for every marker
  $coords= str_replace("POINT(", '', $row['point']);
  $coords= str_replace(')', '', $coords);
  $coords= str_replace(' ', "\t", $coords);
  $osmtype= $row['osmtype'];
  
  // values greater 1 indicate clustering, use different icons for these.
  if($row['count'] > 1) $osmtype= 'c';  //artificial type for cluster
  
  switch ($ftype) {
  case m:
    if($osmtype=='c') echo "$coords\t16,16\t-8,-8\tcb.png\n";
    else echo "$coords\t16,16\t-8,-8\tb.png\n";
    break;
  case n:  // color 21
    if($osmtype=='c') echo "$coords\t32,32\t-16,-20\tcg.png\n";
    else echo "$coords\t32,32\t-16,-20\tg.png\n";
    break;
  case s:  // color 108
    if($osmtype=='c') echo "$coords\t32,32\t-16,-20\tcr.png\n";
    else echo "$coords\t32,32\t-16,-20\tr.png\n";
    break;
  case p:
    if($osmtype=='c') echo "$coords\t32,32\t-16,-20\tcy.png\n";
    else echo "$coords\t32,32\t-16,-20\ty.png\n";
    break;
  case w:
    $icon= htmlentities($row['wheelchair']);
    if(in_array($icon,array("yes","no","limited"))) {
      $icon= "whe_".$icon.".png";
      echo "$coords\t24,24\t-12,-15\t$icon\n";
      }
    break;
  case i:
    $icon= htmlentities($row['internet_access']);
    if(in_array($icon,array("terminal","wlan"))) {
      $icon= "int_".$icon.".png";
      echo "$coords\t24,24\t-12,-15\t$icon\n";
      }
    break;
  case c:
  case a:
  default:
    $cuisine = htmlentities(mb_strtolower($row['cuisine']));
    $cuisine= strtok($cuisine,";, /");
    $ic= 2;  // regular icon for known cuisines
    switch($cuisine) {  // translate cuisine into German
    case 'afghan': $cui= 'afghanische Küche'; break;
    case 'african': $cui= 'afrikanische Küche'; break;
    case 'american': $cui= 'US-amerikanische Küche'; break;
    case 'argentinian': $cui= 'argentinische Küche'; break;
    case 'asian': $cui= 'asiatische Küche'; break;
    case 'australian': $cui= 'australische Küche'; break;
    case 'austrian': $cui= 'österreichische Küche'; break;
    case 'bavarian': $cui= 'bayerische Küche'; break;
    case 'bohemian': $cui= 'böhmische Küche'; break;
    case 'bratwurst': $cui= 'Küche: Bratwürste'; break;
    case 'burger': $cui= 'Küche: Burger'; break;
    case 'croatian': $cui= 'kroatische Küche'; break;
    case 'czech': $cui= 'tschechische Küche'; break;
    case 'chinese': $cui= 'chinesische Küche'; break;
    case 'danish': $cui= 'dänische Küche'; break;
    case 'fish': $cui= 'Küche: Fisch'; break;
    case 'frankonian': $cui= 'fränkische Küche'; break;
    case 'french': $cui= 'französische Küche'; break;
    case 'german': $cui= 'deutsche Küche'; break;
    case 'greek': $cui= 'griechische Küche'; break;
    case 'ice_cream': $cui= 'Küche: Speiseeis'; break;
    case 'indian': $cui= 'indische Küche'; break;
    case 'international': $cui= 'internationale Küche'; break;
    case 'irish': $cui= 'irische Küche'; break;
    case 'italian': $cui= 'italienische Küche'; break;
    case 'japanese': $cui= 'japanische Küche'; break;
    case 'kebab': $cui= 'Küche: Döner'; break;
    case 'korean': $cui= 'koreanische Küche'; break;
    case 'lebanese': $cui= 'libanesische Küche'; break;
    case 'mediterranean': $cui= 'mediterrane Küche'; break;
    case 'mexican': $cui= 'mexikanische Küche'; break;
    case 'noodles': $cui= 'Küche: Nudeln'; break;
    case 'pizza': $cui= 'Küche: Pizza'; break;
    case 'regional': $cui= 'regionale Küche'; break;
    case 'russian': $cui= 'russische Küche'; break;
    case 'shisha': $cui= 'Shisha-Bar'; break;
    case 'south_african': $cui= 'südafrikanische Küche'; break;
    case 'spanish': $cui= 'spanische Küche'; break;
    case 'steak': $cui= 'Küche: Steaks'; break;
    case 'sandwich': $cui= 'Küche: Sandwiches'; break;
    case 'steak_house': $cui= 'Steak-Haus'; break;
    case 'sushi': $cui= 'Küche: Sushi'; break;
    case 'thai': $cui= 'thailändische Küche'; break;
    case 'turkish': $cui= 'türkische Küche'; break;
    case 'vietnamese': $cui= 'vietnamesische Küche'; break;
    default:
      if($cuisine=='') {
        $cui= '_';
        $ic= 0; // icon for undefined cuisines
        }
      else {
        $cui= 'Küche (engl.): '.$cuisine;
        $ic= 1;  // icon for defined cuisines we do not recognize
        }
      }
    if($ic==0) $cuisine_icon= "cui_undefined.png";
    else if($ic==1) $cuisine_icon= "cui_unknown.png";
    else $cuisine_icon= "cui_".$cuisine.".png";

    if($ftype=="c") {
      echo "$coords\t24,24\t-12,-15\t$cuisine_icon\n";
      break;
      }

    $name = htmlspecialchars($row['name']);
    $amenity = htmlentities(mb_strtolower($row['amenity']));
    $smoking = htmlentities(mb_strtolower($row['smoking']));
    $smoking_hours = htmlentities(mb_strtolower($row['smoking_hours']));
    if($smoking_hours=='') $smoking_hours= '_';
    $smoking_outside = htmlentities(mb_strtolower($row['smoking_outside']));
    if($smoking_outside=='') $smoking_outside= '_';
    $wheelchair= htmlentities($row['wheelchair']);
    $internet_access= htmlentities($row['internet_access']);
    $website= htmlspecialchars($row['website']);
    if($website=='') $website= '_';

    echo "$coords\t$row[1]\t$osmtype\t$name\t$amenity\t$smoking\t$smoking_hours\t$smoking_outside\t$cui\t$cuisine_icon\t$wheelchair\t$internet_access\t$website\t24,24\t-12,-15\tu.png\n";
    }
  }  // end   for every marker
}  // end of main loop
?>