Update busstopdensity tile generator for labs and PDO postgres
Update busstopdensity tile generator for labs and PDO postgres

<?php <?php
// Copyright 2009 Google Inc. All Rights Reserved. // Copyright 2009 Google Inc. All Rights Reserved.
$GA_ACCOUNT = "MO-22173039-1"; $GA_ACCOUNT = "MO-22173039-1";
$GA_PIXEL = "/lib/ga.php"; $GA_PIXEL = "/lib/ga.php";
function googleAnalyticsGetImageUrl() function googleAnalyticsGetImageUrl()
{ {
global $GA_ACCOUNT, $GA_PIXEL; global $GA_ACCOUNT, $GA_PIXEL;
//if (stristr($_SERVER['HTTP_USER_AGENT'], 'Googlebot') return ""; //if (stristr($_SERVER['HTTP_USER_AGENT'], 'Googlebot') return "";
$url = ""; $url = "";
$url.= $GA_PIXEL . "?"; $url.= $GA_PIXEL . "?";
$url.= "utmac=" . $GA_ACCOUNT; $url.= "utmac=" . $GA_ACCOUNT;
$url.= "&utmn=" . rand(0, 0x7fffffff); $url.= "&utmn=" . rand(0, 0x7fffffff);
$referer = $_SERVER["HTTP_REFERER"]; $referer = $_SERVER["HTTP_REFERER"];
$query = $_SERVER["QUERY_STRING"]; $query = $_SERVER["QUERY_STRING"];
$path = $_SERVER["REQUEST_URI"]; $path = $_SERVER["REQUEST_URI"];
if (empty($referer)) { if (empty($referer)) {
$referer = "-"; $referer = "-";
} }
$url.= "&utmr=" . urlencode($referer); $url.= "&utmr=" . urlencode($referer);
if (!empty($path)) { if (!empty($path)) {
$url.= "&utmp=" . urlencode($path); $url.= "&utmp=" . urlencode($path);
} }
$url.= "&guid=ON"; $url.= "&guid=ON";
return str_replace("&", "&amp;", $url); return str_replace("&", "&amp;", $url);
} }
function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false, $datepicker = false) function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false, $datepicker = false)
{ {
global $labsPath; global $labsPath;
echo ' echo '
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>' . $pageTitle . '</title> <title>' . $pageTitle . '</title>
<meta name="google-site-verification" content="-53T5Qn4TB_de1NyfR_ZZkEVdUNcNFSaYKSFkWKx-sY" /> <meta name="google-site-verification" content="-53T5Qn4TB_de1NyfR_ZZkEVdUNcNFSaYKSFkWKx-sY" />
  <link rel="dns-prefetch" href="//code.jquery.com">
  <link rel="dns-prefetch" href="//ajax.googleapis.com">
<link rel="stylesheet" href="' . $labsPath . 'css/jquery-ui-1.8.12.custom.css" />'; <link rel="stylesheet" href="' . $labsPath . 'css/jquery-ui-1.8.12.custom.css" />';
if (isDebugServer()) { if (isDebugServer()) {
$jqmcss = $labsPath . 'css/jquery.mobile-1.0b1.css'; $jqmcss = $labsPath . 'css/jquery.mobile-1.0b1.css';
$jqjs = $labsPath . 'js/jquery-1.6.1.min.js'; $jqjs = $labsPath . 'js/jquery-1.6.1.min.js';
$jqmjs = $labsPath . 'js/jquery.mobile-1.0b1.js'; $jqmjs = $labsPath . 'js/jquery.mobile-1.0b1.js';
} }
else { else {
$jqmcss = "http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.css"; $jqmcss = "//code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.css";
$jqjs = "http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"; $jqjs = "//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js";
$jqmjs = "http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.js"; $jqmjs = "//code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.js";
} }
echo '<link rel="stylesheet" href="' . $jqmcss . '" /> echo '<link rel="stylesheet" href="' . $jqmcss . '" />
<script src="'.$jqjs.'"></script> <script src="'.$jqjs.'"></script>
<script>$(document).bind("mobileinit", function(){ <script>$(document).bind("mobileinit", function(){
$.mobile.ajaxEnabled = false; $.mobile.ajaxEnabled = false;
}); });
</script> </script>
<script src="'.$jqmjs.'"></script> <script src="'.$jqmjs.'"></script>
   
<script src="' . $labsPath . 'js/jquery.ui.core.min.js"></script> <script src="' . $labsPath . 'js/jquery.ui.core.min.js"></script>
<script src="' . $labsPath . 'js/jquery.ui.position.min.js"></script> <script src="' . $labsPath . 'js/jquery.ui.position.min.js"></script>
<script src="' . $labsPath . 'js/jquery.ui.widget.min.js"></script> <script src="' . $labsPath . 'js/jquery.ui.widget.min.js"></script>
<script src="' . $labsPath . 'js/jquery.ui.autocomplete.min.js"></script> <script src="' . $labsPath . 'js/jquery.ui.autocomplete.min.js"></script>
<script> <script>
$(function() { $(function() {
$( "#geolocate" ).autocomplete({ $( "#geolocate" ).autocomplete({
source: "lib/autocomplete.php", source: "lib/autocomplete.php",
minLength: 2 minLength: 2
}); });
$( "#from" ).autocomplete({ $( "#from" ).autocomplete({
source: "lib/autocomplete.php", source: "lib/autocomplete.php",
minLength: 2 minLength: 2
}); });
$( "#to" ).autocomplete({ $( "#to" ).autocomplete({
source: "lib/autocomplete.php", source: "lib/autocomplete.php",
minLength: 2 minLength: 2
}); });
}); });
</script>'; </script>';
echo '<style type="text/css">'; echo '<style type="text/css">';
if (strstr($_SERVER['HTTP_USER_AGENT'], 'Android')) echo '.ui-shadow,.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a,.ui-body-b,.ui-btn-up-b,.ui-btn-hover-b, if (strstr($_SERVER['HTTP_USER_AGENT'], 'Android')) echo '.ui-shadow,.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a,.ui-body-b,.ui-btn-up-b,.ui-btn-hover-b,
.ui-btn-down-b,.ui-bar-c,.ui-body-c,.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c,.ui-bar-c,.ui-body-d, .ui-btn-down-b,.ui-bar-c,.ui-body-c,.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c,.ui-bar-c,.ui-body-d,
.ui-btn-up-d,.ui-btn-hover-d,.ui-btn-down-d,.ui-bar-d,.ui-body-e,.ui-btn-up-e,.ui-btn-hover-e, .ui-btn-up-d,.ui-btn-hover-d,.ui-btn-down-d,.ui-bar-d,.ui-body-e,.ui-btn-up-e,.ui-btn-hover-e,
.ui-btn-down-e,.ui-bar-e,.ui-overlay-shadow,.ui-shadow,.ui-btn-active,.ui-body-a,.ui-bar-a { .ui-btn-down-e,.ui-bar-e,.ui-overlay-shadow,.ui-shadow,.ui-btn-active,.ui-body-a,.ui-bar-a {
text-shadow: none; text-shadow: none;
box-shadow: none; box-shadow: none;
-webkit-box-shadow: none; -webkit-box-shadow: none;
}'; }';
echo '</style>'; echo '</style>';
echo '<link rel="stylesheet" href="' . $labsPath . 'css/local.css.php" />'; echo '<link rel="stylesheet" href="' . $labsPath . 'css/local.css.php" />';
if (strstr($_SERVER['HTTP_USER_AGENT'], 'iPhone') || strstr($_SERVER['HTTP_USER_AGENT'], 'iPod') || strstr($_SERVER['HTTP_USER_AGENT'], 'iPad')) { if (strstr($_SERVER['HTTP_USER_AGENT'], 'iPhone') || strstr($_SERVER['HTTP_USER_AGENT'], 'iPod') || strstr($_SERVER['HTTP_USER_AGENT'], 'iPad')) {
echo '<meta name="apple-mobile-web-app-capable" content="yes" /> echo '<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="apple-touch-startup-image" href="startup.png" /> <link rel="apple-touch-startup-image" href="startup.png" />
<link rel="apple-touch-icon" href="apple-touch-icon.png" />'; <link rel="apple-touch-icon" href="apple-touch-icon.png" />';
} }
if ($geolocate) { if ($geolocate) {
echo "<script> echo "<script>
   
function success(position) { function success(position) {
$('#error').val('Location now detected. Please wait for data to load.'); $('#error').val('Location now detected. Please wait for data to load.');
$('#geolocate').val(position.coords.latitude+','+position.coords.longitude); $('#geolocate').val(position.coords.latitude+','+position.coords.longitude);
$.ajax({ url: \"include/common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+position.coords.longitude }); $.ajax({ url: \"include/common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+position.coords.longitude });
location.reload(true); location.reload(true);
} }
function error(msg) { function error(msg) {
$('#error').val('Error: '+msg); $('#error').val('Error: '+msg);
} }
   
function geolocate() { function geolocate() {
if (navigator.geolocation) { if (navigator.geolocation) {
var options = { var options = {
enableHighAccuracy: true, enableHighAccuracy: true,
timeout: 60000, timeout: 60000,
maximumAge: 10000 maximumAge: 10000
} }
navigator.geolocation.getCurrentPosition(success, error, options); navigator.geolocation.getCurrentPosition(success, error, options);
} }
} }
$(document).ready(function() { $(document).ready(function() {
$('#here').click(function(event) { $('#geolocate').val(geolocate()); return false;}); $('#here').click(function(event) { $('#geolocate').val(geolocate()); return false;});
$('#here').show(); $('#here').show();
}); });
"; ";
if (!isset($_SESSION['lat']) || $_SESSION['lat'] == "") echo "geolocate();"; if (!isset($_SESSION['lat']) || $_SESSION['lat'] == "") echo "geolocate();";
echo "</script> "; echo "</script> ";
} }
if (isAnalyticsOn()) echo ' if (isAnalyticsOn()) echo '
<script type="text/javascript">' . " <script type="text/javascript">' . "
   
var _gaq = _gaq || []; var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-22173039-1']); _gaq.push(['_setAccount', 'UA-22173039-1']);
_gaq.push(['_trackPageview']); _gaq.push(['_trackPageview']);
_gaq.push(['_trackPageLoadTime']); _gaq.push(['_trackPageLoadTime']);
</script>"; </script>";
echo '</head> echo '</head>
<body> <body>
<div id="skip"> <div id="skip">
<a href="#maincontent">Skip to content</a> <a href="#maincontent">Skip to content</a>
</div> </div>
'; ';
if ($opendiv) { if ($opendiv) {
echo '<div data-role="page"> echo '<div data-role="page">
<div data-role="header" data-position="inline"> <div data-role="header" data-position="inline">
<a href="' . (isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : "javascript:history.go(-1)") . '" data-icon="arrow-l" data-rel="back" class="ui-btn-left">Back</a> <a href="' . (isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : "javascript:history.go(-1)") . '" data-icon="arrow-l" data-rel="back" class="ui-btn-left">Back</a>
<h1>' . $pageTitle . '</h1> <h1>' . $pageTitle . '</h1>
<a href="' . $labsPath . '/index.php" data-icon="home" class="ui-btn-right">Home</a> <a href="' . $labsPath . '/index.php" data-icon="home" class="ui-btn-right">Home</a>
</div><!-- /header --> </div><!-- /header -->
<a name="maincontent" id="maincontent"></a> <a name="maincontent" id="maincontent"></a>
<div data-role="content"> '; <div data-role="content"> ';
$overrides = getServiceOverride(); $overrides = getServiceOverride();
if ($overrides['service_id']) { if ($overrides['service_id']) {
if ($overrides['service_id'] == "noservice") { if ($overrides['service_id'] == "noservice") {
echo '<div id="servicewarning">Buses are <strong>not running today</strong> due to industrial action/public holiday. See <a echo '<div id="servicewarning">Buses are <strong>not running today</strong> due to industrial action/public holiday. See <a
href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>'; href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>';
} }
else { else {
echo '<div id="servicewarning">Buses are running on an altered timetable today due to industrial action/public holiday. See <a href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>'; echo '<div id="servicewarning">Buses are running on an altered timetable today due to industrial action/public holiday. See <a href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>';
} }
} }
} }
} }
function include_footer() function include_footer()
{ {
global $labsPath; global $labsPath;
echo '<div id="footer"><a href="' . $labsPath . 'about.php">About/Contact Us</a>&nbsp;<a href="' . $labsPath . 'feedback.php">Feedback/Bug Report</a>&nbsp;<a href="' . $labsPath . 'privacy.php">Privacy Policy</a>'; echo '<div id="footer"><a href="' . $labsPath . 'about.php">About/Contact Us</a>&nbsp;<a href="' . $labsPath . 'feedback.php">Feedback/Bug Report</a>&nbsp;<a href="' . $labsPath . 'privacy.php">Privacy Policy</a>';
echo '</div>'; echo '</div>';
if (isAnalyticsOn()) { if (isAnalyticsOn()) {
echo "<script> (function() { echo "<script> (function() {
var ga = document.createElement('script'); ga.type = var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true; 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? ga.src = ('https:' == document.location.protocol ?
'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s); s.parentNode.insertBefore(ga, s);
})();</script>"; })();</script>";
$googleAnalyticsImageUrl = googleAnalyticsGetImageUrl(); $googleAnalyticsImageUrl = googleAnalyticsGetImageUrl();
echo '<noscript><img src="' . $googleAnalyticsImageUrl . '" /></noscript>'; echo '<noscript><img src="' . $googleAnalyticsImageUrl . '" /></noscript>';
} }
echo "\n</div></div></body></html>"; echo "\n</div></div></body></html>";
} }
function placeSettings() function placeSettings()
{ {
global $service_periods; global $service_periods;
$geoerror = false; $geoerror = false;
$geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat']) || $_SESSION['lat'] == "" || $_SESSION['lon'] == ""; $geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat']) || $_SESSION['lat'] == "" || $_SESSION['lon'] == "";
   
echo '<div id="error">'; echo '<div id="error">';
if ($geoerror) { if ($geoerror) {
echo 'Sorry, but your location could not currently be detected. echo 'Sorry, but your location could not currently be detected.
Please allow location permission, wait for your location to be detected, Please allow location permission, wait for your location to be detected,
or enter an address/co-ordinates in the box below.'; or enter an address/co-ordinates in the box below.';
} }
echo '</div>'; echo '</div>';
echo '<div id="settings" data-role="collapsible" data-collapsed="' . !$geoerror . '"> echo '<div id="settings" data-role="collapsible" data-collapsed="' . !$geoerror . '">
<h3>Change Location...</h3> <h3>Change Location...</h3>
<form action="' . basename($_SERVER['PHP_SELF']) . "?" . $_SERVER['QUERY_STRING'] . '" method="post"> <form action="' . basename($_SERVER['PHP_SELF']) . "?" . $_SERVER['QUERY_STRING'] . '" method="post">
<div class="ui-body"> <div class="ui-body">
<div data-role="fieldcontain"> <div data-role="fieldcontain">
<label for="geolocate"> Current Location: </label> <label for="geolocate"> Current Location: </label>
<input type="text" id="geolocate" name="geolocate" value="' . (isset($_SESSION['lat']) && isset($_SESSION['lon']) ? $_SESSION['lat'] . "," . $_SESSION['lon'] : "Enter co-ordinates or address here") . '"/> <a href="#" style="display:none" name="here" id="here">Here?</a> <input type="text" id="geolocate" name="geolocate" value="' . (isset($_SESSION['lat']) && isset($_SESSION['lon']) ? $_SESSION['lat'] . "," . $_SESSION['lon'] : "Enter co-ordinates or address here") . '"/> <a href="#" style="display:none" name="here" id="here">Here?</a>
</div> </div>
<input type="submit" value="Update"/> <input type="submit" value="Update"/>
</div></form> </div></form>
</div>'; </div>';
} }
function trackEvent($category, $action, $label = "", $value = - 1) function trackEvent($category, $action, $label = "", $value = - 1)
{ {
if (isAnalyticsOn()) { if (isAnalyticsOn()) {
echo "\n<script> _gaq.push(['_trackEvent', '$category', '$action'" . ($label != "" ? ", '$label'" : "") . ($value != - 1 ? ", $value" : "") . "]);</script>"; echo "\n<script> _gaq.push(['_trackEvent', '$category', '$action'" . ($label != "" ? ", '$label'" : "") . ($value != - 1 ? ", $value" : "") . "]);</script>";
} }
} }
?> ?>
   
<?php <?php
include ('../include/common.inc.php'); include ('../include/common.inc.php');
$debugOkay = Array(); $debugOkay = Array();
   
/* /*
*DISCLAIMER *DISCLAIMER
* http://blog.gmapify.fr/create-beautiful-tiled-heat-maps-with-php-and-gd * http://blog.gmapify.fr/create-beautiful-tiled-heat-maps-with-php-and-gd
*THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* @author: Olivier G. <olbibigo_AT_gmail_DOT_com> * @author: Olivier G. <olbibigo_AT_gmail_DOT_com>
* @version: 1.0 * @version: 1.0
* @history: * @history:
* 1.0 creation * 1.0 creation
*/ */
set_time_limit(120);//2mn set_time_limit(120);//2mn
ini_set('memory_limit', '256M'); ini_set('memory_limit', '256M');
error_reporting(E_ALL ^ E_DEPRECATED); error_reporting(E_ALL ^ E_DEPRECATED);
require_once ('lib/GoogleMapUtility.php'); require_once ($labsPath . 'lib/GoogleMapUtility.php');
require_once ('lib/HeatMap.php'); require_once ($labsPath . 'lib/HeatMap.php');
   
//Root folder to store generated tiles //Root folder to store generated tiles
define('TILE_DIR', 'tiles/'); define('TILE_DIR', 'tiles/');
//Covered geographic areas //Covered geographic areas
define('MIN_LAT', -35.48); define('MIN_LAT', -35.48);
define('MAX_LAT', -35.15); define('MAX_LAT', -35.15);
define('MIN_LNG', 148.98); define('MIN_LNG', 148.98);
define('MAX_LNG', 149.25); define('MAX_LNG', 149.25);
define('TILE_SIZE_FACTOR', 0.5); define('TILE_SIZE_FACTOR', 0.5);
define('SPOT_RADIUS', 30); define('SPOT_RADIUS', 30);
define('SPOT_DIMMING_LEVEL', 50); define('SPOT_DIMMING_LEVEL', 50);
//Input parameters //Input parameters
if(isset($_GET['x'])) if(isset($_GET['x']))
$X = (int)$_GET['x']; $X = (int)$_GET['x'];
else else
exit("x missing"); exit("x missing");
if(isset($_GET['y'])) if(isset($_GET['y']))
$Y = (int)$_GET['y']; $Y = (int)$_GET['y'];
else else
exit("y missing"); exit("y missing");
if(isset($_GET['zoom'])) if(isset($_GET['zoom']))
$zoom = (int)$_GET['zoom']; $zoom = (int)$_GET['zoom'];
else else
exit("zoom missing"); exit("zoom missing");
if ($zoom < 12) { //enforce minimum zoom if ($zoom < 12) { //enforce minimum zoom
header('Content-type: image/png'); header('Content-type: image/png');
echo file_get_contents(TILE_DIR.'empty.png'); echo file_get_contents(TILE_DIR.'empty.png');
} }
$dir = TILE_DIR.$zoom; $dir = TILE_DIR.$zoom;
$tilename = $dir.'/'.$X.'_'.$Y.'.png'; $tilename = $dir.'/'.$X.'_'.$Y.'.png';
//HTTP headers (data type and caching rule) //HTTP headers (data type and caching rule)
header("Cache-Control: must-revalidate"); header("Cache-Control: must-revalidate");
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 86400) . " GMT"); header("Expires: " . gmdate("D, d M Y H:i:s", time() + 86400) . " GMT");
if(!file_exists($tilename)){ if(!file_exists($tilename)){
$rect = GoogleMapUtility::getTileRect($X, $Y, $zoom); $rect = GoogleMapUtility::getTileRect($X, $Y, $zoom);
//A tile can contain part of a spot with center in an adjacent tile (overlaps). //A tile can contain part of a spot with center in an adjacent tile (overlaps).
//Knowing the spot radius (in pixels) and zoom level, a smart way to process tiles would be to compute the box (in decimal degrees) containing only spots that can be drawn on current tile. We choose a simpler solution by increeasing geo bounds by 2*TILE_SIZE_FACTOR whatever the zoom level and spot radius. //Knowing the spot radius (in pixels) and zoom level, a smart way to process tiles would be to compute the box (in decimal degrees) containing only spots that can be drawn on current tile. We choose a simpler solution by increeasing geo bounds by 2*TILE_SIZE_FACTOR whatever the zoom level and spot radius.
$extend_X = $rect->width * TILE_SIZE_FACTOR;//in decimal degrees $extend_X = $rect->width * TILE_SIZE_FACTOR;//in decimal degrees
$extend_Y = $rect->height * TILE_SIZE_FACTOR;//in decimal degrees $extend_Y = $rect->height * TILE_SIZE_FACTOR;//in decimal degrees
$swlat = $rect->y - $extend_Y; $swlat = $rect->y - $extend_Y;
$swlng = $rect->x - $extend_X; $swlng = $rect->x - $extend_X;
$nelat = $swlat + $rect->height + 2 * $extend_Y; $nelat = $swlat + $rect->height + 2 * $extend_Y;
$nelng = $swlng + $rect->width + 2 * $extend_X; $nelng = $swlng + $rect->width + 2 * $extend_X;
   
if( ($nelat <= MIN_LAT) || ($swlat >= MAX_LAT) || ($nelng <= MIN_LNG) || ($swlng >= MAX_LNG)){ if( ($nelat <= MIN_LAT) || ($swlat >= MAX_LAT) || ($nelng <= MIN_LNG) || ($swlng >= MAX_LNG)){
//No geodata so return generic empty tile //No geodata so return generic empty tile
echo file_get_contents(TILE_DIR.'empty.png'); echo file_get_contents(TILE_DIR.'empty.png');
exit(); exit();
} }
   
//Get McDonald's spots //Get McDonald's spots
$spots = fGetPOI('Select * from stops where $spots = fGetPOI('Select * from stops where
(stop_lon > '.$swlng.' AND stop_lon < '.$nelng.') (stop_lon > '.$swlng.' AND stop_lon < '.$nelng.')
AND (stop_lat < '.$nelat.' AND stop_lat > '.$swlat.')', $im, $X, $Y, $zoom, SPOT_RADIUS); AND (stop_lat < '.$nelat.' AND stop_lat > '.$swlat.')', $im, $X, $Y, $zoom, SPOT_RADIUS);
   
if(empty($spots)){ if(empty($spots)){
//No geodata so return generic empty tile //No geodata so return generic empty tile
header('Content-type: image/png'); header('Content-type: image/png');
echo file_get_contents(TILE_DIR.'empty.png'); echo file_get_contents(TILE_DIR.'empty.png');
}else{ }else{
if(!file_exists($dir)){ if(!file_exists($dir)){
mkdir($dir, 0705); mkdir($dir, 0705);
} }
//All the magics is in HeatMap class :) //All the magics is in HeatMap class :)
$im = HeatMap::createImage($spots, GoogleMapUtility::TILE_SIZE, GoogleMapUtility::TILE_SIZE, heatMap::$WITH_ALPHA, SPOT_RADIUS, SPOT_DIMMING_LEVEL, HeatMap::$GRADIENT_FIRE); $im = HeatMap::createImage($spots, GoogleMapUtility::TILE_SIZE, GoogleMapUtility::TILE_SIZE, heatMap::$WITH_ALPHA, SPOT_RADIUS, SPOT_DIMMING_LEVEL, HeatMap::$GRADIENT_FIRE);
//Store tile for reuse and output it //Store tile f