<?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 for reuse and output it |
header('content-type:image/png;'); |
header('content-type:image/png;'); |
imagepng($im, $tilename); |
imagepng($im, $tilename); |
echo file_get_contents($tilename); |
echo file_get_contents($tilename); |
imagedestroy($im); |
imagedestroy($im); |
unset($im); |
unset($im); |
} |
} |
}else{ |
}else{ |
//Output stored tile |
//Output stored tile |
header('content-type:image/png;'); |
header('content-type:image/png;'); |
echo file_get_contents($tilename); |
echo file_get_contents($tilename); |
} |
} |
///////////// |
///////////// |
//Functions// |
//Functions// |
///////////// |
///////////// |
function fGetPOI($query, &$im, $X, $Y, $zoom, $offset){ |
function fGetPOI($query, &$im, $X, $Y, $zoom, $offset){ |
global $conn; |
global $conn; |
$nbPOIInsideTile = 0; |
$nbPOIInsideTile = 0; |
|
|
$result = pg_query($conn, $query); |
|
$spots = Array(); |
$spots = Array(); |
if (!$result) { |
$query = $conn->prepare($query); |
databaseError(pg_result_error($result)); |
$query->execute(); |
|
if (!$query) { |
|
databaseError($conn->errorInfo()); |
return Array(); |
return Array(); |
} |
} |
foreach( pg_fetch_all($result) as $row){ |
foreach( $query->fetchAll() as $row){ |
$point = GoogleMapUtility::getOffsetPixelCoords($row['stop_lat'], $row['stop_lon'], $zoom, $X, $Y); |
$point = GoogleMapUtility::getOffsetPixelCoords($row['stop_lat'], $row['stop_lon'], $zoom, $X, $Y); |
//Count result only in the tile |
//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))){ |
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); |
$spots[] = new HeatMapPoint($point->x, $point->y); |
} |
} |
|
|
}//while |
}//while |
return $spots; |
return $spots; |
}//fAddPOI |
}//fAddPOI |
?> |
?> |
|
|
|
|