--- a/labs/busstopdensity.tile.php +++ b/labs/busstopdensity.tile.php @@ -1,1 +1,121 @@ + +* @version: 1.0 +* @history: +* 1.0 creation +*/ + set_time_limit(120);//2mn + ini_set('memory_limit', '256M'); +error_reporting(E_ALL ^ E_DEPRECATED); + require_once ('lib/GoogleMapUtility.php'); + require_once ('lib/HeatMap.php'); + + //Root folder to store generated tiles + define('TILE_DIR', 'tiles/'); + //Covered geographic areas + define('MIN_LAT', -35.48); + define('MAX_LAT', -35.15); + define('MIN_LNG', 148.98); + define('MAX_LNG', 149.25); + define('TILE_SIZE_FACTOR', 0.5); + define('SPOT_RADIUS', 30); + define('SPOT_DIMMING_LEVEL', 50); + + //Input parameters + if(isset($_GET['x'])) + $X = (int)$_GET['x']; + else + exit("x missing"); + if(isset($_GET['y'])) + $Y = (int)$_GET['y']; + else + exit("y missing"); + if(isset($_GET['zoom'])) + $zoom = (int)$_GET['zoom']; + else + exit("zoom missing"); + + $dir = TILE_DIR.$zoom; + $tilename = $dir.'/'.$X.'_'.$Y.'.png'; + //HTTP headers (data type and caching rule) + header("Cache-Control: must-revalidate"); + header("Expires: " . gmdate("D, d M Y H:i:s", time() + 86400) . " GMT"); + if(!file_exists($tilename)){ + $rect = GoogleMapUtility::getTileRect($X, $Y, $zoom); + //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. + $extend_X = $rect->width * TILE_SIZE_FACTOR;//in decimal degrees + $extend_Y = $rect->height * TILE_SIZE_FACTOR;//in decimal degrees + $swlat = $rect->y - $extend_Y; + $swlng = $rect->x - $extend_X; + $nelat = $swlat + $rect->height + 2 * $extend_Y; + $nelng = $swlng + $rect->width + 2 * $extend_X; + + if( ($nelat <= MIN_LAT) || ($swlat >= MAX_LAT) || ($nelng <= MIN_LNG) || ($swlng >= MAX_LNG)){ + //No geodata so return generic empty tile + echo file_get_contents(TILE_DIR.'empty.png'); + exit(); + } + + //Get McDonald's spots + $spots = fGetPOI('Select * from stops where + (stop_lon > '.$swlng.' AND stop_lon < '.$nelng.') + AND (stop_lat < '.$nelat.' AND stop_lat > '.$swlat.')', $im, $X, $Y, $zoom, SPOT_RADIUS); + + + if(empty($spots)){ + //No geodata so return generic empty tile + header('Content-type: image/png'); + echo file_get_contents(TILE_DIR.'empty.png'); + }else{ + if(!file_exists($dir)){ + mkdir($dir, 0705); + } + //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); + //Store tile for reuse and output it + header('content-type:image/png;'); + imagepng($im, $tilename); + echo file_get_contents($tilename); + imagedestroy($im); + unset($im); + } + }else{ + //Output stored tile + header('content-type:image/png;'); + echo file_get_contents($tilename); + } + ///////////// + //Functions// + ///////////// + function fGetPOI($query, &$im, $X, $Y, $zoom, $offset){ + global $conn; + $nbPOIInsideTile = 0; + + $result = pg_query($conn, $query); + $spots = Array(); + if (!$result) { + databaseError(pg_result_error($result)); + return Array(); + } + foreach( pg_fetch_all($result) as $row){ + $point = GoogleMapUtility::getOffsetPixelCoords($row['stop_lat'], $row['stop_lon'], $zoom, $X, $Y); + //Count result only in the tile + if( ($point->x > -$offset) && ($point->x < (GoogleMapUtility::TILE_SIZE+$offset)) && ($point->y > -$offset) && ($point->y < (GoogleMapUtility::TILE_SIZE+$offset))){ + $spots[] = new HeatMapPoint($point->x, $point->y); + } + + }//while + return $spots; + }//fAddPOI +?> + +