|
<?php |
|
include ('../include/common.inc.php'); |
|
$debugOkay = Array(); |
|
|
|
/* |
|
*DISCLAIMER |
|
* 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. |
|
* |
|
* @author: Olivier G. <olbibigo_AT_gmail_DOT_com> |
|
* @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 |
|
?> |
|
|
|
|