OpenGastroMap/Installation/features.php

From OpenStreetMap Wiki
Jump to navigation Jump to 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
?>