Travelling all routes thought experiment
Travelling all routes thought experiment

file:b/.box (new)
  shared_writable_dirs:
  - /labs/tiles
  - /lib/staticmaplite/cache
  php_extensions: [pgsql, pdo, pdo_pgsql, curl]
 
<?php <?php
function getTrip($tripID) function getTrip($tripID)
{ {
global $conn; global $conn;
$query = "Select * from trips $query = "Select * from trips
join routes on trips.route_id = routes.route_id join routes on trips.route_id = routes.route_id
where trip_id = :tripID where trip_id = :tripID
LIMIT 1"; LIMIT 1";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":tripID", $tripID); $query->bindParam(":tripID", $tripID);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
return $query->fetch(PDO::FETCH_ASSOC); return $query->fetch(PDO::FETCH_ASSOC);
} }
function getTripShape($tripID) function getTripShape($tripID)
{ {
global $conn; global $conn;
$query = "SELECT ST_AsKML(ST_MakeLine(geometry(a.position))) as the_route $query = "SELECT ST_AsKML(ST_MakeLine(geometry(a.position))) as the_route
FROM (SELECT position, FROM (SELECT position,
stop_sequence, trips.trip_id stop_sequence, trips.trip_id
FROM stop_times FROM stop_times
join trips on trips.trip_id = stop_times.trip_id join trips on trips.trip_id = stop_times.trip_id
join stops on stops.stop_id = stop_times.stop_id join stops on stops.stop_id = stop_times.stop_id
WHERE trips.trip_id = :tripID ORDER BY stop_sequence) as a group by a.trip_id"; WHERE trips.trip_id = :tripID ORDER BY stop_sequence) as a group by a.trip_id";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":tripID", $tripID); $query->bindParam(":tripID", $tripID);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
return $query->fetchColumn(0); return $query->fetchColumn(0);
} }
function getTimeInterpolatedTrip($tripID, $range = "") function getTimeInterpolatedTrip($tripID, $range = "")
{ {
global $conn; global $conn;
$query = "SELECT stop_times.trip_id,arrival_time,stop_times.stop_id,stop_lat,stop_lon,stop_name,stop_code, $query = "SELECT stop_times.trip_id,arrival_time,stop_times.stop_id,stop_lat,stop_lon,stop_name,stop_code,
stop_sequence,service_id,trips.route_id,route_short_name,route_long_name stop_sequence,service_id,trips.route_id,route_short_name,route_long_name
FROM stop_times FROM stop_times
join trips on trips.trip_id = stop_times.trip_id join trips on trips.trip_id = stop_times.trip_id
join routes on trips.route_id = routes.route_id join routes on trips.route_id = routes.route_id
join stops on stops.stop_id = stop_times.stop_id join stops on stops.stop_id = stop_times.stop_id
WHERE trips.trip_id = :tripID $range ORDER BY stop_sequence"; WHERE trips.trip_id = :tripID $range ORDER BY stop_sequence";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":tripID", $tripID); $query->bindParam(":tripID", $tripID);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
$stopTimes = $query->fetchAll(); $stopTimes = $query->fetchAll();
$cur_timepoint = Array(); $cur_timepoint = Array();
$next_timepoint = Array(); $next_timepoint = Array();
$distance_between_timepoints = 0.0; $distance_between_timepoints = 0.0;
$distance_traveled_between_timepoints = 0.0; $distance_traveled_between_timepoints = 0.0;
$rv = Array(); $rv = Array();
foreach ($stopTimes as $i => $stopTime) { foreach ($stopTimes as $i => $stopTime) {
if ($stopTime['arrival_time'] != "") { if ($stopTime['arrival_time'] != "") {
// is timepoint // is timepoint
$cur_timepoint = $stopTime; $cur_timepoint = $stopTime;
$distance_between_timepoints = 0.0; $distance_between_timepoints = 0.0;
$distance_traveled_between_timepoints = 0.0; $distance_traveled_between_timepoints = 0.0;
if ($i + 1 < sizeof($stopTimes)) { if ($i + 1 < sizeof($stopTimes)) {
$k = $i + 1; $k = $i + 1;
$distance_between_timepoints+= distance($stopTimes[$k - 1]["stop_lat"], $stopTimes[$k - 1]["stop_lon"], $stopTimes[$k]["stop_lat"], $stopTimes[$k]["stop_lon"]); $distance_between_timepoints+= distance($stopTimes[$k - 1]["stop_lat"], $stopTimes[$k - 1]["stop_lon"], $stopTimes[$k]["stop_lat"], $stopTimes[$k]["stop_lon"]);
while ($stopTimes[$k]["arrival_time"] == "" && $k + 1 < sizeof($stopTimes)) { while ($stopTimes[$k]["arrival_time"] == "" && $k + 1 < sizeof($stopTimes)) {
$k+= 1; $k+= 1;
//echo "k".$k; //echo "k".$k;
$distance_between_timepoints+= distance($stopTimes[$k - 1]["stop_lat"], $stopTimes[$k - 1]["stop_lon"], $stopTimes[$k]["stop_lat"], $stopTimes[$k]["stop_lon"]); $distance_between_timepoints+= distance($stopTimes[$k - 1]["stop_lat"], $stopTimes[$k - 1]["stop_lon"], $stopTimes[$k]["stop_lat"], $stopTimes[$k]["stop_lon"]);
} }
$next_timepoint = $stopTimes[$k]; $next_timepoint = $stopTimes[$k];
} }
$rv[] = $stopTime; $rv[] = $stopTime;
} }
else { else {
// is untimed point // is untimed point
//echo "i".$i; //echo "i".$i;
$distance_traveled_between_timepoints+= distance($stopTimes[$i - 1]["stop_lat"], $stopTimes[$i - 1]["stop_lon"], $stopTimes[$i]["stop_lat"], $stopTimes[$i]["stop_lon"]); $distance_traveled_between_timepoints+= distance($stopTimes[$i - 1]["stop_lat"], $stopTimes[$i - 1]["stop_lon"], $stopTimes[$i]["stop_lat"], $stopTimes[$i]["stop_lon"]);
//echo "$distance_traveled_between_timepoints / $distance_between_timepoints<br>"; //echo "$distance_traveled_between_timepoints / $distance_between_timepoints<br>";
$distance_percent = $distance_traveled_between_timepoints / $distance_between_timepoints; $distance_percent = $distance_traveled_between_timepoints / $distance_between_timepoints;
if ($next_timepoint["arrival_time"] != "") { if ($next_timepoint["arrival_time"] != "") {
$total_time = strtotime($next_timepoint["arrival_time"]) - strtotime($cur_timepoint["arrival_time"]); $total_time = strtotime($next_timepoint["arrival_time"]) - strtotime($cur_timepoint["arrival_time"]);
//echo strtotime($next_timepoint["arrival_time"])." - ".strtotime($cur_timepoint["arrival_time"])."<br>"; //echo strtotime($next_timepoint["arrival_time"])." - ".strtotime($cur_timepoint["arrival_time"])."<br>";
$time_estimate = ($distance_percent * $total_time) + strtotime($cur_timepoint["arrival_time"]); $time_estimate = ($distance_percent * $total_time) + strtotime($cur_timepoint["arrival_time"]);
$stopTime["arrival_time"] = date("H:i:s", $time_estimate); $stopTime["arrival_time"] = date("H:i:s", $time_estimate);
} }
else { else {
$stopTime["arrival_time"] = $cur_timepoint["arrival_time"]; $stopTime["arrival_time"] = $cur_timepoint["arrival_time"];
} }
$rv[] = $stopTime; $rv[] = $stopTime;
} }
} }
//var_dump($rv); //var_dump($rv);
return $rv; return $rv;
} }
function getTripPreviousTimePoint($tripID, $stop_sequence) function getTripPreviousTimePoint($tripID, $stop_sequence)
{ {
global $conn; global $conn;
$query = " SELECT trip_id,stop_id, $query = " SELECT trip_id,stop_id,
stop_sequence stop_sequence
FROM stop_times FROM stop_times
WHERE trip_id = :tripID and stop_sequence < :stop_sequence WHERE trip_id = :tripID and stop_sequence < :stop_sequence
and stop_times.arrival_time IS NOT NULL ORDER BY stop_sequence DESC LIMIT 1"; and stop_times.arrival_time IS NOT NULL ORDER BY stop_sequence DESC LIMIT 1";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":tripID", $tripID); $query->bindParam(":tripID", $tripID);
$query->bindParam(":stop_sequence", $stop_sequence); $query->bindParam(":stop_sequence", $stop_sequence);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
return $query->fetch(PDO::FETCH_ASSOC); return $query->fetch(PDO::FETCH_ASSOC);
} }
function getTripNextTimePoint($tripID, $stop_sequence) function getTripNextTimePoint($tripID, $stop_sequence)
{ {
global $conn; global $conn;
$query = " SELECT trip_id,stop_id, $query = " SELECT trip_id,stop_id,
stop_sequence stop_sequence
FROM stop_times FROM stop_times
WHERE trip_id = :tripID and stop_sequence > :stop_sequence WHERE trip_id = :tripID and stop_sequence > :stop_sequence
and stop_times.arrival_time IS NOT NULL ORDER BY stop_sequence LIMIT 1"; and stop_times.arrival_time IS NOT NULL ORDER BY stop_sequence LIMIT 1";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":tripID", $tripID); $query->bindParam(":tripID", $tripID);
$query->bindParam(":stop_sequence", $stop_sequence); $query->bindParam(":stop_sequence", $stop_sequence);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
return $query->fetch(PDO::FETCH_ASSOC); return $query->fetch(PDO::FETCH_ASSOC);
} }
function getTimeInterpolatedTripAtStop($tripID, $stop_sequence) function getTimeInterpolatedTripAtStop($tripID, $stop_sequence)
{ {
global $conn; global $conn;
// limit interpolation to between nearest actual points. // limit interpolation to between nearest actual points.
$prevTimePoint = getTripPreviousTimePoint($tripID, $stop_sequence); $prevTimePoint = getTripPreviousTimePoint($tripID, $stop_sequence);
$nextTimePoint = getTripNextTimePoint($tripID, $stop_sequence); $nextTimePoint = getTripNextTimePoint($tripID, $stop_sequence);
//echo " prev {$lowestDelta['stop_sequence']} next {$nextTimePoint['stop_sequence']} "; //echo " prev {$lowestDelta['stop_sequence']} next {$nextTimePoint['stop_sequence']} ";
$range = ""; $range = "";
if ($prevTimePoint != "") $range .= " AND stop_sequence >= '{$prevTimePoint['stop_sequence']}'"; if ($prevTimePoint != "") $range .= " AND stop_sequence >= '{$prevTimePoint['stop_sequence']}'";
if ($nextTimePoint != "") $range .= " AND stop_sequence <= '{$nextTimePoint['stop_sequence']}'"; if ($nextTimePoint != "") $range .= " AND stop_sequence <= '{$nextTimePoint['stop_sequence']}'";
foreach (getTimeInterpolatedTrip($tripID, $range) as $tripStop) { foreach (getTimeInterpolatedTrip($tripID, $range) as $tripStop) {
if ($tripStop['stop_sequence'] == $stop_sequence) return $tripStop; if ($tripStop['stop_sequence'] == $stop_sequence) return $tripStop;
} }
return Array(); return Array();
} }
function getTripStartTime($tripID) function getTripStartTime($tripID)
{ {
global $conn; global $conn;
$query = "Select * from stop_times $query = "Select * from stop_times
where trip_id = :tripID where trip_id = :tripID
AND arrival_time IS NOT NULL AND arrival_time IS NOT NULL
AND stop_sequence = '1'"; AND stop_sequence = '1'";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":tripID", $tripID); $query->bindParam(":tripID", $tripID);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
$r = $query->fetch(PDO::FETCH_ASSOC); $r = $query->fetch(PDO::FETCH_ASSOC);
return $r['arrival_time']; return $r['arrival_time'];
} }
  function getTripEndTime($tripID)
  {
  global $conn;
  $query = "SELECT trip_id,max(arrival_time) as arrival_time from stop_times
  WHERE stop_times.arrival_time IS NOT NULL and trip_id = :tripID group by trip_id";
  debug($query, "database");
  $query = $conn->prepare($query);
  $query->bindParam(":tripID", $tripID);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  $r = $query->fetch(PDO::FETCH_ASSOC);
  return $r['arrival_time'];
  }
