More PHP 5.4 fixes
[busui.git] / labs / busstopdensity.tile.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
include ('../include/common.inc.php');
$debugOkay = Array(); // disable debugging output even on dev server
 
/*
*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 ($basePath . 'lib/GoogleMapUtility.php');
        require_once ($basePath . '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");
if ($zoom < 12) { //enforce minimum zoom
                        header('Content-type: image/png');
                        echo file_get_contents(TILE_DIR.'empty.png');
}
        $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;
 
        $spots = Array();
        $query = $conn->prepare($query);
        $query->execute();
        if (!$query) {
                databaseError($conn->errorInfo());
                return Array();
        }
        foreach( $query->fetchAll() 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
?>