function getActiveTrips($time) function getActiveTrips($time)
{ {
global $conn; global $conn;
if ($time == "") $time = current_time(); if ($time == "") $time = current_time();
$query = "Select distinct stop_times.trip_id, start_times.arrival_time as start_time, end_times.arrival_time as end_time from stop_times, (SELECT trip_id,arrival_time from stop_times WHERE stop_times.arrival_time IS NOT NULL $query = "Select distinct stop_times.trip_id, start_times.arrival_time as start_time, end_times.arrival_time as end_time from stop_times, (SELECT trip_id,arrival_time from stop_times WHERE stop_times.arrival_time IS NOT NULL
AND stop_sequence = '1') as start_times, (SELECT trip_id,max(arrival_time) as arrival_time from stop_times WHERE stop_times.arrival_time IS NOT NULL group by trip_id) as end_times AND stop_sequence = '1') as start_times, (SELECT trip_id,max(arrival_time) as arrival_time from stop_times WHERE stop_times.arrival_time IS NOT NULL group by trip_id) as end_times
WHERE start_times.trip_id = end_times.trip_id AND stop_times.trip_id = end_times.trip_id AND :time > start_times.arrival_time AND :time < end_times.arrival_time"; WHERE start_times.trip_id = end_times.trip_id AND stop_times.trip_id = end_times.trip_id AND :time > start_times.arrival_time AND :time < end_times.arrival_time";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":time", $time); $query->bindParam(":time", $time);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
return $query->fetchAll(); return $query->fetchAll();
} }
function viaPoints($tripID, $stop_sequence = "") function viaPoints($tripID, $stop_sequence = "")
{ {
global $conn; global $conn;
$query = "SELECT stops.stop_id, stop_name, arrival_time $query = "SELECT stops.stop_id, stop_name, arrival_time
FROM stop_times join stops on stops.stop_id = stop_times.stop_id FROM stop_times join stops on stops.stop_id = stop_times.stop_id
WHERE stop_times.trip_id = :tripID WHERE stop_times.trip_id = :tripID
" . ($stop_sequence != "" ? " AND stop_sequence > :stop_sequence " : "") . "AND substr(stop_code,1,2) != 'Wj' ORDER BY stop_sequence"; " . ($stop_sequence != "" ? " AND stop_sequence > :stop_sequence " : "") . "AND substr(stop_code,1,2) != 'Wj' ORDER BY stop_sequence";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
if ($stop_sequence != "") $query->bindParam(":stop_sequence", $stop_sequence); if ($stop_sequence != "") $query->bindParam(":stop_sequence", $stop_sequence);
$query->bindParam(":tripID", $tripID); $query->bindParam(":tripID", $tripID);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
return $query->fetchAll(); return $query->fetchAll();
} }
function viaPointNames($tripid, $stop_sequence = "") function viaPointNames($tripid, $stop_sequence = "")
{ {
$viaPointNames = Array(); $viaPointNames = Array();
foreach (viaPoints($tripid, $stop_sequence) as $point) { foreach (viaPoints($tripid, $stop_sequence) as $point) {
$viaPointNames[] = $point['stop_name']; $viaPointNames[] = $point['stop_name'];
} }
if (sizeof($viaPointNames) > 0) { if (sizeof($viaPointNames) > 0) {
return r_implode(", ", $viaPointNames); return r_implode(", ", $viaPointNames);
} }
else { else {
return ""; return "";
} }
} }
?> ?>
<?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 ($labsPath . 'lib/GoogleMapUtility.php'); require_once ('lib/GoogleMapUtility.php');
require_once ($labsPath . 'lib/HeatMap.php'); require_once ('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_DIM